From 36e25b1d25696b9a1a34c3a2ff40285c4dd7eaff Mon Sep 17 00:00:00 2001 From: scha-ch Date: Fri, 17 Nov 2023 07:53:22 +0100 Subject: [PATCH] DAW#94 User Authentication (Clerk) --- .env.local | 6 +- .vscode/extensions.json | 10 + package-lock.json | 518 +++++++++++++++++++++++- package.json | 6 +- src/app/_common/constants.tsx | 103 ++++- src/app/_common/styles.ts | 24 +- src/app/_common/types/arranger.types.ts | 3 +- src/app/_common/types/project.types.ts | 104 +++-- src/app/_common/types/sheet.types.ts | 12 + src/app/_common/utils.ts | 13 + src/app/_components/App.tsx | 56 ++- src/app/_components/Arranger.tsx | 31 +- src/app/_components/Browser.tsx | 2 +- src/app/_components/Draggable.tsx | 37 +- src/app/_components/Droppable.tsx | 10 +- src/app/_components/Header.tsx | 10 +- src/app/_components/Locator.tsx | 2 +- src/app/_components/Meter.tsx | 2 +- src/app/_components/Mixer.tsx | 9 +- src/app/_components/Navbar.tsx | 18 +- src/app/_components/Note.tsx | 3 +- src/app/_components/PianoRoll.tsx | 2 +- src/app/_components/Progression.tsx | 2 +- src/app/_components/Settings.tsx | 21 +- src/app/_components/Sheet.tsx | 35 +- src/app/_components/SignalFlow.tsx | 2 +- src/app/_components/Song.tsx | 6 +- src/app/_components/SortableItem.tsx | 25 +- src/app/_components/Time.tsx | 11 +- src/app/_components/Transport.tsx | 70 ++-- src/app/_components/index.ts | 82 ++-- src/app/_components/track/Track.tsx | 5 +- src/app/_core/hooks/index.ts | 2 + src/app/_core/hooks/useTransport.ts | 2 +- src/app/layout.tsx | 13 +- src/middleware.ts | 10 + tsconfig.json | 10 +- 37 files changed, 973 insertions(+), 304 deletions(-) create mode 100644 .vscode/extensions.json create mode 100644 src/app/_common/types/sheet.types.ts create mode 100644 src/app/_core/hooks/index.ts create mode 100644 src/middleware.ts diff --git a/.env.local b/.env.local index 4c041e22..7738f893 100644 --- a/.env.local +++ b/.env.local @@ -1,4 +1,8 @@ #*** @Stripe *# NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_51LBfSOLjx992qWAYRekYCPRpgZ3xa6POoteqC7Tp9555GXDGEcm67xHgOQt20N9vTrXaerlfKQdTcxZreijcvwI300GL0SnTOR -STRIPE_SECRET=sk_test_51LBfSOLjx992qWAYx8s062kh2dqbNsjbH6Po0xL93bZjeOKZyFCtxNzQ0gyFNCSOWYLSi45miRAZS6olA3epsayv00C9LKNqPB \ No newline at end of file +STRIPE_SECRET=sk_test_51LBfSOLjx992qWAYx8s062kh2dqbNsjbH6Po0xL93bZjeOKZyFCtxNzQ0gyFNCSOWYLSi45miRAZS6olA3epsayv00C9LKNqPB + +#*** @Clerk *# +NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_c2V0dGxpbmctYXBoaWQtODguY2xlcmsuYWNjb3VudHMuZGV2JA +CLERK_SECRET_KEY=sk_test_vXZyjvBVwcDPtiyKYBeNw4UAb5fOhnFPmPUEmTgTNK \ No newline at end of file diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 00000000..c0e21d91 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + "recommendations": [ + "infeng.vscode-react-typescript", + "dbaeumer.vscode-eslint", + "eamodio.gitlens", + "shd101wyy.markdown-preview-enhanced", + "jebbs.plantuml", + "esbenp.prettier-vscode" + ] +} diff --git a/package-lock.json b/package-lock.json index be00bb23..00c8cef0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,7 @@ "name": "daw", "version": "0.1.0", "dependencies": { + "@clerk/nextjs": "^4.27.1", "@dnd-kit/core": "^6.0.8", "@dnd-kit/sortable": "^7.0.2", "@dnd-kit/utilities": "^3.2.1", @@ -18,8 +19,8 @@ "@stripe/stripe-js": "^2.1.10", "@tensorflow/tfjs": "^4.12.0", "@types/node": "^20.8.9", - "@types/react": "18.2.33", - "@types/react-dom": "18.2.14", + "@types/react": "^18.2.37", + "@types/react-dom": "^18.2.15", "abcjs": "^6.2.2", "audiokeys": "^0.1.1", "autoprefixer": "10.4.16", @@ -31,6 +32,7 @@ "lucide-react": "^0.289.0", "next": "^14.0.0", "postcss": "8.4.31", + "primeicons": "^6.0.1", "primereact": "^10.0.5", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -88,6 +90,181 @@ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==" }, + "node_modules/@clerk/backend": { + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@clerk/backend/-/backend-0.34.1.tgz", + "integrity": "sha512-I6u7vb7XHA0kNek5Ez4VVqBDZKxLepR6wJXlYUy5lGwsTdaQiFwy5Q0nKP2GdQQYtlKpXSAryLu19Cq5zaaNYg==", + "dependencies": { + "@clerk/shared": "1.1.0", + "@clerk/types": "3.58.0", + "@peculiar/webcrypto": "1.4.1", + "@types/node": "16.18.6", + "cookie": "0.5.0", + "deepmerge": "4.2.2", + "node-fetch-native": "1.0.1", + "snakecase-keys": "5.4.4", + "tslib": "2.4.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@clerk/backend/node_modules/@types/node": { + "version": "16.18.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.6.tgz", + "integrity": "sha512-vmYJF0REqDyyU0gviezF/KHq/fYaUbFhkcNbQCuPGFQj6VTbXuHZoxs/Y7mutWe73C8AC6l9fFu8mSYiBAqkGA==" + }, + "node_modules/@clerk/backend/node_modules/deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@clerk/backend/node_modules/tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + }, + "node_modules/@clerk/clerk-react": { + "version": "4.28.0", + "resolved": "https://registry.npmjs.org/@clerk/clerk-react/-/clerk-react-4.28.0.tgz", + "integrity": "sha512-zMFdiqqXkwAks1xmheUrAS6GODDdlpsCHA3VEnNVlSL0XH3bE4jWNr7lr0SJMmcaEsmZE/JQ+uNPJ4qEvEDGjA==", + "dependencies": { + "@clerk/shared": "1.1.0", + "@clerk/types": "3.58.0", + "tslib": "2.4.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "react": ">=16" + } + }, + "node_modules/@clerk/clerk-react/node_modules/tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + }, + "node_modules/@clerk/clerk-sdk-node": { + "version": "4.12.21", + "resolved": "https://registry.npmjs.org/@clerk/clerk-sdk-node/-/clerk-sdk-node-4.12.21.tgz", + "integrity": "sha512-43MdviLlAG3naNzRyxF/Io8YYQBnFEIQiqYFVHzKzZGEsbPST9lBfeFxJZKrCqSE8K7gMx3+3D87bveXq6a7cA==", + "dependencies": { + "@clerk/backend": "0.34.1", + "@clerk/shared": "1.1.0", + "@clerk/types": "3.58.0", + "@types/cookies": "0.7.7", + "@types/express": "4.17.14", + "@types/node-fetch": "2.6.2", + "camelcase-keys": "6.2.2", + "snakecase-keys": "3.2.1", + "tslib": "2.4.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@clerk/clerk-sdk-node/node_modules/@types/node-fetch": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.2.tgz", + "integrity": "sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==", + "dependencies": { + "@types/node": "*", + "form-data": "^3.0.0" + } + }, + "node_modules/@clerk/clerk-sdk-node/node_modules/snakecase-keys": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/snakecase-keys/-/snakecase-keys-3.2.1.tgz", + "integrity": "sha512-CjU5pyRfwOtaOITYv5C8DzpZ8XA/ieRsDpr93HI2r6e3YInC6moZpSQbmUtg8cTk58tq2x3jcG2gv+p1IZGmMA==", + "dependencies": { + "map-obj": "^4.1.0", + "to-snake-case": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@clerk/clerk-sdk-node/node_modules/tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + }, + "node_modules/@clerk/nextjs": { + "version": "4.27.1", + "resolved": "https://registry.npmjs.org/@clerk/nextjs/-/nextjs-4.27.1.tgz", + "integrity": "sha512-FsAwVqCNNOjTC3w9mHjc/T4uP/JzGni0WTXANNXjC4sfh2kDfBzUMLRPNfcgAou5TOsMqYJdRxQ5sx4eCGQIOA==", + "dependencies": { + "@clerk/backend": "0.34.1", + "@clerk/clerk-react": "4.28.0", + "@clerk/clerk-sdk-node": "4.12.21", + "@clerk/shared": "1.1.0", + "@clerk/types": "3.58.0", + "path-to-regexp": "6.2.1", + "tslib": "2.4.1" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "next": ">=10", + "react": "^17.0.2 || ^18.0.0-0", + "react-dom": "^17.0.2 || ^18.0.0-0" + } + }, + "node_modules/@clerk/nextjs/node_modules/tslib": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.1.tgz", + "integrity": "sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==" + }, + "node_modules/@clerk/shared": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@clerk/shared/-/shared-1.1.0.tgz", + "integrity": "sha512-rxQ6bxAERZsf/dzCU35qt3gRp9+a035Vrre8j8tyT60dbP8PQhXUbeNu+oVqqjpHWeyoWWt6fZGLXbDTXdXx7g==", + "dependencies": { + "glob-to-regexp": "0.4.1", + "js-cookie": "3.0.1", + "swr": "2.2.0" + }, + "peerDependencies": { + "react": ">=16" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + } + } + }, + "node_modules/@clerk/shared/node_modules/swr": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/swr/-/swr-2.2.0.tgz", + "integrity": "sha512-AjqHOv2lAhkuUdIiBu9xbuettzAzWXmCEcLONNKJRba87WAefz8Ca9d6ds/SzrPc235n1IxWYdhJ2zF3MNUaoQ==", + "dependencies": { + "use-sync-external-store": "^1.2.0" + }, + "peerDependencies": { + "react": "^16.11.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@clerk/types": { + "version": "3.58.0", + "resolved": "https://registry.npmjs.org/@clerk/types/-/types-3.58.0.tgz", + "integrity": "sha512-fIsvEM3nYQwViOuYxNVcwEl0WkXW6AdYpSghNBKfOge1kriSSHP++T5rRMJBXy6asl2AEydVlUBKx9drAzqKoA==", + "dependencies": { + "csstype": "3.1.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@clerk/types/node_modules/csstype": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", + "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==" + }, "node_modules/@colors/colors": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", @@ -1696,6 +1873,42 @@ "node": ">= 8" } }, + "node_modules/@peculiar/asn1-schema": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.3.8.tgz", + "integrity": "sha512-ULB1XqHKx1WBU/tTFIA+uARuRoBVZ4pNdOA878RDrRbBfBGcSzi5HBkdScC6ZbHn8z7L8gmKCgPC1LHRrP46tA==", + "dependencies": { + "asn1js": "^3.0.5", + "pvtsutils": "^1.3.5", + "tslib": "^2.6.2" + } + }, + "node_modules/@peculiar/json-schema": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz", + "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@peculiar/webcrypto": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.4.1.tgz", + "integrity": "sha512-eK4C6WTNYxoI7JOabMoZICiyqRRtJB220bh0Mbj5RwRycleZf9BPyZoxsTvpP0FpmVS2aS13NKOuh5/tN3sIRw==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.0", + "@peculiar/json-schema": "^1.1.12", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.1", + "webcrypto-core": "^1.7.4" + }, + "engines": { + "node": ">=10.12.0" + } + }, "node_modules/@pkgr/utils": { "version": "2.4.2", "license": "MIT", @@ -3390,6 +3603,15 @@ "optional": true, "peer": true }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, "node_modules/@types/color": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/color/-/color-3.0.4.tgz", @@ -3411,6 +3633,25 @@ "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cookies": { + "version": "0.7.7", + "resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.7.7.tgz", + "integrity": "sha512-h7BcvPUogWbKCzBR2lY4oqaZbO3jXZksexYJVFvkrFeLgbZjQkU4x8pRq6eg2MHXQhY0McQdqmmsxRWlVAHooA==", + "dependencies": { + "@types/connect": "*", + "@types/express": "*", + "@types/keygrip": "*", + "@types/node": "*" + } + }, "node_modules/@types/d3": { "version": "7.4.2", "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.2.tgz", @@ -3633,6 +3874,28 @@ "@types/d3-selection": "*" } }, + "node_modules/@types/express": { + "version": "4.17.14", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.14.tgz", + "integrity": "sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg==", + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.18", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.41", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.41.tgz", + "integrity": "sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, "node_modules/@types/flat": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/@types/flat/-/flat-5.0.3.tgz", @@ -3652,10 +3915,20 @@ "hoist-non-react-statics": "^3.3.0" } }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==" + }, "node_modules/@types/json5": { "version": "0.0.29", "license": "MIT" }, + "node_modules/@types/keygrip": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.5.tgz", + "integrity": "sha512-M+BUYYOXgiYoab5L98VpOY1PzmDwWcTkqqu4mdluez5qOTDV0MVPChxhRIPeIFxQgSi3+6qjg1PnGFaGlW373g==" + }, "node_modules/@types/lodash": { "version": "4.14.199", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.199.tgz", @@ -3705,6 +3978,11 @@ "version": "4.0.2", "license": "MIT" }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" + }, "node_modules/@types/node": { "version": "20.8.9", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.8.9.tgz", @@ -3729,10 +4007,20 @@ "version": "15.7.5", "license": "MIT" }, + "node_modules/@types/qs": { + "version": "6.9.10", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.10.tgz", + "integrity": "sha512-3Gnx08Ns1sEoCrWssEgTSJs/rsT2vhGP+Ja9cnnk9k4ALxinORlQneLXFeFKOTJMOeZUFD1s7w+w2AphTpvzZw==" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" + }, "node_modules/@types/react": { - "version": "18.2.33", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.33.tgz", - "integrity": "sha512-v+I7S+hu3PIBoVkKGpSYYpiBT1ijqEzWpzQD62/jm4K74hPpSP7FF9BnKG6+fg2+62weJYkkBWDJlZt5JO/9hg==", + "version": "18.2.37", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.37.tgz", + "integrity": "sha512-RGAYMi2bhRgEXT3f4B92WTohopH6bIXw05FuGlmJEnv/omEn190+QYEIYxIAuIBdKgboYYdVved2p1AxZVQnaw==", "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -3740,9 +4028,9 @@ } }, "node_modules/@types/react-dom": { - "version": "18.2.14", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.14.tgz", - "integrity": "sha512-V835xgdSVmyQmI1KLV2BEIUgqEuinxp9O4G6g3FqO/SqLac049E53aysv0oEFD2kHfejeKU+ZqL2bcFWj9gLAQ==", + "version": "18.2.15", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.2.15.tgz", + "integrity": "sha512-HWMdW+7r7MR5+PZqJF6YFNSCtjz1T0dsvo/f1BV6HkV+6erD/nA7wd9NM00KVG83zf2nJ7uATPO9ttdIPvi3gg==", "dependencies": { "@types/react": "*" } @@ -3763,6 +4051,25 @@ "version": "2.4.30", "license": "MIT" }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz", + "integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==", + "dependencies": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, "node_modules/@types/sinonjs__fake-timers": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", @@ -4162,6 +4469,19 @@ "safer-buffer": "~2.1.0" } }, + "node_modules/asn1js": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", + "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", + "dependencies": { + "pvtsutils": "^1.3.2", + "pvutils": "^1.1.3", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/assert-plus": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", @@ -4502,6 +4822,14 @@ "node": ">=6" } }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, "node_modules/camelcase-css": { "version": "2.0.1", "license": "MIT", @@ -4509,6 +4837,22 @@ "node": ">= 6" } }, + "node_modules/camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dependencies": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001549", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001549.tgz", @@ -4769,6 +5113,14 @@ "version": "0.0.1", "license": "MIT" }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/core-js": { "version": "3.29.1", "hasInstallScript": true, @@ -5296,6 +5648,15 @@ "csstype": "^3.0.2" } }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, "node_modules/ecc-jsbn": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", @@ -7162,6 +7523,14 @@ "jiti": "bin/jiti.js" } }, + "node_modules/js-cookie": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.1.tgz", + "integrity": "sha512-+0rgsUXZu4ncpPxRL+lNEptWMOWl9etvPHc/koSRp6MPwpRYAhmk0dUG00J4bxVV3r9uUzfo24wW0knS07SKSw==", + "engines": { + "node": ">=12" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "license": "MIT" @@ -7488,6 +7857,14 @@ "loose-envify": "cli.js" } }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dependencies": { + "tslib": "^2.0.3" + } + }, "node_modules/lru-cache": { "version": "6.0.0", "license": "ISC", @@ -7513,6 +7890,17 @@ "optional": true, "peer": true }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "license": "MIT" @@ -7661,6 +8049,15 @@ } } }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, "node_modules/node-fetch": { "version": "2.6.13", "license": "MIT", @@ -7679,6 +8076,11 @@ } } }, + "node_modules/node-fetch-native": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.0.1.tgz", + "integrity": "sha512-VzW+TAk2wE4X9maiKMlT+GsPU4OMmR1U9CrHSmd3DFLn2IcZ9VJ6M6BBugGfYUnPCLSYxXdZy17M0BEJyhUTwg==" + }, "node_modules/node-releases": { "version": "2.0.13", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", @@ -7963,6 +8365,11 @@ "version": "1.0.7", "license": "MIT" }, + "node_modules/path-to-regexp": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.2.1.tgz", + "integrity": "sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==" + }, "node_modules/path-type": { "version": "4.0.0", "license": "MIT", @@ -8162,6 +8569,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/primeicons": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/primeicons/-/primeicons-6.0.1.tgz", + "integrity": "sha512-KDeO94CbWI4pKsPnYpA1FPjo79EsY9I+M8ywoPBSf9XMXoe/0crjbUK7jcQEDHuc0ZMRIZsxH3TYLv4TUtHmAA==" + }, "node_modules/primereact": { "version": "10.0.5", "resolved": "https://registry.npmjs.org/primereact/-/primereact-10.0.5.tgz", @@ -8228,6 +8640,22 @@ "node": ">=6" } }, + "node_modules/pvtsutils": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.5.tgz", + "integrity": "sha512-ARvb14YB9Nm2Xi6nBq1ZX6dAM0FsJnuk+31aUp4TrcZEdKUlSqOqsxJHUPJDNE3qiIp+iUPEIeR6Je/tgV7zsA==", + "dependencies": { + "tslib": "^2.6.1" + } + }, + "node_modules/pvutils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", + "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/qs": { "version": "6.10.4", "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.4.tgz", @@ -8266,6 +8694,14 @@ ], "license": "MIT" }, + "node_modules/quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "engines": { + "node": ">=8" + } + }, "node_modules/react": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", @@ -8883,6 +9319,39 @@ "node": ">=8" } }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/snakecase-keys": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/snakecase-keys/-/snakecase-keys-5.4.4.tgz", + "integrity": "sha512-YTywJG93yxwHLgrYLZjlC75moVEX04LZM4FHfihjHe1FCXm+QaLOFfSf535aXOAd0ArVQMWUAe8ZPm4VtWyXaA==", + "dependencies": { + "map-obj": "^4.1.0", + "snake-case": "^3.0.4", + "type-fest": "^2.5.2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/snakecase-keys/node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/source-map-js": { "version": "1.0.2", "license": "BSD-3-Clause", @@ -9311,6 +9780,11 @@ "node": ">=8.17.0" } }, + "node_modules/to-no-case": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/to-no-case/-/to-no-case-1.0.2.tgz", + "integrity": "sha512-Z3g735FxuZY8rodxV4gH7LxClE4H0hTIyHNIHdk+vpQxjLm0cwnKXq/OFVZ76SOQmto7txVcwSCwkU5kqp+FKg==" + }, "node_modules/to-regex-range": { "version": "5.0.1", "license": "MIT", @@ -9321,6 +9795,22 @@ "node": ">=8.0" } }, + "node_modules/to-snake-case": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-snake-case/-/to-snake-case-1.0.0.tgz", + "integrity": "sha512-joRpzBAk1Bhi2eGEYBjukEWHOe/IvclOkiJl3DtA91jV6NwQ3MwXA4FHYeqk8BNp/D8bmi9tcNbRu/SozP0jbQ==", + "dependencies": { + "to-space-case": "^1.0.0" + } + }, + "node_modules/to-space-case": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-space-case/-/to-space-case-1.0.0.tgz", + "integrity": "sha512-rLdvwXZ39VOn1IxGL3V6ZstoTbwLRckQmn/U8ZDLuWwIXNpuZDhQ3AiRUlhTbOXFVE9C+dR51wM0CBDhk31VcA==", + "dependencies": { + "to-no-case": "^1.0.0" + } + }, "node_modules/tonal": { "version": "5.0.0", "license": "MIT", @@ -9831,6 +10321,18 @@ "integrity": "sha512-RevLfVjp+wwe/dBPe361IpmNpeXXW6JVmlp8dk0YIxLwAh7evn6JpEQQalVgX4PH/jA8tpLpjD/8tFNUYTf88w==", "dev": true }, + "node_modules/webcrypto-core": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.7.7.tgz", + "integrity": "sha512-7FjigXNsBfopEj+5DV2nhNpfic2vumtjjgPmeDKk45z+MJwXKKfhPB7118Pfzrmh4jqOMST6Ch37iPAHoImg5g==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/json-schema": "^1.1.12", + "asn1js": "^3.0.1", + "pvtsutils": "^1.3.2", + "tslib": "^2.4.0" + } + }, "node_modules/webidl-conversions": { "version": "3.0.1", "license": "BSD-2-Clause" diff --git a/package.json b/package.json index 1295592b..ff384e39 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "test:e2e:open": "cypress open" }, "dependencies": { + "@clerk/nextjs": "^4.27.1", "@dnd-kit/core": "^6.0.8", "@dnd-kit/sortable": "^7.0.2", "@dnd-kit/utilities": "^3.2.1", @@ -32,8 +33,8 @@ "@stripe/stripe-js": "^2.1.10", "@tensorflow/tfjs": "^4.12.0", "@types/node": "^20.8.9", - "@types/react": "18.2.33", - "@types/react-dom": "18.2.14", + "@types/react": "^18.2.37", + "@types/react-dom": "^18.2.15", "abcjs": "^6.2.2", "audiokeys": "^0.1.1", "autoprefixer": "10.4.16", @@ -45,6 +46,7 @@ "lucide-react": "^0.289.0", "next": "^14.0.0", "postcss": "8.4.31", + "primeicons": "^6.0.1", "primereact": "^10.0.5", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/src/app/_common/constants.tsx b/src/app/_common/constants.tsx index 43edb196..3cda682d 100644 --- a/src/app/_common/constants.tsx +++ b/src/app/_common/constants.tsx @@ -1,5 +1,4 @@ import _ from 'lodash/fp'; -import * as Tone from 'tone'; import t from 'app/_core/i18n'; @@ -8,7 +7,7 @@ import type { IChannel } from './types/channel.types'; import { EInstrument } from './types/instrument.types'; import { Note } from 'tone/build/esm/core/type/NoteUnits'; import { Subdivision } from 'tone/build/esm/core/type/Units'; -import { useProgress } from '@nextui-org/react'; +import { EScale } from './types/project.types'; // ---------- General /*** @constants */ @@ -52,8 +51,8 @@ export const getMaxNotes = (notes: Note[][]) => const DEFAULT_ACTIVE_TRACK_ID = 'audio-halloween'; const DEFAULT_BPM = 120; const DEFAULT_CLEF = 'D'; -const DEFAULT_SCALE = 'minor'; -const DEFAULT_MEASURE_COUNT = 2; +const DEFAULT_SCALE: EScale = EScale.Minor; +const DEFAULT_MEASURE_COUNT = 4; const DEFAULT_NAME = t('untitled'); const DEFAULT_OFFSET_LEFT = 179; const DEFAULT_POSITION = '0:0:0'; @@ -359,6 +358,54 @@ const DEFAULT_TRACK_SAMPLER: ITrack = { [], ], }, + { + label: 'p3-sampler', + notes: [ + ['C3', 'E3'], + [], + [], + ['C3', 'E3'], + + ['D3'], + [], + ['C3'], + [], + + ['C3', 'E3'], + ['C3'], + [], + [], + + ['D3'], + [], + [], + [], + ], + }, + { + label: 'p4-sampler', + notes: [ + ['C3', 'E3'], + [], + [], + ['C3'], + + ['D3', 'E3'], + [], + ['C3'], + [], + + ['C3', 'E3'], + ['C3'], + [], + [], + + ['D3', 'E3'], + [], + [], + [], + ], + }, ], }, output: 'ch-drums', @@ -461,6 +508,54 @@ const DEFAULT_TRACK_PIANO: ITrack = { [], ], }, + { + label: 'p3-sampler-pno', + notes: [ + ['B4', 'D4', 'F4'], + [], + [], + [], + + ['B4', 'D4', 'F4'], + [], + [], + [], + + ['B4', 'D4', 'F4'], + [], + [], + [], + + ['B4', 'D4', 'F4'], + [], + [], + [], + ], + }, + { + label: 'p4-sampler-pno', + notes: [ + ['B4', 'D4', 'A4'], + [], + [], + [], + + ['B4', 'D4', 'A4'], + [], + [], + [], + + ['B4', 'D4', 'A4'], + [], + [], + [], + + ['B4', 'D4', 'A4'], + [], + [], + [], + ], + }, ], }, output: 'master', diff --git a/src/app/_common/styles.ts b/src/app/_common/styles.ts index e8db59e2..45014681 100644 --- a/src/app/_common/styles.ts +++ b/src/app/_common/styles.ts @@ -18,7 +18,7 @@ const styles = { ol: 'flex-1', innerBack: { main: 'grid absolute top-[32px] right-0', - item: 'item: h-[40px] mb-[4px] border-l border-l-white', + item: 'item: h-[40px] border-r border-r-white last:border-r-0', }, inner: 'flex-1', }, @@ -46,15 +46,16 @@ const styles = { a: 'flex text-white py-2 px-4 gap-2 border-b border-zinc-600', }, mixer: { - main: 'bg-zinc-950 flex w-full text-zinc-200 pl-[179px]', + main: 'h-full bg-zinc-950 flex w-full text-zinc-200 pl-[179px]', inner: 'flex w-full items-center', meter: 'w-full bg-zinc-900', - meterActive: 'bg-zinc-900', + meterActive: 'w-full bg-zinc-800', + meterInactive: 'bg-zinc-900', track: { - main: 'max-w-[110px] pt-6 mr-2 justify-center text-xs items-center content-end relative', - inner: 'flex px-4 items-center gap-1 py-2 border-b border-b-[#555]', + main: 'flex flex-col min-w-[93px] max-w-[150px] border-r border-r-zinc-700 pt-6 justify-center text-xs items-center content-end relative', + inner: 'flex px-4 items-center gap-1 py-2', master: 'h-full', - active: 'bg-zinc-800 text-zinc-300', + active: 'bg-zinc-900 text-zinc-300', inactive: '', }, }, @@ -63,7 +64,7 @@ const styles = { uiInner: 'flex px-4 py-2', }, notes: { - main: 'flex flex-1 justify-center items-center text-center cursor-pointer text-[0.5rem] bg-blue-900 text-zinc-200 border border-zinc-700', + main: 'absolute flex flex-1 justify-center items-center text-center cursor-pointer text-[0.5rem] bg-blue-900 text-zinc-200 border border-blue-700', }, portal: { main: 'fixed top-1/3 left-1/3 z-50 flex justify-center items-center bg-black/90 text-zinc-100 p-8 rounded-sm border border-zinc-700', @@ -74,6 +75,9 @@ const styles = { td2: 'p-1', td3: 'p-1 bg-zinc-200', }, + sheet: { + main: 'bg-white p-8', + }, time: { main: 'flex w-full text-zinc-500 text-xs', col1: 'w-[179px|', @@ -84,14 +88,14 @@ const styles = { audio: 'w-full flex flex-col justify-center', active: 'font-bold bg-zinc-800 text-white', col1: { - main: 'flex justify-between items-center px-4 pl-8 bg-black/10 text-white border-b border-b-zinc-700', + main: 'h-[40px] flex justify-between items-center px-4 pl-8 bg-black/10 text-white', name: 'whitespace-nowrap w-28 overflow-x-hidden text-ellipsis', }, col2: { - main: 'bg-zinc-900/50 relative flex w-full border-b border-b-zinc-700', + main: 'h-[40px] bg-zinc-900/50 relative flex w-full', }, icon: 'fill-white w-[16px] h-[16px]', // TODO not white - li: 'relative flex w-full h-10 text-black mb-1 first:text-zinc-400 text-xs', + li: 'relative flex w-full h-[40px] text-black border-t-zinc-700 first:text-zinc-400 text-xs border-t border-t-zinc-700 last:border-b last:border-b-zinc-700', }, transport: { main: 'flex px-4', diff --git a/src/app/_common/types/arranger.types.ts b/src/app/_common/types/arranger.types.ts index 83bf832d..24fc992f 100644 --- a/src/app/_common/types/arranger.types.ts +++ b/src/app/_common/types/arranger.types.ts @@ -6,7 +6,8 @@ interface IArranger { readonly project: IProject; readonly tracks: ITrack[]; readonly className?: string; - readonly setTracks: (tracks: any) => void; + readonly setProject: (project: IProject) => void; + readonly setTracks: (tracks: ITrack[]) => void; } export type { IArranger }; diff --git a/src/app/_common/types/project.types.ts b/src/app/_common/types/project.types.ts index c634c285..1e201b61 100644 --- a/src/app/_common/types/project.types.ts +++ b/src/app/_common/types/project.types.ts @@ -1,48 +1,82 @@ +import type { ReactNode } from 'react'; import type { Subdivision } from 'tone/build/esm/core/type/Units'; -import type { UniqueIdentifier } from '@dnd-kit/core'; -import type { ITrack } from 'app/_common/types/track.types'; -import type { IChannel } from './channel.types'; -import { Dispatch, ReactNode, SetStateAction } from 'react'; +import type { IChannel } from '@/types/channel.types'; +import type { ITrack } from '@/types/track.types'; +import type { UniqueIdentifier } from '@/types/utility.types'; -export enum ETransportState { - Paused = 'paused', - Started = 'started', - Stopped = 'stopped', +/*** @dialog */ +export interface IStartDialog { + readonly toneReady: boolean; + readonly setToneReady: (toneReady: boolean) => void; } -export enum EPortal { - Instruments = 'portal-instruments', + +/*** @dnd */ +export interface IDraggable { + readonly children: ReactNode; + readonly id: string; +} +export interface IDroppable { + readonly id: string; + readonly children?: ReactNode; +} +export interface ISortableItem { + readonly children: ReactNode; + readonly className: string; + readonly id: UniqueIdentifier; +} + +/*** @dsp */ +export interface ISignalFlow { + readonly in: UniqueIdentifier; + readonly out: UniqueIdentifier; + readonly inserts?: UniqueIdentifier[]; + readonly sends?: UniqueIdentifier[]; } +/*** @song */ export interface ISong { - children: ReactNode; - className?: string; - grow?: boolean; + readonly children: ReactNode; + readonly className?: string; + readonly grow?: boolean; } -export interface IStartDialog { - toneReady: boolean; - setToneReady: Dispatch>; +/*** @portal */ +export enum EPortal { + Instruments = 'portal-instruments', +} + +/*** @settings */ +export enum EScale { + Major, + Minor, } export interface IProject { - activeTrackId: UniqueIdentifier; - bpm: number; - clef: string; - scale: string; // TODO enum - measureCount: number; - name: string; - offsetLeft: number; - position: string; - quantization: number; - swing: number; - swingSubdivision: Subdivision; + readonly activeTrackId: UniqueIdentifier; + readonly bpm: number; + readonly clef: string; + readonly scale: EScale; + readonly measureCount: number; + readonly name: string; + readonly offsetLeft: number; + readonly position: string; + readonly quantization: number; + readonly swing: number; + readonly swingSubdivision: Subdivision; } + +/*** @data move this to api.types */ export interface IData { - channels: IChannel[]; - project: IProject; - tracks: ITrack[]; + readonly channels: IChannel[]; + readonly project: IProject; + readonly tracks: ITrack[]; } -export interface ISignalFlow { - in: UniqueIdentifier; - out: UniqueIdentifier; - inserts?: UniqueIdentifier[]; - sends?: UniqueIdentifier[]; + +/*** @transport */ +export enum ETransportState { + Paused = 'paused', + Started = 'started', + Stopped = 'stopped', +} +export interface ITransport { + readonly project: IProject; + readonly setProject: (project: IProject) => void; } diff --git a/src/app/_common/types/sheet.types.ts b/src/app/_common/types/sheet.types.ts new file mode 100644 index 00000000..2ed85ffe --- /dev/null +++ b/src/app/_common/types/sheet.types.ts @@ -0,0 +1,12 @@ +export enum ESheetNoteStyle { + Rhythm = 'rhythm', + Harmonic = 'harmonic', + X = 'x', + Normal = 'normal', + Triangle = 'triangle', +} + +export interface ISheet { + markdown: string; + noteStyle?: ESheetNoteStyle; +} diff --git a/src/app/_common/utils.ts b/src/app/_common/utils.ts index c7ebb474..f384abb3 100644 --- a/src/app/_common/utils.ts +++ b/src/app/_common/utils.ts @@ -1,2 +1,15 @@ export const ROMAN_NUMS = ['i', 'ii', 'iii', 'iv', 'v', 'vi', 'vii']; export const isRomanNum = (s: string) => ROMAN_NUMS.includes(s.toLowerCase()); + +export const colorScale = [ + '50', + '100', + '200', + '300', + '400', + '500', + '600', + '700', + '800', + '900', +]; diff --git a/src/app/_components/App.tsx b/src/app/_components/App.tsx index 9677f3a1..61d97cc6 100644 --- a/src/app/_components/App.tsx +++ b/src/app/_components/App.tsx @@ -1,6 +1,7 @@ 'use client'; import _ from 'lodash/fp'; import usePortal from 'react-useportal'; +import { Splitter, SplitterPanel } from 'primereact/splitter'; import t from '@/core/i18n'; import { patchProject } from '@/api/project/_presets/DefaultPreset'; @@ -12,7 +13,7 @@ import { Mixer, Song, } from '@/components'; -import { Button, ButtonGroup, Dialog, Flex, Menu } from '@/pfui'; +import { Button, ButtonGroup, Dialog, Menu } from '@/pfui'; import { useSelector } from '@/core/hooks/useSelector'; import { useToneJs } from '@/core/hooks/useToneJs'; @@ -23,10 +24,11 @@ import { useEffect, useState } from 'react'; import { ITrack } from '@/common/types/track.types'; export function App({ - channels: _channels, - project, + channels: initialChannels, + project: initialProject, tracks: initialTracks, }: IData) { + const [project, setProject] = useState(null); const [tracks, setTracks] = useState(null); const { Portal, openPortal, closePortal, isOpen } = usePortal(); const { init, toneReady } = useToneJs(); @@ -41,14 +43,13 @@ export function App({ /* const convertAudioToMidi = async () => { try { - // TODO stream it & not run always at start up const notes = await audioToMidi({ audio: "/halloween.mp3" }); } catch (error) { console.error(error); } }; */ - /* TODO + /* useEffect(() => { (async () => { try { @@ -226,12 +227,13 @@ export function App({ */ useEffect(() => { + setProject(initialProject); setTracks(selectTracks(initialTracks)); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - if (toneReady) { - const channels = selectChannels(_channels); + if (toneReady && tracks?.length && project) { + const channels = selectChannels(initialChannels); const activeTrack = tracks?.find(({ id }) => id === project.activeTrackId); /*** * New way of structuring @@ -240,22 +242,34 @@ export function App({ */ return ( <> -
+
- - - - + + + + + + + +
diff --git a/src/app/_components/Arranger.tsx b/src/app/_components/Arranger.tsx index 7db05d7d..0f695bb9 100644 --- a/src/app/_components/Arranger.tsx +++ b/src/app/_components/Arranger.tsx @@ -1,4 +1,5 @@ 'use client'; +import { useState } from 'react'; import { DndContext, DragEndEvent, @@ -14,37 +15,36 @@ import { verticalListSortingStrategy, } from '@dnd-kit/sortable'; -import styles from '@/common/styles'; import { Locator, Time, Track } from '@/components'; - -import type { IArranger } from '@/common/types/arranger.types'; import { Flex, Grid } from '@/pfui'; -import { useState } from 'react'; -import useTransport from '@/core/hooks/useTransport'; +import { useSelector, useTransport } from '@/core/hooks'; import { patchProject, patchTrack, patchTracks, } from '@/api/project/_presets/DefaultPreset'; -export default function Arranger({ - project: initialProject, +import type { IArranger } from '@/common/types/arranger.types'; + +import styles from '@/common/styles'; +const $ = styles.arranger; + +export function Arranger({ + project, tracks, + setProject, setTracks, className = '', }: IArranger) { const [position, setPosition] = useState('0:0:0.000'); - const [project, setProject] = useState(initialProject); - const [activeTrackId, setActiveTrackId] = useState( - initialProject.activeTrackId, - ); + const [activeTrackId, setActiveTrackId] = useState(project.activeTrackId); const loopFn = setPosition; const { loop } = useTransport({ loopFn }); loop.start(); const { measureCount, quantization, offsetLeft } = project; + const { deselectTracks } = useSelector(); const mouseSensor = useSensor(MouseSensor); const sensors = useSensors(mouseSensor); - const $ = styles.arranger; const events = { dragEnd: ({ active, over }: DragEndEvent) => { @@ -53,7 +53,7 @@ export default function Arranger({ const newIndex = tracks.findIndex(({ id }) => id === over?.id); const sortedTracks = arrayMove(tracks, oldIndex, newIndex); setTracks(sortedTracks); - patchTracks(sortedTracks); + patchTracks(deselectTracks(sortedTracks).tracks); }, }; @@ -78,7 +78,10 @@ export default function Arranger({ strategy={verticalListSortingStrategy} > -