From 766faf5f56c11b24c2b9b66801f9f240db655f06 Mon Sep 17 00:00:00 2001 From: Daniel Ledda Date: Sun, 26 Feb 2023 22:14:43 +0100 Subject: [PATCH] migrated to vue wtf --- package-lock.json | 1744 +++++++++++------ package.json | 9 +- src/AppState.ts | 54 +- src/Beat.ts | 465 ++--- src/BeatStore.ts | 196 +- src/Track.ts | 438 +++-- src/TrackUnit.ts | 96 - src/main.ts | 20 +- src/tests.ts | 4 - src/ui/Beat/Beat.css | 74 - src/ui/Beat/Beat.vue | 119 ++ src/ui/Beat/BeatView.tsx | 113 -- src/ui/BeatSettings/BeatSettings.css | 20 - src/ui/BeatSettings/BeatSettings.vue | 65 + src/ui/BeatSettings/BeatSettingsView.tsx | 128 -- src/ui/BeatSummary/BeatSummarySettings.vue | 8 + src/ui/Root/Root.css | 167 -- src/ui/Root/Root.vue | 268 +++ src/ui/Root/RootView.tsx | 192 -- src/ui/Root/Toolbox.css | 53 - src/ui/Root/Toolbox.vue | 114 ++ src/ui/Root/ToolboxView.tsx | 75 - src/ui/Track/Track.css | 60 - src/ui/Track/Track.vue | 152 ++ src/ui/Track/TrackView.tsx | 181 -- src/ui/TrackSettings/TrackSettings.css | 54 - src/ui/TrackSettings/TrackSettings.vue | 92 + src/ui/TrackSettings/TrackSettingsView.tsx | 116 -- src/ui/TrackUnit/TrackUnit.css | 49 - src/ui/TrackUnit/TrackUnit.vue | 140 ++ src/ui/TrackUnit/TrackUnitView.tsx | 207 -- src/ui/TrackUnit/trackUnit.ts | 36 + src/ui/Widgets/ActionButton/ActionButton.css | 37 - src/ui/Widgets/ActionButton/ActionButton.vue | 78 + .../Widgets/ActionButton/ActionButtonView.tsx | 71 - src/ui/Widgets/BoolBox/BoolBox.css | 67 - src/ui/Widgets/BoolBox/BoolBox.vue | 97 + src/ui/Widgets/BoolBox/BoolBoxView.tsx | 58 - src/ui/Widgets/Dropdown/Dropdown.css | 0 src/ui/Widgets/Dropdown/DropdownView.tsx | 48 - .../EditableTextFIeld/EditableTextField.vue | 71 + .../EditableTextFieldView.css | 14 - .../EditableTextFieldView.tsx | 72 - src/ui/Widgets/Icon/Icon.css | 9 - src/ui/Widgets/Icon/Icon.vue | 33 + src/ui/Widgets/Icon/IconView.tsx | 56 - src/ui/Widgets/Icon/icons.ts | 21 + src/ui/Widgets/NumberInput/NumberInput.css | 76 - src/ui/Widgets/NumberInput/NumberInput.vue | 140 ++ .../Widgets/NumberInput/NumberInputView.tsx | 132 -- src/ui/global.css | 23 + tsconfig.config.json | 8 + tsconfig.json | 7 + vite.config.ts | 46 +- 54 files changed, 3135 insertions(+), 3538 deletions(-) delete mode 100644 src/TrackUnit.ts delete mode 100644 src/tests.ts delete mode 100644 src/ui/Beat/Beat.css create mode 100644 src/ui/Beat/Beat.vue delete mode 100644 src/ui/Beat/BeatView.tsx delete mode 100644 src/ui/BeatSettings/BeatSettings.css create mode 100644 src/ui/BeatSettings/BeatSettings.vue delete mode 100644 src/ui/BeatSettings/BeatSettingsView.tsx create mode 100644 src/ui/BeatSummary/BeatSummarySettings.vue delete mode 100644 src/ui/Root/Root.css create mode 100644 src/ui/Root/Root.vue delete mode 100644 src/ui/Root/RootView.tsx delete mode 100644 src/ui/Root/Toolbox.css create mode 100644 src/ui/Root/Toolbox.vue delete mode 100644 src/ui/Root/ToolboxView.tsx delete mode 100644 src/ui/Track/Track.css create mode 100644 src/ui/Track/Track.vue delete mode 100644 src/ui/Track/TrackView.tsx delete mode 100644 src/ui/TrackSettings/TrackSettings.css create mode 100644 src/ui/TrackSettings/TrackSettings.vue delete mode 100644 src/ui/TrackSettings/TrackSettingsView.tsx delete mode 100644 src/ui/TrackUnit/TrackUnit.css create mode 100644 src/ui/TrackUnit/TrackUnit.vue delete mode 100644 src/ui/TrackUnit/TrackUnitView.tsx create mode 100644 src/ui/TrackUnit/trackUnit.ts delete mode 100644 src/ui/Widgets/ActionButton/ActionButton.css create mode 100644 src/ui/Widgets/ActionButton/ActionButton.vue delete mode 100644 src/ui/Widgets/ActionButton/ActionButtonView.tsx delete mode 100644 src/ui/Widgets/BoolBox/BoolBox.css create mode 100644 src/ui/Widgets/BoolBox/BoolBox.vue delete mode 100644 src/ui/Widgets/BoolBox/BoolBoxView.tsx delete mode 100644 src/ui/Widgets/Dropdown/Dropdown.css delete mode 100644 src/ui/Widgets/Dropdown/DropdownView.tsx create mode 100644 src/ui/Widgets/EditableTextFIeld/EditableTextField.vue delete mode 100644 src/ui/Widgets/EditableTextFIeld/EditableTextFieldView.css delete mode 100644 src/ui/Widgets/EditableTextFIeld/EditableTextFieldView.tsx delete mode 100644 src/ui/Widgets/Icon/Icon.css create mode 100644 src/ui/Widgets/Icon/Icon.vue delete mode 100644 src/ui/Widgets/Icon/IconView.tsx create mode 100644 src/ui/Widgets/Icon/icons.ts delete mode 100644 src/ui/Widgets/NumberInput/NumberInput.css create mode 100644 src/ui/Widgets/NumberInput/NumberInput.vue delete mode 100644 src/ui/Widgets/NumberInput/NumberInputView.tsx create mode 100644 tsconfig.config.json diff --git a/package-lock.json b/package-lock.json index cd2cf60..9d33349 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,12 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "@djledda/ladder": "^1.1.0" + "@djledda/ladder": "^1.1.0", + "@vitejs/plugin-vue": "^4.0.0", + "@vue/tsconfig": "^0.1.3", + "pinia": "^2.0.32", + "sass": "^1.58.3", + "vue": "^3.2.47" }, "devDependencies": { "@types/node": "^17.0.40", @@ -18,7 +23,18 @@ "cross-env": "^7.0.3", "eslint": "^8.16.0", "typescript": "^4.9.4", - "vite": "^3.2.0" + "vite": "^4.1.4" + } + }, + "node_modules/@babel/parser": { + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.2.tgz", + "integrity": "sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ==", + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" } }, "node_modules/@djledda/ladder": { @@ -27,13 +43,12 @@ "integrity": "sha512-QvQhuJDsiL4MrTi+gu+SXr+79ZsVK62Rb9ZCk029j/Do/M3jifGPgeO7Z90adns11aSD6QlWGbmy5hpCMrMXUg==" }, "node_modules/@esbuild/android-arm": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz", - "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==", + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.17.tgz", + "integrity": "sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw==", "cpu": [ "arm" ], - "dev": true, "optional": true, "os": [ "android" @@ -42,14 +57,103 @@ "node": ">=12" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz", - "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==", + "node_modules/@esbuild/android-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.17.tgz", + "integrity": "sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==", "cpu": [ - "loong64" + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.17.tgz", + "integrity": "sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.17.tgz", + "integrity": "sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.17.tgz", + "integrity": "sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.17.tgz", + "integrity": "sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.17.tgz", + "integrity": "sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.17.tgz", + "integrity": "sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ==", + "cpu": [ + "arm" ], - "dev": true, "optional": true, "os": [ "linux" @@ -58,6 +162,216 @@ "node": ">=12" } }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.17.tgz", + "integrity": "sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.17.tgz", + "integrity": "sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.17.tgz", + "integrity": "sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==", + "cpu": [ + "loong64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.17.tgz", + "integrity": "sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw==", + "cpu": [ + "mips64el" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.17.tgz", + "integrity": "sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.17.tgz", + "integrity": "sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.17.tgz", + "integrity": "sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.17.tgz", + "integrity": "sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.17.tgz", + "integrity": "sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.17.tgz", + "integrity": "sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.17.tgz", + "integrity": "sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.17.tgz", + "integrity": "sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.17.tgz", + "integrity": "sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.17.tgz", + "integrity": "sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@eslint/eslintrc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.0.tgz", @@ -152,7 +466,7 @@ "version": "17.0.40", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.40.tgz", "integrity": "sha512-UXdBxNGqTMtm7hCwh9HtncFVLrXoqA3oJW30j6XWp5BH/wu3mVeaxo7cq5benFdBw34HB3XDT2TRPI7rXZ+mDg==", - "dev": true + "devOptional": true }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "5.26.0", @@ -360,6 +674,138 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@vitejs/plugin-vue": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.0.0.tgz", + "integrity": "sha512-e0X4jErIxAB5oLtDqbHvHpJe/uWNkdpYV83AOG2xo2tEVSzCzewgJMtREZM30wXnM5ls90hxiOtAuVU6H5JgbA==", + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.2.47", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.47.tgz", + "integrity": "sha512-p4D7FDnQb7+YJmO2iPEv0SQNeNzcbHdGByJDsT4lynf63AFkOTFN07HsiRSvjGo0QrxR/o3d0hUyNCUnBU2Tig==", + "dependencies": { + "@babel/parser": "^7.16.4", + "@vue/shared": "3.2.47", + "estree-walker": "^2.0.2", + "source-map": "^0.6.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.2.47", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.47.tgz", + "integrity": "sha512-dBBnEHEPoftUiS03a4ggEig74J2YBZ2UIeyfpcRM2tavgMWo4bsEfgCGsu+uJIL/vax9S+JztH8NmQerUo7shQ==", + "dependencies": { + "@vue/compiler-core": "3.2.47", + "@vue/shared": "3.2.47" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.2.47", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.47.tgz", + "integrity": "sha512-rog05W+2IFfxjMcFw10tM9+f7i/+FFpZJJ5XHX72NP9eC2uRD+42M3pYcQqDXVYoj74kHMSEdQ/WmCjt8JFksQ==", + "dependencies": { + "@babel/parser": "^7.16.4", + "@vue/compiler-core": "3.2.47", + "@vue/compiler-dom": "3.2.47", + "@vue/compiler-ssr": "3.2.47", + "@vue/reactivity-transform": "3.2.47", + "@vue/shared": "3.2.47", + "estree-walker": "^2.0.2", + "magic-string": "^0.25.7", + "postcss": "^8.1.10", + "source-map": "^0.6.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.2.47", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.47.tgz", + "integrity": "sha512-wVXC+gszhulcMD8wpxMsqSOpvDZ6xKXSVWkf50Guf/S+28hTAXPDYRTbLQ3EDkOP5Xz/+SY37YiwDquKbJOgZw==", + "dependencies": { + "@vue/compiler-dom": "3.2.47", + "@vue/shared": "3.2.47" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.5.0.tgz", + "integrity": "sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==" + }, + "node_modules/@vue/reactivity": { + "version": "3.2.47", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.47.tgz", + "integrity": "sha512-7khqQ/75oyyg+N/e+iwV6lpy1f5wq759NdlS1fpAhFXa8VeAIKGgk2E/C4VF59lx5b+Ezs5fpp/5WsRYXQiKxQ==", + "dependencies": { + "@vue/shared": "3.2.47" + } + }, + "node_modules/@vue/reactivity-transform": { + "version": "3.2.47", + "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.47.tgz", + "integrity": "sha512-m8lGXw8rdnPVVIdIFhf0LeQ/ixyHkH5plYuS83yop5n7ggVJU+z5v0zecwEnX7fa7HNLBhh2qngJJkxpwEEmYA==", + "dependencies": { + "@babel/parser": "^7.16.4", + "@vue/compiler-core": "3.2.47", + "@vue/shared": "3.2.47", + "estree-walker": "^2.0.2", + "magic-string": "^0.25.7" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.2.47", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.47.tgz", + "integrity": "sha512-RZxbLQIRB/K0ev0K9FXhNbBzT32H9iRtYbaXb0ZIz2usLms/D55dJR2t6cIEUn6vyhS3ALNvNthI+Q95C+NOpA==", + "dependencies": { + "@vue/reactivity": "3.2.47", + "@vue/shared": "3.2.47" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.2.47", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.47.tgz", + "integrity": "sha512-ArXrFTjS6TsDei4qwNvgrdmHtD930KgSKGhS5M+j8QxXrDJYLqYw4RRcDy1bz1m1wMmb6j+zGLifdVHtkXA7gA==", + "dependencies": { + "@vue/runtime-core": "3.2.47", + "@vue/shared": "3.2.47", + "csstype": "^2.6.8" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.2.47", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.47.tgz", + "integrity": "sha512-dN9gc1i8EvmP9RCzvneONXsKfBRgqFeFZLurmHOveL7oH6HiFXJw5OGu294n1nHc/HMgTy6LulU/tv5/A7f/LA==", + "dependencies": { + "@vue/compiler-ssr": "3.2.47", + "@vue/shared": "3.2.47" + }, + "peerDependencies": { + "vue": "3.2.47" + } + }, + "node_modules/@vue/shared": { + "version": "3.2.47", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.47.tgz", + "integrity": "sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ==" + }, + "node_modules/@vue/tsconfig": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@vue/tsconfig/-/tsconfig-0.1.3.tgz", + "integrity": "sha512-kQVsh8yyWPvHpb8gIc9l/HIDiiVUy1amynLNpCy8p+FoCiZXCo6fQos5/097MmnNZc9AtseDsCrfkhqCrJ8Olg==", + "peerDependencies": { + "@types/node": "*" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, "node_modules/acorn": { "version": "8.7.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", @@ -421,6 +867,18 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -442,6 +900,14 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "engines": { + "node": ">=8" + } + }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -456,7 +922,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, "dependencies": { "fill-range": "^7.0.1" }, @@ -489,6 +954,43 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -545,6 +1047,11 @@ "node": ">= 8" } }, + "node_modules/csstype": { + "version": "2.6.21", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz", + "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==" + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -593,10 +1100,9 @@ } }, "node_modules/esbuild": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz", - "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==", - "dev": true, + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.17.tgz", + "integrity": "sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==", "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" @@ -605,348 +1111,28 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.15.18", - "@esbuild/linux-loong64": "0.15.18", - "esbuild-android-64": "0.15.18", - "esbuild-android-arm64": "0.15.18", - "esbuild-darwin-64": "0.15.18", - "esbuild-darwin-arm64": "0.15.18", - "esbuild-freebsd-64": "0.15.18", - "esbuild-freebsd-arm64": "0.15.18", - "esbuild-linux-32": "0.15.18", - "esbuild-linux-64": "0.15.18", - "esbuild-linux-arm": "0.15.18", - "esbuild-linux-arm64": "0.15.18", - "esbuild-linux-mips64le": "0.15.18", - "esbuild-linux-ppc64le": "0.15.18", - "esbuild-linux-riscv64": "0.15.18", - "esbuild-linux-s390x": "0.15.18", - "esbuild-netbsd-64": "0.15.18", - "esbuild-openbsd-64": "0.15.18", - "esbuild-sunos-64": "0.15.18", - "esbuild-windows-32": "0.15.18", - "esbuild-windows-64": "0.15.18", - "esbuild-windows-arm64": "0.15.18" - } - }, - "node_modules/esbuild-android-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz", - "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-android-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz", - "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-darwin-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz", - "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-darwin-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz", - "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-freebsd-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz", - "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-freebsd-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz", - "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-32": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz", - "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz", - "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-arm": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz", - "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz", - "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-mips64le": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz", - "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-ppc64le": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz", - "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-riscv64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz", - "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-linux-s390x": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz", - "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-netbsd-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz", - "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-openbsd-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz", - "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-sunos-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz", - "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-32": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz", - "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz", - "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/esbuild-windows-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz", - "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" + "@esbuild/android-arm": "0.16.17", + "@esbuild/android-arm64": "0.16.17", + "@esbuild/android-x64": "0.16.17", + "@esbuild/darwin-arm64": "0.16.17", + "@esbuild/darwin-x64": "0.16.17", + "@esbuild/freebsd-arm64": "0.16.17", + "@esbuild/freebsd-x64": "0.16.17", + "@esbuild/linux-arm": "0.16.17", + "@esbuild/linux-arm64": "0.16.17", + "@esbuild/linux-ia32": "0.16.17", + "@esbuild/linux-loong64": "0.16.17", + "@esbuild/linux-mips64el": "0.16.17", + "@esbuild/linux-ppc64": "0.16.17", + "@esbuild/linux-riscv64": "0.16.17", + "@esbuild/linux-s390x": "0.16.17", + "@esbuild/linux-x64": "0.16.17", + "@esbuild/netbsd-x64": "0.16.17", + "@esbuild/openbsd-x64": "0.16.17", + "@esbuild/sunos-x64": "0.16.17", + "@esbuild/win32-arm64": "0.16.17", + "@esbuild/win32-ia32": "0.16.17", + "@esbuild/win32-x64": "0.16.17" } }, "node_modules/escape-string-regexp": { @@ -1118,6 +1304,11 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -1198,7 +1389,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -1235,7 +1425,6 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -1248,8 +1437,7 @@ "node_modules/function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "node_modules/functional-red-black-tree": { "version": "1.0.1", @@ -1328,7 +1516,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "dependencies": { "function-bind": "^1.1.1" }, @@ -1354,6 +1541,11 @@ "node": ">= 4" } }, + "node_modules/immutable": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.2.4.tgz", + "integrity": "sha512-WDxL3Hheb1JkRN3sQkyujNlL/xRjAo3rJtaU5xeufUauG66JdMr32bLj4gF+vWl84DIA3Zxw7tiAjneYzRRw+w==" + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -1395,11 +1587,21 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-core-module": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", - "dev": true, "dependencies": { "has": "^1.0.3" }, @@ -1411,7 +1613,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -1420,7 +1621,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -1432,7 +1632,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, "engines": { "node": ">=0.12.0" } @@ -1498,6 +1697,14 @@ "node": ">=10" } }, + "node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dependencies": { + "sourcemap-codec": "^1.4.8" + } + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -1542,7 +1749,6 @@ "version": "3.3.4", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", - "dev": true, "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -1556,6 +1762,14 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -1615,8 +1829,7 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-type": { "version": "4.0.0", @@ -1630,14 +1843,12 @@ "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "engines": { "node": ">=8.6" }, @@ -1645,11 +1856,60 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/pinia": { + "version": "2.0.32", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.32.tgz", + "integrity": "sha512-8Tw4OrpCSJ028UUyp0gYPP/wyjigLoEceuO/x1G+FlHVf73337e5vLm4uDmrRIoBG1hvaed/eSHnrCFjOc4nkA==", + "dependencies": { + "@vue/devtools-api": "^6.5.0", + "vue-demi": "*" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "@vue/composition-api": "^1.4.0", + "typescript": ">=4.4.4", + "vue": "^2.6.14 || ^3.2.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/pinia/node_modules/vue-demi": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", + "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "hasInstallScript": true, + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, "node_modules/postcss": { - "version": "8.4.20", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.20.tgz", - "integrity": "sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g==", - "dev": true, + "version": "8.4.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", + "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", "funding": [ { "type": "opencollective", @@ -1707,6 +1967,17 @@ } ] }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/regexpp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", @@ -1723,7 +1994,6 @@ "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, "dependencies": { "is-core-module": "^2.9.0", "path-parse": "^1.0.7", @@ -1771,15 +2041,15 @@ } }, "node_modules/rollup": { - "version": "2.79.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", - "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", - "dev": true, + "version": "3.17.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.17.3.tgz", + "integrity": "sha512-p5LaCXiiOL/wrOkj8djsIDFmyU9ysUxcyW+EKRLHb6TKldJzXpImjcRSR+vgo09DBdofGcOoLOsRyxxG2n5/qQ==", "bin": { "rollup": "dist/bin/rollup" }, "engines": { - "node": ">=10.0.0" + "node": ">=14.18.0", + "npm": ">=8.0.0" }, "optionalDependencies": { "fsevents": "~2.3.2" @@ -1808,6 +2078,22 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/sass": { + "version": "1.58.3", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.58.3.tgz", + "integrity": "sha512-Q7RaEtYf6BflYrQ+buPudKR26/lH+10EmO9bBqbmPh/KeLqv8bjpTNqxe71ocONqXq+jYiCbpPUmQMS+JJPk4A==", + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/semver": { "version": "7.3.7", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", @@ -1853,15 +2139,28 @@ "node": ">=8" } }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true, "engines": { "node": ">=0.10.0" } }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "deprecated": "Please use @jridgewell/sourcemap-codec instead" + }, "node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", @@ -1902,7 +2201,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, "engines": { "node": ">= 0.4" }, @@ -1920,7 +2218,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "dependencies": { "is-number": "^7.0.0" }, @@ -1977,7 +2274,7 @@ "version": "4.9.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", - "dev": true, + "devOptional": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -2002,15 +2299,14 @@ "dev": true }, "node_modules/vite": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.5.tgz", - "integrity": "sha512-4mVEpXpSOgrssFZAOmGIr85wPHKvaDAcXqxVxVRZhljkJOMZi1ibLibzjLHzJvcok8BMguLc7g1W6W/GqZbLdQ==", - "dev": true, + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.1.4.tgz", + "integrity": "sha512-3knk/HsbSTKEin43zHu7jTwYWv81f8kgAL99G5NWBcA1LKvtvcVAC4JjBH1arBunO9kQka+1oGbrMKOjk4ZrBg==", "dependencies": { - "esbuild": "^0.15.9", - "postcss": "^8.4.18", + "esbuild": "^0.16.14", + "postcss": "^8.4.21", "resolve": "^1.22.1", - "rollup": "^2.79.1" + "rollup": "^3.10.0" }, "bin": { "vite": "bin/vite.js" @@ -2050,6 +2346,18 @@ } } }, + "node_modules/vue": { + "version": "3.2.47", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.47.tgz", + "integrity": "sha512-60188y/9Dc9WVrAZeUVSDxRQOZ+z+y5nO2ts9jWXSTkMvayiWxCWOWtBQoYjLeccfXkiiPZWAHcV+WTPhkqJHQ==", + "dependencies": { + "@vue/compiler-dom": "3.2.47", + "@vue/compiler-sfc": "3.2.47", + "@vue/runtime-dom": "3.2.47", + "@vue/server-renderer": "3.2.47", + "@vue/shared": "3.2.47" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -2088,23 +2396,146 @@ } }, "dependencies": { + "@babel/parser": { + "version": "7.21.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.2.tgz", + "integrity": "sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ==" + }, "@djledda/ladder": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@djledda/ladder/-/ladder-1.1.0.tgz", "integrity": "sha512-QvQhuJDsiL4MrTi+gu+SXr+79ZsVK62Rb9ZCk029j/Do/M3jifGPgeO7Z90adns11aSD6QlWGbmy5hpCMrMXUg==" }, "@esbuild/android-arm": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz", - "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==", - "dev": true, + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.17.tgz", + "integrity": "sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw==", + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.17.tgz", + "integrity": "sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==", + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.17.tgz", + "integrity": "sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ==", + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.17.tgz", + "integrity": "sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==", + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.17.tgz", + "integrity": "sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg==", + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.17.tgz", + "integrity": "sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw==", + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.17.tgz", + "integrity": "sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug==", + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.17.tgz", + "integrity": "sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ==", + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.17.tgz", + "integrity": "sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g==", + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.17.tgz", + "integrity": "sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg==", "optional": true }, "@esbuild/linux-loong64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz", - "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==", - "dev": true, + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.17.tgz", + "integrity": "sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==", + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.17.tgz", + "integrity": "sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw==", + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.17.tgz", + "integrity": "sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g==", + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.17.tgz", + "integrity": "sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw==", + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.17.tgz", + "integrity": "sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w==", + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.17.tgz", + "integrity": "sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==", + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.17.tgz", + "integrity": "sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA==", + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.17.tgz", + "integrity": "sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg==", + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.17.tgz", + "integrity": "sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw==", + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.17.tgz", + "integrity": "sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw==", + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.17.tgz", + "integrity": "sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig==", + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.17.tgz", + "integrity": "sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q==", "optional": true }, "@eslint/eslintrc": { @@ -2185,7 +2616,7 @@ "version": "17.0.40", "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.40.tgz", "integrity": "sha512-UXdBxNGqTMtm7hCwh9HtncFVLrXoqA3oJW30j6XWp5BH/wu3mVeaxo7cq5benFdBw34HB3XDT2TRPI7rXZ+mDg==", - "dev": true + "devOptional": true }, "@typescript-eslint/eslint-plugin": { "version": "5.26.0", @@ -2300,6 +2731,122 @@ "eslint-visitor-keys": "^3.3.0" } }, + "@vitejs/plugin-vue": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.0.0.tgz", + "integrity": "sha512-e0X4jErIxAB5oLtDqbHvHpJe/uWNkdpYV83AOG2xo2tEVSzCzewgJMtREZM30wXnM5ls90hxiOtAuVU6H5JgbA==", + "requires": {} + }, + "@vue/compiler-core": { + "version": "3.2.47", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.2.47.tgz", + "integrity": "sha512-p4D7FDnQb7+YJmO2iPEv0SQNeNzcbHdGByJDsT4lynf63AFkOTFN07HsiRSvjGo0QrxR/o3d0hUyNCUnBU2Tig==", + "requires": { + "@babel/parser": "^7.16.4", + "@vue/shared": "3.2.47", + "estree-walker": "^2.0.2", + "source-map": "^0.6.1" + } + }, + "@vue/compiler-dom": { + "version": "3.2.47", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.2.47.tgz", + "integrity": "sha512-dBBnEHEPoftUiS03a4ggEig74J2YBZ2UIeyfpcRM2tavgMWo4bsEfgCGsu+uJIL/vax9S+JztH8NmQerUo7shQ==", + "requires": { + "@vue/compiler-core": "3.2.47", + "@vue/shared": "3.2.47" + } + }, + "@vue/compiler-sfc": { + "version": "3.2.47", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.2.47.tgz", + "integrity": "sha512-rog05W+2IFfxjMcFw10tM9+f7i/+FFpZJJ5XHX72NP9eC2uRD+42M3pYcQqDXVYoj74kHMSEdQ/WmCjt8JFksQ==", + "requires": { + "@babel/parser": "^7.16.4", + "@vue/compiler-core": "3.2.47", + "@vue/compiler-dom": "3.2.47", + "@vue/compiler-ssr": "3.2.47", + "@vue/reactivity-transform": "3.2.47", + "@vue/shared": "3.2.47", + "estree-walker": "^2.0.2", + "magic-string": "^0.25.7", + "postcss": "^8.1.10", + "source-map": "^0.6.1" + } + }, + "@vue/compiler-ssr": { + "version": "3.2.47", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.2.47.tgz", + "integrity": "sha512-wVXC+gszhulcMD8wpxMsqSOpvDZ6xKXSVWkf50Guf/S+28hTAXPDYRTbLQ3EDkOP5Xz/+SY37YiwDquKbJOgZw==", + "requires": { + "@vue/compiler-dom": "3.2.47", + "@vue/shared": "3.2.47" + } + }, + "@vue/devtools-api": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.5.0.tgz", + "integrity": "sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==" + }, + "@vue/reactivity": { + "version": "3.2.47", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.47.tgz", + "integrity": "sha512-7khqQ/75oyyg+N/e+iwV6lpy1f5wq759NdlS1fpAhFXa8VeAIKGgk2E/C4VF59lx5b+Ezs5fpp/5WsRYXQiKxQ==", + "requires": { + "@vue/shared": "3.2.47" + } + }, + "@vue/reactivity-transform": { + "version": "3.2.47", + "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.2.47.tgz", + "integrity": "sha512-m8lGXw8rdnPVVIdIFhf0LeQ/ixyHkH5plYuS83yop5n7ggVJU+z5v0zecwEnX7fa7HNLBhh2qngJJkxpwEEmYA==", + "requires": { + "@babel/parser": "^7.16.4", + "@vue/compiler-core": "3.2.47", + "@vue/shared": "3.2.47", + "estree-walker": "^2.0.2", + "magic-string": "^0.25.7" + } + }, + "@vue/runtime-core": { + "version": "3.2.47", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.47.tgz", + "integrity": "sha512-RZxbLQIRB/K0ev0K9FXhNbBzT32H9iRtYbaXb0ZIz2usLms/D55dJR2t6cIEUn6vyhS3ALNvNthI+Q95C+NOpA==", + "requires": { + "@vue/reactivity": "3.2.47", + "@vue/shared": "3.2.47" + } + }, + "@vue/runtime-dom": { + "version": "3.2.47", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.47.tgz", + "integrity": "sha512-ArXrFTjS6TsDei4qwNvgrdmHtD930KgSKGhS5M+j8QxXrDJYLqYw4RRcDy1bz1m1wMmb6j+zGLifdVHtkXA7gA==", + "requires": { + "@vue/runtime-core": "3.2.47", + "@vue/shared": "3.2.47", + "csstype": "^2.6.8" + } + }, + "@vue/server-renderer": { + "version": "3.2.47", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.2.47.tgz", + "integrity": "sha512-dN9gc1i8EvmP9RCzvneONXsKfBRgqFeFZLurmHOveL7oH6HiFXJw5OGu294n1nHc/HMgTy6LulU/tv5/A7f/LA==", + "requires": { + "@vue/compiler-ssr": "3.2.47", + "@vue/shared": "3.2.47" + } + }, + "@vue/shared": { + "version": "3.2.47", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.47.tgz", + "integrity": "sha512-BHGyyGN3Q97EZx0taMQ+OLNuZcW3d37ZEVmEAyeoA9ERdGvm9Irc/0Fua8SNyOtV1w6BS4q25wbMzJujO9HIfQ==" + }, + "@vue/tsconfig": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@vue/tsconfig/-/tsconfig-0.1.3.tgz", + "integrity": "sha512-kQVsh8yyWPvHpb8gIc9l/HIDiiVUy1amynLNpCy8p+FoCiZXCo6fQos5/097MmnNZc9AtseDsCrfkhqCrJ8Olg==", + "requires": {} + }, "acorn": { "version": "8.7.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.1.tgz", @@ -2340,6 +2887,15 @@ "color-convert": "^2.0.1" } }, + "anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -2358,6 +2914,11 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -2372,7 +2933,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, "requires": { "fill-range": "^7.0.1" } @@ -2393,6 +2953,31 @@ "supports-color": "^7.1.0" } }, + "chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2434,6 +3019,11 @@ "which": "^2.0.1" } }, + "csstype": { + "version": "2.6.21", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz", + "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==" + }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -2468,175 +3058,34 @@ } }, "esbuild": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz", - "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==", - "dev": true, + "version": "0.16.17", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.17.tgz", + "integrity": "sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==", "requires": { - "@esbuild/android-arm": "0.15.18", - "@esbuild/linux-loong64": "0.15.18", - "esbuild-android-64": "0.15.18", - "esbuild-android-arm64": "0.15.18", - "esbuild-darwin-64": "0.15.18", - "esbuild-darwin-arm64": "0.15.18", - "esbuild-freebsd-64": "0.15.18", - "esbuild-freebsd-arm64": "0.15.18", - "esbuild-linux-32": "0.15.18", - "esbuild-linux-64": "0.15.18", - "esbuild-linux-arm": "0.15.18", - "esbuild-linux-arm64": "0.15.18", - "esbuild-linux-mips64le": "0.15.18", - "esbuild-linux-ppc64le": "0.15.18", - "esbuild-linux-riscv64": "0.15.18", - "esbuild-linux-s390x": "0.15.18", - "esbuild-netbsd-64": "0.15.18", - "esbuild-openbsd-64": "0.15.18", - "esbuild-sunos-64": "0.15.18", - "esbuild-windows-32": "0.15.18", - "esbuild-windows-64": "0.15.18", - "esbuild-windows-arm64": "0.15.18" + "@esbuild/android-arm": "0.16.17", + "@esbuild/android-arm64": "0.16.17", + "@esbuild/android-x64": "0.16.17", + "@esbuild/darwin-arm64": "0.16.17", + "@esbuild/darwin-x64": "0.16.17", + "@esbuild/freebsd-arm64": "0.16.17", + "@esbuild/freebsd-x64": "0.16.17", + "@esbuild/linux-arm": "0.16.17", + "@esbuild/linux-arm64": "0.16.17", + "@esbuild/linux-ia32": "0.16.17", + "@esbuild/linux-loong64": "0.16.17", + "@esbuild/linux-mips64el": "0.16.17", + "@esbuild/linux-ppc64": "0.16.17", + "@esbuild/linux-riscv64": "0.16.17", + "@esbuild/linux-s390x": "0.16.17", + "@esbuild/linux-x64": "0.16.17", + "@esbuild/netbsd-x64": "0.16.17", + "@esbuild/openbsd-x64": "0.16.17", + "@esbuild/sunos-x64": "0.16.17", + "@esbuild/win32-arm64": "0.16.17", + "@esbuild/win32-ia32": "0.16.17", + "@esbuild/win32-x64": "0.16.17" } }, - "esbuild-android-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz", - "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==", - "dev": true, - "optional": true - }, - "esbuild-android-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz", - "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==", - "dev": true, - "optional": true - }, - "esbuild-darwin-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz", - "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==", - "dev": true, - "optional": true - }, - "esbuild-darwin-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz", - "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==", - "dev": true, - "optional": true - }, - "esbuild-freebsd-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz", - "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==", - "dev": true, - "optional": true - }, - "esbuild-freebsd-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz", - "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==", - "dev": true, - "optional": true - }, - "esbuild-linux-32": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz", - "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==", - "dev": true, - "optional": true - }, - "esbuild-linux-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz", - "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==", - "dev": true, - "optional": true - }, - "esbuild-linux-arm": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz", - "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==", - "dev": true, - "optional": true - }, - "esbuild-linux-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz", - "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==", - "dev": true, - "optional": true - }, - "esbuild-linux-mips64le": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz", - "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==", - "dev": true, - "optional": true - }, - "esbuild-linux-ppc64le": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz", - "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==", - "dev": true, - "optional": true - }, - "esbuild-linux-riscv64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz", - "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==", - "dev": true, - "optional": true - }, - "esbuild-linux-s390x": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz", - "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==", - "dev": true, - "optional": true - }, - "esbuild-netbsd-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz", - "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==", - "dev": true, - "optional": true - }, - "esbuild-openbsd-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz", - "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==", - "dev": true, - "optional": true - }, - "esbuild-sunos-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz", - "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==", - "dev": true, - "optional": true - }, - "esbuild-windows-32": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz", - "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==", - "dev": true, - "optional": true - }, - "esbuild-windows-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz", - "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==", - "dev": true, - "optional": true - }, - "esbuild-windows-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz", - "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==", - "dev": true, - "optional": true - }, "escape-string-regexp": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", @@ -2762,6 +3211,11 @@ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true }, + "estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==" + }, "esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -2832,7 +3286,6 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, "requires": { "to-regex-range": "^5.0.1" } @@ -2863,14 +3316,12 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, "optional": true }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "functional-red-black-tree": { "version": "1.0.1", @@ -2928,7 +3379,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -2945,6 +3395,11 @@ "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", "dev": true }, + "immutable": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.2.4.tgz", + "integrity": "sha512-WDxL3Hheb1JkRN3sQkyujNlL/xRjAo3rJtaU5xeufUauG66JdMr32bLj4gF+vWl84DIA3Zxw7tiAjneYzRRw+w==" + }, "import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -2977,11 +3432,18 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "requires": { + "binary-extensions": "^2.0.0" + } + }, "is-core-module": { "version": "2.11.0", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", - "dev": true, "requires": { "has": "^1.0.3" } @@ -2989,14 +3451,12 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "requires": { "is-extglob": "^2.1.1" } @@ -3004,8 +3464,7 @@ "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" }, "isexe": { "version": "2.0.0", @@ -3059,6 +3518,14 @@ "yallist": "^4.0.0" } }, + "magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "requires": { + "sourcemap-codec": "^1.4.8" + } + }, "merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -3093,8 +3560,7 @@ "nanoid": { "version": "3.3.4", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", - "dev": true + "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==" }, "natural-compare": { "version": "1.4.0", @@ -3102,6 +3568,11 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -3149,8 +3620,7 @@ "path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "path-type": { "version": "4.0.0", @@ -3161,20 +3631,34 @@ "picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" }, "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + }, + "pinia": { + "version": "2.0.32", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.0.32.tgz", + "integrity": "sha512-8Tw4OrpCSJ028UUyp0gYPP/wyjigLoEceuO/x1G+FlHVf73337e5vLm4uDmrRIoBG1hvaed/eSHnrCFjOc4nkA==", + "requires": { + "@vue/devtools-api": "^6.5.0", + "vue-demi": "*" + }, + "dependencies": { + "vue-demi": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.13.11.tgz", + "integrity": "sha512-IR8HoEEGM65YY3ZJYAjMlKygDQn25D5ajNFNoKh9RSDMQtlzCxtfQjdQgv9jjK+m3377SsJXY8ysq8kLCZL25A==", + "requires": {} + } + } }, "postcss": { - "version": "8.4.20", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.20.tgz", - "integrity": "sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g==", - "dev": true, + "version": "8.4.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", + "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", "requires": { "nanoid": "^3.3.4", "picocolors": "^1.0.0", @@ -3199,6 +3683,14 @@ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "requires": { + "picomatch": "^2.2.1" + } + }, "regexpp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", @@ -3209,7 +3701,6 @@ "version": "1.22.1", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", - "dev": true, "requires": { "is-core-module": "^2.9.0", "path-parse": "^1.0.7", @@ -3238,10 +3729,9 @@ } }, "rollup": { - "version": "2.79.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz", - "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==", - "dev": true, + "version": "3.17.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.17.3.tgz", + "integrity": "sha512-p5LaCXiiOL/wrOkj8djsIDFmyU9ysUxcyW+EKRLHb6TKldJzXpImjcRSR+vgo09DBdofGcOoLOsRyxxG2n5/qQ==", "requires": { "fsevents": "~2.3.2" } @@ -3255,6 +3745,16 @@ "queue-microtask": "^1.2.2" } }, + "sass": { + "version": "1.58.3", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.58.3.tgz", + "integrity": "sha512-Q7RaEtYf6BflYrQ+buPudKR26/lH+10EmO9bBqbmPh/KeLqv8bjpTNqxe71ocONqXq+jYiCbpPUmQMS+JJPk4A==", + "requires": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + } + }, "semver": { "version": "7.3.7", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", @@ -3285,11 +3785,20 @@ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, "source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true + "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" + }, + "sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==" }, "strip-ansi": { "version": "6.0.1", @@ -3318,8 +3827,7 @@ "supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" }, "text-table": { "version": "0.2.0", @@ -3331,7 +3839,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "requires": { "is-number": "^7.0.0" } @@ -3370,7 +3877,7 @@ "version": "4.9.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", - "dev": true + "devOptional": true }, "uri-js": { "version": "4.4.1", @@ -3388,16 +3895,27 @@ "dev": true }, "vite": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.5.tgz", - "integrity": "sha512-4mVEpXpSOgrssFZAOmGIr85wPHKvaDAcXqxVxVRZhljkJOMZi1ibLibzjLHzJvcok8BMguLc7g1W6W/GqZbLdQ==", - "dev": true, + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.1.4.tgz", + "integrity": "sha512-3knk/HsbSTKEin43zHu7jTwYWv81f8kgAL99G5NWBcA1LKvtvcVAC4JjBH1arBunO9kQka+1oGbrMKOjk4ZrBg==", "requires": { - "esbuild": "^0.15.9", + "esbuild": "^0.16.14", "fsevents": "~2.3.2", - "postcss": "^8.4.18", + "postcss": "^8.4.21", "resolve": "^1.22.1", - "rollup": "^2.79.1" + "rollup": "^3.10.0" + } + }, + "vue": { + "version": "3.2.47", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.47.tgz", + "integrity": "sha512-60188y/9Dc9WVrAZeUVSDxRQOZ+z+y5nO2ts9jWXSTkMvayiWxCWOWtBQoYjLeccfXkiiPZWAHcV+WTPhkqJHQ==", + "requires": { + "@vue/compiler-dom": "3.2.47", + "@vue/compiler-sfc": "3.2.47", + "@vue/runtime-dom": "3.2.47", + "@vue/server-renderer": "3.2.47", + "@vue/shared": "3.2.47" } }, "which": { diff --git a/package.json b/package.json index f443e74..3c726a0 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,12 @@ "author": "Daniel Ledda", "license": "ISC", "dependencies": { - "@djledda/ladder": "^1.1.0" + "@djledda/ladder": "^1.1.0", + "@vitejs/plugin-vue": "^4.0.0", + "@vue/tsconfig": "^0.1.3", + "pinia": "^2.0.32", + "sass": "^1.58.3", + "vue": "^3.2.47" }, "devDependencies": { "@types/node": "^17.0.40", @@ -24,6 +29,6 @@ "cross-env": "^7.0.3", "eslint": "^8.16.0", "typescript": "^4.9.4", - "vite": "^3.2.0" + "vite": "^4.1.4" } } diff --git a/src/AppState.ts b/src/AppState.ts index 43b6831..df3bc4d 100644 --- a/src/AppState.ts +++ b/src/AppState.ts @@ -1,37 +1,31 @@ -import { ISubscriber, Publisher } from "@djledda/ladder"; -import { TrackUnitStickingType, TrackUnitType } from "./TrackUnit"; +import { inject, type InjectionKey, ref } from 'vue'; export type UITool = | "track-unit-type" | "eraser" | "sticking"; -export type AppStateEvent = "appstate-tool-select"; - -export default class AppState { - private publisher = new Publisher(this); - selectedTool: UITool = "track-unit-type"; - activeTrackUnitType: TrackUnitType = "Normal"; - activeStickingType: TrackUnitStickingType = "lh"; - - constructor() {} - - addSubscriber(subscriber: ISubscriber, subscribeTo: Parameters["addSubscriber"]>[1]) { - this.publisher.addSubscriber(subscriber, subscribeTo); - } - - selectStickingTypePaint(stickingType: TrackUnitStickingType) { - this.activeStickingType = stickingType; - this.publisher.notifySubs("appstate-tool-select"); - } - - selectTrackUnitTypePaint(trackUnitType: TrackUnitType) { - this.activeTrackUnitType = trackUnitType; - this.publisher.notifySubs("appstate-tool-select"); - } - - selectTool(tool: UITool) { - this.selectedTool = tool; - this.publisher.notifySubs("appstate-tool-select"); - } +export function createAppStateStore() { + const selectedTool = ref('track-unit-type'); + const activeTrackUnitType = ref(0); + const activeStickingType = ref(1); + const selectingUnits = ref(false); + const deselectingUnits = ref(false); + + return { + selectingUnits, + deselectingUnits, + selectedTool, + activeTrackUnitType, + activeStickingType, + }; +} + + +export type AppStateStore = ReturnType; + +export const AppStateStoreKey = Symbol('AppStateStore') as InjectionKey; + +export function useAppStateStore(): AppStateStore { + return inject(AppStateStoreKey, createAppStateStore, true); } diff --git a/src/Beat.ts b/src/Beat.ts index 4b16d1a..db1a38b 100644 --- a/src/Beat.ts +++ b/src/Beat.ts @@ -1,6 +1,6 @@ -import Track, { TrackEvents, TrackInitOptions } from "@/Track"; +import { deserialise as deserialiseTrack, type TrackInitOptions, createTrack, isValidTimeSigRange, type Track } from "@/Track"; import { greatestCommonDivisor, isPosInt } from "@/utils"; -import { Capsule, ICapsule, IPublisher, ISubscriber, Publisher } from "@djledda/ladder"; +import { watch, computed, effectScope, ref, shallowRef, triggerRef } from "vue"; type BeatGroupInitOptions = { barCount: number; @@ -23,337 +23,182 @@ export type BeatSerial = { name: string, }; -export const enum BeatEvents { - TrackOrderChanged="be-0", - TrackListChanged="be-1", - BarCountChanged="be-2", - TimeSigUpChanged="be-3", - AutoBeatSettingsChanged="be-4", - LockingChanged="be-5", - GlobalLoopLengthChanged="be-5", - GlobalDisplayTypeChanged="be-6", - DeepChange="be-7", +function isBeatSerial(serial: Record): serial is BeatSerial { + return Array.isArray(serial.tracks) && + typeof serial.barCount === "number" && + typeof serial.timeSigUp === "number" && + typeof serial.globalLoopLength === "number" && + typeof serial.globalIsLooping === "boolean" && + typeof serial.useAutoBeatLength === "boolean" && + typeof serial.barSettingsLocked === "boolean"; } -const EventTypeSubscriptions = [ - TrackEvents.LoopLengthChanged, - TrackEvents.DisplayTypeChanged, - TrackEvents.WantsRemoval, - TrackEvents.DeepChange, - TrackEvents.Baked, -]; -type EventTypeSubscriptions = typeof EventTypeSubscriptions[number]; - -export default class Beat implements IPublisher, ISubscriber { - private static globalCounter = 0; - private tracks: Track[] = []; - private publisher: Publisher = new Publisher(this); - private barCount: number; - private timeSigUp: number; - private globalLoopLength: number; - private globalIsLooping: boolean; - private useAutoBeatLength: boolean; - private barSettingsLocked = false; - private name: ICapsule; - - constructor(options?: BeatGroupInitOptions) { - Beat.globalCounter++; - if (options?.name) { - this.name = Capsule.new(options.name); - } else { - this.name = Capsule.new(`Pattern ${Beat.globalCounter}`); - } - if (options?.tracks) { - for (const trackOptions of options.tracks) { - this.addTrack(trackOptions); - } - } - this.barCount = options?.barCount ?? 4; - this.timeSigUp = options?.timeSigUp ?? 4; - this.globalLoopLength = options?.loopLength ?? this.timeSigUp; - this.globalIsLooping = options?.isLooping ?? false; - this.useAutoBeatLength = options?.useAutoBeatLength ?? false; +export function deserialise(serial: {}) { + if (!isBeatSerial(serial)) { + throw new Error("Not a valid beat serial"); } + const newBeat = createBeat({ + loopLength: serial.globalLoopLength, + barCount: serial.barCount, + isLooping: serial.globalIsLooping, + name: serial.name, + timeSigUp: serial.timeSigUp, + useAutoBeatLength: serial.useAutoBeatLength, + }); + serial.tracks.forEach(trackSerial => { + const track = deserialiseTrack(trackSerial); + if (track) newBeat.tracks.value.push(track); + }); + return newBeat; +} - static deserialise(serial: any): Beat { - if (!Beat.isBeatSerial(serial)) { - throw new Error("Not a valid beat serial"); - } - const newBeat = new Beat({ - loopLength: serial.globalLoopLength, - barCount: serial.barCount, - isLooping: serial.globalIsLooping, - name: serial.name, - timeSigUp: serial.timeSigUp, - useAutoBeatLength: serial.useAutoBeatLength, - }); - serial.tracks.forEach(trackSerial => newBeat.addTrack(Track.deserialise(trackSerial))); - return newBeat; - } - - notify(publisher: unknown, event: EventTypeSubscriptions): void { - switch (event) { - case TrackEvents.LoopLengthChanged: - case TrackEvents.DisplayTypeChanged: - this.autoBeatLength(); - break; - case TrackEvents.WantsRemoval: - this.removeTrack((publisher as Track).getKey()); - break; - case TrackEvents.Baked: - this.setIsUsingAutoBeatLength(false); - break; - } - this.publisher.notifySubs(BeatEvents.DeepChange); - } - - addSubscriber(subscriber: ISubscriber, eventType: BeatEvents | Readonly): { unbind: () => void } { - return this.publisher.addSubscriber(subscriber, eventType); - } - - private setBarCountInternal(barCount: number): void { - if (!isPosInt(barCount)) { - barCount = this.barCount; - } - this.barCount = barCount; - for (const track of this.tracks) { - track.setBarCount(barCount); - } - this.publisher.notifySubs(BeatEvents.BarCountChanged); - } - - setBarCount(barCount: number): void { - if (!this.barSettingsLocked) { - this.setBarCountInternal(barCount); - } else { - this.setBarCountInternal(this.barCount); - } - } - - getBarCount(): number { - return this.barCount; - } - - setLoopLength(loopLength: number): void { - if (!isPosInt(loopLength)) { - return; - } - this.globalLoopLength = loopLength; - for (const track of this.tracks) { - track.setLoopLength(loopLength); - } - this.publisher.notifySubs(BeatEvents.GlobalLoopLengthChanged); - } - - getLoopLength(): number { - return this.globalLoopLength; - } - - setLooping(isLooping: boolean): void { - this.globalIsLooping = isLooping; - for (const track of this.tracks) { - track.setLooping(isLooping); - } - this.publisher.notifySubs(BeatEvents.GlobalDisplayTypeChanged); - } - - isLooping(): boolean { - return this.globalIsLooping; - } - - private findSmallestLoopLength(): number { - const loopLengths = [this.timeSigUp]; - for (const track of this.tracks) { - if (track.isLooping()) { - const loopLength = track.getLoopLength(); - if (loopLengths.indexOf(loopLength) === -1) { - loopLengths.push(loopLength); +export function createBeat(opts: BeatGroupInitOptions) { + const scope = effectScope(); + return scope.run(() => { + const tracks = shallowRef([]); + const barCountInternal = ref(opts.barCount ?? 4); + const barCount = computed({ + get() { + if (useAutoBeatLength.value) { + const loopLengths = [timeSigUp.value]; + for (const track of tracks.value) { + if (track.looping.value) { + const loopLength = track.loopLength.value; + if (loopLengths.indexOf(loopLength) === -1) { + loopLengths.push(loopLength); + } + } + } + const smallestLoopLength = loopLengths.reduce((prev, curr) => (prev * curr) / greatestCommonDivisor(prev, curr), 1); + return smallestLoopLength / timeSigUp.value; } + return barCountInternal.value; + }, + set(val) { + if (barSettingsLocked.value || !isPosInt(val)) { + return; + } + barCountInternal.value = val; + }, + }); + const timeSigUp = ref(opts.timeSigUp ?? 4); + const globalLoopLengthInternal = ref(opts.loopLength ?? timeSigUp.value); + const globalLoopLength = computed({ + get() { + return globalLoopLengthInternal.value; + }, + set(val) { + if (!isPosInt(val)) { + return; + } + globalLoopLengthInternal.value = val; + }, + }); + const globalIsLooping = ref(opts.isLooping ?? false); + const useAutoBeatLength = ref(opts.useAutoBeatLength ?? false); + const barSettingsLocked = computed(() => useAutoBeatLength.value); + const name = ref(opts.name ?? 'Beat'); + + function setTimeSigUp(timeSigVal: number): void { + if (!isValidTimeSigRange(timeSigVal)) { + timeSigVal = timeSigUp.value; + } + timeSigUp.value = timeSigVal; + for (const track of tracks.value) { + track.timeSigUp.value = timeSigVal; } } - if (loopLengths.length === 1) { - loopLengths.push(1); + + function getTrackByIndex(trackIndex: number) { + const track = tracks.value[trackIndex]; + if (!track) { + throw new Error(`Could not find the track with index: ${trackIndex}`); + } + return track; } - return loopLengths.reduce((prev, curr) => (prev * curr) / greatestCommonDivisor(prev, curr)); - } - setTimeSigUp(timeSigUp: number): void { - if (!Track.isValidTimeSigRange(timeSigUp)) { - timeSigUp = this.timeSigUp; + function swapTracksByIndices(trackIndex1: number, trackIndex2: number): void { + const track1 = getTrackByIndex(trackIndex1); + const track2 = getTrackByIndex(trackIndex2); + tracks.value[trackIndex1] = track2; + tracks.value[trackIndex2] = track1; } - this.timeSigUp = timeSigUp; - for (const track of this.tracks) { - track.setTimeSignature({ up: timeSigUp }); - } - this.autoBeatLength(); - this.publisher.notifySubs(BeatEvents.TimeSigUpChanged); - } - getTimeSigUp(): number { - return this.timeSigUp; - } - - getTrackByKey(trackKey: string): Track { - const foundTrack = this.tracks.find(track => track.getKey() === trackKey); - if (typeof foundTrack === "undefined") { - throw new Error(`Could not find the track with key: ${trackKey}`); - } - return foundTrack; - } - - getTrackByIndex(trackIndex: number): Track { - if (!this.tracks[trackIndex]) { - throw new Error(`Could not find the track with index: ${trackIndex}`); - } - return this.tracks[trackIndex]; - } - - getTrackCount(): number { - return this.tracks.length; - } - - getTrackKeys(): string[] { - return this.tracks.map(track => track.getKey()); - } - - swapTracksByIndices(trackIndex1: number, trackIndex2: number): void { - const track1 = this.getTrackByIndex(trackIndex1); - const track2 = this.getTrackByIndex(trackIndex2); - this.tracks[trackIndex1] = track2; - this.tracks[trackIndex2] = track1; - this.publisher.notifySubs(BeatEvents.TrackOrderChanged); - } - - moveTrackBack(trackKey: string): void { - const index = this.tracks.indexOf(this.getTrackByKey(trackKey)); - if (typeof index !== "undefined" && index > 0) { - this.swapTracksByIndices(index, index - 1); - } - this.publisher.notifySubs(BeatEvents.TrackOrderChanged); - this.publisher.notifySubs(BeatEvents.TrackListChanged); - } - - moveTrackForward(trackKey: string): void { - const index = this.tracks.indexOf(this.getTrackByKey(trackKey)); - if (typeof index !== "undefined" && index < this.getTrackCount()) { - this.swapTracksByIndices(index, index + 1); - } - this.publisher.notifySubs(BeatEvents.TrackOrderChanged); - this.publisher.notifySubs(BeatEvents.TrackListChanged); - } - - canMoveTrackBack(trackKey: string): boolean { - return this.tracks.indexOf(this.getTrackByKey(trackKey)) > 0; - } - - canMoveTrackForward(trackKey: string): boolean { - return this.tracks.indexOf(this.getTrackByKey(trackKey)) < this.tracks.length - 1; - } - - addTrack(track: Track): void; - addTrack(options?: TrackInitOptions): Track; - addTrack(optionsOrTrack?: Track | TrackInitOptions): Track | void { - let newTrack: Track; - if (optionsOrTrack instanceof Track) { - newTrack = optionsOrTrack; - } else { - optionsOrTrack = { + function addTrack(options?: TrackInitOptions): Track | null { + let newTrack: Track | null; + options = { + bars: barCount.value, + isLooping: globalIsLooping.value, + loopLength: globalLoopLength.value, + ...options, timeSig: { - up: this.timeSigUp, + up: timeSigUp.value, down: 4, + ...options?.timeSig ?? {}, }, - bars: this.barCount, - isLooping: this.globalIsLooping, - loopLength: this.globalLoopLength, - ...optionsOrTrack }; - newTrack = new Track(optionsOrTrack); + newTrack = createTrack(options) ?? null; + if (newTrack) { + tracks.value.push(newTrack); + triggerRef(tracks); + } + return newTrack; } - this.tracks.push(newTrack); - newTrack.addSubscriber(this, EventTypeSubscriptions); - this.publisher.notifySubs(BeatEvents.TrackListChanged); - return newTrack; - } - removeTrack(trackKey: string): void { - const track = this.getTrackByKey(trackKey); - this.tracks.splice(this.tracks.indexOf(track), 1); - this.autoBeatLength(); - this.publisher.notifySubs(BeatEvents.TrackListChanged); - } - - setTrackName(trackKey: string, newName: string): void { - this.getTrackByKey(trackKey).setName(newName); - this.publisher.notifySubs(BeatEvents.TrackOrderChanged); - } - - autoBeatLengthOn(): boolean { - return this.useAutoBeatLength; - } - - private autoBeatLength(): void { - if (this.useAutoBeatLength) { - this.setBarCountInternal(this.findSmallestLoopLength() / this.timeSigUp); + function removeTrack(index: number): void { + const track = getTrackByIndex(index); + tracks.value.splice(index, 1); + track.destroy(); + triggerRef(tracks); } - } - setIsUsingAutoBeatLength(isOn: boolean): void { - this.useAutoBeatLength = isOn; - this.autoBeatLength(); - if (isOn) { - this.lockBars(); - } else { - this.unlockBars(); + function bakeLoops(): void { + const barCountLooped = barCount.value; + useAutoBeatLength.value = false; + barCount.value = barCountLooped; + tracks.value.forEach(track => track.bakeLoops()); } - this.publisher.notifySubs(BeatEvents.AutoBeatSettingsChanged); - } - barsLocked(): boolean { - return this.barSettingsLocked; - } + function serialise(): Readonly { + return { + tracks: tracks.value.map(track => track.serialise()), + barCount: barCount.value, + timeSigUp: timeSigUp.value, + globalLoopLength: globalLoopLength.value, + globalIsLooping: globalIsLooping.value, + useAutoBeatLength: useAutoBeatLength.value, + barSettingsLocked: barSettingsLocked.value, + name: name.value, + } as const; + } - lockBars(): void { - this.barSettingsLocked = true; - this.publisher.notifySubs(BeatEvents.LockingChanged); - } + watch([barCount, timeSigUp], ([newBarCount, newTimeSigUp]) => { + for (const track of tracks.value) { + track.barCount.value = newBarCount; + track.timeSigUp.value = newTimeSigUp; + } + }, { immediate: true }); - unlockBars(): void { - this.barSettingsLocked = false; - this.publisher.notifySubs(BeatEvents.LockingChanged); - } - - bakeLoops(): void { - this.tracks.forEach(track => track.bakeLoops()); - } - - setName(newName: string): void { - this.name.val = newName; - } - - getName(): ICapsule { - return this.name; - } - - serialise(): Readonly { return { - tracks: this.tracks.map(track => track.serialise()), - barCount: this.barCount, - timeSigUp: this.timeSigUp, - globalLoopLength: this.globalLoopLength, - globalIsLooping: this.globalIsLooping, - useAutoBeatLength: this.useAutoBeatLength, - barSettingsLocked: this.barSettingsLocked, - name: this.name.val, - } as const; - } + tracks, + barCount, + timeSigUp, + globalLoopLength, + globalIsLooping, + useAutoBeatLength, + barSettingsLocked, + name, - static isBeatSerial(serial: any): serial is BeatSerial { - return Array.isArray(serial.tracks) && - typeof serial.barCount === "number" && - typeof serial.timeSigUp === "number" && - typeof serial.globalLoopLength === "number" && - typeof serial.globalIsLooping === "boolean" && - typeof serial.useAutoBeatLength === "boolean" && - typeof serial.barSettingsLocked === "boolean"; - } + setTimeSigUp, + getTrackByIndex, + swapTracksByIndices, + addTrack, + removeTrack, + bakeLoops, + serialise, + destroy: scope.stop, + }; + })!; } + +export type Beat = ReturnType; diff --git a/src/BeatStore.ts b/src/BeatStore.ts index 8d20bb9..3b2ec22 100644 --- a/src/BeatStore.ts +++ b/src/BeatStore.ts @@ -1,136 +1,114 @@ -import Beat, { BeatEvents } from "@/Beat"; -import { Capsule, ICapsule, ISubscriber } from "@djledda/ladder"; +import { type Beat, createBeat, deserialise as deserialiseBeat } from "@/Beat"; +import { inject, computed, type InjectionKey, ref, shallowRef, triggerRef, watch } from "vue"; -const EventTypeSubscriptions = [ - BeatEvents.TimeSigUpChanged, - BeatEvents.BarCountChanged, - BeatEvents.GlobalDisplayTypeChanged, - BeatEvents.TrackListChanged, - BeatEvents.LockingChanged, - BeatEvents.AutoBeatSettingsChanged, - BeatEvents.DeepChange, -] as const; -type EventTypeSubscriptions = typeof EventTypeSubscriptions[number]; +function defaultMainBeatGroup(): Beat { + const defaultSettings = { + barCount: 2, + isLooping: false, + timeSigUp: 8, + }; + const mainBeatGroup = createBeat(defaultSettings); + mainBeatGroup.addTrack({ name: "LF" }); + mainBeatGroup.addTrack({ name: "LH" }); + mainBeatGroup.addTrack({ name: "RH" }); + mainBeatGroup.addTrack({ name: "RF" }); + return mainBeatGroup; +} -export default class BeatStore implements ISubscriber { - private readonly beats: Beat[]; - private activeBeat: ICapsule; - private onBeatChangeCbs: (() => void)[] = []; - private autoSave: boolean; - private orientation: "horizontal" | "vertical" | null = null; +export function createBeatStore() { + const beats = shallowRef([ defaultMainBeatGroup() ]); + const activeBeatIndex = ref(0); + const activeBeat = computed(() => beats.value[activeBeatIndex.value] ?? null); + const autoSave = ref(true); + const orientation = ref<'horizontal' | 'vertical' | null>(null); - constructor(options: { loadFromLocalStorage: boolean, autoSave: boolean }) { - this.autoSave = options.autoSave; - if (options.loadFromLocalStorage) { - const save = localStorage.getItem("drum-slayer-save"); - if (save) { - const serial = JSON.parse(save); - this.beats = [BeatStore.defaultMainBeatGroup()]; - this.activeBeat = Capsule.new(this.beats[0]); - this.loadFromSave(serial); - if (this.autoSave) { - this.activeBeat.watch(() => this.save("localStorage"), true); - this.beats.forEach(beat => beat.addSubscriber(this, EventTypeSubscriptions)); - } - return; - } + function resetActiveBeat(): void { + const current = activeBeat.value; + beats.value[activeBeatIndex.value] = defaultMainBeatGroup(); + current?.destroy(); + triggerRef(beats); + } + + function removeBeat(index: number): void { + const beat = beats.value[index]; + beats.value.splice(index, 1); + beat?.destroy(); + triggerRef(beats); + } + + function addNewBeat(): void { + const newBeat = defaultMainBeatGroup(); + beats.value.push(newBeat); + if (autoSave.value) { + save("localStorage"); } - this.beats = [ - BeatStore.defaultMainBeatGroup(), - ]; - this.activeBeat = Capsule.new(this.beats[0]); + triggerRef(beats); } - notify(publisher: unknown, event: EventTypeSubscriptions): void { - this.save("localStorage"); - } - - static defaultMainBeatGroup(): Beat { - const defaultSettings = { - barCount: 2, - isLooping: false, - timeSigUp: 8, - }; - const mainBeatGroup = new Beat(defaultSettings); - mainBeatGroup.addTrack({ name: "LF" }); - mainBeatGroup.addTrack({ name: "LH" }); - mainBeatGroup.addTrack({ name: "RH" }); - mainBeatGroup.addTrack({ name: "RF" }); - return mainBeatGroup; - } - - getActiveBeat(): ICapsule { - return this.activeBeat; - } - - resetActiveBeat(): void { - const index = this.beats.indexOf(this.activeBeat.val); - const reset = BeatStore.defaultMainBeatGroup(); - this.beats[index] = reset; - this.activeBeat.val = reset; - } - - getBeats(): Beat[] { - return this.beats.slice(); - } - - setActiveBeat(beat: Beat): void { - const index = this.beats.indexOf(beat); - if (index !== -1) { - this.activeBeat.val = this.beats[index]; - } - } - - addNewBeat(): void { - const newBeat = BeatStore.defaultMainBeatGroup(); - this.beats.push(newBeat); - if (this.autoSave) { - newBeat.addSubscriber(this, EventTypeSubscriptions); - } - this.onBeatChangeCbs.forEach(cb => cb()); - if (this.autoSave) { - this.save("localStorage"); - } - } - - onBeatChanges(callback: () => void) { - this.onBeatChangeCbs.push(callback); - } - - save(destination: "localStorage"): void { + function save(destination: "localStorage"): void { if (destination === "localStorage") { - const serials = this.beats.map(beat => beat.serialise()); + const serials = beats.value.map(beat => beat.serialise()); localStorage.setItem("drum-slayer-save", JSON.stringify({ beats: serials, - activeBeatIndex: this.beats.indexOf(this.activeBeat.val), - orientation: this.orientation, + activeBeatIndex: activeBeatIndex.value, + orientation: orientation.value, })); } } - loadFromSave(source: any): void { - this.beats.length = 0; + function loadFromSave(source: any): void { + beats.value.length = 0; if (Array.isArray(source.beats) && (typeof source.activeBeatIndex === "number" || typeof source.activeBeatIndex === "undefined") && typeof source.orientation === "string") { try { - source.beats.forEach((beat: any) => this.beats.push(Beat.deserialise(beat))); + source.beats.forEach((beat: any) => beats.value.push(deserialiseBeat(beat))); if (typeof source.activeBeatIndex === "number") { - this.activeBeat.val = this.beats[source.activeBeatIndex]; + activeBeatIndex.value = source.activeBeatIndex; } - this.orientation = source.orientation; + orientation.value = source.orientation; } catch (err) { console.error(err); } + } else { + resetActiveBeat(); } } - - setOrientation(orientation: "horizontal" | "vertical"): void { - this.orientation = orientation; - this.save("localStorage"); + + function bakeAll(): void { + activeBeat.value?.bakeLoops(); } - getSavedOrientation(): "horizontal" | "vertical" | null { - return this.orientation; + watch([activeBeatIndex, orientation, beats], () => { + save('localStorage'); + }); + + const savedItem = localStorage.getItem('drum-slayer-save'); + if (savedItem) { + const serial = JSON.parse(savedItem); + beats.value = [defaultMainBeatGroup()]; + loadFromSave(serial); } -} \ No newline at end of file + + return { + beats, + activeBeatIndex, + activeBeat, + autoSave, + orientation, + + save, + addNewBeat, + removeBeat, + resetActiveBeat, + bakeAll, + }; +} + +export type BeatStore = ReturnType; + +export const BeatStoreKey = Symbol('BeatStore') as InjectionKey; + +export function useBeatStore(): BeatStore { + return inject(BeatStoreKey, createBeatStore, true); +} diff --git a/src/Track.ts b/src/Track.ts index 3d45d05..75df630 100644 --- a/src/Track.ts +++ b/src/Track.ts @@ -1,243 +1,263 @@ -import TrackUnit, { TrackUnitType } from "@/TrackUnit"; import { isPosInt } from "@/utils"; -import { IPublisher, ISubscriber, Publisher } from "@djledda/ladder"; +import { ref, shallowRef, computed, watch, reactive, triggerRef, effectScope } from "vue"; export type TrackInitOptions = { timeSig?: { up: number, down: number, }, + barCount?: number, + units?: TrackUnit[], name?: string, bars?: number, isLooping?: boolean, loopLength?: number, }; -export const enum TrackEvents { - NewTimeSig="be-0", - NewBarCount="be-1", - NewName="be-2", - DisplayTypeChanged="be-3", - LoopLengthChanged="be-4", - WantsRemoval="be-5", - Baked="be-6", - DeepChange="be-7", -} - export type TrackSerial = { name: string, timeSigUp: number, timeSigDown: number, units: { isOn: boolean[], - type: TrackUnitType[], - stickingType: TrackUnitStickingType[], + type: number[], + stickingType: number[], }, barCount: number, loopLength: number, looping: boolean, } -export default class Track implements IPublisher { - private static count = 0; - private readonly key: string; - private name: string; - private timeSigUp = 4; - private timeSigDown = 4; - private readonly unitRecord: TrackUnit[] = []; - private barCount = 1; - private publisher = new Publisher(this); - private loopLength: number; - private looping: boolean; +export const TrackUnitTypeList = [ "Normal", "GhostNote", "Accent", "GhostNoteAccent" ] as const; +export type TrackUnitType = typeof TrackUnitTypeList[number]; - constructor(options?: TrackInitOptions) { - this.key = `B-${Track.count}`; - this.name = options?.name ?? this.key; - this.setTimeSignature({ up: options?.timeSig?.up ?? 4, down: options?.timeSig?.down ?? 4 }); - this.setBarCount(options?.bars ?? 4); - Track.count++; - this.loopLength = options?.loopLength ?? this.timeSigUp * this.barCount; - this.looping = options?.isLooping ?? false; +export const TrackUnitStickingTypeList = [ "none", "lh", "rh", "lf", "rf" ] as const; +export type TrackUnitStickingType = typeof TrackUnitStickingTypeList[number]; + +export function isValidTimeSigRange(sig: number): boolean { + return sig >= 2 && sig <= 32; +} + +function isTrackSerial(serial: any): serial is TrackSerial { + const correctTypes = typeof serial.name === "string" && + typeof serial.timeSigUp === "number" && + typeof serial.timeSigDown === "number" && + typeof serial.units === "object" && + Array.isArray(serial.units.isOn) && + Array.isArray(serial.units.type) && + Array.isArray(serial.units.stickingType) && + typeof serial.barCount === "number" && + typeof serial.loopLength === "number" && + typeof serial.looping === "boolean"; + return correctTypes && serial.units.isOn.length === serial.units.type.length; +} + +export function deserialise(serial: Record) { + if (!isTrackSerial(serial)) { + throw new Error("Invalid track serial."); } + const units = serial.units.isOn.map((isOn, i) => ({ + on: isOn, + type: serial.units.type[i] ?? 0, + stickingType: serial.units.stickingType[i] ?? 0, + })); + return createTrack({ + bars: serial.barCount, + isLooping: serial.looping, + loopLength: serial.loopLength, + name: serial.name, + timeSig: { + up: serial.timeSigUp, + down: serial.timeSigDown, + }, + units, + }); +} - static deserialise(serial: any): Track { - if (!Track.isTrackSerial(serial)) { - throw new Error("Invalid track serial."); - } - const track = new Track({ - bars: serial.barCount, - isLooping: serial.looping, - loopLength: serial.loopLength, - name: serial.name, - timeSig: { - up: serial.timeSigUp, - down: serial.timeSigDown, +export type TrackUnit = { + on: boolean, + type: number, + stickingType: number, +}; + +export function createTrack(options: TrackInitOptions) { + const scope = effectScope(); + return scope.run(() => { + const name = ref(options.name ?? 'New Track'); + const timeSig = reactive({ up: 4, down: 4 }); + const timeSigUp = computed({ + get() { + return timeSig.up; + }, + set(val) { + if (isValidTimeSigRange(val)) { + timeSig.up = val | 0; + } }, }); - const units = serial.units.isOn.map((isOn, i) => new TrackUnit({ - on: isOn, - type: serial.units.type[i], - stickingType: serial.units.stickingType[i], - parent: track, - })); - track.unitRecord.length = 0; - track.unitRecord.push(...units); - return track; - } - - setLoopLength(loopLength: number): void { - if (!isPosInt(loopLength) || loopLength < 2) { - loopLength = this.loopLength; - } - this.loopLength = loopLength; - this.publisher.notifySubs(TrackEvents.LoopLengthChanged); - } - - setLooping(isLooping: boolean): void { - this.looping = isLooping; - this.publisher.notifySubs(TrackEvents.DisplayTypeChanged); - } - - addSubscriber(subscriber: ISubscriber, eventType: TrackEvents | TrackEvents[]): { unbind: () => void } { - return this.publisher.addSubscriber(subscriber, eventType); - } - - setTimeSignature(timeSig: {up?: number, down?: number}): void { - if (timeSig.up && Track.isValidTimeSigRange(timeSig.up)) { - this.timeSigUp = timeSig.up | 0; - } - if (timeSig.down && Track.isValidTimeSigRange(timeSig.down)) { - this.timeSigDown = timeSig.down | 0; - } - this.updateTrackUnitLength(); - this.publisher.notifySubs(TrackEvents.NewTimeSig); - } - - setTimeSigUp(timeSigUp: number): void { - this.setTimeSignature({ up: timeSigUp }); - } - - setTimeSigDown(timeSigUp: number): void { - this.setTimeSignature({ down: timeSigUp }); - } - - setBarCount(barCount: number): void { - if (!isPosInt(barCount) || barCount == this.barCount) { - barCount = this.barCount; - } - this.barCount = barCount; - this.updateTrackUnitLength(); - this.publisher.notifySubs(TrackEvents.NewBarCount); - } - - getUnitByIndex(index: number): TrackUnit | null { - if (this.looping) { - index %= this.loopLength; - } - return this.unitRecord[index] ?? null; - } - - private updateTrackUnitLength() { - const newBarCount = this.barCount * this.timeSigUp; - if (newBarCount < this.unitRecord.length) { - this.unitRecord.splice(this.barCount * this.timeSigUp, this.unitRecord.length - newBarCount); - } else if (newBarCount > this.unitRecord.length) { - const barsToAdd = newBarCount - this.unitRecord.length; - for (let i = 0; i < barsToAdd; i++) { - this.unitRecord.push(new TrackUnit({ - parent: this, - })); - } - } - } - - getTimeSigUp(): number { - return this.timeSigUp; - } - - getTimeSigDown(): number { - return this.timeSigDown; - } - - getBarCount(): number { - return this.barCount; - } - - getKey(): string { - return this.key; - } - - static isValidTimeSigRange(sig: number): boolean { - return sig >= 2 && sig <= 32; - } - - setName(newName: string): void { - this.name = newName; - this.publisher.notifySubs(TrackEvents.NewName); - } - - getName(): string { - return this.name; - } - - isLooping(): boolean { - return this.looping; - } - - getLoopLength(): number { - return this.loopLength; - } - - delete(): void { - this.publisher.notifySubs(TrackEvents.WantsRemoval); - } - - bakeLoops(): void { - if (this.isLooping()) { - this.unitRecord.forEach((unit, i) => { - const reprUnitAtPos = this.getUnitByIndex(i); - if (reprUnitAtPos) { - unit.mimic(reprUnitAtPos); - } - }); - this.publisher.notifySubs(TrackEvents.Baked); - this.setLooping(false); - } else { - this.publisher.notifySubs(TrackEvents.Baked); - } - } - - serialise(): Readonly { - return { - name: this.name, - timeSigUp: this.timeSigUp, - timeSigDown: this.timeSigDown, - units: { - isOn: this.unitRecord.map(unit => unit.isOn()), - type: this.unitRecord.map(unit => unit.getType()), - stickingType: this.unitRecord.map(unit => unit.getStickingType()), + const timeSigDown = computed({ + get() { + return timeSig.down; }, - barCount: this.barCount, - loopLength: this.loopLength, - looping: this.looping, - } as const; - } + set(val) { + if (isValidTimeSigRange(val)) { + timeSig.down = val | 0; + } + }, + }); + const unitRecord = shallowRef([]); + const barCount = ref(options.barCount ?? 4); + const loopLengthInternal = ref(options?.loopLength ?? timeSigUp.value * barCount.value); + const loopLength = computed({ + get() { + return loopLengthInternal.value; + }, + set(val) { + if (!isPosInt(val) || val < 2) { + return; + } + loopLengthInternal.value = val; + triggerRef(unitRecord); + }, + }); + const looping = ref(options?.isLooping ?? false); - static isTrackSerial(serial: any): serial is TrackSerial { - const correctTypes = typeof serial.name === "string" && - typeof serial.timeSigUp === "number" && - typeof serial.timeSigDown === "number" && - typeof serial.units === "object" && - Array.isArray(serial.units.isOn) && - Array.isArray(serial.units.type) && - Array.isArray(serial.units.stickingType) && - typeof serial.barCount === "number" && - typeof serial.loopLength === "number" && - typeof serial.looping === "boolean"; - return correctTypes && serial.units.isOn.length === serial.units.type.length; - } + function getUnitByIndex(index: number): TrackUnit | null { + if (looping.value) { + index %= loopLength.value; + } + return unitRecord.value[index] ?? null; + } - alertDeepChange(): void { - this.publisher.notifySubs(TrackEvents.DeepChange); - } + function updateTrackUnitLength() { + const newBarCount = barCount.value * timeSigUp.value; + if (newBarCount < unitRecord.value.length) { + unitRecord.value.splice(barCount.value * timeSigUp.value, unitRecord.value.length - newBarCount); + } else if (newBarCount > unitRecord.value.length) { + const barsToAdd = newBarCount - unitRecord.value.length; + for (let i = 0; i < barsToAdd; i++) { + unitRecord.value.push(createTrackUnit()); + } + } + triggerRef(unitRecord); + } + + function bakeLoops(): void { + if (looping.value) { + unitRecord.value.forEach((unit, i) => { + const reprUnitAtPos = getUnitByIndex(i); + if (reprUnitAtPos) { + mimicUnit(unit, reprUnitAtPos); + } + }); + looping.value = false; + } + barCount.value + triggerRef(unitRecord); + } + + function serialise(): Readonly { + return { + name: name.value, + timeSigUp: timeSigUp.value, + timeSigDown: timeSigDown.value, + units: { + isOn: unitRecord.value.map(unit => unit.on), + type: unitRecord.value.map(unit => unit.type), + stickingType: unitRecord.value.map(unit => unit.stickingType), + }, + barCount: barCount.value, + loopLength: loopLength.value, + looping: looping.value, + } as const; + } + + function createTrackUnit(): TrackUnit { + return { + on: false, + type: 0, + stickingType: 0, + }; + } + + function setStickingType(index: number, stickingType: number): void { + const unit = getUnitByIndex(index); + if (!unit) { + return; + } + unit.stickingType = stickingType; + triggerRef(unitRecord); + } + + function setUnitOn(index: number, on: boolean): void { + const unit = getUnitByIndex(index); + if (!unit) { + return; + } + unit.on = on; + triggerRef(unitRecord); + } + + function updateUnit(index: number, update: Partial) { + const unit = getUnitByIndex(index); + if (!unit) { + return; + } + Object.assign(unit, update); + triggerRef(unitRecord); + } + + function toggleUnit(index: number): void { + const unit = getUnitByIndex(index); + if (!unit) { + return; + } + unit.on = !unit.on; + triggerRef(unitRecord); + } + + function rotateUnit(index: number): void { + const unit = getUnitByIndex(index); + if (!unit) { + return; + } + if (unit.type === TrackUnitTypeList.length - 1) { + unit.type = 0; + } else { + unit.type += 1; + } + triggerRef(unitRecord); + } + + function mimicUnit(unitA: TrackUnit, unitB: TrackUnit): void { + unitA.on = unitB.on; + unitA.type = unitB.type; + unitA.stickingType = unitB.stickingType; + triggerRef(unitRecord); + } + + watch([barCount, timeSigDown, timeSigUp], () => updateTrackUnitLength(), { immediate: true }); + + return { + name, + timeSigUp, + timeSigDown, + unitRecord, + barCount, + loopLength, + looping, + + serialise, + bakeLoops, + rotateUnit, + toggleUnit, + setUnitOn, + updateUnit, + getUnitByIndex, + setStickingType, + destroy: scope.stop, + }; + })!; } + +export type Track = ReturnType; diff --git a/src/TrackUnit.ts b/src/TrackUnit.ts deleted file mode 100644 index ecbcdc1..0000000 --- a/src/TrackUnit.ts +++ /dev/null @@ -1,96 +0,0 @@ -import Track from "@/Track"; -import { IPublisher, ISubscriber, Publisher } from "@djledda/ladder"; - -export const TrackUnitTypeList = [ "Normal", "GhostNote", "Accent", "GhostNoteAccent" ] as const; -export type TrackUnitType = typeof TrackUnitTypeList[number]; - -export const TrackUnitStickingTypeList = [ "none", "lh", "rh", "lf", "rf" ] as const; -export type TrackUnitStickingType = typeof TrackUnitStickingTypeList[number]; - -export const enum TrackUnitEvent { - Toggle="tue-0", - On="tue-1", - Off="tue-2", - TypeChange="tue-3", -} - -export default class TrackUnit implements IPublisher { - private publisher: Publisher = new Publisher(this); - private on = false; - private typeIndex = 0; - private stickingType: TrackUnitStickingType = "none"; - private parent: Track; - - constructor(options: { - on?: boolean, - type?: TrackUnitType, - stickingType?: TrackUnitStickingType, - parent: Track, - }) { - this.parent = options.parent; - this.on = options.on ?? false; - this.setType(options.type ?? "Normal"); - this.setStickingType(options.stickingType ?? "none"); - } - - addSubscriber(subscriber: ISubscriber, eventType: TrackUnitEvent[]): { unbind: () => void } { - return this.publisher.addSubscriber(subscriber, eventType); - } - - toggle(): void { - this.on = !this.on; - this.publisher.notifySubs(TrackUnitEvent.Toggle); - if (this.on) { - this.publisher.notifySubs(TrackUnitEvent.On); - } else { - this.publisher.notifySubs(TrackUnitEvent.Off); - } - this.parent.alertDeepChange(); - } - - setOn(on: boolean): void { - this.on = on; - this.publisher.notifySubs(this.on ? TrackUnitEvent.On : TrackUnitEvent.Off); - this.parent.alertDeepChange(); - } - - setType(type: TrackUnitType): void { - this.typeIndex = TrackUnitTypeList.indexOf(type); - this.publisher.notifySubs(TrackUnitEvent.TypeChange); - this.parent.alertDeepChange(); - } - - setStickingType(type: TrackUnitStickingType) { - this.stickingType = type; - this.publisher.notifySubs(TrackUnitEvent.TypeChange); - this.parent.alertDeepChange(); - } - - getStickingType() { - return this.stickingType; - } - - getType(): TrackUnitType { - return TrackUnitTypeList[this.typeIndex]; - } - - rotateType(): void { - if (this.typeIndex === TrackUnitTypeList.length - 1) { - this.typeIndex = 0; - } else { - this.typeIndex += 1; - } - this.publisher.notifySubs(TrackUnitEvent.TypeChange); - this.parent.alertDeepChange(); - } - - isOn(): boolean { - return this.on; - } - - mimic(trackUnit: TrackUnit): void { - this.setOn(trackUnit.isOn()); - this.setType(trackUnit.getType()); - this.setStickingType(trackUnit.getStickingType()); - } -} diff --git a/src/main.ts b/src/main.ts index 3a3bdc7..4073786 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,15 +1,9 @@ -import RootView from "@/ui/Root/RootView"; +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import Root from '@/ui/Root/Root.vue' import "@/ui/global.css"; -import { bootstrap } from "@djledda/ladder"; -try { - const appRoot = new RootView({ - orientation: "vertical", - title: "Drum Slayer", - }); - window.appRoot = appRoot; - bootstrap(appRoot, "app"); - console.log("OK!"); -} catch (e) { - console.error("FUCK!", e); -} +const app = createApp(Root, { title: "Drum Slayer" }); +app.use(createPinia()); +app.mount('#app'); + diff --git a/src/tests.ts b/src/tests.ts deleted file mode 100644 index 23b48b3..0000000 --- a/src/tests.ts +++ /dev/null @@ -1,4 +0,0 @@ -import {TrackUnitType} from "./TrackUnit"; -import Track from "./Beat"; - - diff --git a/src/ui/Beat/Beat.css b/src/ui/Beat/Beat.css deleted file mode 100644 index 0b88805..0000000 --- a/src/ui/Beat/Beat.css +++ /dev/null @@ -1,74 +0,0 @@ -.beat { - padding: 1em; - overflow-x: scroll; - overflow-y: hidden; - display: flex; - width: inherit; - flex-direction: column; -} - -.vertical-mode .beat { - padding-bottom: 2em; - align-items: center; - overflow-x: hidden; - overflow-y: scroll; - height: inherit; -} - -.beat-title { - color: var(--color-title-light); - text-align: center; - width: fit-content; - padding-left: 16px; -} - -.vertical-mode .beat-title { - color: var(--color-title-light); - text-align: center; - padding-left: 0; -} - -.beat-track-container { - display: inline-block; -} - -.beat-titles-container { - display: inline-flex; - flex-direction: column; -} - -.vertical-mode .beat-main-container { - display: block; -} - -.vertical-mode .beat-titles-container { - margin-bottom: 10px; - display: flex; - flex-direction: row; - overflow: visible; -} - -.beat-main-container { - display: flex; - white-space: nowrap; -} - -.beat-track-title { - height: 36px; - line-height: 36px; - margin: 0; - flex: 1; - text-align: right; - display: block; - white-space: nowrap; -} - -.vertical-mode .beat-track-title { - height: auto; - transform: rotate(330deg); - transform-origin: bottom; - width: 36px; - display: inline-block; - writing-mode: vertical-rl; - text-align: right; -} diff --git a/src/ui/Beat/Beat.vue b/src/ui/Beat/Beat.vue new file mode 100644 index 0000000..ad94e22 --- /dev/null +++ b/src/ui/Beat/Beat.vue @@ -0,0 +1,119 @@ + + + + + + diff --git a/src/ui/Beat/BeatView.tsx b/src/ui/Beat/BeatView.tsx deleted file mode 100644 index 74ec447..0000000 --- a/src/ui/Beat/BeatView.tsx +++ /dev/null @@ -1,113 +0,0 @@ -import { h, ISubscriber, ISubscription, Rung, RungOptions } from "@djledda/ladder"; -import Beat, { BeatEvents } from "@/Beat"; -import TrackView from "@/ui/Track/TrackView"; -import "./Beat.css"; -import EditableTextFieldView from "@/ui/Widgets/EditableTextFIeld/EditableTextFieldView"; -import AppState from "@/AppState"; - -export type BeatUINodeOptions = RungOptions & { - state: AppState, - beat: Beat, - orientation?: "horizontal" | "vertical", -}; - -const EventTypeSubscriptions = [ - BeatEvents.TrackListChanged, -] as const; -type EventTypeSubscriptions = typeof EventTypeSubscriptions[number]; - -export default class BeatView extends Rung implements ISubscriber { - private beat: Beat; - private title: EditableTextFieldView; - private trackViews: TrackView[] = []; - private titles: HTMLHeadingElement[] = []; - private currentOrientation: "vertical" | "horizontal"; - private subscription: ISubscription; - private state: AppState; - - constructor(options: BeatUINodeOptions) { - super(options); - this.state = options.state; - this.beat = options.beat; - this.currentOrientation = options.orientation ?? "horizontal"; - this.subscription = this.beat.addSubscriber(this, EventTypeSubscriptions); - this.title = new EditableTextFieldView({ - setter: (text: string) => this.beat.setName(text), - noEmpty: true, - initialText: this.beat.getName().val, - }); - this.setupTrackViews(); - } - - notify(publisher: unknown, event: EventTypeSubscriptions): void { - if (event === BeatEvents.TrackListChanged) { - this.setupTrackViews(); - this.redraw(); - } - } - - private setupTrackViews(): void { - const newCount = this.beat.getTrackCount(); - for (let i = 0; i < newCount; i++) { - const track = this.beat.getTrackByIndex(i); - if (track && this.trackViews[i]) { - const title = this.trackViews[i].getTitleNode(); - if (title) { - this.titles[i] = title; - } - this.trackViews[i].setTrack(track); - } else { - this.trackViews.push(new TrackView({ state: this.state, track: this.beat.getTrackByIndex(i) })); - this.titles.push(this.trackViews[i].getTitleNode()); - this.titles[this.titles.length - 1].classList.add("beat-track-title"); - } - } - this.titles.splice(newCount, this.titles.length - newCount); - const deadTrackViews = this.trackViews.splice(newCount, this.trackViews.length - newCount); - deadTrackViews.forEach(beatView => beatView.setTrack(null)); - if (this.currentOrientation === "horizontal") { - this.reverseDisplayOrder(); - } - } - - setOrientation(orientation: "vertical" | "horizontal"): void { - if (this.currentOrientation !== orientation) { - this.reverseDisplayOrder(); - this.currentOrientation = orientation; - } - } - - private reverseDisplayOrder(): void { - this.titles.reverse(); - this.trackViews.reverse(); - this.render().classList.toggle("vertical"); - this.redraw(); - } - - private onNewBeat(): void { - this.beat.getName().watch((newVal) => { - this.title.setText(newVal); - }); - this.title.setText(this.beat.getName().val); - EventTypeSubscriptions.forEach(event => this.notify(this, event)); - this.setupTrackViews(); - this.redraw(); - } - - setBeat(newBeat: Beat): void { - this.beat = newBeat; - this.subscription.unbind(); - this.subscription = this.beat.addSubscriber(this, BeatEvents.TrackListChanged); - this.onNewBeat(); - } - - build(): HTMLDivElement { - return
-

{this.title}

-
-
{...this.titles}
-
{...this.trackViews}
-
-
as HTMLDivElement; - } -} diff --git a/src/ui/BeatSettings/BeatSettings.css b/src/ui/BeatSettings/BeatSettings.css deleted file mode 100644 index c535b8b..0000000 --- a/src/ui/BeatSettings/BeatSettings.css +++ /dev/null @@ -1,20 +0,0 @@ -.beat-settings { -} - -.beat-settings-options { - padding: 1em; - display: flex; - flex-direction: column; - justify-content: space-evenly; -} - -.beat-settings-option { - text-align: center; -} - -.beat-settings-option-group { - display: none; -} -.beat-settings-option-group.visible { - display: inline-block; -} diff --git a/src/ui/BeatSettings/BeatSettings.vue b/src/ui/BeatSettings/BeatSettings.vue new file mode 100644 index 0000000..2a3e4eb --- /dev/null +++ b/src/ui/BeatSettings/BeatSettings.vue @@ -0,0 +1,65 @@ + + + + + diff --git a/src/ui/BeatSettings/BeatSettingsView.tsx b/src/ui/BeatSettings/BeatSettingsView.tsx deleted file mode 100644 index 6b93117..0000000 --- a/src/ui/BeatSettings/BeatSettingsView.tsx +++ /dev/null @@ -1,128 +0,0 @@ -import "./BeatSettings.css"; -import NumberInputView from "@/ui/Widgets/NumberInput/NumberInputView"; -import Beat, { BeatEvents } from "@/Beat"; -import BoolBoxView from "@/ui/Widgets/BoolBox/BoolBoxView"; -import TrackSettingsView from "@/ui/TrackSettings/TrackSettingsView"; -import ActionButtonView from "@/ui/Widgets/ActionButton/ActionButtonView"; -import { h, ISubscriber, Rung, RungOptions } from "@djledda/ladder"; - -export type BeatSettingsUINodeOptions = RungOptions & { - beat: Beat, -}; - -const EventTypeSubscriptions = [ - BeatEvents.TimeSigUpChanged, - BeatEvents.BarCountChanged, - BeatEvents.GlobalDisplayTypeChanged, - BeatEvents.TrackListChanged, - BeatEvents.LockingChanged, - BeatEvents.AutoBeatSettingsChanged, -]; -type EventTypeSubscriptions = typeof EventTypeSubscriptions[number]; - -export default class BeatSettingsView extends Rung implements ISubscriber { - private beat: Beat; - private barCountInput!: NumberInputView; - private timeSigUpInput!: NumberInputView; - private autoBeatLengthCheckbox!: BoolBoxView; - private trackSettingsViews: TrackSettingsView[] = []; - private trackSettingsContainer!: HTMLDivElement; - - constructor(options: BeatSettingsUINodeOptions) { - super(options); - this.beat = options.beat; - this.setupBindings(); - } - - setBeat(newBeat: Beat): void { - this.beat = newBeat; - this.setupBindings(); - EventTypeSubscriptions.forEach(eventType => this.notify(null, eventType)); - } - - setupBindings(): void { - this.beat.addSubscriber(this, EventTypeSubscriptions); - } - - notify(publisher: unknown, event: EventTypeSubscriptions): void { - switch(event) { - case BeatEvents.BarCountChanged: - this.barCountInput.setValue(this.beat.getBarCount()); - break; - case BeatEvents.TimeSigUpChanged: - this.timeSigUpInput.setValue(this.beat.getTimeSigUp()); - break; - case BeatEvents.TrackListChanged: - this.remakeBeatSettingsViews(); - break; - case BeatEvents.LockingChanged: - if (this.beat.barsLocked()) { - this.barCountInput.disable(); - } else { - this.barCountInput.enable(); - } - break; - case BeatEvents.AutoBeatSettingsChanged: - this.autoBeatLengthCheckbox.setValue(this.beat.autoBeatLengthOn()); - break; - case BeatEvents.GlobalDisplayTypeChanged: - break; - } - } - - private remakeBeatSettingsViews() { - const trackCount = this.beat.getTrackCount(); - this.trackSettingsViews.splice(trackCount, this.trackSettingsViews.length - trackCount); - for (let i = 0; i < trackCount; i++) { - if (this.trackSettingsViews[i]) { - this.trackSettingsViews[i].setBeat(this.beat.getTrackByIndex(i)); - } else { - this.trackSettingsViews.unshift(new TrackSettingsView({ track: this.beat.getTrackByIndex(i) })); - } - } - if (!this.trackSettingsContainer) { - this.trackSettingsContainer =
{...this.trackSettingsViews}
as HTMLDivElement; - } else { - this.trackSettingsContainer.replaceChildren(...this.trackSettingsViews.reverse().map(view => view.render())); - } - } - - build(): Node { - this.barCountInput = new NumberInputView({ - label: "Bars:", - initialValue: this.beat.getBarCount(), - setter: (input: number) => this.beat.setBarCount(input), - getter: () => this.beat.getBarCount(), - }); - this.timeSigUpInput = new NumberInputView({ - label: "Boxes per bar:", - initialValue: this.beat.getTimeSigUp(), - setter: (input: number) => this.beat.setTimeSigUp(input), - getter: () => this.beat.getTimeSigUp(), - }); - this.autoBeatLengthCheckbox = new BoolBoxView({ - label: "Auto beat length:", - value: this.beat.autoBeatLengthOn(), - onInput: (isChecked: boolean) => this.beat.setIsUsingAutoBeatLength(isChecked), - }); - this.remakeBeatSettingsViews(); - return
-
-
- {this.timeSigUpInput} -
-
- {this.barCountInput} -
-
- {this.autoBeatLengthCheckbox} -
- {new ActionButtonView({ - label: "New Track", - onClick: () => this.beat.addTrack(), - })} - {this.trackSettingsContainer} -
-
; - } -} diff --git a/src/ui/BeatSummary/BeatSummarySettings.vue b/src/ui/BeatSummary/BeatSummarySettings.vue new file mode 100644 index 0000000..651d1dc --- /dev/null +++ b/src/ui/BeatSummary/BeatSummarySettings.vue @@ -0,0 +1,8 @@ + + + + + diff --git a/src/ui/Root/Root.css b/src/ui/Root/Root.css deleted file mode 100644 index d4b8f05..0000000 --- a/src/ui/Root/Root.css +++ /dev/null @@ -1,167 +0,0 @@ -:root { - --color-ui-accent: #00b3ba; - --color-ui-accent-hover: #00c1c9; - --color-ui-accent-active: #008e93; - --color-ui-neutral-light: #fdfdfe; - --color-ui-neutral-light-hover: #fdfdfe; - --color-ui-neutral-light-active: #fdfdfe; - --color-ui-neutral-dark: #8b8b8b; - --color-ui-neutral-dark-hover: #a1a1a1; - --color-ui-neutral-dark-active: #c1c1c1; - --color-bg-light: #464646; - --color-bg-medium: #323232; - --color-bg-dark: #282828; - --color-p-light: #fafafa; - --color-p-light-hover: #fafafa; - --color-p-light-active: #fafafa; - --color-p-dark: #282828; - --color-p-dark-hover: #464646; - --color-p-dark-active: #464646; - --color-title-light: #fafafa; - --color-title-dark: #282828; -} - -.root { - position: relative; - overflow: hidden; - color: var(--color-p-light); - background-color: var(--color-bg-dark); - height: 100vh; - align-content: center; -} - -.root-sidebar { - position: absolute; - left: -28em; - width: 30em; - height: 100vh; - display: flex; - transition: left 400ms; -} - -.sidebar-visible .root-sidebar { - left: 0; -} - -.root-settings { - z-index: 1; - width: 28em; - background-color: var(--color-bg-light); - overflow: scroll; - display: inline-block; -} - -.root-settings .root-title { - color: var(--color-title-light); - text-align: center; -} - -.root-sidebar-toggle { - z-index: 1; - height: 100vh; - min-width: 2em; - background-color: var(--color-bg-light); - left: 0; -} - -.root-quick-access-button { - right: 0; - width: 2em; - height: 2em; - cursor: pointer; - margin-bottom: 0.5em; -} - -.root-beat-stage-container { - position: absolute; - height: 100%; - left: 0; - width: 100vw; - display: flex; - flex-direction: column; - transition: left 400ms, width 400ms; -} - -.sidebar-visible .root-beat-stage-container { - left: 30em; - width: calc(100vw - 30em); -} - -.root-beat-stage { - position: relative; - max-height: 100vh; - margin: auto; - max-width: 100vw; - transition: max-width 400ms; - padding-left: 3em; -} - -.vertical-mode .root-beat-stage { - margin: auto auto; - height: 100vh; -} - -.sidebar-visible .root-beat-stage { - max-width: calc(100vw - 30em); -} - -.root-sidebar-left-strip { - writing-mode: vertical-rl; - background-color: var(--color-bg-light); -} - -.root-sidebar-left-strip > * { - display: inline-block; -} - -.root-sidebar-left-tab { - transform: rotate(-180deg); - display: inline-block; - width: 100%; - padding: 8px 3px 8px 3px; -} - -.root-sidebar-left-tab.active { - background-color: var(--color-bg-medium); - display: inline-block; -} - -.root-sidebar-add-beat { - width: 100%; - padding: 8px 3px 8px 3px; -} - -.root-sidebar-add-beat:hover, -.root-sidebar-left-tab:hover:not(.active) { - cursor: pointer; - background-color: var(--color-ui-neutral-dark); - transition: background-color 200ms; -} - -@media screen and (max-width: 900px) { - .sidebar-visible .root-sidebar { - left: 0; - width: 100vw; - } - .root-sidebar { - left: calc(-100vw + 2em); - width: 100vw; - } - .root-settings { - width: calc(100vw - 2em); - } - .sidebar-visible .root-beat-stage-container { - left: 100vw; - } - .root-beat-stage-container { - left: 0; - } - .sidebar-visible .root-beat-stage { - max-width: 100vw; - } -} - -* { - user-drag: none; - user-select: none; -} diff --git a/src/ui/Root/Root.vue b/src/ui/Root/Root.vue new file mode 100644 index 0000000..adb29f9 --- /dev/null +++ b/src/ui/Root/Root.vue @@ -0,0 +1,268 @@ + + + + + + diff --git a/src/ui/Root/RootView.tsx b/src/ui/Root/RootView.tsx deleted file mode 100644 index f8eda12..0000000 --- a/src/ui/Root/RootView.tsx +++ /dev/null @@ -1,192 +0,0 @@ -import BeatView from "@/ui/Beat/BeatView"; -import Beat from "@/Beat"; -import "./Root.css"; -import BeatSettingsView from "@/ui/BeatSettings/BeatSettingsView"; -import IconView from "@/ui/Widgets/Icon/IconView"; -import BeatStore from "@/BeatStore"; -import { Capsule, h, frag, Rung, RungOptions, ICapsule, ISubscriber } from "@djledda/ladder"; -import AppState from "@/AppState"; -import ToolboxView from "@/ui/Root/ToolboxView"; - -export type RootUINodeOptions = RungOptions & { - title: string, - mainBeat?: Beat, - orientation?: "horizontal" | "vertical", -}; - -export default class RootView extends Rung { - private title: string; - private beatView: BeatView; - private beatStore: BeatStore; - private activeBeat: ICapsule; - private beatSettingsView: BeatSettingsView; - private currentOrientation: "horizontal" | "vertical"; - private showHideSidebarButton = Capsule.new(null); - private sidebarActive = true; - private sidebarLeftTabs = Capsule.new(null); - private state = new AppState(); - private toolboxView: ToolboxView; - - constructor(options: RootUINodeOptions) { - super(options); - this.beatStore = new BeatStore({ - loadFromLocalStorage: true, - autoSave: true, - }); - this.toolboxView = new ToolboxView({ state: this.state }); - this.activeBeat = this.beatStore.getActiveBeat(); - this.activeBeat.watch((newVal) => { - this.beatSettingsView.setBeat(newVal); - this.beatView.setBeat(newVal); - }); - this.currentOrientation = this.beatStore.getSavedOrientation() ?? options.orientation ?? "horizontal"; - this.beatView = new BeatView({ - state: this.state, - beat: this.activeBeat.val, - orientation: this.currentOrientation, - }); - this.beatStore.onBeatChanges(() => { - this.sidebarLeftTabs.val?.replaceChildren(); - }); - this.beatSettingsView = new BeatSettingsView({ beat: this.activeBeat.val }); - this.title = options.title; - this.setOrientation(this.currentOrientation); - this.openSidebarForDesktop(); - } - - private openSidebarForDesktop() { - const mediaQueryList = window.matchMedia("screen and (max-width: 900px)"); - if (mediaQueryList.matches) { - this.toggleSidebar(); - } - } - - toggleSidebar(): void { - this.sidebarActive = !this.sidebarActive; - if (this.showHideSidebarButton.val) { - this.showHideSidebarButton.val.title = this.sidebarText(); - } - this.render().classList.toggle("sidebar-visible"); - } - - toggleOrientation(): void { - if (this.currentOrientation === "vertical") { - this.setOrientation("horizontal"); - } else { - this.setOrientation("vertical"); - } - } - - setOrientation(orientation: "horizontal" | "vertical"): void { - this.currentOrientation = orientation; - if (orientation === "vertical") { - this.render().classList.add("vertical-mode"); - } else { - this.render().classList.remove("vertical-mode"); - } - this.beatStore.setOrientation(orientation); - this.beatView.setOrientation(orientation); - } - - private sidebarText(): string { - return `${this.sidebarActive ? "Hide" : "Show"} sidebar`; - } - - private SidebarStripLeft = (): HTMLElement => { - return
-
- -
-
this.beatStore.addNewBeat()}>+
-
as HTMLElement; - }; - - private Tabs = (): Node => { - return
- {...this.beatStore.getBeats().map((beat) => { - const node =
this.beatStore.setActiveBeat(beat)}> - {beat.getName()} -
as HTMLDivElement; - this.activeBeat.watch((newVal) => { - if (beat === newVal) { - node.classList.add("active"); - } else { - node.classList.remove("active"); - } - }); - return node; - })} -
; - }; - - private SidebarQuickButtons = (): HTMLElement => { - return
-
this.toggleSidebar()}> - {new IconView({ - iconName: "list", - color: "var(--color-ui-neutral-dark)" - })} -
-
this.toggleOrientation()}> - {new IconView({ - iconName: "arrowClockwise", - color: "var(--color-ui-neutral-dark)" - })} -
-
this.activeBeat.val.bakeLoops()}> - {new IconView({ - iconName: "snowflake", - color: "var(--color-ui-neutral-dark)" - })} -
-
this.beatStore.resetActiveBeat()}> - {new IconView({ - iconName: "trash", - color: "var(--color-ui-neutral-dark)" - })} -
-
as HTMLElement; - }; - - private Sidebar = (): HTMLElement => { - return
- -
-

{this.title}

- {this.beatSettingsView} -
- -
as HTMLElement; - }; - - - build() { - return ( -
- -
- {this.toolboxView} -
- {this.beatView} -
-
-
- ) as HTMLDivElement; - } -} diff --git a/src/ui/Root/Toolbox.css b/src/ui/Root/Toolbox.css deleted file mode 100644 index 26a34af..0000000 --- a/src/ui/Root/Toolbox.css +++ /dev/null @@ -1,53 +0,0 @@ -.root-toolbox { } - -.root-toolbox .main-row { - height: 2.5em; - margin: auto; - display: flex; - background-color: var(--color-ui-neutral-dark); - justify-content: center; - width: 100%; -} - -.root-toolbox .details { - margin: auto; - height: 4em; - width: min-content; - border-radius: 0 0 1em 1em; - padding: 0.5em; - background-color: var(--color-ui-neutral-dark-active); - display: flex; - justify-content: center; -} - -.root-toolbox .details.hidden { - visibility: hidden; -} - -.root-toolbox .track-unit { - margin: 0; - padding: 0; -} - -.root-toolbox .toolbox-button { - padding: 0.5em; - cursor: pointer; - color: black; - background-color: var(--color-ui-neutral-dark); -} -.root-toolbox .toolbox-button:hover { - background-color: var(--color-ui-neutral-dark-hover); -} -.root-toolbox .toolbox-button.active { - background-color: var(--color-ui-neutral-dark-active); -} - -.root-toolbox .details .toolbox-button.active { - background-color: var(--color-ui-neutral-dark); -} -.root-toolbox .details .toolbox-button:hover { - background-color: var(--color-ui-neutral-dark-hover); -} -.root-toolbox .details .toolbox-button { - background-color: var(--color-ui-neutral-dark-active); -} diff --git a/src/ui/Root/Toolbox.vue b/src/ui/Root/Toolbox.vue new file mode 100644 index 0000000..735a4bd --- /dev/null +++ b/src/ui/Root/Toolbox.vue @@ -0,0 +1,114 @@ + + + + + + diff --git a/src/ui/Root/ToolboxView.tsx b/src/ui/Root/ToolboxView.tsx deleted file mode 100644 index 64ddcf7..0000000 --- a/src/ui/Root/ToolboxView.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import AppState, { AppStateEvent } from "@/AppState"; -import { TrackUnitStickingTypeList, TrackUnitTypeList } from "@/TrackUnit"; -import { Capsule, h, frag, Rung, RungOptions, ISubscriber } from "@djledda/ladder"; -import TrackUnitView, { StickingTypeIconMap } from "../TrackUnit/TrackUnitView"; -import IconView from "../Widgets/Icon/IconView"; -import "./Toolbox.css"; - -type ToolboxOptions = RungOptions & { - state: AppState, -}; - -export default class ToolboxView extends Rung implements ISubscriber { - private state: AppState; - - constructor(options: ToolboxOptions) { - super(options); - this.state = options.state; - this.state.addSubscriber(this, 'appstate-tool-select'); - } - - notify(publisher: unknown, event: AppStateEvent): void { - if (event === 'appstate-tool-select') { - this.redraw(); - } - } - - private SubMenuButtons = () => { - switch (this.state.selectedTool) { - case "track-unit-type": - return
{...TrackUnitTypeList.map(type => ( -
this.state.selectTrackUnitTypePaint(type)}> -
-
- ))}
; - case "sticking": - return
{...TrackUnitStickingTypeList.reduce((prev, stickingType) => { - if (stickingType !== "none") { - prev.push(
this.state.selectStickingTypePaint(stickingType)}> - {new IconView({ iconName: StickingTypeIconMap[stickingType] })} -
as HTMLButtonElement); - } - return prev; - }, [] as HTMLElement[])}
; - case "eraser": - return
; - } - } - - protected build() { - return
-
-
this.state.selectTool("track-unit-type")}> - Track Type -
-
this.state.selectTool("sticking")}> - Sticking -
-
this.state.selectTool("eraser")}> - Eraser -
-
- -
as HTMLDivElement; - } -} diff --git a/src/ui/Track/Track.css b/src/ui/Track/Track.css deleted file mode 100644 index 031264e..0000000 --- a/src/ui/Track/Track.css +++ /dev/null @@ -1,60 +0,0 @@ -.vertical-mode .track { - height: 36px; -} - -.vertical-mode .track { - height: auto; -} - -.track > * { - padding-right: 1em; - padding-left: 1em; -} - -.vertical-mode .track > * { - padding-right: 0; - padding-left: 0; -} - -.track-unit-block { - height: 2em; -} - -.vertical-mode .track-unit-block { - height: auto; - width: 2em; -} - -.track-spacer { - display: inline-block; - width: 1em; - height: 2em; -} - -.vertical-mode .track-spacer { - display: block; - width: 2em; - height: 1em; -} - -.track-main { - height: 36px; -} - -.vertical-mode .track-main { - width: 2em; - margin-right: 4px; - display: block; -} - -.track-settings-container { - display: flex; -} - -.track { - width: max-content; -} - -.vertical-mode .track { - display: inline-block; -} \ No newline at end of file diff --git a/src/ui/Track/Track.vue b/src/ui/Track/Track.vue new file mode 100644 index 0000000..85d9c7a --- /dev/null +++ b/src/ui/Track/Track.vue @@ -0,0 +1,152 @@ + + + + + diff --git a/src/ui/Track/TrackView.tsx b/src/ui/Track/TrackView.tsx deleted file mode 100644 index c428ce8..0000000 --- a/src/ui/Track/TrackView.tsx +++ /dev/null @@ -1,181 +0,0 @@ -import Track, { TrackEvents } from "@/Track"; -import TrackUnitView from "@/ui/TrackUnit/TrackUnitView"; -import "./Track.css"; -import { Capsule, h, ISubscriber, ISubscription, Rung, RungOptions } from "@djledda/ladder"; -import AppState from "@/AppState"; - -export type TrackUINodeOptions = RungOptions & { - state: AppState, - track: Track, -}; - -const EventTypeSubscriptions = [ - TrackEvents.NewName, - TrackEvents.NewTimeSig, - TrackEvents.NewBarCount, - TrackEvents.DisplayTypeChanged, - TrackEvents.LoopLengthChanged, -]; - -type EventTypeSubscriptions = typeof EventTypeSubscriptions[number]; - -export default class TrackView extends Rung implements ISubscriber { - private track!: Track; - private title: HTMLHeadingElement; - private trackUnitViews: TrackUnitView[] = []; - private trackUnitViewBlock: HTMLElement | null = null; - private sub: ISubscription | null = null; - private state: AppState; - static deselectingUnits = false; - static selectingUnits = false; - - constructor(options: TrackUINodeOptions) { - super(options); - this.state = options.state; - this.title =

as HTMLHeadingElement; - this.setTrack(options.track); - } - - getTitleNode(): HTMLHeadingElement { - return this.title; - } - - setTrack(track: Track | null): void { - if (track) { - this.track = track; - this.sub?.unbind(); - this.title.innerText = this.track.getName(); - this.sub = this.track.addSubscriber(this, EventTypeSubscriptions); - this.redraw(); - } else { - this.sub?.unbind(); - } - } - - notify(publisher: unknown, event: EventTypeSubscriptions): void { - switch (event) { - case TrackEvents.NewName: - this.title.innerText = this.track.getName(); - break; - case TrackEvents.NewTimeSig: - case TrackEvents.NewBarCount: - case TrackEvents.DisplayTypeChanged: - case TrackEvents.LoopLengthChanged: - this.setupTrackUnits(); - break; - } - } - - private rebuildTrackUnitViews() { - const trackUnitCount = this.track.getBarCount() * this.track.getTimeSigUp(); - for (let i = 0; i < trackUnitCount; i++) { - const trackUnit = this.track.getUnitByIndex(i); - if (trackUnit) { - let view: TrackUnitView; - if (this.trackUnitViews[i]) { - view = this.trackUnitViews[i]; - view.setUnit(trackUnit); - } else { - view = new TrackUnitView({ trackUnit }); - this.trackUnitViews.push(view); - view.onHover(() => this.applyCurrentToolToTrackUnit(view)); - view.onMouseDown((event: MouseEvent) => this.onTrackUnitClick(event.button, view)); - } - } - } - const deadViews = this.trackUnitViews.splice(trackUnitCount, this.trackUnitViews.length - trackUnitCount); - deadViews.forEach(trackUnitView => trackUnitView.setUnit(null)); - } - - private onTrackUnitClick(button: number, view: TrackUnitView) { - if (button === 0) { - TrackView.selectingUnits = true; - } else if (button === 2) { - TrackView.deselectingUnits = true; - } - this.applyCurrentToolToTrackUnit(view); - } - - private applyCurrentToolToTrackUnit(trackUnitView: TrackUnitView) { - if (this.state.selectedTool === "sticking") { - if (TrackView.selectingUnits) { - trackUnitView.setStickingType(this.state.activeStickingType); - } else if (TrackView.deselectingUnits) { - trackUnitView.setStickingType("none"); - } - } else if (this.state.selectedTool === "track-unit-type") { - if (TrackView.selectingUnits) { - trackUnitView.turnOn(); - trackUnitView.setType(this.state.activeTrackUnitType); - } else if (TrackView.deselectingUnits) { - trackUnitView.turnOff(); - } - } else if (this.state.selectedTool === "eraser") { - if (TrackView.selectingUnits || TrackView.deselectingUnits) { - trackUnitView.turnOff(); - } - } - } - - private buildTrackUnitViewBlock(): void { - const trackUnitNodes: HTMLElement[] = []; - for (let i = 0; i < this.trackUnitViews.length; i++) { - trackUnitNodes.push(this.trackUnitViews[i].render()); - } - if (this.trackUnitViewBlock) { - this.trackUnitViewBlock.replaceChildren(...trackUnitNodes); - } else { - this.trackUnitViewBlock =
{...trackUnitNodes}
as HTMLDivElement; - } - } - - private respaceTrackUnits(): void { - if (!this.trackUnitViewBlock) { - return; - } - this.trackUnitViewBlock.querySelectorAll(".unit-spacer").forEach(spacer => spacer.remove()); - const barLength = this.track.getTimeSigUp(); - const barCount = this.track.getBarCount(); - let bars = 0; - let i = -1; - let spacersInserted = false; - while (!spacersInserted) { - i += barLength; - const newSpacer =
as HTMLDivElement; - const leftNeighbour = this.trackUnitViewBlock.children.item(i); - if (leftNeighbour) { - leftNeighbour.insertAdjacentElement("afterend", newSpacer); - } else { - break; - } - i++; - bars++; - if (bars === barCount) { - spacersInserted = true; - } - } - } - - private setupTrackUnits(): void { - this.rebuildTrackUnitViews(); - this.buildTrackUnitViewBlock(); - this.respaceTrackUnits(); - } - - build(): HTMLElement { - this.setupTrackUnits(); - if (!this.trackUnitViewBlock) { - throw new Error("Beat unit block setup failed!"); - } - return
-
- {this.trackUnitViewBlock} -
-
as HTMLElement; - } -} - -window.addEventListener("mouseup", () => { - TrackView.selectingUnits = false; - TrackView.deselectingUnits = false; -}); diff --git a/src/ui/TrackSettings/TrackSettings.css b/src/ui/TrackSettings/TrackSettings.css deleted file mode 100644 index 580d8e7..0000000 --- a/src/ui/TrackSettings/TrackSettings.css +++ /dev/null @@ -1,54 +0,0 @@ -.track-settings { - -} - -.track-settings-title-container { - -} - -.track-settings-title-container input { - min-width: 100%; - height: 2em; -} - -.track-settings-title-container > div { - width: 100%; - font-weight: bold; - padding: 0.5em; - transition: background-color 200ms; - cursor: pointer; -} - -.track-settings-title-container > div:hover { - background-color: var(--color-ui-neutral-dark-hover); -} - -.track-settings-lower { - height: 3.5em; - display: flex; - text-align: center; - align-items: center; - justify-content: space-between; - margin-bottom: 0.5em; -} -.track-settings-lower > * { - margin-right: 0.2em; -} - -.track-settings-lower:last-child { - margin-right: 0; -} - -.track-settings .loop-settings { - text-align: left; - flex: auto; -} - -.track-settings .loop-settings-option.hide { - display: none; -} - -.track-settings .loop-settings-option { - flex: auto; - padding-right: 1em; -} diff --git a/src/ui/TrackSettings/TrackSettings.vue b/src/ui/TrackSettings/TrackSettings.vue new file mode 100644 index 0000000..3537c39 --- /dev/null +++ b/src/ui/TrackSettings/TrackSettings.vue @@ -0,0 +1,92 @@ + + + + + diff --git a/src/ui/TrackSettings/TrackSettingsView.tsx b/src/ui/TrackSettings/TrackSettingsView.tsx deleted file mode 100644 index 11a1b87..0000000 --- a/src/ui/TrackSettings/TrackSettingsView.tsx +++ /dev/null @@ -1,116 +0,0 @@ -import "./TrackSettings.css"; -import Track, { TrackEvents } from "@/Track"; -import NumberInputView from "@/ui/Widgets/NumberInput/NumberInputView"; -import BoolBoxView from "@/ui/Widgets/BoolBox/BoolBoxView"; -import ActionButtonView from "@/ui/Widgets/ActionButton/ActionButtonView"; -import EditableTextFieldView from "@/ui/Widgets/EditableTextFIeld/EditableTextFieldView"; -import { h, ISubscriber, ISubscription, Rung, RungOptions } from "@djledda/ladder"; - -export type BeatSettingsViewUINodeOptions = RungOptions & { - track: Track, -}; - -const EventTypeSubscriptions = [ - TrackEvents.NewName, - TrackEvents.LoopLengthChanged, - TrackEvents.DisplayTypeChanged, -]; -type EventTypeSubscriptions = typeof EventTypeSubscriptions[number]; - -export default class TrackSettingsView extends Rung implements ISubscriber { - private track: Track; - private loopLengthInput!: NumberInputView; - private bakeButton!: ActionButtonView; - private loopCheckbox!: BoolBoxView; - private loopLengthSection!: HTMLDivElement; - private sub!: ISubscription; - private title!: EditableTextFieldView; - private editingTitle: boolean; - - constructor(options: BeatSettingsViewUINodeOptions) { - super(options); - this.editingTitle = false; - this.track = options.track; - this.setupBindings(); - } - - private setupBindings() { - this.sub = this.track.addSubscriber(this, EventTypeSubscriptions); - } - - setBeat(track: Track): void { - this.sub.unbind(); - this.track = track; - this.setupBindings(); - EventTypeSubscriptions.forEach(eventType => this.notify(null, eventType)); - } - - notify(publisher: unknown, event: EventTypeSubscriptions): void { - switch(event) { - case TrackEvents.NewName: - this.title.setText(this.track.getName()); - break; - case TrackEvents.LoopLengthChanged: - this.loopLengthInput.setValue(this.track.getLoopLength()); - break; - case TrackEvents.DisplayTypeChanged: - this.loopCheckbox.setValue(this.track.isLooping()); - this.bakeButton.setDisabled(!this.track.isLooping()); - if (this.track.isLooping()) { - this.loopLengthSection.classList.remove("hide"); - } else { - this.loopLengthSection.classList.add("hide"); - } - break; - } - } - - build(): Node { - this.title = new EditableTextFieldView({ - initialText: this.track.getName(), - setter: (newText: string) => this.track.setName(newText), - }); - this.bakeButton = new ActionButtonView({ - icon: "snowflake", - type: "secondary", - alt: "Bake Loops", - disabled: !this.track.isLooping(), - onClick: () => this.track.bakeLoops(), - }); - this.loopLengthInput = new NumberInputView({ - initialValue: this.track.getLoopLength(), - onDecrement: () => this.track.setLoopLength(this.track.getLoopLength() - 1), - onIncrement: () => this.track.setLoopLength(this.track.getLoopLength() + 1), - onNewInput: (input: number) => this.track.setLoopLength(input), - }); - this.loopCheckbox = new BoolBoxView({ - label: "Loop:", - value: this.track.isLooping(), - onInput: (isChecked: boolean) => this.track.setLooping(isChecked), - }); - this.loopLengthSection =
{this.loopLengthInput}
as HTMLDivElement; - if (this.track.isLooping()) { - this.loopLengthSection.classList.remove("hide"); - } else { - this.loopLengthSection.classList.add("hide"); - } - return
-
- {this.title} -
-
- {this.bakeButton} - {new ActionButtonView({ - icon: "trash", - type: "secondary", - alt: "Delete Track", - onClick: () => this.track.delete(), - })} -
- {this.loopCheckbox} -
- {this.loopLengthSection} -
-
; - } -} diff --git a/src/ui/TrackUnit/TrackUnit.css b/src/ui/TrackUnit/TrackUnit.css deleted file mode 100644 index 4ccc15c..0000000 --- a/src/ui/TrackUnit/TrackUnit.css +++ /dev/null @@ -1,49 +0,0 @@ -.track-unit { - width: 2em; - height: 2em; - margin-right: 4px; - background-color: #464646; - border-color: #464646; - border-width: 0.1em 0.1em 0.1em 0.1em; - border-style: solid; - display: inline-block; - transition: background-color 100ms, border-color 100ms; - cursor: pointer; -} - -.track-unit.highlightable:hover { - border-color: #5f5f5f; - background-color: #5f5f5f; - transition: none; -} - -.vertical-mode .track-unit { - margin-bottom: 4px; - display: block; -} - -.track-unit.on { - border-color: var(--color-ui-accent); - background-color: var(--color-ui-accent); - transition: none; -} - -.track-unit.on.highlightable:hover { - border-color: var(--color-ui-accent-hover); - background-color: var(--color-ui-accent-hover); -} - -.track-unit.on.Accent { - border-color: var(--color-ui-neutral-light); -} - -.track-unit.on.Ghost { - opacity: 60%; -} - -.track-unit .icon-view { - display: none; -} -.track-unit.on.icon-visible .icon-view { - display: block; -} diff --git a/src/ui/TrackUnit/TrackUnit.vue b/src/ui/TrackUnit/TrackUnit.vue new file mode 100644 index 0000000..f0e9414 --- /dev/null +++ b/src/ui/TrackUnit/TrackUnit.vue @@ -0,0 +1,140 @@ + + + + + diff --git a/src/ui/TrackUnit/TrackUnitView.tsx b/src/ui/TrackUnit/TrackUnitView.tsx deleted file mode 100644 index 827b280..0000000 --- a/src/ui/TrackUnit/TrackUnitView.tsx +++ /dev/null @@ -1,207 +0,0 @@ -import TrackUnit, { TrackUnitEvent, TrackUnitStickingType, TrackUnitType } from "@/TrackUnit"; -import "./TrackUnit.css"; -import { Capsule, h, IPublisher, ISubscriber, ISubscription, Publisher, Rung, RungOptions } from "@djledda/ladder"; -import IconView, { IconName } from "@/ui/Widgets/Icon/IconView"; - -export type TrackUnitUINodeOptions = RungOptions & { - trackUnit: TrackUnit, -}; - -const EventTypeSubscriptions = [ - TrackUnitEvent.On, - TrackUnitEvent.Off, - TrackUnitEvent.TypeChange, -]; -type EventTypeSubscriptions = typeof EventTypeSubscriptions[number]; - -export const StickingTypeIconMap = { - none: null, - lf: 'lf', - lh: 'lh', - rf: 'rf', - rh: 'rh', -} as const satisfies Readonly>; - -const TypeClasses = [ "Ghost", "Accent" ] as const; -export const TrackUnitTypeClassMap = { - "Normal": [], - "GhostNote": ["Ghost"], - "Accent": ["Accent"], - "GhostNoteAccent": ["Ghost", "Accent"], -} as const satisfies Readonly>>; - -export default class TrackUnitView extends Rung implements ISubscriber { - private trackUnit: TrackUnit; - private subscription: ISubscription | null = null; - private publisher: IPublisher = new Publisher(this); - private rotationTimeout: ReturnType | null = null; - private mouseDownListeners: ((ev: MouseEvent) => void)[] = []; - private hoverListeners: ((ev: MouseEvent) => void)[] = []; - private blockNextMouseUp = false; - private icon: IconView = new IconView({ iconName: 'list' }); - - constructor(options: TrackUnitUINodeOptions) { - super(options); - this.trackUnit = options.trackUnit; - this.setUnit(this.trackUnit); - } - - setUnit(trackUnit: TrackUnit | null): void { - if (trackUnit) { - this.trackUnit = trackUnit; - this.setupBindings(); - this.notify(this.publisher, trackUnit.isOn() ? TrackUnitEvent.On : TrackUnitEvent.Off); - this.notify(this.publisher, TrackUnitEvent.TypeChange); - } else { - this.subscription?.unbind(); - } - } - - private setupBindings() { - this.subscription?.unbind(); - this.subscription = this.trackUnit.addSubscriber(this, EventTypeSubscriptions); - this.hoverListeners.forEach(listener => this.render().removeEventListener("mouseover", listener)); - this.mouseDownListeners.forEach(listener => this.render().removeEventListener("mousedown", listener)); - this.redraw(); - this.hoverListeners.forEach(listener => this.render().addEventListener("mouseover", listener)); - this.mouseDownListeners.forEach(listener => this.render().addEventListener("mousedown", listener)); - this.render().addEventListener("mousedown", (ev) => this.handleMouseDown(ev)); - this.render().addEventListener("mouseout", (ev) => this.handleMouseOut(ev)); - this.render().addEventListener("mouseup", (ev) => this.handleMouseUp(ev)); - this.render().addEventListener("touchstart", (ev) => this.handleTouchStart(ev)); - this.render().addEventListener("touchend", (ev) => this.handleTouchEnd(ev)); - } - - private handleMouseDown(ev: MouseEvent): void { - if (ev.button === 1) { - this.trackUnit.rotateType(); - } - } - - private handleMouseOut(ev: MouseEvent): void { - if (this.rotationTimeout) { - clearTimeout(this.rotationTimeout); - this.rotationTimeout = null; - } - } - - private handleMouseUp(ev: MouseEvent): void { - if (!this.blockNextMouseUp) { - this.mouseDownListeners.forEach(listener => listener(ev)); - } - this.blockNextMouseUp = false; - } - - private handleTouchStart(ev: TouchEvent): void { - this.rotationTimeout = this.rotationTimeout || setTimeout(() => { - this.trackUnit.rotateType(); - this.rotationTimeout = null; - }, 400); - } - - private handleTouchEnd(ev: TouchEvent): void { - if (this.rotationTimeout) { - clearTimeout(this.rotationTimeout); - this.rotationTimeout = null; - } - } - - toggle(): void { - this.trackUnit.toggle(); - } - - setStickingType(type: TrackUnitStickingType): void { - if (this.trackUnit.isOn()) { - this.trackUnit.setStickingType(type); - } - } - - setType(type: TrackUnitType): void { - this.trackUnit.setType(type); - } - - turnOn(): void { - this.trackUnit.setOn(true); - } - - turnOff(): void { - this.trackUnit.setStickingType("none"); - this.trackUnit.setOn(false); - } - - notify(publisher: unknown, event: EventTypeSubscriptions): void { - switch (event) { - case TrackUnitEvent.On: - this.render().classList.add("on"); - break; - case TrackUnitEvent.Off: - this.render().classList.remove("on"); - break; - case TrackUnitEvent.TypeChange: - this.syncTrackUnitType(); - this.syncStickingType(this.trackUnit.getStickingType()); - } - } - - private syncStickingType(type: TrackUnitStickingType) { - if (StickingTypeIconMap[this.trackUnit.getStickingType()]) { - this.render().classList.add("icon-visible"); - } else { - this.render().classList.remove("icon-visible"); - } - const icon = StickingTypeIconMap[this.trackUnit.getStickingType()]; - if (icon) { - this.icon.setIcon(icon); - } - } - - private syncTrackUnitType() { - for (const className of TypeClasses) { - this.render().classList.remove(className); - } - for (const className of TrackUnitTypeClassMap[this.trackUnit.getType()]) { - this.render().classList.add(className); - } - } - - static getClasses(options: { on: boolean, stickingType: TrackUnitStickingType, type: TrackUnitType, highlightable?: boolean }) { - const classes = ["track-unit"]; - if (options.on) { - classes.push("on"); - } - if (StickingTypeIconMap[options.stickingType]) { - classes.push("icon-visible"); - } - if (options.type) { - classes.push(...TrackUnitTypeClassMap[options.type]); - } - if (options.highlightable) { - classes.push("highlightable"); - } - return classes; - } - - build() { - const classes = TrackUnitView.getClasses({ - on: this.trackUnit.isOn(), - stickingType: this.trackUnit.getStickingType(), - type: this.trackUnit.getType(), - highlightable: true, - }); - return ( -
false}> - {this.icon} -
- ) as HTMLDivElement; - } - - onHover(cb: () => void): void { - this.hoverListeners.push(cb); - this.render().addEventListener("mouseover", cb); - } - - onMouseDown(cb: (ev: MouseEvent) => void): void { - this.mouseDownListeners.push(cb); - this.render().addEventListener("mousedown", cb); - } -} diff --git a/src/ui/TrackUnit/trackUnit.ts b/src/ui/TrackUnit/trackUnit.ts new file mode 100644 index 0000000..285fa08 --- /dev/null +++ b/src/ui/TrackUnit/trackUnit.ts @@ -0,0 +1,36 @@ +import type { TrackUnitStickingType, TrackUnitType } from "@/Track"; +import type { IconName } from "@/ui/Widgets/Icon/icons"; + +export const TypeClasses = [ "Ghost", "Accent" ] as const; + +export const StickingTypeIconMap = { + none: null, + lf: 'lf', + lh: 'lh', + rf: 'rf', + rh: 'rh', +} as const satisfies Readonly>; + +export const TrackUnitTypeClassMap = { + "Normal": [], + "GhostNote": ["Ghost"], + "Accent": ["Accent"], + "GhostNoteAccent": ["Ghost", "Accent"], +} as const satisfies Readonly>>; + +export function getClasses(options: { on: boolean, stickingType: TrackUnitStickingType, type: TrackUnitType, highlightable?: boolean }) { + const classes = ["track-unit"]; + if (options.on) { + classes.push("on"); + } + if (StickingTypeIconMap[options.stickingType]) { + classes.push("icon-visible"); + } + if (options.type) { + classes.push(...TrackUnitTypeClassMap[options.type]); + } + if (options.highlightable) { + classes.push("highlightable"); + } + return classes; +} diff --git a/src/ui/Widgets/ActionButton/ActionButton.css b/src/ui/Widgets/ActionButton/ActionButton.css deleted file mode 100644 index a3f16a7..0000000 --- a/src/ui/Widgets/ActionButton/ActionButton.css +++ /dev/null @@ -1,37 +0,0 @@ -.action-button { - border-radius: 0.5em; - margin: 0.5em; - cursor: pointer; - border: none; -} - -.action-button.disabled { - cursor: default; - opacity: 50%; -} - -.action-button.action-button-primary { - background-color: var(--color-ui-accent); - color: var(--color-p-light); -} -.action-button.action-button-primary:hover { - background-color: var(--color-ui-accent-hover); - color: var(--color-p-light-hover); -} -.action-button.action-button-primary:active { - background-color: var(--color-ui-accent-active); - color: var(--color-p-light-active); -} - -.action-button.action-button-secondary { - background-color: var(--color-ui-neutral-dark); - color: var(--color-p-light); -} -.action-button.action-button-secondary:hover:not(.disabled) { - background-color: var(--color-ui-neutral-dark-hover); - color: var(--color-p-light-hover); -} -.action-button.action-button-secondary:active:not(.disabled) { - background-color: var(--color-ui-neutral-dark-active); - color: var(--color-p-light-active); -} diff --git a/src/ui/Widgets/ActionButton/ActionButton.vue b/src/ui/Widgets/ActionButton/ActionButton.vue new file mode 100644 index 0000000..c0a6c0e --- /dev/null +++ b/src/ui/Widgets/ActionButton/ActionButton.vue @@ -0,0 +1,78 @@ + + + + + + diff --git a/src/ui/Widgets/ActionButton/ActionButtonView.tsx b/src/ui/Widgets/ActionButton/ActionButtonView.tsx deleted file mode 100644 index 199742e..0000000 --- a/src/ui/Widgets/ActionButton/ActionButtonView.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import "./ActionButton.css"; -import IconView, { IconName } from "@/ui/Widgets/Icon/IconView"; -import { h, Rung, RungOptions } from "@djledda/ladder"; - -export type ActionButtonUINodeOptions = RungOptions & { - type?: "primary" | "secondary", - onClick?: (event: MouseEvent) => void, - alt?: string, - disabled?: boolean, -} & ({ - icon: IconName, - label?: never, -} | { - label: string, - icon?: never, -}); - -export default class ActionButtonView extends Rung { - private label: string | null = null; - private icon: IconName | null = null; - private buttonElement!: HTMLButtonElement; - private onClick: (event: MouseEvent) => void; - private type: "primary" | "secondary"; - private alt: string | null; - private disabled: boolean; - - constructor(options: ActionButtonUINodeOptions) { - super(options); - if (typeof options.icon !== "undefined") { - this.icon = options.icon; - } else if (typeof options.label !== "undefined") { - this.label = options.label; - } - this.disabled = options.disabled ?? false; - this.alt = options.alt ?? null; - this.type = options.type ?? "primary"; - this.onClick = options.onClick ?? (() => { /* dummy */ }); - } - - setDisabled(isDisabled: boolean): void { - this.disabled = isDisabled; - this.buttonElement.disabled = this.disabled; - if (isDisabled) { - this.buttonElement.classList.add("disabled"); - } else { - this.buttonElement.classList.remove("disabled"); - } - } - - protected build(): HTMLButtonElement { - this.buttonElement = ( - - ) as HTMLButtonElement; - if (this.alt) { - this.buttonElement.title = this.alt; - } - if (this.disabled) { - this.buttonElement.classList.add("disabled"); - } - return this.buttonElement; - } -} diff --git a/src/ui/Widgets/BoolBox/BoolBox.css b/src/ui/Widgets/BoolBox/BoolBox.css deleted file mode 100644 index 47ea3ed..0000000 --- a/src/ui/Widgets/BoolBox/BoolBox.css +++ /dev/null @@ -1,67 +0,0 @@ -.bool-box { - height: 1.5em; - position: relative; - white-space: nowrap; - line-height: 1.5em; - cursor: pointer; -} - -.bool-box-label { - position: relative; - display: inline-block; - margin-right: 0.5em; - margin-left: 0.5em; - top: -0.33em; - cursor: pointer; -} - -input.bool-box-checkbox[type="checkbox"] { - position: relative; - display: inline-block; - width: 3em; - height: 1.5em; - padding: 0; - margin: 0; - -webkit-appearance: none; - -moz-appearance: none; - appearance: none; - cursor: pointer; -} - -input.bool-box-checkbox[type="checkbox"]::before { - top: 0.3em; - left: 0.3em; - width: 2.3em; - height: 0.9em; - border-radius: 1em; - background-color: var(--color-ui-accent-active); - display: inline-block; - content: ""; - z-index: 0; - position: absolute; - transition: background-color 200ms; -} - -input.bool-box-checkbox[type="checkbox"]:checked::before { - background-color: var(--color-ui-accent); -} - -input.bool-box-checkbox[type="checkbox"]::after { - box-sizing: border-box; - position: absolute; - width: 1.35em; - height: 1.35em; - border-radius: 100%; - background-color: var(--color-ui-neutral-dark); - display: block; - content: ""; - top: 0.075em; - left: 0.025em; - z-index: 1; - transition: left 200ms, background-color 200ms; -} - -input.bool-box-checkbox[type="checkbox"]:checked::after { - left: 1.575em; - background-color: var(--color-ui-neutral-light); -} \ No newline at end of file diff --git a/src/ui/Widgets/BoolBox/BoolBox.vue b/src/ui/Widgets/BoolBox/BoolBox.vue new file mode 100644 index 0000000..97393b0 --- /dev/null +++ b/src/ui/Widgets/BoolBox/BoolBox.vue @@ -0,0 +1,97 @@ + + + + + + diff --git a/src/ui/Widgets/BoolBox/BoolBoxView.tsx b/src/ui/Widgets/BoolBox/BoolBoxView.tsx deleted file mode 100644 index 4a02e40..0000000 --- a/src/ui/Widgets/BoolBox/BoolBoxView.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import "./BoolBox.css"; -import { Capsule, h, Rung, RungOptions } from "@djledda/ladder"; - -export type BoolBoxUINodeOptions = RungOptions & { - label?: string, - value?: boolean, - onInput?: (isChecked: boolean) => void, -}; - -export default class BoolBoxView extends Rung { - private label: string | null; - private labelElement = Capsule.new(null); - private checkboxElement = Capsule.new(null); - private onInput: (isChecked: boolean) => void; - - constructor(options: BoolBoxUINodeOptions) { - super(options); - this.label = options.label ?? ""; - this.onInput = options.onInput ?? (() => { /* dummy */ }); - } - - setLabel(newLabel: string | null): void { - if (!this.labelElement.val) { - return; - } - if (newLabel !== null) { - this.label = newLabel; - this.labelElement.val.innerText = newLabel; - this.labelElement.val.classList.add("visible"); - } else { - this.label = newLabel; - this.labelElement.val.innerText = ""; - this.labelElement.val.classList.remove("visible"); - } - } - - setValue(isChecked: boolean): void { - if (this.checkboxElement.val) { - this.checkboxElement.val.checked = isChecked; - } - } - - build(): HTMLDivElement { - return
- - this.onInput((event.target as HTMLInputElement).checked)}/> -
as HTMLDivElement; - } -} \ No newline at end of file diff --git a/src/ui/Widgets/Dropdown/Dropdown.css b/src/ui/Widgets/Dropdown/Dropdown.css deleted file mode 100644 index e69de29..0000000 diff --git a/src/ui/Widgets/Dropdown/DropdownView.tsx b/src/ui/Widgets/Dropdown/DropdownView.tsx deleted file mode 100644 index aa48d0b..0000000 --- a/src/ui/Widgets/Dropdown/DropdownView.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import "./Dropdown.css"; -import { Capsule, h, ICapsule, Rung, RungOptions } from "@djledda/ladder"; - -export type DropdownViewOption = { - label: string, - value: string, -}; - -export type DropdownUINodeOptions = RungOptions & { - options: ICapsule | DropdownViewOption[], -}; - -export default class DropdownView extends Rung { - private options: ICapsule; - private select = Capsule.new(null); - - constructor(options: DropdownUINodeOptions) { - super(options); - this.options = Capsule.new(options.options); - this.options.watch((newVal) => this.updateOptionsFrom(newVal)); - } - - private updateOptionsFrom(newOptions: DropdownViewOption[]): void { - const select = this.select.val; - if (!select) { - return; - } - const children = new Array(...select.children) as HTMLOptionElement[]; - for (let i = 0; i < newOptions.length; i++) { - if (children[i]) { - children[i].label = newOptions[i].label; - children[i].value = newOptions[i].value; - } else { - children.push(