This commit is contained in:
2025-06-15 13:27:42 +02:00
parent a1d59d21a7
commit 50c9726444
6 changed files with 162 additions and 225 deletions

246
package-lock.json generated
View File

@@ -12,7 +12,7 @@
"@vitejs/plugin-vue": "^5.0.4", "@vitejs/plugin-vue": "^5.0.4",
"@vue/tsconfig": "^0.1.3", "@vue/tsconfig": "^0.1.3",
"sass": "^1.58.3", "sass": "^1.58.3",
"vue": "^3.4.21", "vue": "^3.5.16",
"vue-draggable-next": "^2.2.1", "vue-draggable-next": "^2.2.1",
"vuedraggable": "^4.1.0", "vuedraggable": "^4.1.0",
"zod": "^3.21.4" "zod": "^3.21.4"
@@ -291,17 +291,19 @@
} }
}, },
"node_modules/@babel/helper-string-parser": { "node_modules/@babel/helper-string-parser": {
"version": "7.25.9", "version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
"integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
"license": "MIT",
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/helper-validator-identifier": { "node_modules/@babel/helper-validator-identifier": {
"version": "7.25.9", "version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
"integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
"license": "MIT",
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
@@ -329,11 +331,12 @@
} }
}, },
"node_modules/@babel/parser": { "node_modules/@babel/parser": {
"version": "7.26.2", "version": "7.27.5",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.5.tgz",
"integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", "integrity": "sha512-OsQd175SxWkGlzbny8J3K8TnnDD0N3lrIUtB92xwyRpzaenGZhxDvxN/JgU00U3CDZNj9tPuDJ5H0WS4Nt3vKg==",
"license": "MIT",
"dependencies": { "dependencies": {
"@babel/types": "^7.26.0" "@babel/types": "^7.27.3"
}, },
"bin": { "bin": {
"parser": "bin/babel-parser.js" "parser": "bin/babel-parser.js"
@@ -492,12 +495,13 @@
} }
}, },
"node_modules/@babel/types": { "node_modules/@babel/types": {
"version": "7.26.0", "version": "7.27.6",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.6.tgz",
"integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", "integrity": "sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==",
"license": "MIT",
"dependencies": { "dependencies": {
"@babel/helper-string-parser": "^7.25.9", "@babel/helper-string-parser": "^7.27.1",
"@babel/helper-validator-identifier": "^7.25.9" "@babel/helper-validator-identifier": "^7.27.1"
}, },
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
@@ -1560,106 +1564,54 @@
"@babel/core": "^7.0.0-0" "@babel/core": "^7.0.0-0"
} }
}, },
"node_modules/@vue/babel-plugin-resolve-type/node_modules/@vue/compiler-core": {
"version": "3.5.13",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.13.tgz",
"integrity": "sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==",
"dev": true,
"dependencies": {
"@babel/parser": "^7.25.3",
"@vue/shared": "3.5.13",
"entities": "^4.5.0",
"estree-walker": "^2.0.2",
"source-map-js": "^1.2.0"
}
},
"node_modules/@vue/babel-plugin-resolve-type/node_modules/@vue/compiler-dom": {
"version": "3.5.13",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz",
"integrity": "sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==",
"dev": true,
"dependencies": {
"@vue/compiler-core": "3.5.13",
"@vue/shared": "3.5.13"
}
},
"node_modules/@vue/babel-plugin-resolve-type/node_modules/@vue/compiler-sfc": {
"version": "3.5.13",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz",
"integrity": "sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==",
"dev": true,
"dependencies": {
"@babel/parser": "^7.25.3",
"@vue/compiler-core": "3.5.13",
"@vue/compiler-dom": "3.5.13",
"@vue/compiler-ssr": "3.5.13",
"@vue/shared": "3.5.13",
"estree-walker": "^2.0.2",
"magic-string": "^0.30.11",
"postcss": "^8.4.48",
"source-map-js": "^1.2.0"
}
},
"node_modules/@vue/babel-plugin-resolve-type/node_modules/@vue/compiler-ssr": {
"version": "3.5.13",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz",
"integrity": "sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==",
"dev": true,
"dependencies": {
"@vue/compiler-dom": "3.5.13",
"@vue/shared": "3.5.13"
}
},
"node_modules/@vue/babel-plugin-resolve-type/node_modules/@vue/shared": {
"version": "3.5.13",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.13.tgz",
"integrity": "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==",
"dev": true
},
"node_modules/@vue/compiler-core": { "node_modules/@vue/compiler-core": {
"version": "3.4.27", "version": "3.5.16",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.27.tgz", "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.16.tgz",
"integrity": "sha512-E+RyqY24KnyDXsCuQrI+mlcdW3ALND6U7Gqa/+bVwbcpcR3BRRIckFoz7Qyd4TTlnugtwuI7YgjbvsLmxb+yvg==", "integrity": "sha512-AOQS2eaQOaaZQoL1u+2rCJIKDruNXVBZSiUD3chnUrsoX5ZTQMaCvXlWNIfxBJuU15r1o7+mpo5223KVtIhAgQ==",
"license": "MIT",
"dependencies": { "dependencies": {
"@babel/parser": "^7.24.4", "@babel/parser": "^7.27.2",
"@vue/shared": "3.4.27", "@vue/shared": "3.5.16",
"entities": "^4.5.0", "entities": "^4.5.0",
"estree-walker": "^2.0.2", "estree-walker": "^2.0.2",
"source-map-js": "^1.2.0" "source-map-js": "^1.2.1"
} }
}, },
"node_modules/@vue/compiler-dom": { "node_modules/@vue/compiler-dom": {
"version": "3.4.27", "version": "3.5.16",
"resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.27.tgz", "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.16.tgz",
"integrity": "sha512-kUTvochG/oVgE1w5ViSr3KUBh9X7CWirebA3bezTbB5ZKBQZwR2Mwj9uoSKRMFcz4gSMzzLXBPD6KpCLb9nvWw==", "integrity": "sha512-SSJIhBr/teipXiXjmWOVWLnxjNGo65Oj/8wTEQz0nqwQeP75jWZ0n4sF24Zxoht1cuJoWopwj0J0exYwCJ0dCQ==",
"license": "MIT",
"dependencies": { "dependencies": {
"@vue/compiler-core": "3.4.27", "@vue/compiler-core": "3.5.16",
"@vue/shared": "3.4.27" "@vue/shared": "3.5.16"
} }
}, },
"node_modules/@vue/compiler-sfc": { "node_modules/@vue/compiler-sfc": {
"version": "3.4.27", "version": "3.5.16",
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.27.tgz", "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.16.tgz",
"integrity": "sha512-nDwntUEADssW8e0rrmE0+OrONwmRlegDA1pD6QhVeXxjIytV03yDqTey9SBDiALsvAd5U4ZrEKbMyVXhX6mCGA==", "integrity": "sha512-rQR6VSFNpiinDy/DVUE0vHoIDUF++6p910cgcZoaAUm3POxgNOOdS/xgoll3rNdKYTYPnnbARDCZOyZ+QSe6Pw==",
"license": "MIT",
"dependencies": { "dependencies": {
"@babel/parser": "^7.24.4", "@babel/parser": "^7.27.2",
"@vue/compiler-core": "3.4.27", "@vue/compiler-core": "3.5.16",
"@vue/compiler-dom": "3.4.27", "@vue/compiler-dom": "3.5.16",
"@vue/compiler-ssr": "3.4.27", "@vue/compiler-ssr": "3.5.16",
"@vue/shared": "3.4.27", "@vue/shared": "3.5.16",
"estree-walker": "^2.0.2", "estree-walker": "^2.0.2",
"magic-string": "^0.30.10", "magic-string": "^0.30.17",
"postcss": "^8.4.38", "postcss": "^8.5.3",
"source-map-js": "^1.2.0" "source-map-js": "^1.2.1"
} }
}, },
"node_modules/@vue/compiler-ssr": { "node_modules/@vue/compiler-ssr": {
"version": "3.4.27", "version": "3.5.16",
"resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.27.tgz", "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.16.tgz",
"integrity": "sha512-CVRzSJIltzMG5FcidsW0jKNQnNRYC8bT21VegyMMtHmhW3UOI7knmUehzswXLrExDLE6lQCZdrhD4ogI7c+vuw==", "integrity": "sha512-d2V7kfxbdsjrDSGlJE7my1ZzCXViEcqN6w14DOsDrUCHEA6vbnVCpRFfrc4ryCP/lCKzX2eS1YtnLE/BuC9f/A==",
"license": "MIT",
"dependencies": { "dependencies": {
"@vue/compiler-dom": "3.4.27", "@vue/compiler-dom": "3.5.16",
"@vue/shared": "3.4.27" "@vue/shared": "3.5.16"
} }
}, },
"node_modules/@vue/devtools-core": { "node_modules/@vue/devtools-core": {
@@ -1722,48 +1674,54 @@
} }
}, },
"node_modules/@vue/reactivity": { "node_modules/@vue/reactivity": {
"version": "3.4.27", "version": "3.5.16",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.27.tgz", "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.16.tgz",
"integrity": "sha512-kK0g4NknW6JX2yySLpsm2jlunZJl2/RJGZ0H9ddHdfBVHcNzxmQ0sS0b09ipmBoQpY8JM2KmUw+a6sO8Zo+zIA==", "integrity": "sha512-FG5Q5ee/kxhIm1p2bykPpPwqiUBV3kFySsHEQha5BJvjXdZTUfmya7wP7zC39dFuZAcf/PD5S4Lni55vGLMhvA==",
"license": "MIT",
"dependencies": { "dependencies": {
"@vue/shared": "3.4.27" "@vue/shared": "3.5.16"
} }
}, },
"node_modules/@vue/runtime-core": { "node_modules/@vue/runtime-core": {
"version": "3.4.27", "version": "3.5.16",
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.27.tgz", "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.16.tgz",
"integrity": "sha512-7aYA9GEbOOdviqVvcuweTLe5Za4qBZkUY7SvET6vE8kyypxVgaT1ixHLg4urtOlrApdgcdgHoTZCUuTGap/5WA==", "integrity": "sha512-bw5Ykq6+JFHYxrQa7Tjr+VSzw7Dj4ldR/udyBZbq73fCdJmyy5MPIFR9IX/M5Qs+TtTjuyUTCnmK3lWWwpAcFQ==",
"license": "MIT",
"dependencies": { "dependencies": {
"@vue/reactivity": "3.4.27", "@vue/reactivity": "3.5.16",
"@vue/shared": "3.4.27" "@vue/shared": "3.5.16"
} }
}, },
"node_modules/@vue/runtime-dom": { "node_modules/@vue/runtime-dom": {
"version": "3.4.27", "version": "3.5.16",
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.27.tgz", "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.16.tgz",
"integrity": "sha512-ScOmP70/3NPM+TW9hvVAz6VWWtZJqkbdf7w6ySsws+EsqtHvkhxaWLecrTorFxsawelM5Ys9FnDEMt6BPBDS0Q==", "integrity": "sha512-T1qqYJsG2xMGhImRUV9y/RseB9d0eCYZQ4CWca9ztCuiPj/XWNNN+lkNBuzVbia5z4/cgxdL28NoQCvC0Xcfww==",
"license": "MIT",
"dependencies": { "dependencies": {
"@vue/runtime-core": "3.4.27", "@vue/reactivity": "3.5.16",
"@vue/shared": "3.4.27", "@vue/runtime-core": "3.5.16",
"@vue/shared": "3.5.16",
"csstype": "^3.1.3" "csstype": "^3.1.3"
} }
}, },
"node_modules/@vue/server-renderer": { "node_modules/@vue/server-renderer": {
"version": "3.4.27", "version": "3.5.16",
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.27.tgz", "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.16.tgz",
"integrity": "sha512-dlAMEuvmeA3rJsOMJ2J1kXU7o7pOxgsNHVr9K8hB3ImIkSuBrIdy0vF66h8gf8Tuinf1TK3mPAz2+2sqyf3KzA==", "integrity": "sha512-BrX0qLiv/WugguGsnQUJiYOE0Fe5mZTwi6b7X/ybGB0vfrPH9z0gD/Y6WOR1sGCgX4gc25L1RYS5eYQKDMoNIg==",
"license": "MIT",
"dependencies": { "dependencies": {
"@vue/compiler-ssr": "3.4.27", "@vue/compiler-ssr": "3.5.16",
"@vue/shared": "3.4.27" "@vue/shared": "3.5.16"
}, },
"peerDependencies": { "peerDependencies": {
"vue": "3.4.27" "vue": "3.5.16"
} }
}, },
"node_modules/@vue/shared": { "node_modules/@vue/shared": {
"version": "3.4.27", "version": "3.5.16",
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.27.tgz", "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.16.tgz",
"integrity": "sha512-DL3NmY2OFlqmYYrzp39yi3LDkKxa5vZVwxWdQ3rG0ekuWscHraeIbnI8t+aZK7qhYqEqWKTUdijadunb9pnrgA==" "integrity": "sha512-c/0fWy3Jw6Z8L9FmTyYfkpM5zklnqqa9+a6dz3DvONRKW2NEbh46BP0FHuLFSWi2TnQEtp91Z6zOWNrU6QiyPg==",
"license": "MIT"
}, },
"node_modules/@vue/tsconfig": { "node_modules/@vue/tsconfig": {
"version": "0.1.3", "version": "0.1.3",
@@ -2151,7 +2109,8 @@
"node_modules/csstype": { "node_modules/csstype": {
"version": "3.1.3", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"license": "MIT"
}, },
"node_modules/debug": { "node_modules/debug": {
"version": "4.3.7", "version": "4.3.7",
@@ -2250,6 +2209,7 @@
"version": "4.5.0", "version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
"license": "BSD-2-Clause",
"engines": { "engines": {
"node": ">=0.12" "node": ">=0.12"
}, },
@@ -3204,9 +3164,10 @@
} }
}, },
"node_modules/magic-string": { "node_modules/magic-string": {
"version": "0.30.14", "version": "0.30.17",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.14.tgz", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz",
"integrity": "sha512-5c99P1WKTed11ZC0HMJOj6CDIue6F8ySu+bJL+85q1zBEIY8IklrJ1eiKC2NDRh3Ct3FcvmJPyQHb9erXMTJNw==", "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==",
"license": "MIT",
"dependencies": { "dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0" "@jridgewell/sourcemap-codec": "^1.5.0"
} }
@@ -3267,15 +3228,16 @@
"dev": true "dev": true
}, },
"node_modules/nanoid": { "node_modules/nanoid": {
"version": "3.3.7", "version": "3.3.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
"funding": [ "funding": [
{ {
"type": "github", "type": "github",
"url": "https://github.com/sponsors/ai" "url": "https://github.com/sponsors/ai"
} }
], ],
"license": "MIT",
"bin": { "bin": {
"nanoid": "bin/nanoid.cjs" "nanoid": "bin/nanoid.cjs"
}, },
@@ -3512,9 +3474,9 @@
} }
}, },
"node_modules/postcss": { "node_modules/postcss": {
"version": "8.4.49", "version": "8.5.5",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.5.tgz",
"integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", "integrity": "sha512-d/jtm+rdNT8tpXuHY5MMtcbJFBkhXE6593XVR9UoGCH8jSFGci7jGvMGH5RYd5PBJW+00NZQt6gf7CbagJCrhg==",
"funding": [ "funding": [
{ {
"type": "opencollective", "type": "opencollective",
@@ -3529,8 +3491,9 @@
"url": "https://github.com/sponsors/ai" "url": "https://github.com/sponsors/ai"
} }
], ],
"license": "MIT",
"dependencies": { "dependencies": {
"nanoid": "^3.3.7", "nanoid": "^3.3.11",
"picocolors": "^1.1.1", "picocolors": "^1.1.1",
"source-map-js": "^1.2.1" "source-map-js": "^1.2.1"
}, },
@@ -4232,15 +4195,16 @@
} }
}, },
"node_modules/vue": { "node_modules/vue": {
"version": "3.4.27", "version": "3.5.16",
"resolved": "https://registry.npmjs.org/vue/-/vue-3.4.27.tgz", "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.16.tgz",
"integrity": "sha512-8s/56uK6r01r1icG/aEOHqyMVxd1bkYcSe9j8HcKtr/xTOFWvnzIVTehNW+5Yt89f+DLBe4A569pnZLS5HzAMA==", "integrity": "sha512-rjOV2ecxMd5SiAmof2xzh2WxntRcigkX/He4YFJ6WdRvVUrbt6DxC1Iujh10XLl8xCDRDtGKMeO3D+pRQ1PP9w==",
"license": "MIT",
"dependencies": { "dependencies": {
"@vue/compiler-dom": "3.4.27", "@vue/compiler-dom": "3.5.16",
"@vue/compiler-sfc": "3.4.27", "@vue/compiler-sfc": "3.5.16",
"@vue/runtime-dom": "3.4.27", "@vue/runtime-dom": "3.5.16",
"@vue/server-renderer": "3.4.27", "@vue/server-renderer": "3.5.16",
"@vue/shared": "3.4.27" "@vue/shared": "3.5.16"
}, },
"peerDependencies": { "peerDependencies": {
"typescript": "*" "typescript": "*"

View File

@@ -19,7 +19,7 @@
"@vitejs/plugin-vue": "^5.0.4", "@vitejs/plugin-vue": "^5.0.4",
"@vue/tsconfig": "^0.1.3", "@vue/tsconfig": "^0.1.3",
"sass": "^1.58.3", "sass": "^1.58.3",
"vue": "^3.4.21", "vue": "^3.5.16",
"vue-draggable-next": "^2.2.1", "vue-draggable-next": "^2.2.1",
"vuedraggable": "^4.1.0", "vuedraggable": "^4.1.0",
"zod": "^3.21.4" "zod": "^3.21.4"

View File

@@ -34,7 +34,7 @@ const TrackSerialSchema = z.object({
}); });
export type TrackSerial = z.infer<typeof TrackSerialSchema>; export type TrackSerial = z.infer<typeof TrackSerialSchema>;
export const TrackUnitTypeList = [ "Normal", "GhostNote", "Accent", "GhostNoteAccent" ] as const; export const TrackUnitTypeList = [ "Normal", "GhostNote", "Accent" ] as const;
export type TrackUnitType = typeof TrackUnitTypeList[number]; export type TrackUnitType = typeof TrackUnitTypeList[number];
export const TrackUnitStickingTypeList = [ "none", "lh", "rh", "lf", "rf" ] as const; export const TrackUnitStickingTypeList = [ "none", "lh", "rh", "lf", "rf" ] as const;

View File

@@ -45,12 +45,6 @@
@click="sidebarActive = !sidebarActive"> @click="sidebarActive = !sidebarActive">
<icon icon-name="list" color="var(--color-ui-neutral-dark)" /> <icon icon-name="list" color="var(--color-ui-neutral-dark)" />
</div> </div>
<div
class="quick-access-button"
title="Change orientation"
@click="toggleOrientation">
<icon icon-name="arrowClockwise" color="var(--color-ui-neutral-dark)" />
</div>
<div <div
class="quick-access-button" class="quick-access-button"
title="Reset all" title="Reset all"
@@ -232,14 +226,6 @@
onBeforeUnmount(() => { onBeforeUnmount(() => {
window.removeEventListener('mouseup', windowMouseUp); window.removeEventListener('mouseup', windowMouseUp);
}); });
function toggleOrientation(): void {
if (currentOrientation.value === "vertical") {
currentOrientation.value = "horizontal";
} else {
currentOrientation.value = "vertical";
}
}
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">

View File

@@ -42,12 +42,30 @@
let blockNextMouseUp = false; let blockNextMouseUp = false;
let mouseHeld = false; let mouseHeld = false;
let movement = 0; let movement = 0;
let maybeSelecting = false;
function handleTouchStart(ev: TouchEvent): void {
rotationTimeout ??= setTimeout(() => {
emit('rotateType');
rotationTimeout = null;
blockNextMouseUp = true;
}, 400);
}
function handleTouchEnd(ev: TouchEvent): void {
if (rotationTimeout) {
clearTimeout(rotationTimeout);
rotationTimeout = null;
}
}
function handleMouseDown(ev: MouseEvent): void { function handleMouseDown(ev: MouseEvent): void {
blockNextMouseUp = false; blockNextMouseUp = false;
maybeSelecting = false;
if (ev.button === 0) { if (ev.button === 0) {
handleTouchStart();
unitMouseStart.value = props.id; unitMouseStart.value = props.id;
selectingUnits.value = true; maybeSelecting = true;
} else if (ev.button === 2) { } else if (ev.button === 2) {
unitMouseStart.value = props.id; unitMouseStart.value = props.id;
deselectingUnits.value = true; deselectingUnits.value = true;
@@ -57,6 +75,7 @@
} }
function handleMouseUp(ev: MouseEvent): void { function handleMouseUp(ev: MouseEvent): void {
handleTouchEnd();
if (!blockNextMouseUp && unitMouseStart.value === props.id) { if (!blockNextMouseUp && unitMouseStart.value === props.id) {
if (ev.button === 0) { if (ev.button === 0) {
emit('toggle'); emit('toggle');
@@ -67,6 +86,9 @@
} }
function handleMouseMove(ev: MouseEvent): void { function handleMouseMove(ev: MouseEvent): void {
if (maybeSelecting === true) {
selectingUnits.value = true;
}
if (selectingUnits.value || deselectingUnits.value) { if (selectingUnits.value || deselectingUnits.value) {
movement += ev.movementX**2 + ev.movementY**2; movement += ev.movementX**2 + ev.movementY**2;
} }
@@ -92,19 +114,6 @@
} }
} }
function handleTouchStart(ev: TouchEvent): void {
rotationTimeout ??= setTimeout(() => {
emit('rotateType');
rotationTimeout = null;
}, 400);
}
function handleTouchEnd(ev: TouchEvent): void {
if (rotationTimeout) {
clearTimeout(rotationTimeout);
rotationTimeout = null;
}
}
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">

View File

@@ -1,100 +1,78 @@
<template> <template>
<component <component
v-if="!editing"
ref="textField"
:is="nodeType" :is="nodeType"
class="static editable-text-field" class="static editable-text-field"
@click="onClick">
{{ model }}
</component>
<input
v-else
class="editable-text-field"
ref="inputField" ref="inputField"
@keydown.enter.prevent="onEnter"
@input="onInput"
@blur="onBlur" @blur="onBlur"
@keyup="onKeyUp" @keyup="onKeyUp"
@click="onClick"> v-model="model"
{{ modelValue }} @keydown.enter.prevent="onEnter"
</component> type="text" />
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue'; import { ref, nextTick, watch } from 'vue';
const props = withDefaults(defineProps<{ const props = withDefaults(defineProps<{
nodeType?: string, nodeType?: string,
modelValue: string,
noEmpty?: boolean, noEmpty?: boolean,
}>(), { }>(), {
nodeType: 'div', nodeType: 'div',
noEmpty: true, noEmpty: true,
}); });
const emit = defineEmits<{ const editing = ref(false);
(e: 'update:modelValue', value: string): true,
}>(); const model = defineModel<string>({ default: '' });
let lastNonEmptyInput = props.modelValue ?? "";
const inputField = ref<HTMLElement | null>(null); const inputField = ref<HTMLElement | null>(null);
const textField = ref<HTMLElement | null>(null);
function onClick() { async function onClick() {
editing.value = true;
await nextTick();
if (inputField.value) { if (inputField.value) {
inputField.value.contentEditable = "true";
inputField.value.focus(); inputField.value.focus();
const selection = window.getSelection(); inputField.value.select();
const firstChild = inputField.value.firstChild;
if (selection && firstChild) {
const range = document.createRange();
range.setStart(firstChild, 0);
range.setEnd(firstChild, inputField.value.textContent?.length ?? 1);
selection.removeAllRanges();
selection.addRange(range);
}
} }
} }
function onInput(event: Event) { const width = ref('30px');
const input = (event.target as HTMLElement).textContent ?? "";
const inputToSet = props.noEmpty && input === "" ? lastNonEmptyInput : input; watch(editing, (newEditing) => {
emit('update:modelValue', inputToSet); if (!newEditing && textField.value) {
width.value = `${ textField.value.getBoundingClientRect().width }px`;
} }
}, { flush: 'pre' });
function onBlur(event: Event) { function onBlur(event: Event) {
if ((event.target as HTMLElement).textContent === "") { editing.value = false;
emit('update:modelValue', lastNonEmptyInput);
}
if (inputField.value) {
inputField.value.contentEditable = "false";
window.getSelection()?.removeAllRanges();
inputField.value.textContent = props.modelValue;
}
}
function onKeyUp(event: KeyboardEvent) {
if (event.key === "Enter") {
(event.target as HTMLElement).blur();
}
} }
function onEnter(e: KeyboardEvent) { function onEnter(e: KeyboardEvent) {
onBlur(e); editing.value = false;
} }
</script> </script>
<style scoped lang="scss"> <style scoped>
.editable-text-field { .editable-text-field {
padding: 0.2em; padding: 0.2em;
} }
input.input { input {
height: 100px; width: v-bind(width);
color: black;
}
.vertical-mode {
input.input {
height: 100px;
color: black;
}
} }
.static { .static {
transition: background-color 200ms; transition: background-color 200ms;
width: fit-content;
cursor: pointer; cursor: pointer;
&:hover { &:hover {