diff --git a/package.json b/package.json index d80d240..95e3a4a 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,9 @@ "@commitlint/cli": "catalog:ci", "@commitlint/config-conventional": "catalog:ci", "@favware/cliff-jumper": "catalog:ci", + "@iconify-json/clarity": "catalog:icons", "@iconify-json/ic": "catalog:icons", + "@iconify-json/icomoon-free": "^1.2.1", "@iconify-json/material-icon-theme": "catalog:icons", "@iconify-json/solar": "catalog:icons", "@inlang/paraglide-js": "catalog:i18n", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f661cd4..f7edf53 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -65,7 +65,7 @@ catalogs: version: 1.3.14 svelte: specifier: ^5.55.9 - version: 5.55.9 + version: 5.55.10 svelte-check: specifier: ^4.4.8 version: 4.4.8 @@ -111,6 +111,9 @@ catalogs: specifier: ^2.18.1 version: 2.18.1 icons: + '@iconify-json/clarity': + specifier: ^1.2.4 + version: 1.2.4 '@iconify-json/ic': specifier: ^1.2.4 version: 1.2.4 @@ -122,7 +125,7 @@ catalogs: version: 1.2.5 '@lucide/svelte': specifier: ^1.16.0 - version: 1.16.0 + version: 1.17.0 libs-back: dotenv: specifier: ^17.4.2 @@ -130,7 +133,7 @@ catalogs: libs-front: '@internationalized/date': specifier: ^3.12.1 - version: 3.12.1 + version: 3.12.2 '@tanstack/svelte-query': specifier: ^6.1.33 version: 6.1.33 @@ -164,7 +167,7 @@ catalogs: version: 10.4.0 eslint-plugin-svelte: specifier: ^3.17.1 - version: 3.17.1 + version: 3.18.0 globals: specifier: ^17.6.0 version: 17.6.0 @@ -213,9 +216,15 @@ importers: '@favware/cliff-jumper': specifier: catalog:ci version: 6.1.0 + '@iconify-json/clarity': + specifier: catalog:icons + version: 1.2.4 '@iconify-json/ic': specifier: catalog:icons version: 1.2.4 + '@iconify-json/icomoon-free': + specifier: ^1.2.1 + version: 1.2.1 '@iconify-json/material-icon-theme': specifier: catalog:icons version: 1.2.66 @@ -227,10 +236,10 @@ importers: version: 2.18.1(typescript@6.0.3) '@internationalized/date': specifier: catalog:libs-front - version: 3.12.1 + version: 3.12.2 '@lucide/svelte': specifier: catalog:icons - version: 1.16.0(svelte@5.55.9(@typescript-eslint/types@8.60.0)) + version: 1.17.0(svelte@5.55.10(@typescript-eslint/types@8.60.0)) '@nanoforge-dev/actions': specifier: catalog:ci version: 2.0.0 @@ -248,16 +257,16 @@ importers: version: 1.60.0 '@sveltejs/kit': specifier: catalog:core - version: 2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.9(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)) + version: 2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.10(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)) '@sveltejs/vite-plugin-svelte': specifier: catalog:core - version: 7.1.2(svelte@5.55.9(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)) + version: 7.1.2(svelte@5.55.10(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)) '@tanstack/svelte-query': specifier: catalog:libs-front - version: 6.1.33(svelte@5.55.9(@typescript-eslint/types@8.60.0)) + version: 6.1.33(svelte@5.55.10(@typescript-eslint/types@8.60.0)) '@trivago/prettier-plugin-sort-imports': specifier: catalog:lint - version: 6.0.2(prettier-plugin-svelte@4.0.1(prettier@3.8.3)(svelte@5.55.9(@typescript-eslint/types@8.60.0)))(prettier@3.8.3)(svelte@5.55.9(@typescript-eslint/types@8.60.0)) + version: 6.0.2(prettier-plugin-svelte@4.0.1(prettier@3.8.3)(svelte@5.55.10(@typescript-eslint/types@8.60.0)))(prettier@3.8.3)(svelte@5.55.10(@typescript-eslint/types@8.60.0)) '@tsconfig/svelte': specifier: catalog:build version: 5.0.8 @@ -284,7 +293,7 @@ importers: version: 4.1.7(@vitest/browser@4.1.7)(vitest@4.1.7) bits-ui: specifier: catalog:components - version: 2.18.1(@internationalized/date@3.12.1)(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.9(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0)) + version: 2.18.1(@internationalized/date@3.12.2)(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.10(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0)) bun: specifier: catalog:core version: 1.3.14 @@ -299,16 +308,16 @@ importers: version: 10.4.0(jiti@2.7.0) eslint-plugin-svelte: specifier: catalog:lint - version: 3.17.1(eslint@10.4.0(jiti@2.7.0))(svelte@5.55.9(@typescript-eslint/types@8.60.0)) + version: 3.18.0(eslint@10.4.0(jiti@2.7.0))(svelte@5.55.10(@typescript-eslint/types@8.60.0)) flowbite: specifier: catalog:components version: 4.0.2 flowbite-svelte: specifier: catalog:components - version: 1.33.1(svelte@5.55.9(@typescript-eslint/types@8.60.0))(tailwindcss@4.3.0) + version: 1.33.1(svelte@5.55.10(@typescript-eslint/types@8.60.0))(tailwindcss@4.3.0) formsnap: specifier: catalog:libs-front - version: 2.0.1(svelte@5.55.9(@typescript-eslint/types@8.60.0))(sveltekit-superforms@2.30.1(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.9(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(@types/json-schema@7.0.15)(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@6.0.3)) + version: 2.0.1(svelte@5.55.10(@typescript-eslint/types@8.60.0))(sveltekit-superforms@2.30.1(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.10(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(@types/json-schema@7.0.15)(svelte@5.55.10(@typescript-eslint/types@8.60.0))(typescript@6.0.3)) globals: specifier: catalog:lint version: 17.6.0 @@ -320,7 +329,7 @@ importers: version: 17.0.5 mode-watcher: specifier: catalog:libs-front - version: 1.1.0(svelte@5.55.9(@typescript-eslint/types@8.60.0)) + version: 1.1.0(svelte@5.55.10(@typescript-eslint/types@8.60.0)) monaco-editor: specifier: catalog:components version: 0.55.1 @@ -332,25 +341,25 @@ importers: version: 3.8.3 prettier-plugin-svelte: specifier: catalog:lint - version: 4.0.1(prettier@3.8.3)(svelte@5.55.9(@typescript-eslint/types@8.60.0)) + version: 4.0.1(prettier@3.8.3)(svelte@5.55.10(@typescript-eslint/types@8.60.0)) svelte: specifier: catalog:core - version: 5.55.9(@typescript-eslint/types@8.60.0) + version: 5.55.10(@typescript-eslint/types@8.60.0) svelte-adapter-bun: specifier: catalog:build - version: 1.0.1(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.9(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(typescript@6.0.3) + version: 1.0.1(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.10(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(typescript@6.0.3) svelte-check: specifier: catalog:core - version: 4.4.8(picomatch@4.0.4)(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@6.0.3) + version: 4.4.8(picomatch@4.0.4)(svelte@5.55.10(@typescript-eslint/types@8.60.0))(typescript@6.0.3) svelte-kit-sessions: specifier: catalog:core - version: 0.4.0(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.9(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0)) + version: 0.4.0(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.10(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0)) svelte-sonner: specifier: catalog:libs-front - version: 1.1.1(svelte@5.55.9(@typescript-eslint/types@8.60.0)) + version: 1.1.1(svelte@5.55.10(@typescript-eslint/types@8.60.0)) sveltekit-superforms: specifier: catalog:libs-front - version: 2.30.1(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.9(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(@types/json-schema@7.0.15)(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@6.0.3) + version: 2.30.1(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.10(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(@types/json-schema@7.0.15)(svelte@5.55.10(@typescript-eslint/types@8.60.0))(typescript@6.0.3) tailwind-merge: specifier: catalog:css version: 3.6.0 @@ -377,7 +386,7 @@ importers: version: 4.1.7(@types/node@25.9.1)(@vitest/browser-playwright@4.1.7)(@vitest/coverage-v8@4.1.7)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)) vitest-browser-svelte: specifier: catalog:test - version: 2.1.1(svelte@5.55.9(@typescript-eslint/types@8.60.0))(vitest@4.1.7) + version: 2.1.1(svelte@5.55.10(@typescript-eslint/types@8.60.0))(vitest@4.1.7) zod: specifier: catalog:libs-front version: 4.4.3 @@ -646,9 +655,15 @@ packages: resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} + '@iconify-json/clarity@1.2.4': + resolution: {integrity: sha512-9hQ405dgvK2b2BWQdAIb/+ayH02k5VE4lKw2456wpjtq+57shHXE4Kk8bFa7RwchQHFuTtJBItVhlU4kjejxDw==} + '@iconify-json/ic@1.2.4': resolution: {integrity: sha512-pzPMmrZrBQuwT7nmtrYdkttun8KalRGgZPIL1Ny9KpF2zjRGIUPN+npTfuD3lrgO/OnSwAoJWuekQwBpt/Cqrw==} + '@iconify-json/icomoon-free@1.2.1': + resolution: {integrity: sha512-Me5L0/vH/LlhVr5R85TFah0LcJD7an6mv+5dagvXY/YnXQsOx3eB7GUioXheSoB8tObhvCuZFbvujMYKPKNWfw==} + '@iconify-json/material-icon-theme@1.2.66': resolution: {integrity: sha512-TxWgH1twATqzvdMOafXf3V7NtgdLGkg77ySoEUo0uKv4cmzsy/8fHUZWNn6t9s7ZAzAjxf41ZIDdWIwxIsMrbQ==} @@ -677,8 +692,8 @@ packages: resolution: {integrity: sha512-E/SxcSji8WIt4DqQG9APlOs6tVtJxrrOUS3dE4ho3pWRCLLIY0PIVzgNwSukuFT+m8LuJDFwpRY5VY3ryzyGWQ==} engines: {node: '>=20.0.0'} - '@internationalized/date@3.12.1': - resolution: {integrity: sha512-6IedsVWXyq4P9Tj+TxuU8WGWM70hYLl12nbYU8jkikVpa6WXapFazPUcHUMDMoWftIDE2ILDkFFte6W2nFCkRQ==} + '@internationalized/date@3.12.2': + resolution: {integrity: sha512-FY1Y+H64NDs+HAF6omlnWxm3mEpfgaCSWtL5l551ZZfImA+kGjPFgrnJrGjH6lfmLL0g8Z/mBu1R3kufeCp6Jw==} '@isaacs/ttlcache@1.4.1': resolution: {integrity: sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==} @@ -707,8 +722,8 @@ packages: '@lix-js/server-protocol-schema@0.1.1': resolution: {integrity: sha512-jBeALB6prAbtr5q4vTuxnRZZv1M2rKe8iNqRQhFJ4Tv7150unEa0vKyz0hs8Gl3fUGsWaNJBh3J8++fpbrpRBQ==} - '@lucide/svelte@1.16.0': - resolution: {integrity: sha512-AvvPJnaWxeiNkAljI5MsSEc84yHPLMaWQIAJOcbX7k9au/f9ITS7cxTTQiautDiOFKVOXiYdZ+d6mtl88J+Kbg==} + '@lucide/svelte@1.17.0': + resolution: {integrity: sha512-q06YCFBN5CO8cd1ADmLCxWRVMVb7xxvHzqC0lvNoxGa+FLW6Cd1Y1AOxgbQk4Iwe68vkAMCRveNHint4WoaVKg==} peerDependencies: svelte: ^5 @@ -779,8 +794,8 @@ packages: resolution: {integrity: sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw==} engines: {node: '>= 20'} - '@octokit/request@10.0.9': - resolution: {integrity: sha512-o8Bi3f608eyM+7BmBiUWxFsdjLb3/ym1cQek5LZOv9KkZcxRrHCPhhRzm6xjO6HVZ85ItD6+sTsjxo821SVa/A==} + '@octokit/request@10.0.10': + resolution: {integrity: sha512-KxNC2pTqqhszMNrf12ZRd4PonRgyJdsM4F/jySiddQK+DsRcfBtUvqn8t7UsyZhnRJHvX46OohDt5N3VqIWC2w==} engines: {node: '>= 20'} '@octokit/types@16.0.0': @@ -999,6 +1014,9 @@ packages: '@oxc-project/types@0.132.0': resolution: {integrity: sha512-FESMOxil5Se014ui/Eq8fT5uHJo6nIRwH0PfJrZJXs6Gek3ZVFOrpUv3YIZT20m+extU98Hg1Ym72U58rlsxUQ==} + '@oxc-project/types@0.133.0': + resolution: {integrity: sha512-KzkdCd6Uxqnf6l3HOw1xfatAlUURA0g14cvBYFyJ5SaNOQbOUvBr9PKArcPcrNIeRsBdgcUzOGrhKveVpvOIGA==} + '@oxfmt/binding-android-arm-eabi@0.35.0': resolution: {integrity: sha512-BaRKlM3DyG81y/xWTsE6gZiv89F/3pHe2BqX2H4JbiB8HNVlWWtplzgATAE5IDSdwChdeuWLDTQzJ92Lglw3ZA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1121,9 +1139,9 @@ packages: cpu: [x64] os: [win32] - '@pkgr/core@0.2.9': - resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} - engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + '@pkgr/core@0.3.6': + resolution: {integrity: sha512-SEeaJLb3qBNF/OaXnaR1NmmBbFYk1zC0ZH/52fATcRPLFg/p791YrcyFFy44Bo9sLaGuSuLp5Q6axbb/O+v/RA==} + engines: {node: ^14.18.0 || >=16.0.0} '@playwright/test@1.60.0': resolution: {integrity: sha512-O71yZIbAh/PxDMNGns37GHBIfrVkEVyn+AXyIa5dOTfb4/xNvRWV+Vv/NMbNCtODB/pO7vLlF2OTmMVLhmr7Ag==} @@ -1148,30 +1166,60 @@ packages: cpu: [arm64] os: [android] + '@rolldown/binding-android-arm64@1.0.3': + resolution: {integrity: sha512-454rs7jHngixp/NMxd5srYD57OnzSlZ/eFTETjORQHLwJG1lRtmNOJcBerZlfu4GjKqeq8aCCIQrMdHyhI51Hw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + '@rolldown/binding-darwin-arm64@1.0.2': resolution: {integrity: sha512-vdFA9+C/rekyGce7WqHs/xoT0ioZEWaOFyZLIV1mEeNFaFDUQrPIo8Vs2GvJ6eetb3rzDUtUBgzto3ExpXJB3w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [darwin] + '@rolldown/binding-darwin-arm64@1.0.3': + resolution: {integrity: sha512-PcAhP+ynjURNyy8SKGl5DQP94aGuB/7JrXJb/t7P+hanXvQVMWzUvRRhBAcg/lNRadBhoUPqSoP4xw5tR/KBEA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + '@rolldown/binding-darwin-x64@1.0.2': resolution: {integrity: sha512-BewSOwTHazv77DTYiAZXSqqKZ4KP/KonFisDMVU7PImxoWfB2aepnPhd2E4SWz3zDzYgDNbs6jBmTdgNnF02GA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [darwin] + '@rolldown/binding-darwin-x64@1.0.3': + resolution: {integrity: sha512-9YpfeUvSE2RS7wysJ81uOZkXJz7f7Q55H2Gvp3VEw/EsahqDtrphrZ0EwDLK5vvKOzaCrBsjF8JmnMLcUt78Gg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + '@rolldown/binding-freebsd-x64@1.0.2': resolution: {integrity: sha512-m41o7M0YWtUdqk61Tb+jnKb2rN++iRdIASlExkUoKfIAH30DOHCB8fVLzSUpbWHHU8esmEioY62PxzexE8MBuA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [freebsd] + '@rolldown/binding-freebsd-x64@1.0.3': + resolution: {integrity: sha512-yB1IlAsSNHncV6SCTL27/MVGR5htvQsoGxIv5KMGXALp+Ll1wYsn+x98M9MW7qa+NdSbvrrY7ANI4wLJ0n1e6g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + '@rolldown/binding-linux-arm-gnueabihf@1.0.2': resolution: {integrity: sha512-jcojB9H7W/jS29pMKWAK1N+fU99vXodHDTatS3b3y/XSOCiHo0kkA74pL3jJmkoQtYpOCxDvaKs1fo2Ij/1X5w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm] os: [linux] + '@rolldown/binding-linux-arm-gnueabihf@1.0.3': + resolution: {integrity: sha512-Yi30IVAAfLUCy2MseFjbB1jAMDl1VMCAas5StnYp8da9+CKvMd2H2cbEjWcw5NPaPqzvYkVIaF1nNUG+b7u/sw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + '@rolldown/binding-linux-arm64-gnu@1.0.2': resolution: {integrity: sha512-1jn6qDU5iiOgFgygDzKUuKP0maTi0/f1+sBLgvij/76C77Nm3ts6ufz9Bjg5q5dduxiUIxtq86JIoBvo1xQ4Ig==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1179,6 +1227,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-arm64-gnu@1.0.3': + resolution: {integrity: sha512-jsO7R8To+AdlYgUmN5sHSCZbfhtMBkO0WUx8iORQnPcMMdgr7qM2DQmMwgabs3GhNztdmoKkMKQFHD6DTMCIQw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-arm64-musl@1.0.2': resolution: {integrity: sha512-QVLO/czFMdoMFSqlX3bcswcJNm/23r+qoa/jgtmFc/qEp6/jXmIkDjF/XIo8dPfGaiwy1xfQn8o77L79GeXFgw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1186,6 +1241,13 @@ packages: os: [linux] libc: [musl] + '@rolldown/binding-linux-arm64-musl@1.0.3': + resolution: {integrity: sha512-VWkUHwWriDciit80wleYwKILoR/KMvxh/IdwS/paX+ZgpuRpCrKLUdadJbc0NpBEiyhpYawsJ73j9aCvOH+f7Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + '@rolldown/binding-linux-ppc64-gnu@1.0.2': resolution: {integrity: sha512-hgO5Abm0w5UL6FEa2iFnZqo2KlK7TQ5QhV5x09hujBf7t5KzHQ1VmfPuTpqRy/rNlSxua3eWH374xxiVrP+lcA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1193,6 +1255,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-ppc64-gnu@1.0.3': + resolution: {integrity: sha512-5f1laC0SlIR0yDbFCd8acUhvJIag6N3zC5P7oUPN6wX0aOma+uKJ0wBDH5aq7I1PVI2ttTlhJwzwRIBnLiSGEg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-s390x-gnu@1.0.2': resolution: {integrity: sha512-fy8rXxuYEu602abC8MUNaPjYLIFzReOaEIEMKMUa0rFEUxNpVXhs15KSSQ4qlqSaM7B6rcj9rDZgADh/IGDzLQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1200,6 +1269,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-s390x-gnu@1.0.3': + resolution: {integrity: sha512-Iq4ko0r4XsgbrF/LunNgHtAGLRRVE2kXonAXQ/MV0mC6jQpMOhW1SvtZja2EhC/kd05++bP78dsqBeIQyYJ6Yg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-x64-gnu@1.0.2': resolution: {integrity: sha512-0+bOkiQ779+r1WpoHOWHqncvyySci0vKph+myNDYb+im6meJAzHQXay6oEgnkHuUGouM1LKTZwqKpBow6Kj7CQ==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1207,6 +1283,13 @@ packages: os: [linux] libc: [glibc] + '@rolldown/binding-linux-x64-gnu@1.0.3': + resolution: {integrity: sha512-B8m6tD5+/N5FeNQFbKlLA/2yVq9ycQP1SeedyEYYKWBNR3ZQbkvIUcNnDNM03lO1l5F2roiiFJGgvoLLyZXtSg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + '@rolldown/binding-linux-x64-musl@1.0.2': resolution: {integrity: sha512-mjSkrzZK5Qsl0a9d1JgILOiuZOSDTVdKENcSXBoqbzSrspLR/4/IRVDo5wd2GgZjNss/viBFJdeq+j7qH2nypw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -1214,29 +1297,59 @@ packages: os: [linux] libc: [musl] + '@rolldown/binding-linux-x64-musl@1.0.3': + resolution: {integrity: sha512-pSdpdUJHkuCxun9LE7jvgUB9qsRgaiyNNCX7m/AvHTcq67AiT/Yhoxvw5zPfhrM8k/BfP8ce/hMOpthKDpEUow==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + '@rolldown/binding-openharmony-arm64@1.0.2': resolution: {integrity: sha512-1v5vHasdfQAZoEHakBV72LIFAC9JjnymsiKxp+GEr/ma3+NJCPSaYK+qavInOovJkgwFrs7GccX2d6IgDA3Z5w==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [openharmony] + '@rolldown/binding-openharmony-arm64@1.0.3': + resolution: {integrity: sha512-OXXS3RKJgX2uLwM+gYyuH5omcH8fL1LJs96pZGgtetVCahON57+d4SJHzTgZiOjxgGkSnpXpOsWuPDGAKAigEg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + '@rolldown/binding-wasm32-wasi@1.0.2': resolution: {integrity: sha512-mb1VobWn6NheziTk5/WEaR6AKVbrwT5sOi6C7zk3gy/pD1qtJfU1j4PgTo2NJnOtbL9Dl3Aeei8w9jJ7qC2jZQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [wasm32] + '@rolldown/binding-wasm32-wasi@1.0.3': + resolution: {integrity: sha512-JTtb8BWFynicNSoPrehsCzBtOKjZ6jhMiPFEmOiuXg1Fl8dn2KHQob+GuPSGR0dryQa1PQJbzjF3dqO/whhjLg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [wasm32] + '@rolldown/binding-win32-arm64-msvc@1.0.2': resolution: {integrity: sha512-SqKonF56vA/L2yHwHYcEp2P34URpOZ7d1fS635cTkpDnUtEGdUbhI6NzsPdqeSWvAAeGDrxjWjNmibDIdFf9/A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [win32] + '@rolldown/binding-win32-arm64-msvc@1.0.3': + resolution: {integrity: sha512-gEdFFEN70A/jxb2svrWsN3aDL7OUtmvlOy+6fa2jxG8K0wQ1ZbdeLGnidov6Yu5/733dI5ySfzFlQ/cb0bSz1g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + '@rolldown/binding-win32-x64-msvc@1.0.2': resolution: {integrity: sha512-v7qRI7gXLRINcOGXt+7YmAZ6iFuyZVMIoXAxhd8oP+DR9dLfL9GfNIx7PLMxmhZdvq8waUJBQiWN9EKNy+TRBQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [win32] + '@rolldown/binding-win32-x64-msvc@1.0.3': + resolution: {integrity: sha512-eXB7CHuaQdqmJcc3koCNtNPmT/bj2gc999kUFgBxG8Ac0NdgXc4rkCHhqrgrhN3zddvvvrgzj1e90SuSfmyIXA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + '@rolldown/pluginutils@1.0.1': resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} @@ -1328,8 +1441,8 @@ packages: svelte: ^5.46.4 vite: ^8.0.0-beta.7 || ^8.0.0 - '@swc/helpers@0.5.21': - resolution: {integrity: sha512-jI/VAmtdjB/RnI8GTnokyX7Ug8c+g+ffD6QRLa6XQewtnGyukKkKSk3wLTM3b5cjt1jNh9x0jfVlagdN2gDKQg==} + '@swc/helpers@0.5.23': + resolution: {integrity: sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==} '@tailwindcss/node@4.3.0': resolution: {integrity: sha512-aFb4gUhFOgdh9AXo4IzBEOzBkkAxm9VigwDJnMIYv3lcfXCJVesNfbEaBl4BNgVRyid92AmdviqwBUBRKSeY3g==} @@ -1514,14 +1627,6 @@ packages: '@types/json-schema': optional: true - '@typescript-eslint/eslint-plugin@8.59.4': - resolution: {integrity: sha512-PegsU+XfyJJNjd4+u/k6f9yTyp0lEXXiPopUNobZcIAUJFGICFLN+sP0Rb3JehVmiij1Ph0dFGYqODoRo/2+6A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - '@typescript-eslint/parser': ^8.59.4 - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/eslint-plugin@8.60.0': resolution: {integrity: sha512-QYb/sa74/s7OKMbACMjrYnGspj9Hs5YI5aaffSL65UfeBUzVzBJfVo3oWSpbzPurvm7yaCCo2Lk7lVj610HqKw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1530,13 +1635,6 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@8.59.4': - resolution: {integrity: sha512-zORHqO/tuhxY1zWuTvMUqddRxpiFJ72xVfcNoWpqdLjs6lfPbuQBJuW4pk+49/uBMy7Ssr4bzgjiKmmDB1UbZQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/parser@8.60.0': resolution: {integrity: sha512-fcqpj/MyK4sxDPcbe7STNPbpQL4RLZOPWuaTmwZYuc+hJKzRf58yRxfhqGpc6PIq9ZyfSBpfHgmUHmHs0KwHwg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1544,45 +1642,22 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/project-service@8.59.4': - resolution: {integrity: sha512-Ly00Vu4oAacfDeHp2Zg85ioNG6l8HG+tN1D7J+xTHSxu9y0awYKJ2zH1rFBn8ZSfuGK+7FxK3Cgl3uAz0aZZLg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/project-service@8.60.0': resolution: {integrity: sha512-aZu74NNKJeUWqCjDddzdiKaS82dgYgV/vmf+Ui3ZdZejmgfXR/q+pRumgobnQ2cCJTgGTWp4ypiwsuofFubavg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/scope-manager@8.59.4': - resolution: {integrity: sha512-mUeR/3H1WrTAddJrwut8OoPjfauaztMQmRwV5fQTUyNVJCLiUXXe4lGEyYIL2oFDpP7UtgbGJXCt72wT0z2S3Q==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/scope-manager@8.60.0': resolution: {integrity: sha512-pFzqhllJMs+jghLQWzV00ds39xLzuyqPSev5pd8f4Ir0rtKR3ZLUB4/4dhjOFighWb9larvtfJvqL+4yKDI3Xw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/tsconfig-utils@8.59.4': - resolution: {integrity: sha512-DLCpnKgD4alVxTBSKulK+gU1KCqOgUXfDRDXh2mZgzokQKa/70ax93I2uVO3m/LLvIAtWZIFoiifudmIqAxpMA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/tsconfig-utils@8.60.0': resolution: {integrity: sha512-BZPR3RGYlAXnly6ymAxfkVn5rCbZzQNou0rxv3GfWZ8cTQp+hhVd73khbGLAd8k1TlAPLISH337M+tAgAnaJDQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/type-utils@8.59.4': - resolution: {integrity: sha512-uonTuPAAKr9XaBGqJ3LjYTh72zy5DyGesljO9gtmk/eFW0W1fRHjnwVYKB35Lm8d5Q5CluEW3gPHjTvZTmgrfA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/type-utils@8.60.0': resolution: {integrity: sha512-SX46wEUtitCpq7AN38HkUU/+zvUpdKf7ephtWAFgckH8O7PQIyL5gvrhQgBLuEYgLfuKWOVvWVskMbuFHAz5xg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1590,33 +1665,16 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/types@8.59.4': - resolution: {integrity: sha512-F1o7WJcCq+bc8dwcO/YsSEOudAH8RDtaOhM6wcAQhcUsFhnWQl81JKy48q1hoxAU0qrzM89+31GYh1515Zde3Q==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/types@8.60.0': resolution: {integrity: sha512-AsE7x2XaAK+CVbeih0Fvbn+r1qHxtpLDJ3XUuFcIinT318T90yHMJC+Zgv+jUuDjQQd06HKwxnDu6sz1IcTilA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/typescript-estree@8.59.4': - resolution: {integrity: sha512-F+RuOmcDXo4+TPdfd/TCLS3m2nw8gE9XXyZLrA3JBfaA5tz9TtdkyD3YJFmPxulyc2cKbEok/CvFE3MgSLWnag==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/typescript-estree@8.60.0': resolution: {integrity: sha512-3AcZNBGMClm6CXDyo8kYvVGT/sx29sS0oBsIb9oZI2gunA4Vm2M3YHzRLPvsUBBsl+yB5FPtltq7gGH0iTlp9g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/utils@8.59.4': - resolution: {integrity: sha512-cYXeNAUsG4lJo5dbc1FcKm+JwIWrj1/UpTORsC6tGMjEZ81DYcvIr9/ueikhMa/Y/gDQYGp+YX9/xQrXje5BJw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/utils@8.60.0': resolution: {integrity: sha512-HtXuPfrHTyBDkameWpl+vJb1Uevu2tznAyahM1Oc4AENidCLTPiZDWIo4GfcxNdC/RcfGcadzzkqbRG87dUrQA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1624,10 +1682,6 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' - '@typescript-eslint/visitor-keys@8.59.4': - resolution: {integrity: sha512-U3gxVaDVnuZKhSspW/MzMxE1kq7zOdc072FcSNoqA1I9p8HyKbBFfEHoWckBAMgNMph4MamwS5iTVzFmrnt8TQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/visitor-keys@8.60.0': resolution: {integrity: sha512-9WI52t8ZGLVGrPMBet25yAftqY/n95+zmoUUtJBBQTKDSKUu7OsPTroT2op7U9JatkoRccL0YkWDNMFfC4Sjxg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2018,8 +2072,8 @@ packages: date-fns@4.3.0: resolution: {integrity: sha512-OYcL+3N/jyWbYdFGqoMAhytDgxP9pbYPUUiRCOgn4Fewaadk9l/Wam4Avciiyp2BgkpfQyBV9B+ehnVJych+eQ==} - dayjs@1.11.20: - resolution: {integrity: sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==} + dayjs@1.11.21: + resolution: {integrity: sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==} debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} @@ -2085,8 +2139,8 @@ packages: emoji-regex@10.6.0: resolution: {integrity: sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==} - enhanced-resolve@5.22.0: - resolution: {integrity: sha512-xYcDWrpELkFzz9SpZ3PlI6Eu6eD93Yf0WLDRxikGhWJ3MAir2SNZTIVCVZqZ/NUyx8AdMc2gT9C0gPiw18kG+A==} + enhanced-resolve@5.22.1: + resolution: {integrity: sha512-6QEuw3zoX1SJQc7b87aBXke/no+mG2bTBgw29gWMQonLmpEkWoCAVkl+M49e48AZlWzxiDzDZzYdp6kobcyLww==} engines: {node: '>=10.13.0'} env-paths@2.2.1: @@ -2141,8 +2195,8 @@ packages: peerDependencies: eslint: ^8.40.0 || ^9.0.0 || ^10.0.0 - eslint-plugin-prettier@5.5.5: - resolution: {integrity: sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw==} + eslint-plugin-prettier@5.5.6: + resolution: {integrity: sha512-ifetmTcxWfz+4qRW3pH/ujdTq2jQIj59AxJMIN26K5avYgU8dxycUETQonWiW+wPrYXA0j3Try0l1CnwVQtDqQ==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: '@types/eslint': '>=8.0.0' @@ -2155,8 +2209,8 @@ packages: eslint-config-prettier: optional: true - eslint-plugin-svelte@3.17.1: - resolution: {integrity: sha512-NyiXHtS3Ni7e532RBwS9OXlMKDIrENg3gY+/+ODjZzQx2xhU3NlJ+nIl1a93iUUQeiJL3lS8KLmY+W8hklzweQ==} + eslint-plugin-svelte@3.18.0: + resolution: {integrity: sha512-vc3P37lrDronWDb2kPXiG8sqkuiMqitGXSSaflb7Y+jpDgNoAzW8i7tdqyJKpcLZmFIqZCD+je2oZRf9qyRyBw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.1 || ^9.0.0 || ^10.0.0 @@ -2259,9 +2313,6 @@ packages: resolution: {integrity: sha512-h5+1OzzfCC3Ef7VbtKdcv7zsstUQwUDlYpUTvjeUsJAssPgLn7QzbboPtL5ro04Mq0rPOsMzl7q5hIbRs2wD1A==} engines: {node: '>=8.0.0'} - fast-content-type-parse@3.0.0: - resolution: {integrity: sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg==} - fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -2429,8 +2480,8 @@ packages: resolution: {integrity: sha512-CsNUt5x9LUdx6hnk/E2SZLsDyvfqANZSUq4+D3D8RzDJ2M+HDTIkF60ibS1vHaK55vzgiZw1bEPFG9yH7l33wA==} engines: {node: '>=12'} - hasown@2.0.3: - resolution: {integrity: sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==} + hasown@2.0.4: + resolution: {integrity: sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==} engines: {node: '>= 0.4'} html-escaper@2.0.2: @@ -3040,6 +3091,11 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} hasBin: true + rolldown@1.0.3: + resolution: {integrity: sha512-i00lAJ2ks1BYr7rjNjKC7BcqAS7nVfiT3QX1SI5aY+AFHblCmaUf9OE9dbdzDvW6dJxbi2ZCZiy9v3CcwOiX3g==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + runed@0.23.4: resolution: {integrity: sha512-9q8oUiBYeXIDLWNK5DfCWlkL0EW3oGbk845VdKlPeia28l751VpfesaB/+7pI6rnbx1I6rqoZ2fZxptOJLxILA==} peerDependencies: @@ -3217,8 +3273,8 @@ packages: peerDependencies: svelte: ^5.0.0 - svelte@5.55.9: - resolution: {integrity: sha512-fTjjT8cHLDwigcu2j3pv7Jq04LklXevPB8uBgyHNiTXv+RMNvVnrjS4UEYrLMkhuq1vpCodHjiW+z/95SDs/fg==} + svelte@5.55.10: + resolution: {integrity: sha512-v9mFVBY1USosyIWdXE7Cg4AN0ywyKCMcAhONvli8doMowEhFhMdNLKD1j7O/UnsrdVTHaUOk/jv8hD/HClVy+g==} engines: {node: '>=18'} sveltekit-superforms@2.30.1: @@ -3227,8 +3283,8 @@ packages: '@sveltejs/kit': 1.x || 2.x svelte: 3.x || 4.x || >=5.0.0-next.51 - synckit@0.11.12: - resolution: {integrity: sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==} + synckit@0.11.13: + resolution: {integrity: sha512-eNRKgb3z66Yp3D2CixVujOUvXLFUTij/zVnV8KRyvFdQwpz7I5DS8UfRkTeLzb64u+dkzDSdelE24izu+zSSUg==} engines: {node: ^14.18.0 || >=16.0.0} tabbable@6.4.0: @@ -3314,15 +3370,8 @@ packages: type-level-regexp@0.1.17: resolution: {integrity: sha512-wTk4DH3cxwk196uGLK/E9pE45aLfeKJacKmcEgEOA/q5dnPGNxXt0cfYdFxb57L+sEpf1oJH4Dnx/pnRcku9jg==} - typebox@1.1.38: - resolution: {integrity: sha512-pZ0aQPmMmXoUvSbeuWf/Hzsc+avNw/Zd6VeE8CFgkVGWyuHPJvqeJJDeJqLve+K70LvjYIoleGcoJHPT17cWoA==} - - typescript-eslint@8.59.4: - resolution: {integrity: sha512-Rw6+44QNFaXtgHSjPy+Kw8hrJniMYzR85E9yLmOLcfZ91/rz+JXQbDTCmc6ccxMPY6K6PgAq26f0JCBfR7LIPQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 - typescript: '>=4.8.4 <6.1.0' + typebox@1.1.39: + resolution: {integrity: sha512-vj0afVtOfLQvv0GR0VxVagYxsXN64btL7Z9XoaG0ZggH3mruMMkOO6hXdgMsjCY3shZgEvooAWVeznQVs5c43w==} typescript-eslint@8.60.0: resolution: {integrity: sha512-9f65qWLZdAW9m1JaxBDUHcqRUfL8bkxxXL7XxEfI+F09q56PkBvIfCjLF3yInsDM/BBmwkqmCQdCZe/RYlIWEw==} @@ -3348,8 +3397,8 @@ packages: undici-types@7.24.6: resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==} - undici@6.25.0: - resolution: {integrity: sha512-ZgpWDC5gmNiuY9CnLVXEH8rl50xhRCuLNA97fAUnKi8RRuV4E6KG31pDTsLVUKnohJE0I3XDrTeEydAXRw47xg==} + undici@6.26.0: + resolution: {integrity: sha512-4yqz8a3n5HmGTlsbADNtr/dJlhkh/55Rq798G6ibiULcXbDtaLpTl1pvdqcbFfeoj3iSi52lePFM7h9H21cw/A==} engines: {node: '>=18.17'} unicorn-magic@0.3.0: @@ -3601,19 +3650,19 @@ snapshots: '@octokit/core': 7.0.6 '@octokit/plugin-paginate-rest': 14.0.0(@octokit/core@7.0.6) '@octokit/plugin-rest-endpoint-methods': 17.0.0(@octokit/core@7.0.6) - '@octokit/request': 10.0.9 + '@octokit/request': 10.0.10 '@octokit/request-error': 7.1.0 - undici: 6.25.0 + undici: 6.26.0 '@actions/http-client@3.0.2': dependencies: tunnel: 0.0.6 - undici: 6.25.0 + undici: 6.26.0 '@actions/http-client@4.0.1': dependencies: tunnel: 0.0.6 - undici: 6.25.0 + undici: 6.26.0 '@actions/io@3.0.2': {} @@ -3922,10 +3971,18 @@ snapshots: '@humanwhocodes/retry@0.4.3': {} + '@iconify-json/clarity@1.2.4': + dependencies: + '@iconify/types': 2.0.0 + '@iconify-json/ic@1.2.4': dependencies: '@iconify/types': 2.0.0 + '@iconify-json/icomoon-free@1.2.1': + dependencies: + '@iconify/types': 2.0.0 + '@iconify-json/material-icon-theme@1.2.66': dependencies: '@iconify/types': 2.0.0 @@ -3970,9 +4027,9 @@ snapshots: transitivePeerDependencies: - babel-plugin-macros - '@internationalized/date@3.12.1': + '@internationalized/date@3.12.2': dependencies: - '@swc/helpers': 0.5.21 + '@swc/helpers': 0.5.23 '@isaacs/ttlcache@1.4.1': {} @@ -4009,9 +4066,9 @@ snapshots: '@lix-js/server-protocol-schema@0.1.1': {} - '@lucide/svelte@1.16.0(svelte@5.55.9(@typescript-eslint/types@8.60.0))': + '@lucide/svelte@1.17.0(svelte@5.55.10(@typescript-eslint/types@8.60.0))': dependencies: - svelte: 5.55.9(@typescript-eslint/types@8.60.0) + svelte: 5.55.10(@typescript-eslint/types@8.60.0) '@nanoforge-dev/actions@2.0.0': dependencies: @@ -4033,9 +4090,9 @@ snapshots: eslint-config-prettier: 10.1.8(eslint@10.4.0(jiti@2.7.0)) eslint-formatter-pretty: 7.1.0 eslint-plugin-format: 1.5.0(eslint@10.4.0(jiti@2.7.0)) - eslint-plugin-prettier: 5.5.5(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.4.0(jiti@2.7.0)))(eslint@10.4.0(jiti@2.7.0))(prettier@3.8.3) + eslint-plugin-prettier: 5.5.6(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.4.0(jiti@2.7.0)))(eslint@10.4.0(jiti@2.7.0))(prettier@3.8.3) globals: 16.5.0 - typescript-eslint: 8.59.4(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3) + typescript-eslint: 8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3) transitivePeerDependencies: - '@types/eslint' - eslint @@ -4058,7 +4115,7 @@ snapshots: dependencies: '@octokit/auth-token': 6.0.0 '@octokit/graphql': 9.0.3 - '@octokit/request': 10.0.9 + '@octokit/request': 10.0.10 '@octokit/request-error': 7.1.0 '@octokit/types': 16.0.0 before-after-hook: 4.0.0 @@ -4071,7 +4128,7 @@ snapshots: '@octokit/graphql@9.0.3': dependencies: - '@octokit/request': 10.0.9 + '@octokit/request': 10.0.10 '@octokit/types': 16.0.0 universal-user-agent: 7.0.3 @@ -4098,13 +4155,12 @@ snapshots: dependencies: '@octokit/types': 16.0.0 - '@octokit/request@10.0.9': + '@octokit/request@10.0.10': dependencies: '@octokit/endpoint': 11.0.3 '@octokit/request-error': 7.1.0 '@octokit/types': 16.0.0 content-type: 2.0.0 - fast-content-type-parse: 3.0.0 json-with-bigint: 3.5.8 universal-user-agent: 7.0.3 @@ -4228,6 +4284,8 @@ snapshots: '@oxc-project/types@0.132.0': {} + '@oxc-project/types@0.133.0': {} + '@oxfmt/binding-android-arm-eabi@0.35.0': optional: true @@ -4285,7 +4343,7 @@ snapshots: '@oxfmt/binding-win32-x64-msvc@0.35.0': optional: true - '@pkgr/core@0.2.9': {} + '@pkgr/core@0.3.6': {} '@playwright/test@1.60.0': dependencies: @@ -4305,39 +4363,75 @@ snapshots: '@rolldown/binding-android-arm64@1.0.2': optional: true + '@rolldown/binding-android-arm64@1.0.3': + optional: true + '@rolldown/binding-darwin-arm64@1.0.2': optional: true + '@rolldown/binding-darwin-arm64@1.0.3': + optional: true + '@rolldown/binding-darwin-x64@1.0.2': optional: true + '@rolldown/binding-darwin-x64@1.0.3': + optional: true + '@rolldown/binding-freebsd-x64@1.0.2': optional: true + '@rolldown/binding-freebsd-x64@1.0.3': + optional: true + '@rolldown/binding-linux-arm-gnueabihf@1.0.2': optional: true + '@rolldown/binding-linux-arm-gnueabihf@1.0.3': + optional: true + '@rolldown/binding-linux-arm64-gnu@1.0.2': optional: true + '@rolldown/binding-linux-arm64-gnu@1.0.3': + optional: true + '@rolldown/binding-linux-arm64-musl@1.0.2': optional: true + '@rolldown/binding-linux-arm64-musl@1.0.3': + optional: true + '@rolldown/binding-linux-ppc64-gnu@1.0.2': optional: true + '@rolldown/binding-linux-ppc64-gnu@1.0.3': + optional: true + '@rolldown/binding-linux-s390x-gnu@1.0.2': optional: true + '@rolldown/binding-linux-s390x-gnu@1.0.3': + optional: true + '@rolldown/binding-linux-x64-gnu@1.0.2': optional: true + '@rolldown/binding-linux-x64-gnu@1.0.3': + optional: true + '@rolldown/binding-linux-x64-musl@1.0.2': optional: true + '@rolldown/binding-linux-x64-musl@1.0.3': + optional: true + '@rolldown/binding-openharmony-arm64@1.0.2': optional: true + '@rolldown/binding-openharmony-arm64@1.0.3': + optional: true + '@rolldown/binding-wasm32-wasi@1.0.2': dependencies: '@emnapi/core': 1.10.0 @@ -4345,12 +4439,25 @@ snapshots: '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) optional: true + '@rolldown/binding-wasm32-wasi@1.0.3': + dependencies: + '@emnapi/core': 1.10.0 + '@emnapi/runtime': 1.10.0 + '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) + optional: true + '@rolldown/binding-win32-arm64-msvc@1.0.2': optional: true + '@rolldown/binding-win32-arm64-msvc@1.0.3': + optional: true + '@rolldown/binding-win32-x64-msvc@1.0.2': optional: true + '@rolldown/binding-win32-x64-msvc@1.0.3': + optional: true + '@rolldown/pluginutils@1.0.1': {} '@rollup/plugin-node-resolve@15.3.1': @@ -4402,11 +4509,11 @@ snapshots: dependencies: acorn: 8.16.0 - '@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.9(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0))': + '@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.10(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0))': dependencies: '@standard-schema/spec': 1.1.0 '@sveltejs/acorn-typescript': 1.0.10(acorn@8.16.0) - '@sveltejs/vite-plugin-svelte': 7.1.2(svelte@5.55.9(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)) + '@sveltejs/vite-plugin-svelte': 7.1.2(svelte@5.55.10(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)) '@types/cookie': 0.6.0 acorn: 8.16.0 cookie: 0.6.0 @@ -4417,28 +4524,28 @@ snapshots: mrmime: 2.0.1 set-cookie-parser: 3.1.0 sirv: 3.0.2 - svelte: 5.55.9(@typescript-eslint/types@8.60.0) + svelte: 5.55.10(@typescript-eslint/types@8.60.0) vite: 8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0) optionalDependencies: typescript: 6.0.3 - '@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.9(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0))': + '@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.10(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0))': dependencies: deepmerge: 4.3.1 magic-string: 0.30.21 obug: 2.1.1 - svelte: 5.55.9(@typescript-eslint/types@8.60.0) + svelte: 5.55.10(@typescript-eslint/types@8.60.0) vite: 8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0) vitefu: 1.1.3(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)) - '@swc/helpers@0.5.21': + '@swc/helpers@0.5.23': dependencies: tslib: 2.8.1 '@tailwindcss/node@4.3.0': dependencies: '@jridgewell/remapping': 2.3.5 - enhanced-resolve: 5.22.0 + enhanced-resolve: 5.22.1 jiti: 2.7.0 lightningcss: 1.32.0 magic-string: 0.30.21 @@ -4506,16 +4613,16 @@ snapshots: '@tanstack/query-core@5.100.14': {} - '@tanstack/svelte-query@6.1.33(svelte@5.55.9(@typescript-eslint/types@8.60.0))': + '@tanstack/svelte-query@6.1.33(svelte@5.55.10(@typescript-eslint/types@8.60.0))': dependencies: '@tanstack/query-core': 5.100.14 - svelte: 5.55.9(@typescript-eslint/types@8.60.0) + svelte: 5.55.10(@typescript-eslint/types@8.60.0) - '@testing-library/svelte-core@1.0.0(svelte@5.55.9(@typescript-eslint/types@8.60.0))': + '@testing-library/svelte-core@1.0.0(svelte@5.55.10(@typescript-eslint/types@8.60.0))': dependencies: - svelte: 5.55.9(@typescript-eslint/types@8.60.0) + svelte: 5.55.10(@typescript-eslint/types@8.60.0) - '@trivago/prettier-plugin-sort-imports@6.0.2(prettier-plugin-svelte@4.0.1(prettier@3.8.3)(svelte@5.55.9(@typescript-eslint/types@8.60.0)))(prettier@3.8.3)(svelte@5.55.9(@typescript-eslint/types@8.60.0))': + '@trivago/prettier-plugin-sort-imports@6.0.2(prettier-plugin-svelte@4.0.1(prettier@3.8.3)(svelte@5.55.10(@typescript-eslint/types@8.60.0)))(prettier@3.8.3)(svelte@5.55.10(@typescript-eslint/types@8.60.0))': dependencies: '@babel/generator': 7.29.7 '@babel/parser': 7.29.7 @@ -4527,8 +4634,8 @@ snapshots: parse-imports-exports: 0.2.4 prettier: 3.8.3 optionalDependencies: - prettier-plugin-svelte: 4.0.1(prettier@3.8.3)(svelte@5.55.9(@typescript-eslint/types@8.60.0)) - svelte: 5.55.9(@typescript-eslint/types@8.60.0) + prettier-plugin-svelte: 4.0.1(prettier@3.8.3)(svelte@5.55.10(@typescript-eslint/types@8.60.0)) + svelte: 5.55.10(@typescript-eslint/types@8.60.0) transitivePeerDependencies: - supports-color @@ -4588,22 +4695,6 @@ snapshots: '@types/json-schema': 7.0.15 optional: true - '@typescript-eslint/eslint-plugin@8.59.4(@typescript-eslint/parser@8.59.4(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3)': - dependencies: - '@eslint-community/regexpp': 4.12.2 - '@typescript-eslint/parser': 8.59.4(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3) - '@typescript-eslint/scope-manager': 8.59.4 - '@typescript-eslint/type-utils': 8.59.4(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3) - '@typescript-eslint/utils': 8.59.4(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.59.4 - eslint: 10.4.0(jiti@2.7.0) - ignore: 7.0.5 - natural-compare: 1.4.0 - ts-api-utils: 2.5.0(typescript@6.0.3) - typescript: 6.0.3 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/eslint-plugin@8.60.0(@typescript-eslint/parser@8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3)': dependencies: '@eslint-community/regexpp': 4.12.2 @@ -4620,18 +4711,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.59.4(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3)': - dependencies: - '@typescript-eslint/scope-manager': 8.59.4 - '@typescript-eslint/types': 8.59.4 - '@typescript-eslint/typescript-estree': 8.59.4(typescript@6.0.3) - '@typescript-eslint/visitor-keys': 8.59.4 - debug: 4.4.3 - eslint: 10.4.0(jiti@2.7.0) - typescript: 6.0.3 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/parser@8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3)': dependencies: '@typescript-eslint/scope-manager': 8.60.0 @@ -4644,15 +4723,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.59.4(typescript@6.0.3)': - dependencies: - '@typescript-eslint/tsconfig-utils': 8.59.4(typescript@6.0.3) - '@typescript-eslint/types': 8.59.4 - debug: 4.4.3 - typescript: 6.0.3 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/project-service@8.60.0(typescript@6.0.3)': dependencies: '@typescript-eslint/tsconfig-utils': 8.60.0(typescript@6.0.3) @@ -4662,36 +4732,15 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@8.59.4': - dependencies: - '@typescript-eslint/types': 8.59.4 - '@typescript-eslint/visitor-keys': 8.59.4 - '@typescript-eslint/scope-manager@8.60.0': dependencies: '@typescript-eslint/types': 8.60.0 '@typescript-eslint/visitor-keys': 8.60.0 - '@typescript-eslint/tsconfig-utils@8.59.4(typescript@6.0.3)': - dependencies: - typescript: 6.0.3 - '@typescript-eslint/tsconfig-utils@8.60.0(typescript@6.0.3)': dependencies: typescript: 6.0.3 - '@typescript-eslint/type-utils@8.59.4(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3)': - dependencies: - '@typescript-eslint/types': 8.59.4 - '@typescript-eslint/typescript-estree': 8.59.4(typescript@6.0.3) - '@typescript-eslint/utils': 8.59.4(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3) - debug: 4.4.3 - eslint: 10.4.0(jiti@2.7.0) - ts-api-utils: 2.5.0(typescript@6.0.3) - typescript: 6.0.3 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/type-utils@8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3)': dependencies: '@typescript-eslint/types': 8.60.0 @@ -4704,25 +4753,8 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/types@8.59.4': {} - '@typescript-eslint/types@8.60.0': {} - '@typescript-eslint/typescript-estree@8.59.4(typescript@6.0.3)': - dependencies: - '@typescript-eslint/project-service': 8.59.4(typescript@6.0.3) - '@typescript-eslint/tsconfig-utils': 8.59.4(typescript@6.0.3) - '@typescript-eslint/types': 8.59.4 - '@typescript-eslint/visitor-keys': 8.59.4 - debug: 4.4.3 - minimatch: 10.2.5 - semver: 7.8.1 - tinyglobby: 0.2.16 - ts-api-utils: 2.5.0(typescript@6.0.3) - typescript: 6.0.3 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/typescript-estree@8.60.0(typescript@6.0.3)': dependencies: '@typescript-eslint/project-service': 8.60.0(typescript@6.0.3) @@ -4738,17 +4770,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.59.4(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3)': - dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@10.4.0(jiti@2.7.0)) - '@typescript-eslint/scope-manager': 8.59.4 - '@typescript-eslint/types': 8.59.4 - '@typescript-eslint/typescript-estree': 8.59.4(typescript@6.0.3) - eslint: 10.4.0(jiti@2.7.0) - typescript: 6.0.3 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/utils@8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3)': dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@10.4.0(jiti@2.7.0)) @@ -4760,11 +4781,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/visitor-keys@8.59.4': - dependencies: - '@typescript-eslint/types': 8.59.4 - eslint-visitor-keys: 5.0.1 - '@typescript-eslint/visitor-keys@8.60.0': dependencies: '@typescript-eslint/types': 8.60.0 @@ -4932,7 +4948,7 @@ snapshots: '@types/validator': 13.15.10 '@vinejs/compiler': 3.0.0 camelcase: 8.0.0 - dayjs: 1.11.20 + dayjs: 1.11.21 dlv: 1.1.3 normalize-url: 8.1.1 validator: 13.15.35 @@ -5091,15 +5107,15 @@ snapshots: before-after-hook@4.0.0: {} - bits-ui@2.18.1(@internationalized/date@3.12.1)(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.9(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0)): + bits-ui@2.18.1(@internationalized/date@3.12.2)(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.10(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0)): dependencies: '@floating-ui/core': 1.7.5 '@floating-ui/dom': 1.7.6 - '@internationalized/date': 3.12.1 + '@internationalized/date': 3.12.2 esm-env: 1.2.2 - runed: 0.35.1(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.9(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0)) - svelte: 5.55.9(@typescript-eslint/types@8.60.0) - svelte-toolbelt: 0.10.6(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.9(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0)) + runed: 0.35.1(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.10(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0)) + svelte: 5.55.10(@typescript-eslint/types@8.60.0) + svelte-toolbelt: 0.10.6(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.10(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0)) tabbable: 6.4.0 transitivePeerDependencies: - '@sveltejs/kit' @@ -5264,7 +5280,7 @@ snapshots: date-fns@4.3.0: {} - dayjs@1.11.20: + dayjs@1.11.21: optional: true debug@4.4.3: @@ -5310,7 +5326,7 @@ snapshots: emoji-regex@10.6.0: {} - enhanced-resolve@5.22.0: + enhanced-resolve@5.22.1: dependencies: graceful-fs: 4.2.11 tapable: 2.3.3 @@ -5366,19 +5382,19 @@ snapshots: ohash: 2.0.11 oxfmt: 0.35.0 prettier: 3.8.3 - synckit: 0.11.12 + synckit: 0.11.13 - eslint-plugin-prettier@5.5.5(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.4.0(jiti@2.7.0)))(eslint@10.4.0(jiti@2.7.0))(prettier@3.8.3): + eslint-plugin-prettier@5.5.6(@types/eslint@9.6.1)(eslint-config-prettier@10.1.8(eslint@10.4.0(jiti@2.7.0)))(eslint@10.4.0(jiti@2.7.0))(prettier@3.8.3): dependencies: eslint: 10.4.0(jiti@2.7.0) prettier: 3.8.3 prettier-linter-helpers: 1.0.1 - synckit: 0.11.12 + synckit: 0.11.13 optionalDependencies: '@types/eslint': 9.6.1 eslint-config-prettier: 10.1.8(eslint@10.4.0(jiti@2.7.0)) - eslint-plugin-svelte@3.17.1(eslint@10.4.0(jiti@2.7.0))(svelte@5.55.9(@typescript-eslint/types@8.60.0)): + eslint-plugin-svelte@3.18.0(eslint@10.4.0(jiti@2.7.0))(svelte@5.55.10(@typescript-eslint/types@8.60.0)): dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@10.4.0(jiti@2.7.0)) '@jridgewell/sourcemap-codec': 1.5.5 @@ -5390,9 +5406,9 @@ snapshots: postcss-load-config: 3.1.4(postcss@8.5.15) postcss-safe-parser: 7.0.1(postcss@8.5.15) semver: 7.8.1 - svelte-eslint-parser: 1.6.1(svelte@5.55.9(@typescript-eslint/types@8.60.0)) + svelte-eslint-parser: 1.6.1(svelte@5.55.10(@typescript-eslint/types@8.60.0)) optionalDependencies: - svelte: 5.55.9(@typescript-eslint/types@8.60.0) + svelte: 5.55.10(@typescript-eslint/types@8.60.0) transitivePeerDependencies: - ts-node @@ -5517,8 +5533,6 @@ snapshots: pure-rand: 6.1.0 optional: true - fast-content-type-parse@3.0.0: {} - fast-deep-equal@3.1.3: {} fast-diff@1.3.0: {} @@ -5567,7 +5581,7 @@ snapshots: transitivePeerDependencies: - rollup - flowbite-svelte@1.33.1(svelte@5.55.9(@typescript-eslint/types@8.60.0))(tailwindcss@4.3.0): + flowbite-svelte@1.33.1(svelte@5.55.10(@typescript-eslint/types@8.60.0))(tailwindcss@4.3.0): dependencies: '@floating-ui/dom': 1.7.6 '@floating-ui/utils': 0.2.11 @@ -5576,7 +5590,7 @@ snapshots: date-fns: 4.3.0 esm-env: 1.2.2 flowbite: 3.1.2 - svelte: 5.55.9(@typescript-eslint/types@8.60.0) + svelte: 5.55.10(@typescript-eslint/types@8.60.0) tailwind-merge: 3.6.0 tailwind-variants: 3.2.2(tailwind-merge@3.6.0)(tailwindcss@4.3.0) tailwindcss: 4.3.0 @@ -5610,11 +5624,11 @@ snapshots: transitivePeerDependencies: - rollup - formsnap@2.0.1(svelte@5.55.9(@typescript-eslint/types@8.60.0))(sveltekit-superforms@2.30.1(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.9(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(@types/json-schema@7.0.15)(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@6.0.3)): + formsnap@2.0.1(svelte@5.55.10(@typescript-eslint/types@8.60.0))(sveltekit-superforms@2.30.1(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.10(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(@types/json-schema@7.0.15)(svelte@5.55.10(@typescript-eslint/types@8.60.0))(typescript@6.0.3)): dependencies: - svelte: 5.55.9(@typescript-eslint/types@8.60.0) - svelte-toolbelt: 0.5.0(svelte@5.55.9(@typescript-eslint/types@8.60.0)) - sveltekit-superforms: 2.30.1(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.9(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(@types/json-schema@7.0.15)(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@6.0.3) + svelte: 5.55.10(@typescript-eslint/types@8.60.0) + svelte-toolbelt: 0.5.0(svelte@5.55.10(@typescript-eslint/types@8.60.0)) + sveltekit-superforms: 2.30.1(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.10(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(@types/json-schema@7.0.15)(svelte@5.55.10(@typescript-eslint/types@8.60.0))(typescript@6.0.3) fsevents@2.3.2: optional: true @@ -5692,7 +5706,7 @@ snapshots: has-flag@5.0.1: {} - hasown@2.0.3: + hasown@2.0.4: dependencies: function-bind: 1.1.2 @@ -5732,7 +5746,7 @@ snapshots: is-core-module@2.16.2: dependencies: - hasown: 2.0.3 + hasown: 2.0.4 is-extglob@2.1.1: {} @@ -5982,11 +5996,11 @@ snapshots: pkg-types: 1.3.1 ufo: 1.6.4 - mode-watcher@1.1.0(svelte@5.55.9(@typescript-eslint/types@8.60.0)): + mode-watcher@1.1.0(svelte@5.55.10(@typescript-eslint/types@8.60.0)): dependencies: - runed: 0.25.0(svelte@5.55.9(@typescript-eslint/types@8.60.0)) - svelte: 5.55.9(@typescript-eslint/types@8.60.0) - svelte-toolbelt: 0.7.1(svelte@5.55.9(@typescript-eslint/types@8.60.0)) + runed: 0.25.0(svelte@5.55.10(@typescript-eslint/types@8.60.0)) + svelte: 5.55.10(@typescript-eslint/types@8.60.0) + svelte-toolbelt: 0.7.1(svelte@5.55.10(@typescript-eslint/types@8.60.0)) monaco-editor@0.55.1: dependencies: @@ -6187,10 +6201,10 @@ snapshots: dependencies: fast-diff: 1.3.0 - prettier-plugin-svelte@4.0.1(prettier@3.8.3)(svelte@5.55.9(@typescript-eslint/types@8.60.0)): + prettier-plugin-svelte@4.0.1(prettier@3.8.3)(svelte@5.55.10(@typescript-eslint/types@8.60.0)): dependencies: prettier: 3.8.3 - svelte: 5.55.9(@typescript-eslint/types@8.60.0) + svelte: 5.55.10(@typescript-eslint/types@8.60.0) prettier@2.5.1: {} @@ -6257,29 +6271,50 @@ snapshots: '@rolldown/binding-win32-arm64-msvc': 1.0.2 '@rolldown/binding-win32-x64-msvc': 1.0.2 - runed@0.23.4(svelte@5.55.9(@typescript-eslint/types@8.60.0)): + rolldown@1.0.3: + dependencies: + '@oxc-project/types': 0.133.0 + '@rolldown/pluginutils': 1.0.1 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.0.3 + '@rolldown/binding-darwin-arm64': 1.0.3 + '@rolldown/binding-darwin-x64': 1.0.3 + '@rolldown/binding-freebsd-x64': 1.0.3 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.3 + '@rolldown/binding-linux-arm64-gnu': 1.0.3 + '@rolldown/binding-linux-arm64-musl': 1.0.3 + '@rolldown/binding-linux-ppc64-gnu': 1.0.3 + '@rolldown/binding-linux-s390x-gnu': 1.0.3 + '@rolldown/binding-linux-x64-gnu': 1.0.3 + '@rolldown/binding-linux-x64-musl': 1.0.3 + '@rolldown/binding-openharmony-arm64': 1.0.3 + '@rolldown/binding-wasm32-wasi': 1.0.3 + '@rolldown/binding-win32-arm64-msvc': 1.0.3 + '@rolldown/binding-win32-x64-msvc': 1.0.3 + + runed@0.23.4(svelte@5.55.10(@typescript-eslint/types@8.60.0)): dependencies: esm-env: 1.2.2 - svelte: 5.55.9(@typescript-eslint/types@8.60.0) + svelte: 5.55.10(@typescript-eslint/types@8.60.0) - runed@0.25.0(svelte@5.55.9(@typescript-eslint/types@8.60.0)): + runed@0.25.0(svelte@5.55.10(@typescript-eslint/types@8.60.0)): dependencies: esm-env: 1.2.2 - svelte: 5.55.9(@typescript-eslint/types@8.60.0) + svelte: 5.55.10(@typescript-eslint/types@8.60.0) - runed@0.28.0(svelte@5.55.9(@typescript-eslint/types@8.60.0)): + runed@0.28.0(svelte@5.55.10(@typescript-eslint/types@8.60.0)): dependencies: esm-env: 1.2.2 - svelte: 5.55.9(@typescript-eslint/types@8.60.0) + svelte: 5.55.10(@typescript-eslint/types@8.60.0) - runed@0.35.1(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.9(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0)): + runed@0.35.1(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.10(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0)): dependencies: dequal: 2.0.3 esm-env: 1.2.2 lz-string: 1.5.0 - svelte: 5.55.9(@typescript-eslint/types@8.60.0) + svelte: 5.55.10(@typescript-eslint/types@8.60.0) optionalDependencies: - '@sveltejs/kit': 2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.9(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)) + '@sveltejs/kit': 2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.10(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)) sade@1.8.1: dependencies: @@ -6367,25 +6402,25 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - svelte-adapter-bun@1.0.1(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.9(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(typescript@6.0.3): + svelte-adapter-bun@1.0.1(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.10(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(typescript@6.0.3): dependencies: - '@sveltejs/kit': 2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.9(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)) - rolldown: 1.0.2 + '@sveltejs/kit': 2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.10(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)) + rolldown: 1.0.3 typescript: 6.0.3 - svelte-check@4.4.8(picomatch@4.0.4)(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@6.0.3): + svelte-check@4.4.8(picomatch@4.0.4)(svelte@5.55.10(@typescript-eslint/types@8.60.0))(typescript@6.0.3): dependencies: '@jridgewell/trace-mapping': 0.3.31 chokidar: 4.0.3 fdir: 6.5.0(picomatch@4.0.4) picocolors: 1.1.1 sade: 1.8.1 - svelte: 5.55.9(@typescript-eslint/types@8.60.0) + svelte: 5.55.10(@typescript-eslint/types@8.60.0) typescript: 6.0.3 transitivePeerDependencies: - picomatch - svelte-eslint-parser@1.6.1(svelte@5.55.9(@typescript-eslint/types@8.60.0)): + svelte-eslint-parser@1.6.1(svelte@5.55.10(@typescript-eslint/types@8.60.0)): dependencies: eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 @@ -6395,42 +6430,42 @@ snapshots: postcss-selector-parser: 7.1.1 semver: 7.8.1 optionalDependencies: - svelte: 5.55.9(@typescript-eslint/types@8.60.0) + svelte: 5.55.10(@typescript-eslint/types@8.60.0) - svelte-kit-sessions@0.4.0(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.9(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0)): + svelte-kit-sessions@0.4.0(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.10(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0)): dependencies: '@isaacs/ttlcache': 1.4.1 - '@sveltejs/kit': 2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.9(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)) - svelte: 5.55.9(@typescript-eslint/types@8.60.0) + '@sveltejs/kit': 2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.10(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)) + svelte: 5.55.10(@typescript-eslint/types@8.60.0) - svelte-sonner@1.1.1(svelte@5.55.9(@typescript-eslint/types@8.60.0)): + svelte-sonner@1.1.1(svelte@5.55.10(@typescript-eslint/types@8.60.0)): dependencies: - runed: 0.28.0(svelte@5.55.9(@typescript-eslint/types@8.60.0)) - svelte: 5.55.9(@typescript-eslint/types@8.60.0) + runed: 0.28.0(svelte@5.55.10(@typescript-eslint/types@8.60.0)) + svelte: 5.55.10(@typescript-eslint/types@8.60.0) - svelte-toolbelt@0.10.6(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.9(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0)): + svelte-toolbelt@0.10.6(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.10(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0)): dependencies: clsx: 2.1.1 - runed: 0.35.1(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.9(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0)) + runed: 0.35.1(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.10(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0)) style-to-object: 1.0.14 - svelte: 5.55.9(@typescript-eslint/types@8.60.0) + svelte: 5.55.10(@typescript-eslint/types@8.60.0) transitivePeerDependencies: - '@sveltejs/kit' - svelte-toolbelt@0.5.0(svelte@5.55.9(@typescript-eslint/types@8.60.0)): + svelte-toolbelt@0.5.0(svelte@5.55.10(@typescript-eslint/types@8.60.0)): dependencies: clsx: 2.1.1 style-to-object: 1.0.14 - svelte: 5.55.9(@typescript-eslint/types@8.60.0) + svelte: 5.55.10(@typescript-eslint/types@8.60.0) - svelte-toolbelt@0.7.1(svelte@5.55.9(@typescript-eslint/types@8.60.0)): + svelte-toolbelt@0.7.1(svelte@5.55.10(@typescript-eslint/types@8.60.0)): dependencies: clsx: 2.1.1 - runed: 0.23.4(svelte@5.55.9(@typescript-eslint/types@8.60.0)) + runed: 0.23.4(svelte@5.55.10(@typescript-eslint/types@8.60.0)) style-to-object: 1.0.14 - svelte: 5.55.9(@typescript-eslint/types@8.60.0) + svelte: 5.55.10(@typescript-eslint/types@8.60.0) - svelte@5.55.9(@typescript-eslint/types@8.60.0): + svelte@5.55.10(@typescript-eslint/types@8.60.0): dependencies: '@jridgewell/remapping': 2.3.5 '@jridgewell/sourcemap-codec': 1.5.5 @@ -6451,12 +6486,12 @@ snapshots: transitivePeerDependencies: - '@typescript-eslint/types' - sveltekit-superforms@2.30.1(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.9(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(@types/json-schema@7.0.15)(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@6.0.3): + sveltekit-superforms@2.30.1(@sveltejs/kit@2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.10(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(@types/json-schema@7.0.15)(svelte@5.55.10(@typescript-eslint/types@8.60.0))(typescript@6.0.3): dependencies: - '@sveltejs/kit': 2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.9(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.9(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)) + '@sveltejs/kit': 2.61.1(@sveltejs/vite-plugin-svelte@7.1.2(svelte@5.55.10(@typescript-eslint/types@8.60.0))(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)))(svelte@5.55.10(@typescript-eslint/types@8.60.0))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)) devalue: 5.8.1 memoize-weak: 1.0.2 - svelte: 5.55.9(@typescript-eslint/types@8.60.0) + svelte: 5.55.10(@typescript-eslint/types@8.60.0) ts-deepmerge: 7.0.3 optionalDependencies: '@exodus/schemasafe': 1.3.0 @@ -6470,7 +6505,7 @@ snapshots: joi: 17.13.3 json-schema-to-ts: 3.1.1 superstruct: 2.0.2 - typebox: 1.1.38 + typebox: 1.1.39 valibot: 1.4.1(typescript@6.0.3) yup: 1.7.1 zod: 4.4.3 @@ -6479,9 +6514,9 @@ snapshots: - '@types/json-schema' - typescript - synckit@0.11.12: + synckit@0.11.13: dependencies: - '@pkgr/core': 0.2.9 + '@pkgr/core': 0.3.6 tabbable@6.4.0: {} @@ -6540,20 +6575,9 @@ snapshots: type-level-regexp@0.1.17: {} - typebox@1.1.38: + typebox@1.1.39: optional: true - typescript-eslint@8.59.4(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3): - dependencies: - '@typescript-eslint/eslint-plugin': 8.59.4(@typescript-eslint/parser@8.59.4(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3) - '@typescript-eslint/parser': 8.59.4(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3) - '@typescript-eslint/typescript-estree': 8.59.4(typescript@6.0.3) - '@typescript-eslint/utils': 8.59.4(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3) - eslint: 10.4.0(jiti@2.7.0) - typescript: 6.0.3 - transitivePeerDependencies: - - supports-color - typescript-eslint@8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3): dependencies: '@typescript-eslint/eslint-plugin': 8.60.0(@typescript-eslint/parser@8.60.0(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3))(eslint@10.4.0(jiti@2.7.0))(typescript@6.0.3) @@ -6584,7 +6608,7 @@ snapshots: undici-types@7.24.6: {} - undici@6.25.0: {} + undici@6.26.0: {} unicorn-magic@0.3.0: {} @@ -6659,10 +6683,10 @@ snapshots: optionalDependencies: vite: 8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0) - vitest-browser-svelte@2.1.1(svelte@5.55.9(@typescript-eslint/types@8.60.0))(vitest@4.1.7): + vitest-browser-svelte@2.1.1(svelte@5.55.10(@typescript-eslint/types@8.60.0))(vitest@4.1.7): dependencies: - '@testing-library/svelte-core': 1.0.0(svelte@5.55.9(@typescript-eslint/types@8.60.0)) - svelte: 5.55.9(@typescript-eslint/types@8.60.0) + '@testing-library/svelte-core': 1.0.0(svelte@5.55.10(@typescript-eslint/types@8.60.0)) + svelte: 5.55.10(@typescript-eslint/types@8.60.0) vitest: 4.1.7(@types/node@25.9.1)(@vitest/browser-playwright@4.1.7)(@vitest/coverage-v8@4.1.7)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)) vitest@4.1.7(@types/node@25.9.1)(@vitest/browser-playwright@4.1.7)(@vitest/coverage-v8@4.1.7)(vite@8.0.14(@types/node@25.9.1)(jiti@2.7.0)(yaml@2.9.0)): diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 9fb5654..872da56 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -44,7 +44,9 @@ catalogs: i18n: '@inlang/paraglide-js': ^2.18.1 icons: + '@iconify-json/clarity': ^1.2.4 '@iconify-json/ic': ^1.2.4 + '@iconify-json/icomoon-free': ^1.2.1 '@iconify-json/material-icon-theme': ^1.2.66 '@iconify-json/solar': ^1.2.5 '@lucide/svelte': ^1.16.0 @@ -75,24 +77,3 @@ catalogs: playwright: ^1.60.0 vitest: ^4.1.7 vitest-browser-svelte: ^2.1.1 - -minimumReleaseAgeExclude: - - '@iconify-json/material-icon-theme@1.2.66' - - '@nanoforge-dev/actions@2.0.0' - - '@nanoforge-dev/common@1.3.0' - - '@nanoforge-dev/ecs-lib@1.3.0' - - '@typescript-eslint/eslint-plugin@8.60.0' - - '@typescript-eslint/parser@8.60.0' - - '@typescript-eslint/project-service@8.60.0' - - '@typescript-eslint/scope-manager@8.60.0' - - '@typescript-eslint/tsconfig-utils@8.60.0' - - '@typescript-eslint/type-utils@8.60.0' - - '@typescript-eslint/types@8.60.0' - - '@typescript-eslint/typescript-estree@8.60.0' - - '@typescript-eslint/utils@8.60.0' - - '@typescript-eslint/visitor-keys@8.60.0' - - typescript-eslint@8.60.0 - -onlyBuiltDependencies: - - bun - - esbuild diff --git a/src/lib/client/action/repositories/library.repository.ts b/src/lib/client/action/repositories/library.repository.ts new file mode 100644 index 0000000..5ed4341 --- /dev/null +++ b/src/lib/client/action/repositories/library.repository.ts @@ -0,0 +1,8 @@ +import { BaseRepository } from '../base.repository'; +import type { InstallLibraryActionInput, InstallLibraryPackageResult } from '../types'; + +export class ProjectLibraryRepository extends BaseRepository { + install(input: InstallLibraryActionInput): Promise { + return this.run(`/actions/project/library?/install`, input); + } +} diff --git a/src/lib/client/action/repositories/package.repository.ts b/src/lib/client/action/repositories/package.repository.ts index a3e98d7..daeb816 100644 --- a/src/lib/client/action/repositories/package.repository.ts +++ b/src/lib/client/action/repositories/package.repository.ts @@ -4,28 +4,28 @@ import { BaseRepository } from '../base.repository'; import type { AddComponentsActionInput, AddSystemsActionInput, + ComponentPackageResult, CreateComponentActionInput, CreateSystemActionInput, GetComponentsManifestsActionInput, GetSystemsManifestsActionInput, - NewComponentPackageResult, - NewSystemPackageResult, + SystemPackageResult, } from '../types'; export class ProjectPackageRepository extends BaseRepository { - addComponents(input: AddComponentsActionInput): Promise { + addComponents(input: AddComponentsActionInput): Promise { return this.run(`/actions/project/package?/add-components`, input); } - addSystems(input: AddSystemsActionInput): Promise { + addSystems(input: AddSystemsActionInput): Promise { return this.run(`/actions/project/package?/add-systems`, input); } - createComponent(input: CreateComponentActionInput): Promise { + createComponent(input: CreateComponentActionInput): Promise { return this.run(`/actions/project/package?/create-component`, input); } - createSystem(input: CreateSystemActionInput): Promise { + createSystem(input: CreateSystemActionInput): Promise { return this.run(`/actions/project/package?/create-system`, input); } @@ -38,4 +38,12 @@ export class ProjectPackageRepository extends BaseRepository { getSystemsManifests(input: GetSystemsManifestsActionInput): Promise { return this.run(`/actions/project/package?/get-systems-manifests`, input); } + + getComponents(): Promise { + return this.run(`/actions/project/package?/get-components`); + } + + getSystems(): Promise { + return this.run(`/actions/project/package?/get-systems`); + } } diff --git a/src/lib/client/action/types/index.ts b/src/lib/client/action/types/index.ts index 78759b4..bd622f2 100644 --- a/src/lib/client/action/types/index.ts +++ b/src/lib/client/action/types/index.ts @@ -1,4 +1,5 @@ export * from './fs.type'; +export * from './library.type'; export * from './loader.type'; export * from './project.type'; export * from './package.type'; diff --git a/src/lib/client/action/types/library.type.ts b/src/lib/client/action/types/library.type.ts new file mode 100644 index 0000000..c3a3880 --- /dev/null +++ b/src/lib/client/action/types/library.type.ts @@ -0,0 +1,6 @@ +import type { InstallLibraryBody } from '$lib/server/actions/project/library/install-library.action'; +import type { LibraryPackage } from '$lib/server/project/library'; + +export type InstallLibraryActionInput = InstallLibraryBody; + +export type InstallLibraryPackageResult = LibraryPackage; diff --git a/src/lib/client/action/types/package.type.ts b/src/lib/client/action/types/package.type.ts index c347943..645db8c 100644 --- a/src/lib/client/action/types/package.type.ts +++ b/src/lib/client/action/types/package.type.ts @@ -4,14 +4,11 @@ import type { CreateComponentBody } from '$lib/server/actions/project/package/cr import type { CreateSystemBody } from '$lib/server/actions/project/package/create-system.action'; import type { GetComponentManifestBody } from '$lib/server/actions/project/package/get-components-manifests.action'; import type { GetSystemManifestBody } from '$lib/server/actions/project/package/get-systems-manifests.action'; -import type { - NewComponentPackage, - NewSystemPackage, -} from '$lib/server/project/package/package.type'; +import type { ComponentPackage, SystemPackage } from '$lib/server/project/package/package.type'; -export type NewComponentPackageResult = NewComponentPackage; +export type ComponentPackageResult = ComponentPackage; -export type NewSystemPackageResult = NewSystemPackage; +export type SystemPackageResult = SystemPackage; export type AddComponentsActionInput = AddComponentBody; diff --git a/src/lib/client/ecs/component/component-handle.ts b/src/lib/client/ecs/component/component-handle.ts new file mode 100644 index 0000000..4ec19d3 --- /dev/null +++ b/src/lib/client/ecs/component/component-handle.ts @@ -0,0 +1,40 @@ +import { type Writable, get, writable } from 'svelte/store'; + +import { resolveStore } from '../utils'; +import type { ComponentManager } from './component-manager'; +import type { Component } from './component.type'; + +const _storage = writable>>({}); + +export class ComponentHandle { + private _manager: ComponentManager; + private readonly _store: Writable; + public readonly id: string; + + static reset() { + _storage.set({}); + } + + constructor(manager: ComponentManager, component: Component) { + this._manager = manager; + this.id = component.id; + + this._store = resolveStore(_storage, this.id, component); + } + + get store() { + return this._store; + } + + get data() { + return get(this._store); + } + + update(component: Partial) { + this._store.set({ ...get(this._store), ...component }); + } + + delete() { + this._manager.delete(this.id); + } +} diff --git a/src/lib/client/ecs/component/component-manager.ts b/src/lib/client/ecs/component/component-manager.ts new file mode 100644 index 0000000..d00c912 --- /dev/null +++ b/src/lib/client/ecs/component/component-manager.ts @@ -0,0 +1,75 @@ +import { type Unsubscriber, get, writable } from 'svelte/store'; + +import { getId, resetSubscriptions } from '../utils'; +import { ComponentHandle } from './component-handle'; +import type { Component } from './component.type'; + +const _storage = writable([]); + +const _subscriptions = writable>({}); + +export class ComponentManager { + static reset() { + _storage.set([]); + resetSubscriptions(_subscriptions); + } + + constructor(components: Component[]) { + _storage.set(components); + } + + get store() { + return _storage; + } + + get data() { + return get(_storage); + } + + add(component: Omit & Partial>) { + const components = get(_storage); + const id = getId(this.data, component.name); + components.push({ ...component, id, path: component.path ?? `components/${id}.ts` }); + _storage.set(components); + return id; + } + + get(id: string): ComponentHandle { + const component = get(_storage).find((component) => component.id === id); + if (!component) throw new Error(`Component with id ${id} not found`); + const handle = new ComponentHandle(this, component); + + this._subscribe(id, handle); + + return handle; + } + + delete(id: string) { + const components = get(_storage); + _storage.set(components.filter((component) => component.id !== id)); + + const subscriptions = get(_subscriptions); + if (subscriptions[id]) { + subscriptions[id](); + subscriptions[id] = null; + _subscriptions.set(subscriptions); + } + } + + private _subscribe(id: string, handle: ComponentHandle) { + setTimeout(() => { + const subscriptions = get(_subscriptions); + if (subscriptions[id]) return; + subscriptions[id] = handle.store.subscribe((component) => this._update(id, component)); + _subscriptions.set(subscriptions); + }, 0); + } + + private _update(id: string, component: Component) { + const components = get(_storage); + const index = components.findIndex((s) => s.id === id); + if (index === -1) return; + components[index] = component; + _storage.set(components); + } +} diff --git a/src/lib/client/ecs/component/component.type.ts b/src/lib/client/ecs/component/component.type.ts new file mode 100644 index 0000000..cd70660 --- /dev/null +++ b/src/lib/client/ecs/component/component.type.ts @@ -0,0 +1,10 @@ +import type { EditorComponentManifest } from '@nanoforge-dev/ecs-lib'; + +export type ComponentParam = EditorComponentManifest['params'][number]; + +export interface Component { + id: string; + name: string; + path: string; + params: ComponentParam[]; +} diff --git a/src/lib/client/ecs/ecs-handler.ts b/src/lib/client/ecs/ecs-handler.ts new file mode 100644 index 0000000..f5a4eab --- /dev/null +++ b/src/lib/client/ecs/ecs-handler.ts @@ -0,0 +1,91 @@ +import { + componentsTransformer, + librariesTransformer, + scenesTransformer, + systemsTransformer, +} from '$lib/client/ecs/transformers'; +import type { Project } from '$lib/client/project'; + +import { ComponentHandle } from './component/component-handle'; +import { ComponentManager } from './component/component-manager'; +import { LibraryHandle } from './library/library-handle'; +import { LibraryManager } from './library/library-manager'; +import { EntityComponentManager } from './scene/entity/component/component-manager'; +import { ComponentParamHandle } from './scene/entity/component/component-param-handle'; +import { ComponentParamManager } from './scene/entity/component/component-param-manager'; +import { SceneEntityHandle } from './scene/entity/entity-handle'; +import { SceneEntityManager } from './scene/entity/entity-manager'; +import { SceneHandle } from './scene/scene-handle'; +import { SceneManager } from './scene/scene-manager'; +import { SceneSystemManager } from './scene/system/system-manager'; +import { SystemHandle } from './system/system-handle'; +import { SystemManager } from './system/system-manager'; + +export class ECSHandler { + private readonly _project: Project; + + private _sceneManager: SceneManager | undefined; + private _componentManager: ComponentManager | undefined; + private _systemManager: SystemManager | undefined; + private _libraryManager: LibraryManager | undefined; + + static reset() { + ComponentHandle.reset(); + ComponentManager.reset(); + SystemManager.reset(); + SystemHandle.reset(); + LibraryManager.reset(); + LibraryHandle.reset(); + SceneHandle.reset(); + SceneManager.reset(); + SceneSystemManager.reset(); + SceneEntityHandle.reset(); + SceneEntityManager.reset(); + EntityComponentManager.reset(); + ComponentParamHandle.reset(); + ComponentParamManager.reset(); + } + + constructor(project: Project) { + this._project = project; + } + + async init() { + /** + * @todo + * This init is only made for the current version of the editor + * When scenes will be implemented, this init must be changed accordingly + */ + + const components = await this._project.actions.package.getComponents(); + const systems = await this._project.actions.package.getSystems(); + // Cannot use save handler as it needs to use ecs handler to subscribe to ecs changes + const save = await this._project.actions.save.get(); + + this._componentManager = new ComponentManager(componentsTransformer(components)); + this._systemManager = new SystemManager(systemsTransformer(systems)); + this._libraryManager = new LibraryManager(librariesTransformer(save)); + // Scene Manager needs others managers to be initialized + this._sceneManager = new SceneManager(this, scenesTransformer(save), ['default'], 'default'); + } + + get scenes(): SceneManager { + if (!this._sceneManager) throw new Error('ECS handler not initialized'); + return this._sceneManager; + } + + get components(): ComponentManager { + if (!this._componentManager) throw new Error('ECS handler not initialized'); + return this._componentManager; + } + + get systems(): SystemManager { + if (!this._systemManager) throw new Error('ECS handler not initialized'); + return this._systemManager; + } + + get libraries(): LibraryManager { + if (!this._libraryManager) throw new Error('ECS handler not initialized'); + return this._libraryManager; + } +} diff --git a/src/lib/client/ecs/index.ts b/src/lib/client/ecs/index.ts new file mode 100644 index 0000000..b1e94f8 --- /dev/null +++ b/src/lib/client/ecs/index.ts @@ -0,0 +1,30 @@ +export { ECSHandler } from './ecs-handler'; + +export type { ComponentHandle } from './component/component-handle'; +export type { ComponentManager } from './component/component-manager'; +export type { Component, ComponentParam } from './component/component.type'; + +export type { LibraryManager } from './library/library-manager'; +export type { LibraryHandle } from './library/library-handle'; +export type { Library } from './library/library.type'; + +export type { SystemManager } from './system/system-manager'; +export type { SystemHandle } from './system/system-handle'; +export type { System } from './system/system.type'; + +export type { SceneHandle } from './scene/scene-handle'; +export type { SceneManager } from './scene/scene-manager'; +export type { Scene } from './scene/scene.type'; + +export type { SceneSystemManager } from './scene/system/system-manager'; +export type { SceneSystemHandle } from './scene/system/system-handle'; + +export type { SceneEntityHandle } from './scene/entity/entity-handle'; +export type { SceneEntityManager } from './scene/entity/entity-manager'; +export type { Entity } from './scene/entity/entity.type'; + +export type { EntityComponentHandle } from './scene/entity/component/component-handle'; +export type { EntityComponentManager } from './scene/entity/component/component-manager'; + +export type { ComponentParamHandle } from './scene/entity/component/component-param-handle'; +export type { ComponentParamManager } from './scene/entity/component/component-param-manager'; diff --git a/src/lib/client/ecs/library/library-handle.ts b/src/lib/client/ecs/library/library-handle.ts new file mode 100644 index 0000000..6c2c9fb --- /dev/null +++ b/src/lib/client/ecs/library/library-handle.ts @@ -0,0 +1,40 @@ +import { type Writable, get, writable } from 'svelte/store'; + +import { resolveStore } from '../utils'; +import type { LibraryManager } from './library-manager'; +import type { Library } from './library.type'; + +const _storage = writable>>({}); + +export class LibraryHandle { + private _manager: LibraryManager; + public readonly id: string; + private readonly _store: Writable; + + static reset() { + _storage.set({}); + } + + constructor(manager: LibraryManager, library: Library) { + this._manager = manager; + this.id = library.id; + + this._store = resolveStore(_storage, this.id, library); + } + + get store() { + return this._store; + } + + get data() { + return get(this._store); + } + + update(library: Partial) { + this._store.set({ ...get(this._store), ...library }); + } + + delete() { + this._manager.delete(this.id); + } +} diff --git a/src/lib/client/ecs/library/library-manager.ts b/src/lib/client/ecs/library/library-manager.ts new file mode 100644 index 0000000..ef7599c --- /dev/null +++ b/src/lib/client/ecs/library/library-manager.ts @@ -0,0 +1,73 @@ +import { type Unsubscriber, get, writable } from 'svelte/store'; + +import { resetSubscriptions } from '../utils'; +import { LibraryHandle } from './library-handle'; +import type { Library } from './library.type'; + +const _storage = writable([]); +const _subscriptions = writable>({}); + +export class LibraryManager { + static reset() { + _storage.set([]); + resetSubscriptions(_subscriptions); + } + + constructor(libraries: Library[]) { + _storage.set(libraries); + } + + get store() { + return _storage; + } + + get data() { + return get(_storage); + } + + add(library: { name: string }): string { + const libraries = get(_storage); + libraries.push({ ...library, id: library.name }); + _storage.set(libraries); + return library.name; + } + + get(id: string): LibraryHandle { + const library = get(_storage).find((library) => library.id === id); + if (!library) throw new Error(`Library with id ${id} not found`); + const handle = new LibraryHandle(this, library); + + this._subscribe(id, handle); + + return handle; + } + + delete(id: string) { + const libraries = get(_storage); + _storage.set(libraries.filter((library) => library.id !== id)); + + const subscriptions = get(_subscriptions); + if (subscriptions[id]) { + subscriptions[id](); + subscriptions[id] = null; + _subscriptions.set(subscriptions); + } + } + + private _subscribe(id: string, handle: LibraryHandle) { + setTimeout(() => { + const subscriptions = get(_subscriptions); + if (subscriptions[id]) return; + subscriptions[id] = handle.store.subscribe((library) => this._update(id, library)); + _subscriptions.set(subscriptions); + }, 0); + } + + private _update(id: string, library: Library) { + const libraries = get(_storage); + const index = libraries.findIndex((s) => s.id === id); + if (index === -1) return; + libraries[index] = library; + _storage.set(libraries); + } +} diff --git a/src/lib/client/ecs/library/library.type.ts b/src/lib/client/ecs/library/library.type.ts new file mode 100644 index 0000000..4c3389c --- /dev/null +++ b/src/lib/client/ecs/library/library.type.ts @@ -0,0 +1,4 @@ +export interface Library { + id: string; + name: string; +} diff --git a/src/lib/client/ecs/scene/entity/component/component-handle.ts b/src/lib/client/ecs/scene/entity/component/component-handle.ts new file mode 100644 index 0000000..27be6f6 --- /dev/null +++ b/src/lib/client/ecs/scene/entity/component/component-handle.ts @@ -0,0 +1,39 @@ +import { type Readable, get } from 'svelte/store'; + +import type { Component } from '../../../component/component.type'; +import type { EntityComponentManager } from './component-manager'; +import { ComponentParamManager } from './component-param-manager'; + +export class EntityComponentHandle { + public readonly manager: EntityComponentManager; + public readonly id: string; + private readonly _store: Readable; + private readonly _params: ComponentParamManager; + + constructor( + manager: EntityComponentManager, + componentId: string, + params: Record, + ) { + this.manager = manager; + this._store = manager.entity.manager.scene.manager.ecs.components.get(componentId).store; + this.id = componentId; + this._params = new ComponentParamManager(this, params); + } + + get store() { + return this._store; + } + + get data() { + return get(this._store); + } + + get params(): ComponentParamManager { + return this._params; + } + + delete() { + this.manager.delete(this.id); + } +} diff --git a/src/lib/client/ecs/scene/entity/component/component-manager.ts b/src/lib/client/ecs/scene/entity/component/component-manager.ts new file mode 100644 index 0000000..f40514b --- /dev/null +++ b/src/lib/client/ecs/scene/entity/component/component-manager.ts @@ -0,0 +1,108 @@ +import { type Unsubscriber, type Writable, get, writable } from 'svelte/store'; + +import { resetListeners, resetSubscriptions } from '../../../utils'; +import { resolveStore } from '../../../utils'; +import type { SceneEntityHandle } from '../entity-handle'; +import { EntityComponentHandle } from './component-handle'; + +const _storage = writable>>>>({}); + +const _subscriptions = writable>({}); + +const _listener = writable(); + +export class EntityComponentManager { + public readonly entity: SceneEntityHandle; + private readonly _store: Writable>>; + + static reset() { + _storage.set({}); + resetSubscriptions(_subscriptions); + resetListeners(_listener); + } + + constructor(entity: SceneEntityHandle, components: Record>) { + this.entity = entity; + + const storageResolvable = `${this.entity.manager.scene.id}/${this.entity.id}`; + + this._store = resolveStore(_storage, storageResolvable, components); + + this._listen(); + } + + get store() { + return this._store; + } + + get data() { + return get(this._store); + } + + add(component: string) { + const components = get(this._store); + const manifest = this.entity.manager.scene.manager.ecs.components.get(component).data; + components[component] = { + ...Object.fromEntries( + manifest.params + .filter((param) => param.default) + .map((param) => [param.name, param.default as string]), + ), + }; + this._store.set(components); + } + + get(id: string): EntityComponentHandle { + const params = get(this._store)[id]; + if (!params) throw new Error(`Component with id ${id} not found`); + const handle = new EntityComponentHandle(this, id, params); + + this._subscribe(id, handle); + + return handle; + } + + delete(id: string) { + const components = get(this._store); + const newComponents: Record> = {}; + Object.entries(components).forEach(([key, params]) => { + if (key !== id) newComponents[key] = params; + }); + this._store.set(newComponents); + + const subscriptions = get(_subscriptions); + if (subscriptions[id]) { + subscriptions[id](); + subscriptions[id] = null; + _subscriptions.set(subscriptions); + } + } + + private _listen() { + if (get(_listener)) return; + const unsub = this.entity.manager.scene.manager.ecs.components.store.subscribe((components) => { + const entityComponents = get(this._store); + const newComponents: Record> = {}; + Object.entries(entityComponents).forEach(([key, params]) => { + if (components.find((s) => s.id === key)) newComponents[key] = params; + }); + this._store.set(newComponents); + }); + _listener.set([unsub]); + } + + private _subscribe(id: string, handle: EntityComponentHandle) { + setTimeout(() => { + const subscriptions = get(_subscriptions); + if (subscriptions[id]) return; + subscriptions[id] = handle.params.values.subscribe((params) => this._update(id, params)); + _subscriptions.set(subscriptions); + }, 0); + } + + private _update(id: string, params: Record) { + const component = get(this._store); + component[id] = params; + this._store.set(component); + } +} diff --git a/src/lib/client/ecs/scene/entity/component/component-param-handle.ts b/src/lib/client/ecs/scene/entity/component/component-param-handle.ts new file mode 100644 index 0000000..a9b1c6b --- /dev/null +++ b/src/lib/client/ecs/scene/entity/component/component-param-handle.ts @@ -0,0 +1,57 @@ +import { type Readable, type Unsubscriber, type Writable, get, writable } from 'svelte/store'; + +import type { ComponentParam } from '../../../component/component.type'; +import { resetListeners, resolveStore } from '../../../utils'; +import type { ComponentParamManager } from './component-param-manager'; + +const _storage = writable>>({}); +const _valueStorage = writable>>({}); + +const _listener = writable(); + +export class ComponentParamHandle { + public readonly manager: ComponentParamManager; + public readonly id: string; + private readonly _store: Writable; + private readonly _valueStore: Writable; + + static reset() { + _storage.set({}); + _valueStorage.set({}); + resetListeners(_listener); + } + + constructor(manager: ComponentParamManager, param: ComponentParam, value: any | undefined) { + this.manager = manager; + this.id = param.name; + + const storageResolvable = `${this.manager.component.manager.entity.manager.scene.id}/${this.manager.component.manager.entity.id}/${this.manager.component.id}/${this.id}`; + + this._store = resolveStore(_storage, storageResolvable, param); + this._valueStore = resolveStore(_valueStorage, storageResolvable, value); + + this._listen(); + } + + get store(): Readable { + return this._store; + } + + get value() { + return this._valueStore; + } + + delete() { + this.manager.delete(this.id); + } + + private _listen() { + if (get(_listener)) return; + const unsub = this.manager.component.store.subscribe((component) => { + const newParam = component.params.find((param) => param.name === this.id); + if (!newParam) return; + this._store.set(newParam); + }); + _listener.set([unsub]); + } +} diff --git a/src/lib/client/ecs/scene/entity/component/component-param-manager.ts b/src/lib/client/ecs/scene/entity/component/component-param-manager.ts new file mode 100644 index 0000000..47b8adc --- /dev/null +++ b/src/lib/client/ecs/scene/entity/component/component-param-manager.ts @@ -0,0 +1,95 @@ +import { type Unsubscriber, type Writable, get, writable } from 'svelte/store'; + +import type { ComponentParam } from '../../../component/component.type'; +import { resetListeners, resetSubscriptions } from '../../../utils'; +import { resolveStore } from '../../../utils'; +import type { EntityComponentHandle } from './component-handle'; +import { ComponentParamHandle } from './component-param-handle'; + +const _storage = writable>>({}); +const _valueStorage = writable>>>({}); + +const _subscriptions = writable>({}); + +const _listener = writable(); + +export class ComponentParamManager { + public readonly component: EntityComponentHandle; + private readonly _store: Writable; + private readonly _valuesStore: Writable>; + + static reset() { + _storage.set({}); + _valueStorage.set({}); + resetSubscriptions(_subscriptions); + resetListeners(_listener); + } + + constructor(component: EntityComponentHandle, params: Record) { + this.component = component; + + const storageResolvable = `${this.component.manager.entity.manager.scene.id}/${this.component.manager.entity.id}/${this.component.id}`; + + this._store = resolveStore(_storage, storageResolvable, get(component.store).params); + this._valuesStore = resolveStore(_valueStorage, storageResolvable, params); + + this._listen(); + } + + get store() { + return this._store; + } + + get values() { + return this._valuesStore; + } + + get(id: string): ComponentParamHandle { + const param = get(this._store).find((param) => param.name === id); + if (!param) throw new Error(`Param with id ${id} not found`); + + const value = get(this._valuesStore)[id]; + const handle = new ComponentParamHandle(this, param, value); + + this._subscribe(id, handle); + + return handle; + } + + delete(id: string) { + const params = get(this._store); + this._store.set( + params.map((param) => (param.name === id ? { ...param, value: undefined } : param)), + ); + + const subscriptions = get(_subscriptions); + if (subscriptions[id]) { + subscriptions[id](); + subscriptions[id] = null; + _subscriptions.set(subscriptions); + } + } + + private _listen() { + if (get(_listener)) return; + const unsub = this.component.store.subscribe((component) => { + this._store.set(component.params); + }); + _listener.set([unsub]); + } + + private _subscribe(id: string, handle: ComponentParamHandle) { + setTimeout(() => { + const subscriptions = get(_subscriptions); + if (subscriptions[id]) return; + subscriptions[id] = handle.value.subscribe((param) => this._update(id, param)); + _subscriptions.set(subscriptions); + }, 0); + } + + private _update(id: string, value: any | undefined) { + const params = get(this._valuesStore); + params[id] = value; + this._valuesStore.set(params); + } +} diff --git a/src/lib/client/ecs/scene/entity/entity-handle.ts b/src/lib/client/ecs/scene/entity/entity-handle.ts new file mode 100644 index 0000000..cec2794 --- /dev/null +++ b/src/lib/client/ecs/scene/entity/entity-handle.ts @@ -0,0 +1,67 @@ +import { type Unsubscriber, type Writable, get, writable } from 'svelte/store'; + +import { resetListeners, resolveStore } from '../../utils'; +import { EntityComponentManager } from './component/component-manager'; +import type { SceneEntityManager } from './entity-manager'; +import type { Entity } from './entity.type'; + +const _storage = writable>>({}); + +const _listener = writable(); + +export class SceneEntityHandle { + public readonly manager: SceneEntityManager; + public readonly id: string; + private readonly _store: Writable; + private readonly _components: EntityComponentManager; + + static reset() { + _storage.set({}); + resetListeners(_listener); + } + + constructor(manager: SceneEntityManager, entity: Entity) { + this.manager = manager; + this.id = entity.id; + + this._store = resolveStore(_storage, `${this.manager.scene.id}/${this.id}`, entity); + + this._components = new EntityComponentManager(this, entity.components); + + this._listen(); + } + + get store() { + return this._store; + } + + get data() { + return get(this._store); + } + + get components() { + return this._components; + } + + update(entity: Partial) { + this._store.set({ ...get(this._store), ...entity }); + } + + delete() { + this.manager.delete(this.id); + } + + setSelected() { + this.manager.selected = this; + } + + private _listen() { + if (get(_listener)) return; + const unsub = this._components.store.subscribe((components) => { + const entity = get(this._store); + entity.components = components; + this._store.set(entity); + }); + _listener.set([unsub]); + } +} diff --git a/src/lib/client/ecs/scene/entity/entity-manager.ts b/src/lib/client/ecs/scene/entity/entity-manager.ts new file mode 100644 index 0000000..7c2238d --- /dev/null +++ b/src/lib/client/ecs/scene/entity/entity-manager.ts @@ -0,0 +1,100 @@ +import { type Unsubscriber, type Writable, get, writable } from 'svelte/store'; + +import { getId, resetSubscriptions } from '../../utils'; +import { resolveStore } from '../../utils'; +import type { SceneHandle } from '../scene-handle'; +import { SceneEntityHandle } from './entity-handle'; +import type { Entity } from './entity.type'; + +const _storage = writable>>({}); + +const _subscriptions = writable>({}); + +const selectedEntity = writable(undefined); + +export class SceneEntityManager { + public readonly scene: SceneHandle; + private readonly _store: Writable; + + static reset() { + _storage.set({}); + resetSubscriptions(_subscriptions); + } + + constructor(scene: SceneHandle, entities: Entity[]) { + this.scene = scene; + + this._store = resolveStore(_storage, this.scene.id, entities); + } + + get store() { + return this._store; + } + + get data() { + return get(this._store); + } + + get selectedData(): SceneEntityHandle | undefined { + return get(selectedEntity); + } + + get selected(): Writable { + return selectedEntity; + } + + set selected(entity: SceneEntityHandle | undefined) { + selectedEntity.set(entity); + } + + add(entity: Omit): string { + const entities = get(this._store); + const id = getId(this.data, entity.name); + entities.push({ ...entity, id }); + this._store.set(entities); + return id; + } + + get(id: string): SceneEntityHandle { + const entity = get(this._store).find((entity) => entity.id === id); + if (!entity) throw new Error(`Entity with id ${id} not found`); + const handle = new SceneEntityHandle(this, entity); + + this._subscribe(id, handle); + + return handle; + } + + delete(id: string) { + const entities = get(this._store); + this._store.set(entities.filter((entity) => entity.id !== id)); + + const subscriptions = get(_subscriptions); + if (subscriptions[id]) { + subscriptions[id](); + subscriptions[id] = null; + _subscriptions.set(subscriptions); + } + + if (this.selectedData?.id === id) { + this.selected = undefined; + } + } + + private _subscribe(id: string, handle: SceneEntityHandle) { + setTimeout(() => { + const subscriptions = get(_subscriptions); + if (subscriptions[id]) return; + subscriptions[id] = handle.store.subscribe((entity) => this._update(id, entity)); + _subscriptions.set(subscriptions); + }, 0); + } + + private _update(id: string, entity: Entity) { + const entities = get(this._store); + const index = entities.findIndex((s) => s.id === id); + if (index === -1) return; + entities[index] = entity; + this._store.set(entities); + } +} diff --git a/src/lib/client/ecs/scene/entity/entity.type.ts b/src/lib/client/ecs/scene/entity/entity.type.ts new file mode 100644 index 0000000..50e6edd --- /dev/null +++ b/src/lib/client/ecs/scene/entity/entity.type.ts @@ -0,0 +1,6 @@ +export interface Entity { + id: string; + name: string; + treePath: string; + components: Record>; +} diff --git a/src/lib/client/ecs/scene/scene-handle.ts b/src/lib/client/ecs/scene/scene-handle.ts new file mode 100644 index 0000000..05eb4eb --- /dev/null +++ b/src/lib/client/ecs/scene/scene-handle.ts @@ -0,0 +1,85 @@ +import { type Unsubscriber, type Writable, get, writable } from 'svelte/store'; + +import { resetListeners, resolveStore } from '../utils'; +import { SceneEntityManager } from './entity/entity-manager'; +import type { SceneManager } from './scene-manager'; +import type { Scene } from './scene.type'; +import { SceneSystemManager } from './system/system-manager'; + +const _storage = writable>>({}); + +const _listener = writable(); + +export class SceneHandle { + public readonly manager: SceneManager; + public readonly id: string; + private readonly _store: Writable; + private readonly _entities: SceneEntityManager; + private readonly _systems: SceneSystemManager; + + static reset() { + _storage.set({}); + resetListeners(_listener); + } + + constructor(manager: SceneManager, scene: Scene) { + this.manager = manager; + this.id = scene.id; + + this._store = resolveStore(_storage, this.id, scene); + + this._entities = new SceneEntityManager(this, scene.entities); + this._systems = new SceneSystemManager(this, scene.systems); + + this._listen(); + } + + get store() { + return this._store; + } + + get data() { + return get(this._store); + } + + get entities() { + return this._entities; + } + + get systems() { + return this._systems; + } + + update(scene: Partial) { + this._store.set({ ...get(this._store), ...scene }); + } + + delete() { + this.manager.delete(this.id); + } + + setActive() { + this.manager.active = this; + } + + setDefault() { + this.manager.default = this.id; + } + + private _listen() { + if (get(_listener)) return; + const unsub = [ + this._entities.store.subscribe((entities) => { + const scene = get(this._store); + scene.entities = entities; + this._store.set(scene); + }), + this._systems.store.subscribe((systems) => { + const scene = get(this._store); + scene.systems = systems; + this._store.set(scene); + }), + ]; + _listener.set(unsub); + } +} diff --git a/src/lib/client/ecs/scene/scene-manager.ts b/src/lib/client/ecs/scene/scene-manager.ts new file mode 100644 index 0000000..99b5914 --- /dev/null +++ b/src/lib/client/ecs/scene/scene-manager.ts @@ -0,0 +1,142 @@ +import { type Unsubscriber, type Writable, get, writable } from 'svelte/store'; + +import type { ECSHandler } from '../ecs-handler'; +import { getId, resetSubscriptions } from '../utils'; +import { SceneHandle } from './scene-handle'; +import type { Scene } from './scene.type'; + +const _storage = writable([]); +const _rootScenesStorage = writable([]); +const _activeSceneStorage = writable(); +const _defaultSceneStorage = writable(); + +const _subscriptions = writable>({}); + +export class SceneManager { + public readonly ecs: ECSHandler; + + static reset() { + _storage.set([]); + _rootScenesStorage.set([]); + _activeSceneStorage.set(undefined as any); + _defaultSceneStorage.set(undefined as any); + resetSubscriptions(_subscriptions); + } + + constructor(ecs: ECSHandler, scenes: Scene[], rootScenes: string[], defaultSceneId: string) { + this.ecs = ecs; + _storage.set(scenes); + + const defaultScene = scenes.find((scene) => scene.id === defaultSceneId); + if (!defaultScene) throw new Error(`Default scene with id ${defaultSceneId} not found`); + + _activeSceneStorage.set(new SceneHandle(this, defaultScene)); + _defaultSceneStorage.set(defaultSceneId); + _rootScenesStorage.set(rootScenes); + } + + get store() { + return _storage; + } + + get data() { + return get(_storage); + } + + get activeData(): SceneHandle { + return get(_activeSceneStorage); + } + + get active(): Writable { + return _activeSceneStorage; + } + + set active(handle: SceneHandle) { + _activeSceneStorage.set(handle); + } + + get defaultData(): string { + return get(_defaultSceneStorage); + } + + get default(): Writable { + return _defaultSceneStorage; + } + + set default(handle: string) { + _defaultSceneStorage.set(handle); + } + + get rootScenes(): string[] { + return get(_rootScenesStorage); + } + + get rootScenesStore(): Writable { + return _rootScenesStorage; + } + + set rootScenes(scenes: string[]) { + _rootScenesStorage.set(Array.from(new Set(scenes))); + } + + add(scene: Omit): string { + const scenes = get(_storage); + const id = getId(this.data, scene.name); + scenes.push({ ...scene, id }); + _storage.set(scenes); + return id; + } + + get(id: string): SceneHandle { + const scene = get(_storage).find((scene) => scene.id === id); + if (!scene) throw new Error(`Scene with id ${id} not found`); + const handle = new SceneHandle(this, scene); + + this._subscribe(id, handle); + + return handle; + } + + delete(id: string) { + const scenes = get(_storage); + _storage.set(scenes.filter((scene) => scene.id !== id)); + + const subscriptions = get(_subscriptions); + if (subscriptions[id]) { + subscriptions[id](); + subscriptions[id] = null; + _subscriptions.set(subscriptions); + } + + if (this.rootScenes.includes(id)) + this.rootScenes = this.rootScenes.filter((scene) => scene !== id); + + if (this.defaultData === id) { + this.get(this.data.find((v) => !!v)?.id ?? '').setDefault(); + } + + if (this.activeData.id === id) { + this.get( + (this.data.find((scene) => scene.id === this.defaultData) ?? this.data.find((v) => !!v)) + ?.id ?? '', + ).setActive(); + } + } + + private _subscribe(id: string, handle: SceneHandle) { + setTimeout(() => { + const subscriptions = get(_subscriptions); + if (subscriptions[id]) return; + subscriptions[id] = handle.store.subscribe((scene) => this._update(id, scene)); + _subscriptions.set(subscriptions); + }, 0); + } + + private _update(id: string, scene: Scene) { + const scenes = get(_storage); + const index = scenes.findIndex((s) => s.id === id); + if (index === -1) return; + scenes[index] = scene; + _storage.set(scenes); + } +} diff --git a/src/lib/client/ecs/scene/scene.type.ts b/src/lib/client/ecs/scene/scene.type.ts new file mode 100644 index 0000000..c7c8330 --- /dev/null +++ b/src/lib/client/ecs/scene/scene.type.ts @@ -0,0 +1,11 @@ +import type { Entity } from './entity/entity.type'; + +export interface Scene { + id: string; + name: string; + path: string; + subScenes: string[]; + assets: string[]; + systems: string[]; + entities: Entity[]; +} diff --git a/src/lib/client/ecs/scene/system/system-handle.ts b/src/lib/client/ecs/scene/system/system-handle.ts new file mode 100644 index 0000000..10965d3 --- /dev/null +++ b/src/lib/client/ecs/scene/system/system-handle.ts @@ -0,0 +1,29 @@ +import { type Readable, get } from 'svelte/store'; + +import type { System } from '../../system/system.type'; +import type { SceneSystemManager } from './system-manager'; + +export class SceneSystemHandle { + public readonly manager: SceneSystemManager; + public readonly id: string; + private readonly _store: Readable; + + constructor(manager: SceneSystemManager, systemId: string) { + this.manager = manager; + this.id = systemId; + + this._store = manager.scene.manager.ecs.systems.get(systemId).store; + } + + get store() { + return this._store; + } + + get data() { + return get(this._store); + } + + delete() { + this.manager.delete(this.id); + } +} diff --git a/src/lib/client/ecs/scene/system/system-manager.ts b/src/lib/client/ecs/scene/system/system-manager.ts new file mode 100644 index 0000000..d17dedd --- /dev/null +++ b/src/lib/client/ecs/scene/system/system-manager.ts @@ -0,0 +1,62 @@ +import { type Unsubscriber, type Writable, get, writable } from 'svelte/store'; + +import { resetListeners, resolveStore } from '../../utils'; +import type { SceneHandle } from '../scene-handle'; +import { SceneSystemHandle } from './system-handle'; + +const _storage = writable>>({}); + +const _listener = writable(); + +export class SceneSystemManager { + public readonly scene: SceneHandle; + private readonly _store: Writable; + + static reset() { + _storage.set({}); + resetListeners(_listener); + } + + constructor(scene: SceneHandle, systems: string[]) { + this.scene = scene; + + this._store = resolveStore(_storage, this.scene.id, systems); + + this._listen(); + } + + get store() { + return this._store; + } + + get data() { + return get(this._store); + } + + add(system: string) { + const systems = get(this._store); + systems.push(system); + this._store.set(systems); + } + + get(id: string) { + const system = get(this._store).find((system) => system === id); + if (!system) throw new Error(`System with id ${id} not found`); + return new SceneSystemHandle(this, system); + } + + delete(id: string) { + const systems = get(this._store); + this._store.set(systems.filter((system) => system !== id)); + } + + private _listen() { + if (get(_listener)) return; + const unsub = this.scene.manager.ecs.systems.store.subscribe((systems) => { + const sceneSystems = get(this._store); + sceneSystems.filter((system) => systems.find((s) => s.id === system)); + this._store.set(sceneSystems); + }); + _listener.set([unsub]); + } +} diff --git a/src/lib/client/ecs/system/system-handle.ts b/src/lib/client/ecs/system/system-handle.ts new file mode 100644 index 0000000..d963691 --- /dev/null +++ b/src/lib/client/ecs/system/system-handle.ts @@ -0,0 +1,40 @@ +import { type Writable, get, writable } from 'svelte/store'; + +import { resolveStore } from '../utils'; +import type { SystemManager } from './system-manager'; +import type { System } from './system.type'; + +const _storage = writable>>({}); + +export class SystemHandle { + private _manager: SystemManager; + public readonly id: string; + private readonly _store: Writable; + + static reset() { + _storage.set({}); + } + + constructor(manager: SystemManager, system: System) { + this._manager = manager; + this.id = system.id; + + this._store = resolveStore(_storage, this.id, system); + } + + get store() { + return this._store; + } + + get data() { + return get(this._store); + } + + update(system: Partial) { + this._store.set({ ...get(this._store), ...system }); + } + + delete() { + this._manager.delete(this.id); + } +} diff --git a/src/lib/client/ecs/system/system-manager.ts b/src/lib/client/ecs/system/system-manager.ts new file mode 100644 index 0000000..3fdfedc --- /dev/null +++ b/src/lib/client/ecs/system/system-manager.ts @@ -0,0 +1,74 @@ +import { type Unsubscriber, get, writable } from 'svelte/store'; + +import { getId, resetSubscriptions } from '../utils'; +import { SystemHandle } from './system-handle'; +import type { System } from './system.type'; + +const _storage = writable([]); +const _subscriptions = writable>({}); + +export class SystemManager { + static reset() { + _storage.set([]); + resetSubscriptions(_subscriptions); + } + + constructor(systems: System[]) { + _storage.set(systems); + } + + get store() { + return _storage; + } + + get data() { + return get(_storage); + } + + add(system: Omit & Partial>): string { + const systems = get(_storage); + const id = getId(this.data, system.name); + systems.push({ ...system, id, path: system.path ?? `systems/${id}.ts` }); + _storage.set(systems); + return id; + } + + get(id: string): SystemHandle { + const system = get(_storage).find((system) => system.id === id); + if (!system) throw new Error(`System with id ${id} not found`); + const handle = new SystemHandle(this, system); + + this._subscribe(id, handle); + + return handle; + } + + delete(id: string) { + const systems = get(_storage); + _storage.set(systems.filter((system) => system.id !== id)); + + const subscriptions = get(_subscriptions); + if (subscriptions[id]) { + subscriptions[id](); + subscriptions[id] = null; + _subscriptions.set(subscriptions); + } + } + + private _subscribe(id: string, handle: SystemHandle) { + setTimeout(() => { + const subscriptions = get(_subscriptions); + if (subscriptions[id]) return; + subscriptions[id] = handle.store.subscribe((system) => this._update(id, system)); + _subscriptions.set(subscriptions); + }, 0); + } + + private _update(id: string, system: System) { + const systems = get(_storage); + const index = systems.findIndex((s) => s.id === id); + if (index === -1) return; + systems[index] = system; + _storage.set(systems); + } +} diff --git a/src/lib/client/ecs/system/system.type.ts b/src/lib/client/ecs/system/system.type.ts new file mode 100644 index 0000000..1fb33ea --- /dev/null +++ b/src/lib/client/ecs/system/system.type.ts @@ -0,0 +1,5 @@ +export interface System { + id: string; + name: string; + path: string; +} diff --git a/src/lib/client/ecs/transformers.ts b/src/lib/client/ecs/transformers.ts new file mode 100644 index 0000000..031dceb --- /dev/null +++ b/src/lib/client/ecs/transformers.ts @@ -0,0 +1,42 @@ +import type { Component, Library, Scene, System } from '$lib/client/ecs'; +import type { ComponentPackage, SystemPackage } from '$lib/server/project/package'; + +import type { Save } from '@utils/types'; + +export const componentsTransformer = (components: ComponentPackage[]): Component[] => + components.map((component) => ({ + id: component.manifest.name, + name: component.manifest.name, + path: component.save.path, + params: component.manifest.params, + })); + +export const systemsTransformer = (systems: SystemPackage[]): System[] => + systems.map((system) => ({ + id: system.manifest.name, + name: system.manifest.name, + path: system.save.path, + })); + +export const librariesTransformer = (save: Save): Library[] => + save.libraries.map((lib) => ({ + id: lib.path, + name: lib.name, + })); + +export const scenesTransformer = (save: Save): Scene[] => [ + { + id: 'default', + name: 'Default', + path: 'unknown', + subScenes: [], + assets: [], + systems: save.systems.map((system) => system.name), + entities: save.entities.map((entity) => ({ + id: entity.id, + name: entity.id, + treePath: entity.treePath, + components: entity.components, + })), + }, +]; diff --git a/src/lib/client/ecs/utils.ts b/src/lib/client/ecs/utils.ts new file mode 100644 index 0000000..7d09836 --- /dev/null +++ b/src/lib/client/ecs/utils.ts @@ -0,0 +1,49 @@ +import { type Unsubscriber, type Writable, get, writable } from 'svelte/store'; + +import { formatFrom } from '@utils/format'; +import { randomString } from '@utils/string'; + +export const resetSubscriptions = (store: Writable>) => { + const subscriptions = get(store); + Object.values(subscriptions).forEach((sub) => { + try { + sub?.(); + } catch { + /* empty */ + } + }); + store.set({}); +}; + +export const resetListeners = (store: Writable) => { + const listeners = get(store); + listeners?.forEach((sub) => { + try { + sub(); + } catch { + /* empty */ + } + }); + store.set(null); +}; + +export const resolveStore = ( + storage: Writable>>, + resolvable: string, + defaultValue?: T, +) => { + const content = get(storage); + if (resolvable in content) return content[resolvable]; + content[resolvable] = writable(defaultValue); + storage.set(content); + return content[resolvable]; +}; + +export const getId = (data: { id: string }[], name: string): string => { + const baseId = formatFrom.all(name).toSnake(); + let id = baseId; + while (data.find((d) => d.id === id)) { + id = `${baseId}_${randomString(5)}`; + } + return id; +}; diff --git a/src/lib/client/project/package-handler.ts b/src/lib/client/project/package-handler.ts index d3e0a01..e69fc51 100644 --- a/src/lib/client/project/package-handler.ts +++ b/src/lib/client/project/package-handler.ts @@ -3,7 +3,7 @@ import type { EditorComponentManifest, EditorSystemManifest } from '@nanoforge-d import type { Project } from '$lib/client/project'; export class PackageHandler { - private _project: Project; + private readonly _project: Project; private _componentsManifests: Map = new Map(); private _systemsManifests: Map = new Map(); @@ -13,30 +13,31 @@ export class PackageHandler { } async init() { - if (this._project.save.save.components.length > 0) { - this._componentsManifests = new Map( - ( - await this._project.actions.package.getComponentsManifests({ - componentPaths: this._project.save.save.components.map((c) => c.path) as [ - string, - ...string[], - ], - }) - ).map((e, index) => [this._project.save.save.components[index].name, e]), - ); - } - if (this._project.save.save.systems.length > 0) { - this._systemsManifests = new Map( - ( - await this._project.actions.package.getSystemsManifests({ - systemPaths: this._project.save.save.systems.map((s) => s.path) as [ - string, - ...string[], - ], - }) - ).map((e, index) => [this._project.save.save.systems[index].name, e]), - ); - } + // Not working but not used currently + // if (this._project.save.save.components.length > 0) { + // this._componentsManifests = new Map( + // ( + // await this._project.actions.package.getComponentsManifests({ + // componentPaths: this._project.save.save.components.map((c) => c.path) as [ + // string, + // ...string[], + // ], + // }) + // ).map((e, index) => [this._project.save.save.components[index].name, e]), + // ); + // } + // if (this._project.save.save.systems.length > 0) { + // this._systemsManifests = new Map( + // ( + // await this._project.actions.package.getSystemsManifests({ + // systemPaths: this._project.save.save.systems.map((s) => s.path) as [ + // string, + // ...string[], + // ], + // }) + // ).map((e, index) => [this._project.save.save.systems[index].name, e]), + // ); + // } } getComponentManifest(componentName: string): EditorComponentManifest | undefined { diff --git a/src/lib/client/project/project-loader/project-cache.ts b/src/lib/client/project/project-loader/project-cache.ts index e513379..4635923 100644 --- a/src/lib/client/project/project-loader/project-cache.ts +++ b/src/lib/client/project/project-loader/project-cache.ts @@ -1,7 +1,7 @@ import { noProjectActions } from '$lib/client/action'; import { getConfig } from '$lib/client/config'; -import { generateKey } from '@utils/string'; +import { randomString } from '@utils/string'; export interface ProjectDataCache { id: string; @@ -30,7 +30,7 @@ export class ProjectCache { static async getOnlineProjects(): Promise { const projects = await noProjectActions.project.getGatewayProjects(); return projects.map((project) => ({ - id: generateKey(10), + id: randomString(10), resolvable: project.gatewayId, lastOpened: Date.now(), name: project.name, diff --git a/src/lib/client/project/project.ts b/src/lib/client/project/project.ts index e2ef54c..537a6bb 100644 --- a/src/lib/client/project/project.ts +++ b/src/lib/client/project/project.ts @@ -1,4 +1,5 @@ import { type ActionClient, getActionClient } from '$lib/client/action'; +import { ECSHandler } from '$lib/client/ecs'; import { EventHandler } from '$lib/client/event'; import { InfoHandler } from '$lib/client/info'; import { Loader } from '$lib/client/loader'; @@ -14,6 +15,7 @@ export class Project { private _save: SaveHandler | undefined; private _packageHandler: PackageHandler | undefined; private _eventHandler: EventHandler | undefined; + private _ecsHandler: ECSHandler | undefined; private _inited = false; @@ -28,6 +30,7 @@ export class Project { async init(): Promise { await this.fs.init(); + await this.ecs.init(); await this.save.init(); await this.packages.init(); this._inited = true; @@ -72,4 +75,9 @@ export class Project { if (!this._eventHandler) this._eventHandler = new EventHandler(); return this._eventHandler; } + + get ecs(): ECSHandler { + if (!this._ecsHandler) this._ecsHandler = new ECSHandler(this); + return this._ecsHandler; + } } diff --git a/src/lib/client/project/save-handler.ts b/src/lib/client/project/save-handler.ts index caa6f65..76c5425 100644 --- a/src/lib/client/project/save-handler.ts +++ b/src/lib/client/project/save-handler.ts @@ -1,9 +1,8 @@ -import type { EditorComponentManifest } from '@nanoforge-dev/ecs-lib'; import { type Writable, get, writable } from 'svelte/store'; import type { Project } from '$lib/client/project'; -import type { Save, SaveComponent, SaveEntity, SaveSystem } from '@utils/types'; +import type { Save } from '@utils/types'; export class SaveHandler { private _project: Project; @@ -23,6 +22,9 @@ export class SaveHandler { async init() { await this.fetchFromServer(); + + this._listeners(); + this._save.subscribe(() => { this.syncToServer(); }); @@ -61,33 +63,43 @@ export class SaveHandler { return get(this._save); } - get needSync(): Writable { - return this._needSync; - } - - addComponent(component: SaveComponent) { - get(this._save).components.push(component); - } - - addEntity(entity: SaveEntity) { - get(this._save).entities.push(entity); - } + private _listeners() { + this._project.ecs.components.store.subscribe((components) => { + this._save.set({ + ...this.save, + components: components.map((component) => ({ + name: component.name, + path: component.path, + paramsNames: component.params.map((p) => p.name), + })), + }); + void this.forceSyncToServer(); + }); - addSystem(system: SaveSystem) { - get(this._save).systems.push(system); - } + this._project.ecs.scenes.activeData.systems.store.subscribe((systems) => { + this._save.set({ + ...this.save, + systems: systems.map((name) => { + const system = this._project.ecs.systems.get(name).data; + return { + name: system.name, + path: system.path, + }; + }), + }); + void this.forceSyncToServer(); + }); - addComponentToEntity( - entityId: string, - componentName: string, - componentManifest: EditorComponentManifest, - ) { - const entity = get(this._save).entities.find((e) => e.id === entityId); - if (!entity) { - throw new Error('Entity not found: ' + entityId); - } - const newComp: Record = {}; - componentManifest.params.forEach((c) => (newComp[c.name] = c.default)); - entity.components[componentName] = newComp; + this._project.ecs.scenes.activeData.entities.store.subscribe((entities) => { + this._save.set({ + ...this.save, + entities: entities.map((entity) => ({ + id: entity.id, + treePath: entity.treePath, + components: entity.components, + })), + }); + void this.syncToServer(); + }); } } diff --git a/src/lib/components/Menu/MenuButton.svelte b/src/lib/components/Menu/MenuButton.svelte index 31ddc26..8ed942d 100644 --- a/src/lib/components/Menu/MenuButton.svelte +++ b/src/lib/components/Menu/MenuButton.svelte @@ -13,7 +13,7 @@
-
- Entities -
- {#if save.save} - {#each save.save.entities as entity (entity.id)} - - {/each} - {/if} -
- diff --git a/src/lib/components/Widget/ECSTree/EntityItem.svelte b/src/lib/components/Widget/ECSTree/EntityItem.svelte deleted file mode 100644 index d34400f..0000000 --- a/src/lib/components/Widget/ECSTree/EntityItem.svelte +++ /dev/null @@ -1,22 +0,0 @@ - - - diff --git a/src/lib/components/Widget/ECSTree/entity-selected.store.svelte.ts b/src/lib/components/Widget/ECSTree/entity-selected.store.svelte.ts deleted file mode 100644 index 9c35873..0000000 --- a/src/lib/components/Widget/ECSTree/entity-selected.store.svelte.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { type Writable, writable } from 'svelte/store'; - -import type { SaveEntity } from '@utils/types'; - -export const selectedEntityId: Writable = writable(''); -export const selectedEntity: Writable = writable(); diff --git a/src/lib/components/Widget/EntityInspector/ComponentSelector.svelte b/src/lib/components/Widget/EntityInspector/ComponentSelector.svelte deleted file mode 100644 index 524ecb1..0000000 --- a/src/lib/components/Widget/EntityInspector/ComponentSelector.svelte +++ /dev/null @@ -1,70 +0,0 @@ - - -{#if open} - -{/if} diff --git a/src/lib/components/Widget/EntityInspector/EntityInspectorWidget.svelte b/src/lib/components/Widget/EntityInspector/EntityInspectorWidget.svelte deleted file mode 100644 index c80d581..0000000 --- a/src/lib/components/Widget/EntityInspector/EntityInspectorWidget.svelte +++ /dev/null @@ -1,147 +0,0 @@ - - -
- {#key refresh} - {#if $selectedEntity} -
-
- {$selectedEntity.id} - -
- -
- {#each Object.keys($selectedEntity.components) as componentName (componentName)} - - {#if !openMap[componentName]} - {#each packages.getComponentManifest(componentName)?.params as param (param.name)} -
-
{param.name}
- - {#if param.type === 'string'} - - {:else if param.type === 'number'} - - {:else if param.type === 'boolean'} - - {/if} -
- {/each} - {/if} - {/each} -
-
-
- -
- !Object.keys($selectedEntity?.components ?? {}).includes(c.name), - )} - open={openComponentSelector} - onClose={() => (openComponentSelector = false)} - onSelect={(c) => { - addComponent(c.name); - openComponentSelector = false; - }} - /> - {:else} -
- Select an entity in the left panel -
- {/if} - {/key} -
diff --git a/src/lib/components/Widget/content-browser/header.svelte b/src/lib/components/Widget/content-browser/header.svelte index fbcedd3..fc02d22 100644 --- a/src/lib/components/Widget/content-browser/header.svelte +++ b/src/lib/components/Widget/content-browser/header.svelte @@ -22,7 +22,7 @@ {#each dirs as dir, i (i)} - diff --git a/src/lib/components/Widget/content-browser/side-item.svelte b/src/lib/components/Widget/content-browser/side-item.svelte index 9ad3633..5d70bb2 100644 --- a/src/lib/components/Widget/content-browser/side-item.svelte +++ b/src/lib/components/Widget/content-browser/side-item.svelte @@ -21,7 +21,7 @@ + + {/if} + + + + + + + {#if type !== 'library'} + + + Open code + + + + {items.addTooltip} + + + {/if} + + + Delete + + + diff --git a/src/lib/components/Widget/ecs-tree/packages/package-tab.svelte b/src/lib/components/Widget/ecs-tree/packages/package-tab.svelte new file mode 100644 index 0000000..f89eb6e --- /dev/null +++ b/src/lib/components/Widget/ecs-tree/packages/package-tab.svelte @@ -0,0 +1,135 @@ + + + + + +
+
+ + + + + + {#if query} + + (query = '')} + variant="ghost" + class="rounded-md text-destructive hover:text-destructive hover:bg-destructive/10" + > + + + + {/if} + + + + {#snippet child({ props })} + + {/snippet} + + + {#if type !== 'library'} + (createOpen = true)}> + + Create + + {/if} + (importOpen = true)}> + + Import + + + +
+ + + {#each sorted as pkg (pkg.id)} + {@const handle = manager.get(pkg.id)} + + {/each} + + {#if sorted.length === 0} +
+ {query ? 'No matches.' : `No ${namePlural} - add one with +.`} +
+ {/if} +
+
diff --git a/src/lib/components/Widget/ecs-tree/scenes/dialog-edit-scene.svelte b/src/lib/components/Widget/ecs-tree/scenes/dialog-edit-scene.svelte new file mode 100644 index 0000000..749cac0 --- /dev/null +++ b/src/lib/components/Widget/ecs-tree/scenes/dialog-edit-scene.svelte @@ -0,0 +1,19 @@ + + + diff --git a/src/lib/components/Widget/ecs-tree/scenes/dialog-new-scene.svelte b/src/lib/components/Widget/ecs-tree/scenes/dialog-new-scene.svelte new file mode 100644 index 0000000..74f3247 --- /dev/null +++ b/src/lib/components/Widget/ecs-tree/scenes/dialog-new-scene.svelte @@ -0,0 +1,12 @@ + + + diff --git a/src/lib/components/Widget/ecs-tree/scenes/entities/dialog-delete-entity.svelte b/src/lib/components/Widget/ecs-tree/scenes/entities/dialog-delete-entity.svelte new file mode 100644 index 0000000..19a9acc --- /dev/null +++ b/src/lib/components/Widget/ecs-tree/scenes/entities/dialog-delete-entity.svelte @@ -0,0 +1,15 @@ + + + diff --git a/src/lib/components/Widget/ecs-tree/scenes/entities/dialog-edit-entity.svelte b/src/lib/components/Widget/ecs-tree/scenes/entities/dialog-edit-entity.svelte new file mode 100644 index 0000000..86479ad --- /dev/null +++ b/src/lib/components/Widget/ecs-tree/scenes/entities/dialog-edit-entity.svelte @@ -0,0 +1,22 @@ + + + diff --git a/src/lib/components/Widget/ecs-tree/scenes/entities/dialog-new-entity.svelte b/src/lib/components/Widget/ecs-tree/scenes/entities/dialog-new-entity.svelte new file mode 100644 index 0000000..07faf0c --- /dev/null +++ b/src/lib/components/Widget/ecs-tree/scenes/entities/dialog-new-entity.svelte @@ -0,0 +1,15 @@ + + + diff --git a/src/lib/components/Widget/ecs-tree/scenes/entities/entity-tree-node.svelte b/src/lib/components/Widget/ecs-tree/scenes/entities/entity-tree-node.svelte new file mode 100644 index 0000000..1643716 --- /dev/null +++ b/src/lib/components/Widget/ecs-tree/scenes/entities/entity-tree-node.svelte @@ -0,0 +1,152 @@ + + + + + + + + + {#if !readonly} + + + + New entity + + + + New folder + + + + + Edit + + + + + Delete + + + {/if} + diff --git a/src/lib/components/Widget/ecs-tree/scenes/entities/entity-tree.svelte b/src/lib/components/Widget/ecs-tree/scenes/entities/entity-tree.svelte new file mode 100644 index 0000000..102fd5d --- /dev/null +++ b/src/lib/components/Widget/ecs-tree/scenes/entities/entity-tree.svelte @@ -0,0 +1,360 @@ + + + + + +
+
+ Entities +
+ + + + {#snippet child({ props })} + + {/snippet} + + + + + New entity + + + + New folder + + + +
+
+ {#if searchOpen} + + + + + + {#if search} + + (search = '')} + variant="ghost" + class="rounded-md text-destructive hover:text-destructive hover:bg-destructive/10" + > + + + + {/if} + + {/if} +
+ +{#if ancestor && inherited.length > 0} +
+ + {#if !inheritedCollapsed} +
+ {#each inheritedTree as node (node.kind === 'entity' ? node.id : node.path)} + {#if node.kind === 'entity'} + + {:else} + + {/if} + {/each} +
+ {/if} +
+{/if} + +
+ {#each tree as node (node.kind === 'entity' ? node.id : node.path)} + {#if node.kind === 'entity'} + + {:else} + + {/if} + {/each} + + {#if $entities.length === 0 && folders.size === 0} +
+ No entities - use + to add one. +
+ {/if} +
+ +{#if dragging} + +{/if} diff --git a/src/lib/components/Widget/ecs-tree/scenes/entities/folder-tree-node.svelte b/src/lib/components/Widget/ecs-tree/scenes/entities/folder-tree-node.svelte new file mode 100644 index 0000000..7bc7348 --- /dev/null +++ b/src/lib/components/Widget/ecs-tree/scenes/entities/folder-tree-node.svelte @@ -0,0 +1,202 @@ + + + + + + + + + + {#if !readonly} + + + + New entity + + + + New folder + + + + + Edit + + + + Delete folder & contents + + + {/if} + + +{#if expandedFolders.has(node.path)} + {#each node.children as child (child.kind === 'entity' ? child.id : child.path)} + {#if child.kind === 'entity'} + + {:else} + + {/if} + {/each} +{/if} diff --git a/src/lib/components/Widget/ecs-tree/scenes/scene-detail.svelte b/src/lib/components/Widget/ecs-tree/scenes/scene-detail.svelte new file mode 100644 index 0000000..01acb3f --- /dev/null +++ b/src/lib/components/Widget/ecs-tree/scenes/scene-detail.svelte @@ -0,0 +1,49 @@ + + +
+
+ + {$scene.name} + {#if isActive} +
+ + Active +
+ {/if} +
+ + + + Entities + Systems + + + + + + + + +
diff --git a/src/lib/components/Widget/ecs-tree/scenes/scene-list.svelte b/src/lib/components/Widget/ecs-tree/scenes/scene-list.svelte new file mode 100644 index 0000000..ac87369 --- /dev/null +++ b/src/lib/components/Widget/ecs-tree/scenes/scene-list.svelte @@ -0,0 +1,265 @@ + + + + +{#snippet sceneRow(scene: Scene, depth: number)} + {@const isSelf = dragSceneId === scene.id} + {@const isInvalid = + !dragSceneId || dragSceneId === scene.id || isDescendantOf(scene.id, dragSceneId)} + {@const isDropBefore = dropTarget?.id === scene.id && dropTarget.pos === 'before'} + {@const isDropOn = dropTarget?.id === scene.id && dropTarget.pos === 'on'} + {@const isDropAfter = dropTarget?.id === scene.id && dropTarget.pos === 'after'} + {@const barLeft = 8 + depth * 12} + {@const handle = manager.get(scene.id)} + +
+
+ {#if isDropBefore} +
+ {/if} + +
+ + {#if expandedSceneItems.has(scene.id) && scene.subScenes.length > 0} + {#each scene.subScenes as subId (subId)} + {@const sub = $scenes.find((s) => s.id === subId)} + {#if sub}{@render sceneRow(sub, depth + 1)}{/if} + {/each} +
+ {/if} + +
+ {#if dragSceneId && !isInvalid} + + {/if} +
+
+{/snippet} + +
+
+ Scenes + +
+ +
{ + if (dragSceneId) e.preventDefault(); + }} + ondragleave={(e) => { + if (!e.currentTarget.contains(e.relatedTarget as Node)) dropTarget = null; + }} + ondrop={() => { + dragSceneId = null; + dropTarget = null; + }} + > + {#each rootScenes as scene (scene.id)} + {@render sceneRow(scene, 0)} + {/each} +
+
diff --git a/src/lib/components/Widget/ecs-tree/scenes/scene-row.svelte b/src/lib/components/Widget/ecs-tree/scenes/scene-row.svelte new file mode 100644 index 0000000..e5eae4e --- /dev/null +++ b/src/lib/components/Widget/ecs-tree/scenes/scene-row.svelte @@ -0,0 +1,146 @@ + + + + + + + +
+ {#if $scene.subScenes.length > 0} + + {:else} + + {/if} + +
+
+ + + + Edit + + + {#if !isActive || !isDefault} + {#if !isActive} + + + Set active + + {/if} + {#if !isDefault} + + + Set default + + {/if} + + {/if} + + + Delete + + +
diff --git a/src/lib/components/Widget/ecs-tree/scenes/scenes-tab.svelte b/src/lib/components/Widget/ecs-tree/scenes/scenes-tab.svelte new file mode 100644 index 0000000..01544db --- /dev/null +++ b/src/lib/components/Widget/ecs-tree/scenes/scenes-tab.svelte @@ -0,0 +1,29 @@ + + +
+ + + {#if selected} + + {:else} +
+ Select a scene +
+ {/if} +
diff --git a/src/lib/components/Widget/ecs-tree/scenes/systems/dialog-add-scene-system.svelte b/src/lib/components/Widget/ecs-tree/scenes/systems/dialog-add-scene-system.svelte new file mode 100644 index 0000000..1ab7d65 --- /dev/null +++ b/src/lib/components/Widget/ecs-tree/scenes/systems/dialog-add-scene-system.svelte @@ -0,0 +1,20 @@ + + + ({ label: sys.name, value: sys.id }))} + bind:open + {onConfirm} +/> diff --git a/src/lib/components/Widget/ecs-tree/scenes/systems/scene-systems-list.svelte b/src/lib/components/Widget/ecs-tree/scenes/systems/scene-systems-list.svelte new file mode 100644 index 0000000..acfe1ba --- /dev/null +++ b/src/lib/components/Widget/ecs-tree/scenes/systems/scene-systems-list.svelte @@ -0,0 +1,178 @@ + + + + +
+ Systems + +
+ +
+ {#each $systems as sysName (sysName)} + {@const isSelf = dragId === sysName} + {@const isDropBefore = + !isNext(dragId, sysName, 'before') && + dropTarget?.id === sysName && + dropTarget.pos === 'before'} + {@const isDropAfter = + !isNext(dragId, sysName, 'after') && dropTarget?.id === sysName && dropTarget.pos === 'after'} + + + + {#if isDropBefore} +
+ {/if} + + {#if isDropAfter} +
+ {/if} +
+ + + + Open code + + + + Find in systems + + + + + Remove from scene + + +
+ {/each} + + {#if $systems.length === 0} +
No systems - use + to add one.
+ {/if} +
diff --git a/src/lib/components/Widget/ecs-tree/systems/system.items.ts b/src/lib/components/Widget/ecs-tree/systems/system.items.ts new file mode 100644 index 0000000..876bff3 --- /dev/null +++ b/src/lib/components/Widget/ecs-tree/systems/system.items.ts @@ -0,0 +1,11 @@ +import type { PackageItems } from '../types'; + +export const SYSTEM_ITEMS: PackageItems = { + icon: { + name: 'i-icomoon-free-steam', + color: 'text-amber-400', + }, + addTooltip: 'Add to active scene', + disableAddTooltipNotSelected: 'No active scene', + disableAddTooltipAlreadyAdded: 'The active scene already had this system', +}; diff --git a/src/lib/components/Widget/ecs-tree/systems/systems-tab.svelte b/src/lib/components/Widget/ecs-tree/systems/systems-tab.svelte new file mode 100644 index 0000000..e4264cf --- /dev/null +++ b/src/lib/components/Widget/ecs-tree/systems/systems-tab.svelte @@ -0,0 +1,12 @@ + + + diff --git a/src/lib/components/Widget/ecs-tree/types.ts b/src/lib/components/Widget/ecs-tree/types.ts new file mode 100644 index 0000000..571059b --- /dev/null +++ b/src/lib/components/Widget/ecs-tree/types.ts @@ -0,0 +1,30 @@ +export interface PackageItems { + icon: { + name: string; + color: string; + }; + addTooltip: string | null; + disableAddTooltipNotSelected: string | null; + disableAddTooltipAlreadyAdded: string | null; +} + +export type TreeEntity = { kind: 'entity'; id: string; scene?: string }; +export type TreeFolder = { kind: 'folder'; name: string; path: string; children: TreeNode[] }; +export type TreeNode = TreeEntity | TreeFolder; + +export type EntityDragItem = { type: 'entity'; id: string } | { type: 'folder'; path: string }; + +export interface EntityDragContext { + readonly dragging: EntityDragItem | null; + startDrag(item: EntityDragItem): void; + endDrag(): void; + dropOnFolder(folderPath: string): void; + dropOnEntity(entityId: string): void; + dropOnRoot(): void; +} + +export interface Package { + id: string; + name?: string; + path?: string; +} diff --git a/src/lib/components/Widget/ecs-tree/utils.ts b/src/lib/components/Widget/ecs-tree/utils.ts new file mode 100644 index 0000000..0b4b720 --- /dev/null +++ b/src/lib/components/Widget/ecs-tree/utils.ts @@ -0,0 +1,62 @@ +import type { Entity } from '$lib/client/ecs'; + +import type { TreeEntity, TreeFolder, TreeNode } from './types'; + +export const resolveParentPath = (path: string): string => { + if (!path) return ''; + const parts = path.split('/'); + return parts.slice(0, -1).join('/'); +}; + +export function buildTree( + entities: (Entity & { scene?: string })[], + extraFolderPaths: Iterable = [], + search?: string, +): TreeNode[] { + if (search) { + entities = entities.filter((e) => e.id.includes(search)); + extraFolderPaths = Array.from(extraFolderPaths).filter((p) => + p.split('/').at(-1)?.includes(search), + ); + } + const folderMap = new Map(); + const root: TreeNode[] = []; + + function getOrCreate(path: string): TreeFolder { + if (folderMap.has(path)) return folderMap.get(path)!; + const parts = path.split('/'); + const folder: TreeFolder = { kind: 'folder', name: parts.at(-1)!, path, children: [] }; + folderMap.set(path, folder); + const parentPath = parts.slice(0, -1).join('/'); + (parentPath ? getOrCreate(parentPath).children : root).push(folder); + return folder; + } + + for (const path of extraFolderPaths) if (path) getOrCreate(path); + for (const entity of entities) { + (entity.treePath ? getOrCreate(entity.treePath).children : root).push({ + kind: 'entity', + id: entity.id, + scene: entity.scene, + }); + } + + function sort(nodes: TreeNode[]): TreeNode[] { + const folders = nodes + .filter((n): n is TreeFolder => n.kind === 'folder') + .sort((a, b) => a.name.localeCompare(b.name)); + const entities = nodes + .filter((n): n is TreeEntity => n.kind === 'entity') + .sort((a, b) => a.id.localeCompare(b.id)); + for (const f of folders) f.children = sort(f.children); + return [...folders, ...entities]; + } + + return sort(root); +} + +export function folderPaths(treePath: string): string[] { + if (!treePath) return []; + const parts = treePath.split('/'); + return parts.map((_, i) => parts.slice(0, i + 1).join('/')); +} diff --git a/src/lib/components/Widget/ecs-tree/widget.svelte b/src/lib/components/Widget/ecs-tree/widget.svelte new file mode 100644 index 0000000..22d26a6 --- /dev/null +++ b/src/lib/components/Widget/ecs-tree/widget.svelte @@ -0,0 +1,39 @@ + + + + + Scenes + Components + Systems + Libraries + + + + + + + + + + + + + + diff --git a/src/lib/components/Widget/entity-inspector/component-list.svelte b/src/lib/components/Widget/entity-inspector/component-list.svelte new file mode 100644 index 0000000..2dad228 --- /dev/null +++ b/src/lib/components/Widget/entity-inspector/component-list.svelte @@ -0,0 +1,20 @@ + + +
+ {#each Object.keys($components) as component (component)} + {@const handle = manager.get(component)} + + {/each} +
diff --git a/src/lib/components/Widget/entity-inspector/component-param-list.svelte b/src/lib/components/Widget/entity-inspector/component-param-list.svelte new file mode 100644 index 0000000..cf06c52 --- /dev/null +++ b/src/lib/components/Widget/entity-inspector/component-param-list.svelte @@ -0,0 +1,18 @@ + + +{#each $params as param (param.name)} + {@const handle = manager.get(param.name)} + +{/each} diff --git a/src/lib/components/Widget/entity-inspector/component-param-row.svelte b/src/lib/components/Widget/entity-inspector/component-param-row.svelte new file mode 100644 index 0000000..d69081a --- /dev/null +++ b/src/lib/components/Widget/entity-inspector/component-param-row.svelte @@ -0,0 +1,32 @@ + + +
+
{$param.name}
+ + {#if $param.type === 'string'} + + {:else if $param.type === 'number'} + + {:else if $param.type === 'boolean'} + + {/if} +
diff --git a/src/lib/components/Widget/entity-inspector/component-row.svelte b/src/lib/components/Widget/entity-inspector/component-row.svelte new file mode 100644 index 0000000..f72f225 --- /dev/null +++ b/src/lib/components/Widget/entity-inspector/component-row.svelte @@ -0,0 +1,53 @@ + + + + +{#if !componentCollapsed} + +{/if} diff --git a/src/lib/components/Widget/entity-inspector/dialog-component-selector.svelte b/src/lib/components/Widget/entity-inspector/dialog-component-selector.svelte new file mode 100644 index 0000000..417fbe4 --- /dev/null +++ b/src/lib/components/Widget/entity-inspector/dialog-component-selector.svelte @@ -0,0 +1,77 @@ + + + + + + Add component + Select a component to add to {$entity.name} + + + + +
+ {#if availableComponents.length === 0} +
No component found
+ {:else} + {#each availableComponents as component (component.name)} + + {/each} + {/if} +
+
+
diff --git a/src/lib/components/Widget/entity-inspector/index.ts b/src/lib/components/Widget/entity-inspector/index.ts new file mode 100644 index 0000000..8805b91 --- /dev/null +++ b/src/lib/components/Widget/entity-inspector/index.ts @@ -0,0 +1,3 @@ +import Widget from './widget.svelte'; + +export { Widget, Widget as EntityInspectorWidget }; diff --git a/src/lib/components/Widget/entity-inspector/widget.svelte b/src/lib/components/Widget/entity-inspector/widget.svelte new file mode 100644 index 0000000..8890d63 --- /dev/null +++ b/src/lib/components/Widget/entity-inspector/widget.svelte @@ -0,0 +1,63 @@ + + +
+ {#if $entity} +
+
+ {$entity.id} + +
+ +
+
+ +
+ + {:else} +
+ Select an entity in the left panel +
+ {/if} +
diff --git a/src/lib/components/Widget/widgets.ts b/src/lib/components/Widget/widgets.ts index 8f0630f..989dd16 100644 --- a/src/lib/components/Widget/widgets.ts +++ b/src/lib/components/Widget/widgets.ts @@ -1,11 +1,11 @@ import type { Component } from 'svelte'; import MonacoEditor from './CodeEditor/MonacoEditor.svelte'; -import ECSTreeWidget from './ECSTree/ECSTree.svelte'; import EditorGame from './EditorGame/EditorGame.svelte'; -import EntityInspectorWidget from './EntityInspector/EntityInspectorWidget.svelte'; import OutputLogWidget from './OutputLog/OutputLogWidget.svelte'; import { ContentBrowserWidget } from './content-browser'; +import { ECSTreeWidget } from './ecs-tree'; +import { EntityInspectorWidget } from './entity-inspector'; export interface WidgetType { id: string; diff --git a/src/lib/components/dialogs/base-dialog.svelte b/src/lib/components/dialogs/base-dialog.svelte new file mode 100644 index 0000000..2075e90 --- /dev/null +++ b/src/lib/components/dialogs/base-dialog.svelte @@ -0,0 +1,67 @@ + + + + + {#if title || description} + + {#if title} + {title} + {/if} + {#if description} + {description} + {/if} + + {/if} + {@render children?.(confirm, cancel)} + + + + + + diff --git a/src/lib/components/dialogs/delete-confirm-dialog.svelte b/src/lib/components/dialogs/delete-confirm-dialog.svelte new file mode 100644 index 0000000..a40dd04 --- /dev/null +++ b/src/lib/components/dialogs/delete-confirm-dialog.svelte @@ -0,0 +1,71 @@ + + + + + + {#if 'title' in props} + {props.title} + {:else} + Deleting {props.type} + {/if} + {#if description} + {description} + {/if} + + + {#if 'children' in props} + {@render props.children()} + {:else} +
+ Are you sure you want to delete {props.name} ? +
+ {/if} + + + + + +
+
diff --git a/src/lib/components/dialogs/index.ts b/src/lib/components/dialogs/index.ts new file mode 100644 index 0000000..887b861 --- /dev/null +++ b/src/lib/components/dialogs/index.ts @@ -0,0 +1,5 @@ +import Base from './base-dialog.svelte'; +import DeleteConfirm from './delete-confirm-dialog.svelte'; +import Input from './input-dialog.svelte'; + +export { Base as BaseDialog, DeleteConfirm as DeleteConfirmDialog, Input as InputDialog }; diff --git a/src/lib/components/dialogs/input-dialog.svelte b/src/lib/components/dialogs/input-dialog.svelte new file mode 100644 index 0000000..8087d9e --- /dev/null +++ b/src/lib/components/dialogs/input-dialog.svelte @@ -0,0 +1,26 @@ + + + diff --git a/src/lib/components/ui/badge/badge.svelte b/src/lib/components/ui/badge/badge.svelte new file mode 100644 index 0000000..16be78a --- /dev/null +++ b/src/lib/components/ui/badge/badge.svelte @@ -0,0 +1,50 @@ + + + + + + {@render children?.()} + diff --git a/src/lib/components/ui/badge/index.ts b/src/lib/components/ui/badge/index.ts new file mode 100644 index 0000000..f05fb87 --- /dev/null +++ b/src/lib/components/ui/badge/index.ts @@ -0,0 +1,2 @@ +export { default as Badge } from './badge.svelte'; +export { badgeVariants, type BadgeVariant } from './badge.svelte'; diff --git a/src/lib/components/ui/button/button.svelte b/src/lib/components/ui/button/button.svelte index 5a572e1..9d24463 100644 --- a/src/lib/components/ui/button/button.svelte +++ b/src/lib/components/ui/button/button.svelte @@ -4,7 +4,7 @@ import { type VariantProps, tv } from 'tailwind-variants'; export const buttonVariants = tv({ - base: "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-lg border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-3 active:not-aria-[haspopup]:translate-y-px aria-invalid:ring-3 [&_svg:not([class*='size-'])]:size-4 group/button inline-flex shrink-0 items-center justify-center whitespace-nowrap transition-all outline-none select-none disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0", + base: "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 rounded-lg border border-transparent bg-clip-padding text-sm font-medium focus-visible:ring-3 active:not-aria-[haspopup]:translate-y-px aria-invalid:ring-3 [&_svg:not([class*='size-'])]:size-4 group/button inline-flex shrink-0 items-center justify-center whitespace-nowrap transition-all outline-none select-none cursor-pointer disabled:pointer-events-none disabled:opacity-50 disable:cursor-not-allowed [&_svg]:pointer-events-none [&_svg]:shrink-0", variants: { variant: { default: 'bg-primary text-primary-foreground [a]:hover:bg-primary/80', diff --git a/src/lib/components/ui/context-menu/context-menu-checkbox-item.svelte b/src/lib/components/ui/context-menu/context-menu-checkbox-item.svelte new file mode 100644 index 0000000..4b36704 --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-checkbox-item.svelte @@ -0,0 +1,41 @@ + + + + {#snippet children({ checked })} + + {#if checked} + + {/if} + + {@render childrenProp?.()} + {/snippet} + diff --git a/src/lib/components/ui/context-menu/context-menu-content.svelte b/src/lib/components/ui/context-menu/context-menu-content.svelte new file mode 100644 index 0000000..b924d91 --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-content.svelte @@ -0,0 +1,28 @@ + + + + + diff --git a/src/lib/components/ui/context-menu/context-menu-group-heading.svelte b/src/lib/components/ui/context-menu/context-menu-group-heading.svelte new file mode 100644 index 0000000..446e838 --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-group-heading.svelte @@ -0,0 +1,21 @@ + + + diff --git a/src/lib/components/ui/context-menu/context-menu-group.svelte b/src/lib/components/ui/context-menu/context-menu-group.svelte new file mode 100644 index 0000000..19f694b --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-group.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/context-menu/context-menu-item.svelte b/src/lib/components/ui/context-menu/context-menu-item.svelte new file mode 100644 index 0000000..9225922 --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-item.svelte @@ -0,0 +1,27 @@ + + + diff --git a/src/lib/components/ui/context-menu/context-menu-label.svelte b/src/lib/components/ui/context-menu/context-menu-label.svelte new file mode 100644 index 0000000..f08196c --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-label.svelte @@ -0,0 +1,27 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/context-menu/context-menu-portal.svelte b/src/lib/components/ui/context-menu/context-menu-portal.svelte new file mode 100644 index 0000000..2897cc0 --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/context-menu/context-menu-radio-group.svelte b/src/lib/components/ui/context-menu/context-menu-radio-group.svelte new file mode 100644 index 0000000..b1abdf3 --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-radio-group.svelte @@ -0,0 +1,16 @@ + + + diff --git a/src/lib/components/ui/context-menu/context-menu-radio-item.svelte b/src/lib/components/ui/context-menu/context-menu-radio-item.svelte new file mode 100644 index 0000000..9354465 --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-radio-item.svelte @@ -0,0 +1,35 @@ + + + + {#snippet children({ checked })} + + {#if checked} + + {/if} + + {@render childrenProp?.({ checked })} + {/snippet} + diff --git a/src/lib/components/ui/context-menu/context-menu-separator.svelte b/src/lib/components/ui/context-menu/context-menu-separator.svelte new file mode 100644 index 0000000..9dcf853 --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-separator.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/lib/components/ui/context-menu/context-menu-shortcut.svelte b/src/lib/components/ui/context-menu/context-menu-shortcut.svelte new file mode 100644 index 0000000..5e13d6c --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-shortcut.svelte @@ -0,0 +1,23 @@ + + + + {@render children?.()} + diff --git a/src/lib/components/ui/context-menu/context-menu-sub-content.svelte b/src/lib/components/ui/context-menu/context-menu-sub-content.svelte new file mode 100644 index 0000000..bc441dd --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-sub-content.svelte @@ -0,0 +1,20 @@ + + + diff --git a/src/lib/components/ui/context-menu/context-menu-sub-trigger.svelte b/src/lib/components/ui/context-menu/context-menu-sub-trigger.svelte new file mode 100644 index 0000000..d309e4c --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-sub-trigger.svelte @@ -0,0 +1,29 @@ + + + + {@render children?.()} + + diff --git a/src/lib/components/ui/context-menu/context-menu-sub.svelte b/src/lib/components/ui/context-menu/context-menu-sub.svelte new file mode 100644 index 0000000..0ba70c9 --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-sub.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/context-menu/context-menu-trigger.svelte b/src/lib/components/ui/context-menu/context-menu-trigger.svelte new file mode 100644 index 0000000..3831cca --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu-trigger.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/lib/components/ui/context-menu/context-menu.svelte b/src/lib/components/ui/context-menu/context-menu.svelte new file mode 100644 index 0000000..4b6908e --- /dev/null +++ b/src/lib/components/ui/context-menu/context-menu.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/context-menu/index.ts b/src/lib/components/ui/context-menu/index.ts new file mode 100644 index 0000000..4177ab6 --- /dev/null +++ b/src/lib/components/ui/context-menu/index.ts @@ -0,0 +1,52 @@ +import CheckboxItem from './context-menu-checkbox-item.svelte'; +import Content from './context-menu-content.svelte'; +import GroupHeading from './context-menu-group-heading.svelte'; +import Group from './context-menu-group.svelte'; +import Item from './context-menu-item.svelte'; +import Label from './context-menu-label.svelte'; +import Portal from './context-menu-portal.svelte'; +import RadioGroup from './context-menu-radio-group.svelte'; +import RadioItem from './context-menu-radio-item.svelte'; +import Separator from './context-menu-separator.svelte'; +import Shortcut from './context-menu-shortcut.svelte'; +import SubContent from './context-menu-sub-content.svelte'; +import SubTrigger from './context-menu-sub-trigger.svelte'; +import Sub from './context-menu-sub.svelte'; +import Trigger from './context-menu-trigger.svelte'; +import Root from './context-menu.svelte'; + +export { + Root, + Sub, + Portal, + Item, + GroupHeading, + Label, + Group, + Trigger, + Content, + Shortcut, + Separator, + RadioItem, + SubContent, + SubTrigger, + RadioGroup, + CheckboxItem, + // + Root as ContextMenu, + Sub as ContextMenuSub, + Portal as ContextMenuPortal, + Item as ContextMenuItem, + GroupHeading as ContextMenuGroupHeading, + Group as ContextMenuGroup, + Content as ContextMenuContent, + Trigger as ContextMenuTrigger, + Shortcut as ContextMenuShortcut, + RadioItem as ContextMenuRadioItem, + Separator as ContextMenuSeparator, + RadioGroup as ContextMenuRadioGroup, + SubContent as ContextMenuSubContent, + SubTrigger as ContextMenuSubTrigger, + CheckboxItem as ContextMenuCheckboxItem, + Label as ContextMenuLabel, +}; diff --git a/src/lib/components/ui/dialog/dialog-footer.svelte b/src/lib/components/ui/dialog/dialog-footer.svelte index 5283c65..5ef8a1e 100644 --- a/src/lib/components/ui/dialog/dialog-footer.svelte +++ b/src/lib/components/ui/dialog/dialog-footer.svelte @@ -19,7 +19,7 @@ bind:this={ref} data-slot="dialog-footer" class={cn( - 'bg-muted/50 -mx-4 -mb-4 rounded-b-xl border-t p-4 flex flex-col-reverse gap-2 sm:flex-row sm:justify-end', + 'bg-muted/50 -mx-4 -mb-4 rounded-b-xl p-4 flex flex-col-reverse gap-2 sm:flex-row sm:justify-end', className, )} {...restProps} diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte new file mode 100644 index 0000000..6b4d728 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte @@ -0,0 +1,16 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte new file mode 100644 index 0000000..4f59a7d --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte @@ -0,0 +1,44 @@ + + + + {#snippet children({ checked, indeterminate })} + + {#if indeterminate} + + {:else if checked} + + {/if} + + {@render childrenProp?.()} + {/snippet} + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte new file mode 100644 index 0000000..4e9143f --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte @@ -0,0 +1,31 @@ + + + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte new file mode 100644 index 0000000..321802b --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte @@ -0,0 +1,22 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte new file mode 100644 index 0000000..bf972af --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte new file mode 100644 index 0000000..38a5269 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte @@ -0,0 +1,27 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte new file mode 100644 index 0000000..9066564 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte @@ -0,0 +1,27 @@ + + +
+ {@render children?.()} +
diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte new file mode 100644 index 0000000..130c20f --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte new file mode 100644 index 0000000..7452366 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte @@ -0,0 +1,16 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte new file mode 100644 index 0000000..b37cfd3 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte @@ -0,0 +1,34 @@ + + + + {#snippet children({ checked })} + + {#if checked} + + {/if} + + {@render childrenProp?.({ checked })} + {/snippet} + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte new file mode 100644 index 0000000..343ae2c --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte @@ -0,0 +1,17 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte new file mode 100644 index 0000000..02254af --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte @@ -0,0 +1,23 @@ + + + + {@render children?.()} + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte new file mode 100644 index 0000000..05fe6a2 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte @@ -0,0 +1,20 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte new file mode 100644 index 0000000..4f3e045 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte @@ -0,0 +1,29 @@ + + + + {@render children?.()} + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte new file mode 100644 index 0000000..02f5f63 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte new file mode 100644 index 0000000..7409c77 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/dropdown-menu.svelte b/src/lib/components/ui/dropdown-menu/dropdown-menu.svelte new file mode 100644 index 0000000..5c2776c --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/dropdown-menu.svelte @@ -0,0 +1,7 @@ + + + diff --git a/src/lib/components/ui/dropdown-menu/index.ts b/src/lib/components/ui/dropdown-menu/index.ts new file mode 100644 index 0000000..6ec2de8 --- /dev/null +++ b/src/lib/components/ui/dropdown-menu/index.ts @@ -0,0 +1,54 @@ +import CheckboxGroup from './dropdown-menu-checkbox-group.svelte'; +import CheckboxItem from './dropdown-menu-checkbox-item.svelte'; +import Content from './dropdown-menu-content.svelte'; +import GroupHeading from './dropdown-menu-group-heading.svelte'; +import Group from './dropdown-menu-group.svelte'; +import Item from './dropdown-menu-item.svelte'; +import Label from './dropdown-menu-label.svelte'; +import Portal from './dropdown-menu-portal.svelte'; +import RadioGroup from './dropdown-menu-radio-group.svelte'; +import RadioItem from './dropdown-menu-radio-item.svelte'; +import Separator from './dropdown-menu-separator.svelte'; +import Shortcut from './dropdown-menu-shortcut.svelte'; +import SubContent from './dropdown-menu-sub-content.svelte'; +import SubTrigger from './dropdown-menu-sub-trigger.svelte'; +import Sub from './dropdown-menu-sub.svelte'; +import Trigger from './dropdown-menu-trigger.svelte'; +import Root from './dropdown-menu.svelte'; + +export { + CheckboxGroup, + CheckboxItem, + Content, + Portal, + Root as DropdownMenu, + CheckboxGroup as DropdownMenuCheckboxGroup, + CheckboxItem as DropdownMenuCheckboxItem, + Content as DropdownMenuContent, + Portal as DropdownMenuPortal, + Group as DropdownMenuGroup, + Item as DropdownMenuItem, + Label as DropdownMenuLabel, + RadioGroup as DropdownMenuRadioGroup, + RadioItem as DropdownMenuRadioItem, + Separator as DropdownMenuSeparator, + Shortcut as DropdownMenuShortcut, + Sub as DropdownMenuSub, + SubContent as DropdownMenuSubContent, + SubTrigger as DropdownMenuSubTrigger, + Trigger as DropdownMenuTrigger, + GroupHeading as DropdownMenuGroupHeading, + Group, + GroupHeading, + Item, + Label, + RadioGroup, + RadioItem, + Root, + Separator, + Shortcut, + Sub, + SubContent, + SubTrigger, + Trigger, +}; diff --git a/src/lib/components/ui/input-group/index.ts b/src/lib/components/ui/input-group/index.ts new file mode 100644 index 0000000..00f6d4f --- /dev/null +++ b/src/lib/components/ui/input-group/index.ts @@ -0,0 +1,22 @@ +import Addon from './input-group-addon.svelte'; +import Button from './input-group-button.svelte'; +import Input from './input-group-input.svelte'; +import Text from './input-group-text.svelte'; +import Textarea from './input-group-textarea.svelte'; +import Root from './input-group.svelte'; + +export { + Root, + Addon, + Button, + Input, + Text, + Textarea, + // + Root as InputGroup, + Addon as InputGroupAddon, + Button as InputGroupButton, + Input as InputGroupInput, + Text as InputGroupText, + Textarea as InputGroupTextarea, +}; diff --git a/src/lib/components/ui/input-group/input-group-addon.svelte b/src/lib/components/ui/input-group/input-group-addon.svelte new file mode 100644 index 0000000..5a27b20 --- /dev/null +++ b/src/lib/components/ui/input-group/input-group-addon.svelte @@ -0,0 +1,53 @@ + + + + +
{ + if ((e.target as HTMLElement).closest('button')) { + return; + } + e.currentTarget.parentElement?.querySelector('input')?.focus(); + }} + {...restProps} +> + {@render children?.()} +
diff --git a/src/lib/components/ui/input-group/input-group-button.svelte b/src/lib/components/ui/input-group/input-group-button.svelte new file mode 100644 index 0000000..e52202d --- /dev/null +++ b/src/lib/components/ui/input-group/input-group-button.svelte @@ -0,0 +1,49 @@ + + + + + diff --git a/src/lib/components/ui/input-group/input-group-input.svelte b/src/lib/components/ui/input-group/input-group-input.svelte new file mode 100644 index 0000000..91b78c1 --- /dev/null +++ b/src/lib/components/ui/input-group/input-group-input.svelte @@ -0,0 +1,23 @@ + + + diff --git a/src/lib/components/ui/input-group/input-group-text.svelte b/src/lib/components/ui/input-group/input-group-text.svelte new file mode 100644 index 0000000..af33024 --- /dev/null +++ b/src/lib/components/ui/input-group/input-group-text.svelte @@ -0,0 +1,22 @@ + + + + {@render children?.()} + diff --git a/src/lib/components/ui/input-group/input-group-textarea.svelte b/src/lib/components/ui/input-group/input-group-textarea.svelte new file mode 100644 index 0000000..1882b9f --- /dev/null +++ b/src/lib/components/ui/input-group/input-group-textarea.svelte @@ -0,0 +1,23 @@ + + + diff --git a/src/lib/server/actions/project/library/install-library.action.ts b/src/lib/server/actions/project/library/install-library.action.ts new file mode 100644 index 0000000..5109b9c --- /dev/null +++ b/src/lib/server/actions/project/library/install-library.action.ts @@ -0,0 +1,16 @@ +import type { LibraryPackage } from '$lib/server/project/library'; + +import { useActionHandler } from '@utils-server/request-handler'; + +export class InstallLibraryBody { + libraryName!: string; +} + +export const installLibraryProjectAction = useActionHandler( + async ({ body, project }): Promise => { + return await project.client.library.installLibrary(body.libraryName); + }, + { + body: InstallLibraryBody, + }, +); diff --git a/src/lib/server/actions/project/package/add-components.action.ts b/src/lib/server/actions/project/package/add-components.action.ts index 670c0e6..1d7e495 100644 --- a/src/lib/server/actions/project/package/add-components.action.ts +++ b/src/lib/server/actions/project/package/add-components.action.ts @@ -1,4 +1,4 @@ -import type { NewComponentPackage } from '$lib/server/project/package/package.type'; +import type { ComponentPackage } from '$lib/server/project/package/package.type'; import { useActionHandler } from '@utils-server/request-handler'; @@ -7,7 +7,7 @@ export class AddComponentBody { } export const addComponentsProjectAction = useActionHandler( - async ({ body, project }): Promise => { + async ({ body, project }): Promise => { return await Promise.all( body.componentNames.map((componentName) => project.client.package.installComponent(componentName), diff --git a/src/lib/server/actions/project/package/add-systems.action.ts b/src/lib/server/actions/project/package/add-systems.action.ts index 96a4e92..96d7658 100644 --- a/src/lib/server/actions/project/package/add-systems.action.ts +++ b/src/lib/server/actions/project/package/add-systems.action.ts @@ -1,4 +1,4 @@ -import type { NewSystemPackage } from '$lib/server/project/package/package.type'; +import type { SystemPackage } from '$lib/server/project/package/package.type'; import { useActionHandler } from '@utils-server/request-handler'; @@ -7,7 +7,7 @@ export class AddSystemBody { } export const addSystemsProjectAction = useActionHandler( - async ({ body, project }): Promise => { + async ({ body, project }): Promise => { return await Promise.all( body.systemNames.map((systemName) => project.client.package.installSystem(systemName)), ); diff --git a/src/lib/server/actions/project/package/create-component.action.ts b/src/lib/server/actions/project/package/create-component.action.ts index 01adc91..a826e9d 100644 --- a/src/lib/server/actions/project/package/create-component.action.ts +++ b/src/lib/server/actions/project/package/create-component.action.ts @@ -1,4 +1,4 @@ -import type { NewComponentPackage } from '$lib/server/project/package/package.type'; +import type { ComponentPackage } from '$lib/server/project/package/package.type'; import { useActionHandler } from '@utils-server/request-handler'; @@ -7,7 +7,7 @@ export class CreateComponentBody { } export const createComponentProjectAction = useActionHandler( - async ({ body, project }): Promise => { + async ({ body, project }): Promise => { return project.client.package.createComponent(body.componentName); }, { diff --git a/src/lib/server/actions/project/package/create-system.action.ts b/src/lib/server/actions/project/package/create-system.action.ts index 12c102d..97963ef 100644 --- a/src/lib/server/actions/project/package/create-system.action.ts +++ b/src/lib/server/actions/project/package/create-system.action.ts @@ -1,4 +1,4 @@ -import type { NewSystemPackage } from '$lib/server/project/package/package.type'; +import type { SystemPackage } from '$lib/server/project/package/package.type'; import { useActionHandler } from '@utils-server/request-handler'; @@ -7,7 +7,7 @@ export class CreateSystemBody { } export const createSystemProjectAction = useActionHandler( - async ({ body, project }): Promise => { + async ({ body, project }): Promise => { return project.client.package.createSystem(body.systemName); }, { diff --git a/src/lib/server/actions/project/package/get-components.action.ts b/src/lib/server/actions/project/package/get-components.action.ts new file mode 100644 index 0000000..31387d8 --- /dev/null +++ b/src/lib/server/actions/project/package/get-components.action.ts @@ -0,0 +1,9 @@ +import type { ComponentPackage } from '$lib/server/project/package'; + +import { useActionHandler } from '@utils-server/request-handler'; + +export const getComponentsAction = useActionHandler( + async ({ project }): Promise => { + return await project.client.package.getComponents(); + }, +); diff --git a/src/lib/server/actions/project/package/get-systems.action.ts b/src/lib/server/actions/project/package/get-systems.action.ts new file mode 100644 index 0000000..53b9c0b --- /dev/null +++ b/src/lib/server/actions/project/package/get-systems.action.ts @@ -0,0 +1,7 @@ +import type { SystemPackage } from '$lib/server/project/package'; + +import { useActionHandler } from '@utils-server/request-handler'; + +export const getSystemsAction = useActionHandler(async ({ project }): Promise => { + return await project.client.package.getSystems(); +}); diff --git a/src/lib/server/cli/cli.ts b/src/lib/server/cli/cli.ts index 67f8da6..7eb578a 100644 --- a/src/lib/server/cli/cli.ts +++ b/src/lib/server/cli/cli.ts @@ -10,7 +10,7 @@ import { CLI_START_DEFAULTS, } from '$lib/server/cli/cli-defaults'; -import { camelToKebab } from '@utils/format'; +import { formatFrom } from '@utils/format'; import type { Context } from '@utils-server/request-handler'; @@ -173,7 +173,7 @@ export class Cli { ): string[] { const params = []; for (const [key, value] of Object.entries(this.mergeParams(defaultOpts, opts))) { - const name = camelToKebab(key); + const name = formatFrom.camel(key).toKebab(); if (typeof value === 'boolean') { if (value) params.push(`--${name}`); diff --git a/src/lib/server/git/git.ts b/src/lib/server/git/git.ts index 4583737..b99ce7b 100644 --- a/src/lib/server/git/git.ts +++ b/src/lib/server/git/git.ts @@ -3,7 +3,7 @@ import { resolve } from 'path'; import { env } from '$env/dynamic/private'; -import { generateKey } from '@utils/string'; +import { generateKey } from '@utils-server/string'; export class Git { private readonly _rootPath: string; diff --git a/src/lib/server/project/library/index.ts b/src/lib/server/project/library/index.ts new file mode 100644 index 0000000..a08aaeb --- /dev/null +++ b/src/lib/server/project/library/index.ts @@ -0,0 +1 @@ +export * from './library.type'; diff --git a/src/lib/server/project/library/library-handler.ts b/src/lib/server/project/library/library-handler.ts new file mode 100644 index 0000000..7373816 --- /dev/null +++ b/src/lib/server/project/library/library-handler.ts @@ -0,0 +1,36 @@ +import { type ProjectHandler } from '$lib/server/project'; + +import { formatFrom } from '@utils/format'; + +import { type LibraryPackage } from './library.type'; + +export class LibraryHandler { + private readonly handler: ProjectHandler; + + constructor(handler: ProjectHandler) { + this.handler = handler; + } + + async installLibrary(name: string): Promise { + this.handler._cli.install([name], { + server: this.handler._part === 'server' || undefined, + lib: true, + }); + + return { + save: { + id: this._resolveIdFromName(name), + type: '', + name: '', + path: name, + }, + }; + } + + private _resolveIdFromName(name: string): string { + const [org, pkg] = name.split('/'); + if (!org || !pkg) throw new Error('Invalid library name'); + const id = !pkg ? org : pkg; + return `${formatFrom.kebab(id).toCamel()}Library`; + } +} diff --git a/src/lib/server/project/library/library.type.ts b/src/lib/server/project/library/library.type.ts new file mode 100644 index 0000000..20096aa --- /dev/null +++ b/src/lib/server/project/library/library.type.ts @@ -0,0 +1,5 @@ +import type { SaveLibrary } from '@utils/types'; + +export interface LibraryPackage { + save: SaveLibrary; +} diff --git a/src/lib/server/project/package/index.ts b/src/lib/server/project/package/index.ts new file mode 100644 index 0000000..defaadf --- /dev/null +++ b/src/lib/server/project/package/index.ts @@ -0,0 +1 @@ +export * from './package.type'; diff --git a/src/lib/server/project/package/package-handler.ts b/src/lib/server/project/package/package-handler.ts index 4ec20ed..b751f8c 100644 --- a/src/lib/server/project/package/package-handler.ts +++ b/src/lib/server/project/package/package-handler.ts @@ -2,12 +2,13 @@ import type { EditorComponentManifest, EditorSystemManifest } from '@nanoforge-d import { join } from 'path'; import { FileSystemError } from '$lib/server/file-system/file-system-error'; +import type { DirectoryContent } from '$lib/server/file-system/project-directory'; import { type ProjectHandler } from '$lib/server/project'; -import { toCamelCase, toKebabCase, toPascalCase } from '@utils/format'; +import { formatFrom } from '@utils/format'; import { resolveManifest } from './manifest-resolver'; -import { type NewComponentPackage, type NewSystemPackage, PackageTypeEnum } from './package.type'; +import { type ComponentPackage, PackageTypeEnum, type SystemPackage } from './package.type'; export class PackageHandler { private readonly handler: ProjectHandler; @@ -16,7 +17,7 @@ export class PackageHandler { this.handler = handler; } - async installComponent(name: string): Promise { + async installComponent(name: string): Promise { const rc = await this.handler._api.registry.getPackage(name); if (rc.type !== 'component') throw new Error(`Can only add component: ${name} is a ${rc.type}`); this.handler._cli.install([name], { server: this.handler._part === 'server' || undefined }); @@ -24,7 +25,7 @@ export class PackageHandler { return this._getNewComponentPackage(rc.name, rc._file); } - async installSystem(name: string): Promise { + async installSystem(name: string): Promise { const rs = await this.handler._api.registry.getPackage(name); if (rs.type !== 'system') throw new Error(`Can only add system: ${name} is a ${rs.type}`); this.handler._cli.install([name], { server: this.handler._part === 'server' || undefined }); @@ -38,11 +39,11 @@ export class PackageHandler { * * @param {string} name - Name of the component */ - createComponent(name: string): NewComponentPackage { + createComponent(name: string): ComponentPackage { this._createPackage(PackageTypeEnum.COMPONENT, name); return this._getNewComponentPackage( - toPascalCase(name) + 'Component', - toKebabCase(name) + '.component', + formatFrom.all(name).toPascal() + 'Component', + formatFrom.all(name).toKebab() + '.component', ); } @@ -52,9 +53,12 @@ export class PackageHandler { * * @param {string} name - Name of the system */ - createSystem(name: string): NewSystemPackage { + createSystem(name: string): SystemPackage { this._createPackage(PackageTypeEnum.SYSTEM, name); - return this._getNewSystemPackage(toCamelCase(name) + 'System', toKebabCase(name) + '.system'); + return this._getNewSystemPackage( + formatFrom.all(name).toCamel() + 'System', + formatFrom.all(name).toKebab() + '.system', + ); } /** @@ -81,7 +85,56 @@ export class PackageHandler { return this._getPackageManifest(PackageTypeEnum.SYSTEM, path); } - private _getNewComponentPackage(name: string, fileName: string): NewComponentPackage { + async getComponents(): Promise { + return this._resolvesPackages(PackageTypeEnum.COMPONENT); + } + + async getSystems(): Promise { + return this._resolvesPackages(PackageTypeEnum.SYSTEM); + } + + private _resolvesPackages( + type: T, + ): (T extends PackageTypeEnum.COMPONENT ? ComponentPackage : SystemPackage)[] { + const basePath = type === PackageTypeEnum.COMPONENT ? './components' : './systems'; + const dir = this.handler.fs.getDirectory(basePath); + const content = dir.read(true); + const paths = this._resolvesPackageFilesPathFromContent(content); + return paths.map((path) => this._resolvesPackage(type, join(basePath, path))); + } + + private _resolvesPackage( + type: T, + path: string, + ): T extends PackageTypeEnum.COMPONENT ? ComponentPackage : SystemPackage { + const manifest = this._getPackageManifest(type, path); + const res: any = { + manifest, + save: { + name: manifest.name, + path, + }, + }; + if (type === PackageTypeEnum.COMPONENT) { + res.save.params = manifest.params.map(({ name }: { name: string }) => name); + } + return res; + } + + private _resolvesPackageFilesPathFromContent( + content: DirectoryContent, + path: string = '', + ): string[] { + const files = content.files.map((file) => join(path, file)); + const directories = Object.entries(content.directories).map(([key, value]) => { + if (!value) return []; + return this._resolvesPackageFilesPathFromContent(value, join(path, key)).filter(Boolean); + }); + + return [...files, ...directories.flat()]; + } + + private _getNewComponentPackage(name: string, fileName: string): ComponentPackage { const path = `./components/${fileName}`; const manifest = this._findPackageManifest(this.getComponentManifest, path); @@ -96,7 +149,7 @@ export class PackageHandler { }; } - private _getNewSystemPackage(name: string, fileName: string): NewSystemPackage { + private _getNewSystemPackage(name: string, fileName: string): SystemPackage { const path = `./systems/${fileName}`; return { manifest: this._findPackageManifest(this.getSystemManifest, path), diff --git a/src/lib/server/project/package/package.type.ts b/src/lib/server/project/package/package.type.ts index ce231b2..6858487 100644 --- a/src/lib/server/project/package/package.type.ts +++ b/src/lib/server/project/package/package.type.ts @@ -7,12 +7,12 @@ export enum PackageTypeEnum { SYSTEM = 'system', } -export interface NewComponentPackage { +export interface ComponentPackage { manifest: EditorComponentManifest; save: SaveComponent; } -export interface NewSystemPackage { +export interface SystemPackage { manifest: EditorSystemManifest; save: SaveSystem; } diff --git a/src/lib/server/project/project-handler.ts b/src/lib/server/project/project-handler.ts index f5af6fd..dc3cdd2 100644 --- a/src/lib/server/project/project-handler.ts +++ b/src/lib/server/project/project-handler.ts @@ -9,6 +9,7 @@ import type { Part } from '@utils/types'; import { type Context, type Handler } from '@utils-server/request-handler'; +import { LibraryHandler } from './library/library-handler'; import { Loader } from './loader'; import { PackageHandler } from './package/package-handler'; import { SaveHandler } from './save/save-handler'; @@ -24,6 +25,7 @@ export class ProjectHandler { private _loader: Loader | undefined; private _save: SaveHandler | undefined; private _package: PackageHandler | undefined; + private _library: LibraryHandler | undefined; constructor(handler: Handler, context: Context, part: Part) { if (!context.project) throw new Exception('Bad Request', 'Project missing in context', 400); @@ -60,4 +62,9 @@ export class ProjectHandler { if (!this._package) this._package = new PackageHandler(this); return this._package; } + + get library(): LibraryHandler { + if (!this._library) this._library = new LibraryHandler(this); + return this._library; + } } diff --git a/src/lib/server/session/project/project-functions.ts b/src/lib/server/session/project/project-functions.ts index 85a511e..1df1e9c 100644 --- a/src/lib/server/session/project/project-functions.ts +++ b/src/lib/server/session/project/project-functions.ts @@ -1,5 +1,6 @@ import { SESSION_PROJECT_HEADER } from '@utils/const'; -import { generateKey } from '@utils/string'; + +import { generateKey } from '@utils-server/string'; import type { Session } from '../session.type'; import { projectStore } from './project.store'; diff --git a/src/lib/server/session/session-functions.ts b/src/lib/server/session/session-functions.ts index c6d6285..ab417d4 100644 --- a/src/lib/server/session/session-functions.ts +++ b/src/lib/server/session/session-functions.ts @@ -1,7 +1,8 @@ import { type Session as SvelteSession } from 'svelte-kit-sessions'; import { Exception } from '@utils/exception'; -import { generateKey } from '@utils/string'; + +import { generateKey } from '@utils-server/string'; import { PUBLIC_PATHS } from './session.const'; import { sessionStore } from './session.store'; diff --git a/src/lib/server/session/session-handle.ts b/src/lib/server/session/session-handle.ts index b6a3593..d784773 100644 --- a/src/lib/server/session/session-handle.ts +++ b/src/lib/server/session/session-handle.ts @@ -3,7 +3,7 @@ import { sveltekitSessionHandle } from 'svelte-kit-sessions'; import { env } from '$env/dynamic/private'; -import { generateKey } from '@utils/string'; +import { generateKey } from '@utils-server/string'; import { isPublicPath, isSessionExist, resetSession } from './session-functions'; diff --git a/src/lib/server/utils/string.ts b/src/lib/server/utils/string.ts new file mode 100644 index 0000000..08c33af --- /dev/null +++ b/src/lib/server/utils/string.ts @@ -0,0 +1,6 @@ +import crypto from 'crypto'; + +export const generateKey = (size = 50) => { + const buffer = crypto.randomBytes(size); + return buffer.toString('base64url').substring(0, size); +}; diff --git a/src/lib/utils/format.ts b/src/lib/utils/format.ts index de3e61e..52d7925 100644 --- a/src/lib/utils/format.ts +++ b/src/lib/utils/format.ts @@ -1,3 +1,31 @@ +class WordList { + words: string[]; + + constructor(words: string[]) { + this.words = words; + } + + toKebab() { + return this.words.join('-'); + } + + toPascal() { + return this.words.map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(''); + } + + toCamel() { + return this.words + .map((word, i) => + i === 0 ? word.toLowerCase() : word.charAt(0).toUpperCase() + word.slice(1), + ) + .join(''); + } + + toSnake() { + return this.words.join('_'); + } +} + const toWords = (str: string): string[] => { return str .replace(/([a-z])([A-Z])/g, '$1 $2') @@ -8,26 +36,23 @@ const toWords = (str: string): string[] => { .filter(Boolean); }; -export const toKebabCase = (str: string): string => { - return toWords(str) - .map((word) => word.toLowerCase()) - .join('-'); -}; +const fromKebab = (str: string): WordList => new WordList(str.split('-')); -export const toPascalCase = (str: string): string => { - return toWords(str) - .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) - .join(''); -}; +const fromPascal = (str: string): WordList => + new WordList(str.split(/(?=[A-Z])/).map((word) => word.toLowerCase())); -export const toCamelCase = (str: string): string => { - const words = toWords(str); - return words - .map((word, i) => - i === 0 ? word.toLowerCase() : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase(), - ) - .join(''); -}; +const fromCamel = (str: string): WordList => + new WordList(str.split(/(?=[A-Z])/).map((word) => word.toLowerCase())); -export const camelToKebab = (str: string) => - str.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`); +const fromSnake = (str: string): WordList => new WordList(str.split('_')); + +const fromAll = (str: string): WordList => + new WordList(toWords(str).map((word) => word.toLowerCase())); + +export const formatFrom = { + kebab: fromKebab, + pascal: fromPascal, + camel: fromCamel, + snake: fromSnake, + all: fromAll, +}; diff --git a/src/lib/utils/string.ts b/src/lib/utils/string.ts index 08c33af..162272f 100644 --- a/src/lib/utils/string.ts +++ b/src/lib/utils/string.ts @@ -1,6 +1,18 @@ -import crypto from 'crypto'; +export const capitalize = (str: string) => str.charAt(0).toUpperCase() + str.slice(1); -export const generateKey = (size = 50) => { - const buffer = crypto.randomBytes(size); - return buffer.toString('base64url').substring(0, size); +export const randomString = ( + nb: number, + { + numbers = true, + lowers = true, + uppers = false, + specials = false, + }: { numbers?: boolean; lowers?: boolean; uppers?: boolean; specials?: boolean } = {}, +) => { + let chars = ''; + if (numbers) chars += '0123456789'; + if (lowers) chars += 'abcdefghijklmnopqrstuvwxyz'; + if (uppers) chars += 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + if (specials) chars += '!@#$%^&*()_+~`|}{[]:;?><,./-='; + return [...Array(nb)].map(() => chars[Math.floor(Math.random() * chars.length)]).join(''); }; diff --git a/src/lib/utils/types/save.type.ts b/src/lib/utils/types/save.type.ts index efadb04..1f79a46 100644 --- a/src/lib/utils/types/save.type.ts +++ b/src/lib/utils/types/save.type.ts @@ -27,6 +27,7 @@ export interface SaveSystem { export interface SaveEntity { id: string; + treePath: string; components: Record>; } diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index ec11de2..d9cabb8 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -103,7 +103,7 @@