From e9b0e9d85623f04e58b8c626ef914e1a30a5ba37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Forment?= Date: Mon, 1 Dec 2025 17:42:42 +0100 Subject: [PATCH] OK --- .gitignore | 61 ++ .vscode/extensions.json | 3 + README.md | 47 + index.html | 13 + package.json | 41 + pnpm-lock.yaml | 1138 ++++++++++++++++++++++ public/fonts/DepartureMono-Regular.woff | Bin 0 -> 25256 bytes public/fonts/DepartureMono-Regular.woff2 | Bin 0 -> 22496 bytes src/App.svelte | 163 ++++ src/app.css | 28 + src/lib/Canvas.svelte | 174 ++++ src/lib/Editor.svelte | 258 +++++ src/lib/Item.svelte | 298 ++++++ src/lib/Palette.svelte | 224 +++++ src/lib/Toolbar.svelte | 207 ++++ src/lib/geometry.ts | 81 ++ src/lib/io.ts | 93 ++ src/lib/state.svelte.ts | 358 +++++++ src/lib/theme.ts | 131 +++ src/lib/types.ts | 42 + src/main.ts | 9 + svelte.config.js | 8 + tsconfig.app.json | 21 + tsconfig.json | 7 + tsconfig.node.json | 26 + vite.config.ts | 7 + 26 files changed, 3438 insertions(+) create mode 100644 .gitignore create mode 100644 .vscode/extensions.json create mode 100644 README.md create mode 100644 index.html create mode 100644 package.json create mode 100644 pnpm-lock.yaml create mode 100644 public/fonts/DepartureMono-Regular.woff create mode 100644 public/fonts/DepartureMono-Regular.woff2 create mode 100644 src/App.svelte create mode 100644 src/app.css create mode 100644 src/lib/Canvas.svelte create mode 100644 src/lib/Editor.svelte create mode 100644 src/lib/Item.svelte create mode 100644 src/lib/Palette.svelte create mode 100644 src/lib/Toolbar.svelte create mode 100644 src/lib/geometry.ts create mode 100644 src/lib/io.ts create mode 100644 src/lib/state.svelte.ts create mode 100644 src/lib/theme.ts create mode 100644 src/lib/types.ts create mode 100644 src/main.ts create mode 100644 svelte.config.js create mode 100644 tsconfig.app.json create mode 100644 tsconfig.json create mode 100644 tsconfig.node.json create mode 100644 vite.config.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dda74cc --- /dev/null +++ b/.gitignore @@ -0,0 +1,61 @@ +# Dependencies +node_modules/ + +# Build output +dist/ +dist-ssr/ +*.local + +# Tauri +src-tauri/target/ +src-tauri/WixTools/ +src-tauri/Cargo.lock + +# Rust +**/*.rs.bk +*.pdb + +# Editor +.vscode/* +!.vscode/extensions.json +.idea/ +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? +*.swp +*.swo +*~ + +# OS +.DS_Store +Thumbs.db +Desktop.ini + +# Env +.env +.env.* +!.env.example + +# Logs +logs/ +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +# Cache +.cache/ +*.tsbuildinfo +.eslintcache +.prettiercache + +# Test +coverage/ + +# Temp +*.tmp +*.temp diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..bdef820 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["svelte.svelte-vscode"] +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..e6cd94f --- /dev/null +++ b/README.md @@ -0,0 +1,47 @@ +# Svelte + TS + Vite + +This template should help get you started developing with Svelte and TypeScript in Vite. + +## Recommended IDE Setup + +[VS Code](https://code.visualstudio.com/) + [Svelte](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode). + +## Need an official Svelte framework? + +Check out [SvelteKit](https://github.com/sveltejs/kit#readme), which is also powered by Vite. Deploy anywhere with its serverless-first approach and adapt to various platforms, with out of the box support for TypeScript, SCSS, and Less, and easily-added support for mdsvex, GraphQL, PostCSS, Tailwind CSS, and more. + +## Technical considerations + +**Why use this over SvelteKit?** + +- It brings its own routing solution which might not be preferable for some users. +- It is first and foremost a framework that just happens to use Vite under the hood, not a Vite app. + +This template contains as little as possible to get started with Vite + TypeScript + Svelte, while taking into account the developer experience with regards to HMR and intellisense. It demonstrates capabilities on par with the other `create-vite` templates and is a good starting point for beginners dipping their toes into a Vite + Svelte project. + +Should you later need the extended capabilities and extensibility provided by SvelteKit, the template has been structured similarly to SvelteKit so that it is easy to migrate. + +**Why `global.d.ts` instead of `compilerOptions.types` inside `jsconfig.json` or `tsconfig.json`?** + +Setting `compilerOptions.types` shuts out all other types not explicitly listed in the configuration. Using triple-slash references keeps the default TypeScript setting of accepting type information from the entire workspace, while also adding `svelte` and `vite/client` type information. + +**Why include `.vscode/extensions.json`?** + +Other templates indirectly recommend extensions via the README, but this file allows VS Code to prompt the user to install the recommended extension upon opening the project. + +**Why enable `allowJs` in the TS template?** + +While `allowJs: false` would indeed prevent the use of `.js` files in the project, it does not prevent the use of JavaScript syntax in `.svelte` files. In addition, it would force `checkJs: false`, bringing the worst of both worlds: not being able to guarantee the entire codebase is TypeScript, and also having worse typechecking for the existing JavaScript. In addition, there are valid use cases in which a mixed codebase may be relevant. + +**Why is HMR not preserving my local component state?** + +HMR state preservation comes with a number of gotchas! It has been disabled by default in both `svelte-hmr` and `@sveltejs/vite-plugin-svelte` due to its often surprising behavior. You can read the details [here](https://github.com/rixo/svelte-hmr#svelte-hmr). + +If you have state that's important to retain within a component, consider creating an external store which would not be replaced by HMR. + +```ts +// store.ts +// An extremely simple external store +import { writable } from 'svelte/store' +export default writable(0) +``` diff --git a/index.html b/index.html new file mode 100644 index 0000000..4e4c72b --- /dev/null +++ b/index.html @@ -0,0 +1,13 @@ + + + + + + + buboard + + +
+ + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..b7a11bd --- /dev/null +++ b/package.json @@ -0,0 +1,41 @@ +{ + "name": "buboard", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "check": "svelte-check --tsconfig ./tsconfig.app.json && tsc -p tsconfig.node.json" + }, + "devDependencies": { + "@sveltejs/vite-plugin-svelte": "^6.2.1", + "@tsconfig/svelte": "^5.0.6", + "@types/node": "^24.10.1", + "svelte": "^5.43.8", + "svelte-check": "^4.3.4", + "typescript": "~5.9.3", + "vite": "npm:rolldown-vite@7.2.5" + }, + "pnpm": { + "overrides": { + "vite": "npm:rolldown-vite@7.2.5" + } + }, + "dependencies": { + "@codemirror/commands": "^6.10.0", + "@codemirror/lang-css": "^6.3.1", + "@codemirror/lang-html": "^6.4.11", + "@codemirror/language": "^6.11.3", + "@codemirror/state": "^6.5.2", + "@codemirror/theme-one-dark": "^6.1.3", + "@codemirror/view": "^6.38.8", + "@lezer/highlight": "^1.2.3", + "@replit/codemirror-emacs": "^6.1.0", + "@replit/codemirror-vim": "^6.3.0", + "codemirror": "^6.0.2", + "jszip": "^3.10.1", + "lucide-svelte": "^0.555.0" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..32ae746 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,1138 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +overrides: + vite: npm:rolldown-vite@7.2.5 + +importers: + + .: + dependencies: + '@codemirror/commands': + specifier: ^6.10.0 + version: 6.10.0 + '@codemirror/lang-css': + specifier: ^6.3.1 + version: 6.3.1 + '@codemirror/lang-html': + specifier: ^6.4.11 + version: 6.4.11 + '@codemirror/language': + specifier: ^6.11.3 + version: 6.11.3 + '@codemirror/state': + specifier: ^6.5.2 + version: 6.5.2 + '@codemirror/theme-one-dark': + specifier: ^6.1.3 + version: 6.1.3 + '@codemirror/view': + specifier: ^6.38.8 + version: 6.38.8 + '@lezer/highlight': + specifier: ^1.2.3 + version: 1.2.3 + '@replit/codemirror-emacs': + specifier: ^6.1.0 + version: 6.1.0(@codemirror/autocomplete@6.20.0)(@codemirror/commands@6.10.0)(@codemirror/search@6.5.11)(@codemirror/state@6.5.2)(@codemirror/view@6.38.8) + '@replit/codemirror-vim': + specifier: ^6.3.0 + version: 6.3.0(@codemirror/commands@6.10.0)(@codemirror/language@6.11.3)(@codemirror/search@6.5.11)(@codemirror/state@6.5.2)(@codemirror/view@6.38.8) + codemirror: + specifier: ^6.0.2 + version: 6.0.2 + jszip: + specifier: ^3.10.1 + version: 3.10.1 + lucide-svelte: + specifier: ^0.555.0 + version: 0.555.0(svelte@5.45.2) + devDependencies: + '@sveltejs/vite-plugin-svelte': + specifier: ^6.2.1 + version: 6.2.1(rolldown-vite@7.2.5(@types/node@24.10.1))(svelte@5.45.2) + '@tsconfig/svelte': + specifier: ^5.0.6 + version: 5.0.6 + '@types/node': + specifier: ^24.10.1 + version: 24.10.1 + svelte: + specifier: ^5.43.8 + version: 5.45.2 + svelte-check: + specifier: ^4.3.4 + version: 4.3.4(picomatch@4.0.3)(svelte@5.45.2)(typescript@5.9.3) + typescript: + specifier: ~5.9.3 + version: 5.9.3 + vite: + specifier: npm:rolldown-vite@7.2.5 + version: rolldown-vite@7.2.5(@types/node@24.10.1) + +packages: + + '@codemirror/autocomplete@6.20.0': + resolution: {integrity: sha512-bOwvTOIJcG5FVo5gUUupiwYh8MioPLQ4UcqbcRf7UQ98X90tCa9E1kZ3Z7tqwpZxYyOvh1YTYbmZE9RTfTp5hg==} + + '@codemirror/commands@6.10.0': + resolution: {integrity: sha512-2xUIc5mHXQzT16JnyOFkh8PvfeXuIut3pslWGfsGOhxP/lpgRm9HOl/mpzLErgt5mXDovqA0d11P21gofRLb9w==} + + '@codemirror/lang-css@6.3.1': + resolution: {integrity: sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==} + + '@codemirror/lang-html@6.4.11': + resolution: {integrity: sha512-9NsXp7Nwp891pQchI7gPdTwBuSuT3K65NGTHWHNJ55HjYcHLllr0rbIZNdOzas9ztc1EUVBlHou85FFZS4BNnw==} + + '@codemirror/lang-javascript@6.2.4': + resolution: {integrity: sha512-0WVmhp1QOqZ4Rt6GlVGwKJN3KW7Xh4H2q8ZZNGZaP6lRdxXJzmjm4FqvmOojVj6khWJHIb9sp7U/72W7xQgqAA==} + + '@codemirror/language@6.11.3': + resolution: {integrity: sha512-9HBM2XnwDj7fnu0551HkGdrUrrqmYq/WC5iv6nbY2WdicXdGbhR/gfbZOH73Aqj4351alY1+aoG9rCNfiwS1RA==} + + '@codemirror/lint@6.9.2': + resolution: {integrity: sha512-sv3DylBiIyi+xKwRCJAAsBZZZWo82shJ/RTMymLabAdtbkV5cSKwWDeCgtUq3v8flTaXS2y1kKkICuRYtUswyQ==} + + '@codemirror/search@6.5.11': + resolution: {integrity: sha512-KmWepDE6jUdL6n8cAAqIpRmLPBZ5ZKnicE8oGU/s3QrAVID+0VhLFrzUucVKHG5035/BSykhExDL/Xm7dHthiA==} + + '@codemirror/state@6.5.2': + resolution: {integrity: sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==} + + '@codemirror/theme-one-dark@6.1.3': + resolution: {integrity: sha512-NzBdIvEJmx6fjeremiGp3t/okrLPYT0d9orIc7AFun8oZcRk58aejkqhv6spnz4MLAevrKNPMQYXEWMg4s+sKA==} + + '@codemirror/view@6.38.8': + resolution: {integrity: sha512-XcE9fcnkHCbWkjeKyi0lllwXmBLtyYb5dt89dJyx23I9+LSh5vZDIuk7OLG4VM1lgrXZQcY6cxyZyk5WVPRv/A==} + + '@emnapi/core@1.7.1': + resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==} + + '@emnapi/runtime@1.7.1': + resolution: {integrity: sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==} + + '@emnapi/wasi-threads@1.1.0': + resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@lezer/common@1.4.0': + resolution: {integrity: sha512-DVeMRoGrgn/k45oQNu189BoW4SZwgZFzJ1+1TV5j2NJ/KFC83oa/enRqZSGshyeMk5cPWMhsKs9nx+8o0unwGg==} + + '@lezer/css@1.3.0': + resolution: {integrity: sha512-pBL7hup88KbI7hXnZV3PQsn43DHy6TWyzuyk2AO9UyoXcDltvIdqWKE1dLL/45JVZ+YZkHe1WVHqO6wugZZWcw==} + + '@lezer/highlight@1.2.3': + resolution: {integrity: sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==} + + '@lezer/html@1.3.12': + resolution: {integrity: sha512-RJ7eRWdaJe3bsiiLLHjCFT1JMk8m1YP9kaUbvu2rMLEoOnke9mcTVDyfOslsln0LtujdWespjJ39w6zo+RsQYw==} + + '@lezer/javascript@1.5.4': + resolution: {integrity: sha512-vvYx3MhWqeZtGPwDStM2dwgljd5smolYD2lR2UyFcHfxbBQebqx8yjmFmxtJ/E6nN6u1D9srOiVWm3Rb4tmcUA==} + + '@lezer/lr@1.4.4': + resolution: {integrity: sha512-LHL17Mq0OcFXm1pGQssuGTQFPPdxARjKM8f7GA5+sGtHi0K3R84YaSbmche0+RKWHnCsx9asEe5OWOI4FHfe4A==} + + '@marijn/find-cluster-break@1.0.2': + resolution: {integrity: sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==} + + '@napi-rs/wasm-runtime@1.0.7': + resolution: {integrity: sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==} + + '@oxc-project/runtime@0.97.0': + resolution: {integrity: sha512-yH0zw7z+jEws4dZ4IUKoix5Lh3yhqIJWF9Dc8PWvhpo7U7O+lJrv7ZZL4BeRO0la8LBQFwcCewtLBnVV7hPe/w==} + engines: {node: ^20.19.0 || >=22.12.0} + + '@oxc-project/types@0.97.0': + resolution: {integrity: sha512-lxmZK4xFrdvU0yZiDwgVQTCvh2gHWBJCBk5ALsrtsBWhs0uDIi+FTOnXRQeQfs304imdvTdaakT/lqwQ8hkOXQ==} + + '@replit/codemirror-emacs@6.1.0': + resolution: {integrity: sha512-74DITnht6Cs6sHg02PQ169IKb1XgtyhI9sLD0JeOFco6Ds18PT+dkD8+DgXBDokne9UIFKsBbKPnpFRAz60/Lw==} + peerDependencies: + '@codemirror/autocomplete': ^6.0.2 + '@codemirror/commands': ^6.0.0 + '@codemirror/search': ^6.0.0 + '@codemirror/state': ^6.0.1 + '@codemirror/view': ^6.3.0 + + '@replit/codemirror-vim@6.3.0': + resolution: {integrity: sha512-aTx931ULAMuJx6xLf7KQDOL7CxD+Sa05FktTDrtLaSy53uj01ll3Zf17JdKsriER248oS55GBzg0CfCTjEneAQ==} + peerDependencies: + '@codemirror/commands': 6.x.x + '@codemirror/language': 6.x.x + '@codemirror/search': 6.x.x + '@codemirror/state': 6.x.x + '@codemirror/view': 6.x.x + + '@rolldown/binding-android-arm64@1.0.0-beta.50': + resolution: {integrity: sha512-XlEkrOIHLyGT3avOgzfTFSjG+f+dZMw+/qd+Y3HLN86wlndrB/gSimrJCk4gOhr1XtRtEKfszpadI3Md4Z4/Ag==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.0.0-beta.50': + resolution: {integrity: sha512-+JRqKJhoFlt5r9q+DecAGPLZ5PxeLva+wCMtAuoFMWPoZzgcYrr599KQ+Ix0jwll4B4HGP43avu9My8KtSOR+w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.0.0-beta.50': + resolution: {integrity: sha512-fFXDjXnuX7/gQZQm/1FoivVtRcyAzdjSik7Eo+9iwPQ9EgtA5/nB2+jmbzaKtMGG3q+BnZbdKHCtOacmNrkIDA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.0.0-beta.50': + resolution: {integrity: sha512-F1b6vARy49tjmT/hbloplzgJS7GIvwWZqt+tAHEstCh0JIh9sa8FAMVqEmYxDviqKBaAI8iVvUREm/Kh/PD26Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.50': + resolution: {integrity: sha512-U6cR76N8T8M6lHj7EZrQ3xunLPxSvYYxA8vJsBKZiFZkT8YV4kjgCO3KwMJL0NOjQCPGKyiXO07U+KmJzdPGRw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.50': + resolution: {integrity: sha512-ONgyjofCrrE3bnh5GZb8EINSFyR/hmwTzZ7oVuyUB170lboza1VMCnb8jgE6MsyyRgHYmN8Lb59i3NKGrxrYjw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.50': + resolution: {integrity: sha512-L0zRdH2oDPkmB+wvuTl+dJbXCsx62SkqcEqdM+79LOcB+PxbAxxjzHU14BuZIQdXcAVDzfpMfaHWzZuwhhBTcw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.50': + resolution: {integrity: sha512-gyoI8o/TGpQd3OzkJnh1M2kxy1Bisg8qJ5Gci0sXm9yLFzEXIFdtc4EAzepxGvrT2ri99ar5rdsmNG0zP0SbIg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@rolldown/binding-linux-x64-musl@1.0.0-beta.50': + resolution: {integrity: sha512-zti8A7M+xFDpKlghpcCAzyOi+e5nfUl3QhU023ce5NCgUxRG5zGP2GR9LTydQ1rnIPwZUVBWd4o7NjZDaQxaXA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + + '@rolldown/binding-openharmony-arm64@1.0.0-beta.50': + resolution: {integrity: sha512-eZUssog7qljrrRU9Mi0eqYEPm3Ch0UwB+qlWPMKSUXHNqhm3TvDZarJQdTevGEfu3EHAXJvBIe0YFYr0TPVaMA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-wasm32-wasi@1.0.0-beta.50': + resolution: {integrity: sha512-nmCN0nIdeUnmgeDXiQ+2HU6FT162o+rxnF7WMkBm4M5Ds8qTU7Dzv2Wrf22bo4ftnlrb2hKK6FSwAJSAe2FWLg==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.50': + resolution: {integrity: sha512-7kcNLi7Ua59JTTLvbe1dYb028QEPaJPJQHqkmSZ5q3tJueUeb6yjRtx8mw4uIqgWZcnQHAR3PrLN4XRJxvgIkA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.50': + resolution: {integrity: sha512-lL70VTNvSCdSZkDPPVMwWn/M2yQiYvSoXw9hTLgdIWdUfC3g72UaruezusR6ceRuwHCY1Ayu2LtKqXkBO5LIwg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.50': + resolution: {integrity: sha512-4qU4x5DXWB4JPjyTne/wBNPqkbQU8J45bl21geERBKtEittleonioACBL1R0PsBu0Aq21SwMK5a9zdBkWSlQtQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.0-beta.50': + resolution: {integrity: sha512-5e76wQiQVeL1ICOZVUg4LSOVYg9jyhGCin+icYozhsUzM+fHE7kddi1bdiE0jwVqTfkjba3jUFbEkoC9WkdvyA==} + + '@sveltejs/acorn-typescript@1.0.8': + resolution: {integrity: sha512-esgN+54+q0NjB0Y/4BomT9samII7jGwNy/2a3wNZbT2A2RpmXsXwUt24LvLhx6jUq2gVk4cWEvcRO6MFQbOfNA==} + peerDependencies: + acorn: ^8.9.0 + + '@sveltejs/vite-plugin-svelte-inspector@5.0.1': + resolution: {integrity: sha512-ubWshlMk4bc8mkwWbg6vNvCeT7lGQojE3ijDh3QTR6Zr/R+GXxsGbyH4PExEPpiFmqPhYiVSVmHBjUcVc1JIrA==} + engines: {node: ^20.19 || ^22.12 || >=24} + peerDependencies: + '@sveltejs/vite-plugin-svelte': ^6.0.0-next.0 + svelte: ^5.0.0 + vite: npm:rolldown-vite@7.2.5 + + '@sveltejs/vite-plugin-svelte@6.2.1': + resolution: {integrity: sha512-YZs/OSKOQAQCnJvM/P+F1URotNnYNeU3P2s4oIpzm1uFaqUEqRxUB0g5ejMjEb5Gjb9/PiBI5Ktrq4rUUF8UVQ==} + engines: {node: ^20.19 || ^22.12 || >=24} + peerDependencies: + svelte: ^5.0.0 + vite: npm:rolldown-vite@7.2.5 + + '@tsconfig/svelte@5.0.6': + resolution: {integrity: sha512-yGxYL0I9eETH1/DR9qVJey4DAsCdeau4a9wYPKuXfEhm8lFO8wg+LLYJjIpAm6Fw7HSlhepPhYPDop75485yWQ==} + + '@tybys/wasm-util@0.10.1': + resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/node@24.10.1': + resolution: {integrity: sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==} + + acorn@8.15.0: + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + engines: {node: '>=0.4.0'} + hasBin: true + + aria-query@5.3.2: + resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} + engines: {node: '>= 0.4'} + + axobject-query@4.1.0: + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} + + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + codemirror@6.0.2: + resolution: {integrity: sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw==} + + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + + crelt@1.0.6: + resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + devalue@5.5.0: + resolution: {integrity: sha512-69sM5yrHfFLJt0AZ9QqZXGCPfJ7fQjvpln3Rq5+PS03LD32Ost1Q9N+eEnaQwGRIriKkMImXD56ocjQmfjbV3w==} + + esm-env@1.2.2: + resolution: {integrity: sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==} + + esrap@2.2.0: + resolution: {integrity: sha512-WBmtxe7R9C5mvL4n2le8nMUe4mD5V9oiK2vJpQ9I3y20ENPUomPcphBXE8D1x/Bm84oN1V+lOfgXxtqmxTp3Xg==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + immediate@3.0.6: + resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + is-reference@3.0.3: + resolution: {integrity: sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==} + + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + + jszip@3.10.1: + resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==} + + lie@3.3.0: + resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} + + lightningcss-android-arm64@1.30.2: + resolution: {integrity: sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.30.2: + resolution: {integrity: sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.30.2: + resolution: {integrity: sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.30.2: + resolution: {integrity: sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.30.2: + resolution: {integrity: sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.30.2: + resolution: {integrity: sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-arm64-musl@1.30.2: + resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + + lightningcss-linux-x64-gnu@1.30.2: + resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-linux-x64-musl@1.30.2: + resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + + lightningcss-win32-arm64-msvc@1.30.2: + resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.30.2: + resolution: {integrity: sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.30.2: + resolution: {integrity: sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ==} + engines: {node: '>= 12.0.0'} + + locate-character@3.0.0: + resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==} + + lucide-svelte@0.555.0: + resolution: {integrity: sha512-2kWIcstKGgQObLGpYXmcYwm/Y83Am+AQcP7MnybrmaRU1+QUJ/WSEpv/wAbwaSkrWUiN1TX/9FuWQKLeEeWCrQ==} + peerDependencies: + svelte: ^3 || ^4 || ^5.0.0-next.42 + + magic-string@0.30.21: + resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + + mri@1.2.0: + resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} + engines: {node: '>=4'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + pako@1.0.11: + resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} + + postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + engines: {node: ^10 || ^12 || >=14} + + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + + rolldown-vite@7.2.5: + resolution: {integrity: sha512-u09tdk/huMiN8xwoiBbig197jKdCamQTtOruSalOzbqGje3jdHiV0njQlAW0YvzoahkirFePNQ4RYlfnRQpXZA==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + esbuild: ^0.25.0 + jiti: '>=1.21.0' + less: ^4.0.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + rolldown@1.0.0-beta.50: + resolution: {integrity: sha512-JFULvCNl/anKn99eKjOSEubi0lLmNqQDAjyEMME2T4CwezUDL0i6t1O9xZsu2OMehPnV2caNefWpGF+8TnzB6A==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + sade@1.8.1: + resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} + engines: {node: '>=6'} + + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + + setimmediate@1.0.5: + resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + + style-mod@4.1.3: + resolution: {integrity: sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==} + + svelte-check@4.3.4: + resolution: {integrity: sha512-DVWvxhBrDsd+0hHWKfjP99lsSXASeOhHJYyuKOFYJcP7ThfSCKgjVarE8XfuMWpS5JV3AlDf+iK1YGGo2TACdw==} + engines: {node: '>= 18.0.0'} + hasBin: true + peerDependencies: + svelte: ^4.0.0 || ^5.0.0-next.0 + typescript: '>=5.0.0' + + svelte@5.45.2: + resolution: {integrity: sha512-yyXdW2u3H0H/zxxWoGwJoQlRgaSJLp+Vhktv12iRw2WRDlKqUPT54Fi0K/PkXqrdkcQ98aBazpy0AH4BCBVfoA==} + engines: {node: '>=18'} + + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@7.16.0: + resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + vitefu@1.1.1: + resolution: {integrity: sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==} + peerDependencies: + vite: npm:rolldown-vite@7.2.5 + peerDependenciesMeta: + vite: + optional: true + + w3c-keyname@2.2.8: + resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==} + + zimmerframe@1.1.4: + resolution: {integrity: sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==} + +snapshots: + + '@codemirror/autocomplete@6.20.0': + dependencies: + '@codemirror/language': 6.11.3 + '@codemirror/state': 6.5.2 + '@codemirror/view': 6.38.8 + '@lezer/common': 1.4.0 + + '@codemirror/commands@6.10.0': + dependencies: + '@codemirror/language': 6.11.3 + '@codemirror/state': 6.5.2 + '@codemirror/view': 6.38.8 + '@lezer/common': 1.4.0 + + '@codemirror/lang-css@6.3.1': + dependencies: + '@codemirror/autocomplete': 6.20.0 + '@codemirror/language': 6.11.3 + '@codemirror/state': 6.5.2 + '@lezer/common': 1.4.0 + '@lezer/css': 1.3.0 + + '@codemirror/lang-html@6.4.11': + dependencies: + '@codemirror/autocomplete': 6.20.0 + '@codemirror/lang-css': 6.3.1 + '@codemirror/lang-javascript': 6.2.4 + '@codemirror/language': 6.11.3 + '@codemirror/state': 6.5.2 + '@codemirror/view': 6.38.8 + '@lezer/common': 1.4.0 + '@lezer/css': 1.3.0 + '@lezer/html': 1.3.12 + + '@codemirror/lang-javascript@6.2.4': + dependencies: + '@codemirror/autocomplete': 6.20.0 + '@codemirror/language': 6.11.3 + '@codemirror/lint': 6.9.2 + '@codemirror/state': 6.5.2 + '@codemirror/view': 6.38.8 + '@lezer/common': 1.4.0 + '@lezer/javascript': 1.5.4 + + '@codemirror/language@6.11.3': + dependencies: + '@codemirror/state': 6.5.2 + '@codemirror/view': 6.38.8 + '@lezer/common': 1.4.0 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.4 + style-mod: 4.1.3 + + '@codemirror/lint@6.9.2': + dependencies: + '@codemirror/state': 6.5.2 + '@codemirror/view': 6.38.8 + crelt: 1.0.6 + + '@codemirror/search@6.5.11': + dependencies: + '@codemirror/state': 6.5.2 + '@codemirror/view': 6.38.8 + crelt: 1.0.6 + + '@codemirror/state@6.5.2': + dependencies: + '@marijn/find-cluster-break': 1.0.2 + + '@codemirror/theme-one-dark@6.1.3': + dependencies: + '@codemirror/language': 6.11.3 + '@codemirror/state': 6.5.2 + '@codemirror/view': 6.38.8 + '@lezer/highlight': 1.2.3 + + '@codemirror/view@6.38.8': + dependencies: + '@codemirror/state': 6.5.2 + crelt: 1.0.6 + style-mod: 4.1.3 + w3c-keyname: 2.2.8 + + '@emnapi/core@1.7.1': + dependencies: + '@emnapi/wasi-threads': 1.1.0 + tslib: 2.8.1 + optional: true + + '@emnapi/runtime@1.7.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.1.0': + dependencies: + tslib: 2.8.1 + optional: true + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@lezer/common@1.4.0': {} + + '@lezer/css@1.3.0': + dependencies: + '@lezer/common': 1.4.0 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.4 + + '@lezer/highlight@1.2.3': + dependencies: + '@lezer/common': 1.4.0 + + '@lezer/html@1.3.12': + dependencies: + '@lezer/common': 1.4.0 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.4 + + '@lezer/javascript@1.5.4': + dependencies: + '@lezer/common': 1.4.0 + '@lezer/highlight': 1.2.3 + '@lezer/lr': 1.4.4 + + '@lezer/lr@1.4.4': + dependencies: + '@lezer/common': 1.4.0 + + '@marijn/find-cluster-break@1.0.2': {} + + '@napi-rs/wasm-runtime@1.0.7': + dependencies: + '@emnapi/core': 1.7.1 + '@emnapi/runtime': 1.7.1 + '@tybys/wasm-util': 0.10.1 + optional: true + + '@oxc-project/runtime@0.97.0': {} + + '@oxc-project/types@0.97.0': {} + + '@replit/codemirror-emacs@6.1.0(@codemirror/autocomplete@6.20.0)(@codemirror/commands@6.10.0)(@codemirror/search@6.5.11)(@codemirror/state@6.5.2)(@codemirror/view@6.38.8)': + dependencies: + '@codemirror/autocomplete': 6.20.0 + '@codemirror/commands': 6.10.0 + '@codemirror/search': 6.5.11 + '@codemirror/state': 6.5.2 + '@codemirror/view': 6.38.8 + + '@replit/codemirror-vim@6.3.0(@codemirror/commands@6.10.0)(@codemirror/language@6.11.3)(@codemirror/search@6.5.11)(@codemirror/state@6.5.2)(@codemirror/view@6.38.8)': + dependencies: + '@codemirror/commands': 6.10.0 + '@codemirror/language': 6.11.3 + '@codemirror/search': 6.5.11 + '@codemirror/state': 6.5.2 + '@codemirror/view': 6.38.8 + + '@rolldown/binding-android-arm64@1.0.0-beta.50': + optional: true + + '@rolldown/binding-darwin-arm64@1.0.0-beta.50': + optional: true + + '@rolldown/binding-darwin-x64@1.0.0-beta.50': + optional: true + + '@rolldown/binding-freebsd-x64@1.0.0-beta.50': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.50': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.0.0-beta.50': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.0.0-beta.50': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.0.0-beta.50': + optional: true + + '@rolldown/binding-linux-x64-musl@1.0.0-beta.50': + optional: true + + '@rolldown/binding-openharmony-arm64@1.0.0-beta.50': + optional: true + + '@rolldown/binding-wasm32-wasi@1.0.0-beta.50': + dependencies: + '@napi-rs/wasm-runtime': 1.0.7 + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.0.0-beta.50': + optional: true + + '@rolldown/binding-win32-ia32-msvc@1.0.0-beta.50': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.0.0-beta.50': + optional: true + + '@rolldown/pluginutils@1.0.0-beta.50': {} + + '@sveltejs/acorn-typescript@1.0.8(acorn@8.15.0)': + dependencies: + acorn: 8.15.0 + + '@sveltejs/vite-plugin-svelte-inspector@5.0.1(@sveltejs/vite-plugin-svelte@6.2.1(rolldown-vite@7.2.5(@types/node@24.10.1))(svelte@5.45.2))(rolldown-vite@7.2.5(@types/node@24.10.1))(svelte@5.45.2)': + dependencies: + '@sveltejs/vite-plugin-svelte': 6.2.1(rolldown-vite@7.2.5(@types/node@24.10.1))(svelte@5.45.2) + debug: 4.4.3 + svelte: 5.45.2 + vite: rolldown-vite@7.2.5(@types/node@24.10.1) + transitivePeerDependencies: + - supports-color + + '@sveltejs/vite-plugin-svelte@6.2.1(rolldown-vite@7.2.5(@types/node@24.10.1))(svelte@5.45.2)': + dependencies: + '@sveltejs/vite-plugin-svelte-inspector': 5.0.1(@sveltejs/vite-plugin-svelte@6.2.1(rolldown-vite@7.2.5(@types/node@24.10.1))(svelte@5.45.2))(rolldown-vite@7.2.5(@types/node@24.10.1))(svelte@5.45.2) + debug: 4.4.3 + deepmerge: 4.3.1 + magic-string: 0.30.21 + svelte: 5.45.2 + vite: rolldown-vite@7.2.5(@types/node@24.10.1) + vitefu: 1.1.1(rolldown-vite@7.2.5(@types/node@24.10.1)) + transitivePeerDependencies: + - supports-color + + '@tsconfig/svelte@5.0.6': {} + + '@tybys/wasm-util@0.10.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@types/estree@1.0.8': {} + + '@types/node@24.10.1': + dependencies: + undici-types: 7.16.0 + + acorn@8.15.0: {} + + aria-query@5.3.2: {} + + axobject-query@4.1.0: {} + + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + + clsx@2.1.1: {} + + codemirror@6.0.2: + dependencies: + '@codemirror/autocomplete': 6.20.0 + '@codemirror/commands': 6.10.0 + '@codemirror/language': 6.11.3 + '@codemirror/lint': 6.9.2 + '@codemirror/search': 6.5.11 + '@codemirror/state': 6.5.2 + '@codemirror/view': 6.38.8 + + core-util-is@1.0.3: {} + + crelt@1.0.6: {} + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + deepmerge@4.3.1: {} + + detect-libc@2.1.2: {} + + devalue@5.5.0: {} + + esm-env@1.2.2: {} + + esrap@2.2.0: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + + fsevents@2.3.3: + optional: true + + immediate@3.0.6: {} + + inherits@2.0.4: {} + + is-reference@3.0.3: + dependencies: + '@types/estree': 1.0.8 + + isarray@1.0.0: {} + + jszip@3.10.1: + dependencies: + lie: 3.3.0 + pako: 1.0.11 + readable-stream: 2.3.8 + setimmediate: 1.0.5 + + lie@3.3.0: + dependencies: + immediate: 3.0.6 + + lightningcss-android-arm64@1.30.2: + optional: true + + lightningcss-darwin-arm64@1.30.2: + optional: true + + lightningcss-darwin-x64@1.30.2: + optional: true + + lightningcss-freebsd-x64@1.30.2: + optional: true + + lightningcss-linux-arm-gnueabihf@1.30.2: + optional: true + + lightningcss-linux-arm64-gnu@1.30.2: + optional: true + + lightningcss-linux-arm64-musl@1.30.2: + optional: true + + lightningcss-linux-x64-gnu@1.30.2: + optional: true + + lightningcss-linux-x64-musl@1.30.2: + optional: true + + lightningcss-win32-arm64-msvc@1.30.2: + optional: true + + lightningcss-win32-x64-msvc@1.30.2: + optional: true + + lightningcss@1.30.2: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.30.2 + lightningcss-darwin-arm64: 1.30.2 + lightningcss-darwin-x64: 1.30.2 + lightningcss-freebsd-x64: 1.30.2 + lightningcss-linux-arm-gnueabihf: 1.30.2 + lightningcss-linux-arm64-gnu: 1.30.2 + lightningcss-linux-arm64-musl: 1.30.2 + lightningcss-linux-x64-gnu: 1.30.2 + lightningcss-linux-x64-musl: 1.30.2 + lightningcss-win32-arm64-msvc: 1.30.2 + lightningcss-win32-x64-msvc: 1.30.2 + + locate-character@3.0.0: {} + + lucide-svelte@0.555.0(svelte@5.45.2): + dependencies: + svelte: 5.45.2 + + magic-string@0.30.21: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + + mri@1.2.0: {} + + ms@2.1.3: {} + + nanoid@3.3.11: {} + + pako@1.0.11: {} + + picocolors@1.1.1: {} + + picomatch@4.0.3: {} + + postcss@8.5.6: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + process-nextick-args@2.0.1: {} + + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + + readdirp@4.1.2: {} + + rolldown-vite@7.2.5(@types/node@24.10.1): + dependencies: + '@oxc-project/runtime': 0.97.0 + fdir: 6.5.0(picomatch@4.0.3) + lightningcss: 1.30.2 + picomatch: 4.0.3 + postcss: 8.5.6 + rolldown: 1.0.0-beta.50 + tinyglobby: 0.2.15 + optionalDependencies: + '@types/node': 24.10.1 + fsevents: 2.3.3 + + rolldown@1.0.0-beta.50: + dependencies: + '@oxc-project/types': 0.97.0 + '@rolldown/pluginutils': 1.0.0-beta.50 + optionalDependencies: + '@rolldown/binding-android-arm64': 1.0.0-beta.50 + '@rolldown/binding-darwin-arm64': 1.0.0-beta.50 + '@rolldown/binding-darwin-x64': 1.0.0-beta.50 + '@rolldown/binding-freebsd-x64': 1.0.0-beta.50 + '@rolldown/binding-linux-arm-gnueabihf': 1.0.0-beta.50 + '@rolldown/binding-linux-arm64-gnu': 1.0.0-beta.50 + '@rolldown/binding-linux-arm64-musl': 1.0.0-beta.50 + '@rolldown/binding-linux-x64-gnu': 1.0.0-beta.50 + '@rolldown/binding-linux-x64-musl': 1.0.0-beta.50 + '@rolldown/binding-openharmony-arm64': 1.0.0-beta.50 + '@rolldown/binding-wasm32-wasi': 1.0.0-beta.50 + '@rolldown/binding-win32-arm64-msvc': 1.0.0-beta.50 + '@rolldown/binding-win32-ia32-msvc': 1.0.0-beta.50 + '@rolldown/binding-win32-x64-msvc': 1.0.0-beta.50 + + sade@1.8.1: + dependencies: + mri: 1.2.0 + + safe-buffer@5.1.2: {} + + setimmediate@1.0.5: {} + + source-map-js@1.2.1: {} + + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + + style-mod@4.1.3: {} + + svelte-check@4.3.4(picomatch@4.0.3)(svelte@5.45.2)(typescript@5.9.3): + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + chokidar: 4.0.3 + fdir: 6.5.0(picomatch@4.0.3) + picocolors: 1.1.1 + sade: 1.8.1 + svelte: 5.45.2 + typescript: 5.9.3 + transitivePeerDependencies: + - picomatch + + svelte@5.45.2: + dependencies: + '@jridgewell/remapping': 2.3.5 + '@jridgewell/sourcemap-codec': 1.5.5 + '@sveltejs/acorn-typescript': 1.0.8(acorn@8.15.0) + '@types/estree': 1.0.8 + acorn: 8.15.0 + aria-query: 5.3.2 + axobject-query: 4.1.0 + clsx: 2.1.1 + devalue: 5.5.0 + esm-env: 1.2.2 + esrap: 2.2.0 + is-reference: 3.0.3 + locate-character: 3.0.0 + magic-string: 0.30.21 + zimmerframe: 1.1.4 + + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + + tslib@2.8.1: + optional: true + + typescript@5.9.3: {} + + undici-types@7.16.0: {} + + util-deprecate@1.0.2: {} + + vitefu@1.1.1(rolldown-vite@7.2.5(@types/node@24.10.1)): + optionalDependencies: + vite: rolldown-vite@7.2.5(@types/node@24.10.1) + + w3c-keyname@2.2.8: {} + + zimmerframe@1.1.4: {} diff --git a/public/fonts/DepartureMono-Regular.woff b/public/fonts/DepartureMono-Regular.woff new file mode 100644 index 0000000000000000000000000000000000000000..b7bb67236e78e77a40239d0f90cc04ab48d916f2 GIT binary patch literal 25256 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

*MC{SPsY?*wD|S>ug#Sfh-z7}KR(Q49#|7Z7V_ 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

#(?CjpKCQ=`i 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 ND8(#$|209TLz0RR9100000000000000000000 z0000DgW3=pg<>0&ZXA{r24Dc{ZUHs|BmCrObD{ZH=hZA*&!MH+zI zVgQwY&Xv7oaDi>piFnp|L%N=YblB`*3>zna;rXqz|NsC0|NsA$%a_OIlC<^Z{4FiW z5Mlt1+f*Rat075p$4JQ#bNd8rcH26dxfJf!f+<%oEMz zWCgC9uTrU$ItyD;yOMObCg-bfw%u*mK7!m2%)d)VRdOn3#+A|-Mt04Ut=LICW2s;* zA|kjunV{LHI~RKYoW#P3Pt@LQT4+s0e=T}E+&xIyQo1A03H+%fHu;|>Y$AJil-e?cEWRiLUXmj*mfu(sZxSrLgc z3UQ4_M8v{EL_{UqAloiX%(DwK`pOJ?kg?Z$B~@2Flv6;G6oRIB0!M0@T;_;4eoB$- zF93o0*DXJR1UWUCyY+QghEC^#Tf~46#1cdapi}R6(v789DI^^mXcHEc%m33a``

S&Y$B6bQNVy_}t=+?^%B}Y(` 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 v7oUo5C)>^E>&CZV$&|CqZZE~UofZ=oq + import { Eye } from 'lucide-svelte'; + import Canvas from './lib/Canvas.svelte'; + import Toolbar from './lib/Toolbar.svelte'; + import Editor from './lib/Editor.svelte'; + import { state as appState } from './lib/state.svelte'; + + let editingItem = $derived(appState.editingId ? appState.getItem(appState.editingId) : null); + let showEditor = $derived(editingItem || appState.editingGlobal); + + let editorWidth = $state(320); + let isResizing = $state(false); + let interfaceHidden = $state(false); + + $effect(() => { + if (appState.editingId || appState.editingGlobal) { + interfaceHidden = false; + } + }); + + function handleResizeStart(e: MouseEvent) { + e.preventDefault(); + isResizing = true; + } + + function handleResizeMove(e: MouseEvent) { + if (!isResizing) return; + const newWidth = window.innerWidth - e.clientX; + editorWidth = Math.max(200, Math.min(800, newWidth)); + } + + function handleResizeEnd() { + isResizing = false; + } + + + + {@html ``} + + + + +
+ {#if !interfaceHidden} + (interfaceHidden = true)} /> + {/if} +
+
+ +
+ {#if showEditor && !interfaceHidden} + +
+
+ {#if editingItem} + appState.edit(null)} /> + {:else} + appState.editGlobal(false)} /> + {/if} +
+ {/if} +
+ {#if interfaceHidden} +
+ + {#each ['1', '2', '3', '4', '5', '6', '7', '8', '9'] as key} + + {/each} +
+ {/if} +
+ + diff --git a/src/app.css b/src/app.css new file mode 100644 index 0000000..6484edc --- /dev/null +++ b/src/app.css @@ -0,0 +1,28 @@ +@font-face { + font-family: 'Departure Mono'; + src: url('/fonts/DepartureMono-Regular.woff2') format('woff2'), + url('/fonts/DepartureMono-Regular.woff') format('woff'); + font-weight: normal; + font-style: normal; + font-display: swap; +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +:root { + font-family: 'Departure Mono', monospace; + color: var(--text, #fff); + background: var(--bg, #1a1a1a); +} + +html, +body, +#app { + width: 100%; + height: 100%; + overflow: hidden; +} diff --git a/src/lib/Canvas.svelte b/src/lib/Canvas.svelte new file mode 100644 index 0000000..224e91b --- /dev/null +++ b/src/lib/Canvas.svelte @@ -0,0 +1,174 @@ + + + + + +
+
+ {#each state.manifest.items as item (item.id)} + + {/each} +
+
+ + diff --git a/src/lib/Editor.svelte b/src/lib/Editor.svelte new file mode 100644 index 0000000..e0e2941 --- /dev/null +++ b/src/lib/Editor.svelte @@ -0,0 +1,258 @@ + + +
+
+
+ {#if mode === 'item'} + + + {/if} + + +
+ + +
+
+ {#if mode === 'item'} +
+
+ {/if} +
+
+
+
+ + diff --git a/src/lib/Item.svelte b/src/lib/Item.svelte new file mode 100644 index 0000000..5fcc7dd --- /dev/null +++ b/src/lib/Item.svelte @@ -0,0 +1,298 @@ + + + + +
+ + + {#if !isFocused} +
+ {/if} + + {#if isSelected} +
+ +
handleResizeStart(e, 'nw')}>
+ +
handleResizeStart(e, 'ne')}>
+ +
handleResizeStart(e, 'sw')}>
+ +
handleResizeStart(e, 'se')}>
+ +
+
+
+ {/if} +
+ + diff --git a/src/lib/Palette.svelte b/src/lib/Palette.svelte new file mode 100644 index 0000000..be5f16e --- /dev/null +++ b/src/lib/Palette.svelte @@ -0,0 +1,224 @@ + + +
+ + + + + + + + + + +
+ + diff --git a/src/lib/Toolbar.svelte b/src/lib/Toolbar.svelte new file mode 100644 index 0000000..9e8b84b --- /dev/null +++ b/src/lib/Toolbar.svelte @@ -0,0 +1,207 @@ + + +
+ Buboard + +
+ {#each flagKeys as key} + + {/each} +
+
+
+ + {zoomPercent}% +
+ + + + + {#if onHide} + + {/if} + +
+ + diff --git a/src/lib/geometry.ts b/src/lib/geometry.ts new file mode 100644 index 0000000..2306595 --- /dev/null +++ b/src/lib/geometry.ts @@ -0,0 +1,81 @@ +export interface Point { + x: number; + y: number; +} + +export function calculateCenterOffset( + corner: string, + deltaWidth: number, + deltaHeight: number, + rotation: number +): Point { + const rad = (rotation * Math.PI) / 180; + const cos = Math.cos(rad); + const sin = Math.sin(rad); + + let localDx = 0; + let localDy = 0; + + if (corner.includes('w')) localDx = -deltaWidth / 2; + else if (corner.includes('e')) localDx = deltaWidth / 2; + + if (corner.includes('n')) localDy = -deltaHeight / 2; + else if (corner.includes('s')) localDy = deltaHeight / 2; + + return { + x: localDx * cos - localDy * sin, + y: localDx * sin + localDy * cos + }; +} + +export function constrainToAspectRatio( + newWidth: number, + newHeight: number, + aspectRatio: number +): { width: number; height: number } { + const newRatio = newWidth / newHeight; + + if (newRatio > aspectRatio) { + return { width: newHeight * aspectRatio, height: newHeight }; + } else { + return { width: newWidth, height: newWidth / aspectRatio }; + } +} + +export function detectRotationCorner( + localX: number, + localY: number, + halfWidth: number, + halfHeight: number, + zoneRadius: number +): string | null { + const corners: Record = { + nw: { x: -halfWidth, y: -halfHeight }, + ne: { x: halfWidth, y: -halfHeight }, + sw: { x: -halfWidth, y: halfHeight }, + se: { x: halfWidth, y: halfHeight } + }; + + const isInsideBounds = + localX >= -halfWidth && + localX <= halfWidth && + localY >= -halfHeight && + localY <= halfHeight; + + if (isInsideBounds) return null; + + for (const [name, corner] of Object.entries(corners)) { + const dx = localX - corner.x; + const dy = localY - corner.y; + const dist = Math.sqrt(dx * dx + dy * dy); + + if (dist > zoneRadius || dist < 3) continue; + + const isOutwardX = (name.includes('w') && dx < 0) || (name.includes('e') && dx > 0); + const isOutwardY = (name.includes('n') && dy < 0) || (name.includes('s') && dy > 0); + + if (isOutwardX || isOutwardY) return name; + } + + return null; +} diff --git a/src/lib/io.ts b/src/lib/io.ts new file mode 100644 index 0000000..83b5975 --- /dev/null +++ b/src/lib/io.ts @@ -0,0 +1,93 @@ +import JSZip from 'jszip'; +import type { Manifest, AssetStore } from './types'; +import { state } from './state.svelte'; + +export async function exportBoard(): Promise<{ success: boolean; error?: string }> { + try { + const zip = new JSZip(); + const assetsFolder = zip.folder('assets'); + if (!assetsFolder) throw new Error('Failed to create assets folder'); + + const exportManifest: Manifest = { + version: 1, + items: state.manifest.items.map((item) => ({ ...item })), + sharedCss: state.manifest.sharedCss, + appCss: state.manifest.appCss + }; + + for (const item of exportManifest.items) { + if (item.assetId) { + const asset = state.assets[item.assetId]; + if (asset) { + const ext = asset.filename.split('.').pop() || 'bin'; + const filename = `${item.assetId}.${ext}`; + assetsFolder.file(filename, asset.blob); + } + } + } + + zip.file('manifest.json', JSON.stringify(exportManifest, null, 2)); + + const blob = await zip.generateAsync({ type: 'blob' }); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = 'board.bub'; + a.click(); + URL.revokeObjectURL(url); + return { success: true }; + } catch (e) { + return { success: false, error: e instanceof Error ? e.message : 'Export failed' }; + } +} + +export async function importBoard(file: File): Promise<{ success: boolean; error?: string }> { + try { + const zip = await JSZip.loadAsync(file); + + const manifestFile = zip.file('manifest.json'); + if (!manifestFile) throw new Error('Invalid .bub file: missing manifest.json'); + + const manifestJson = await manifestFile.async('string'); + const raw = JSON.parse(manifestJson); + + if (raw.version !== 1) throw new Error(`Unsupported manifest version: ${raw.version}`); + + const manifest: Manifest = { + version: 1, + items: raw.items, + sharedCss: raw.sharedCss ?? '', + appCss: raw.appCss ?? '', + flags: raw.flags ?? {} + }; + + const assets: AssetStore = {}; + const urlReplacements: Map = new Map(); + + for (const item of manifest.items) { + if (item.assetId) { + const assetFiles = zip.folder('assets')?.file(new RegExp(`^${item.assetId}\\.`)); + if (assetFiles && assetFiles.length > 0) { + const assetFile = assetFiles[0]; + const blob = await assetFile.async('blob'); + const url = URL.createObjectURL(blob); + const filename = assetFile.name.split('/').pop() || 'asset'; + assets[item.assetId] = { blob, url, filename }; + urlReplacements.set(item.assetId, url); + } + } + } + + for (const item of manifest.items) { + if (item.assetId && urlReplacements.has(item.assetId)) { + const newUrl = urlReplacements.get(item.assetId)!; + item.html = item.html.replace(/src="[^"]*"/g, `src="${newUrl}"`); + } + } + + state.load(manifest, assets); + return { success: true }; + } catch (e) { + return { success: false, error: e instanceof Error ? e.message : 'Import failed' }; + } +} diff --git a/src/lib/state.svelte.ts b/src/lib/state.svelte.ts new file mode 100644 index 0000000..392ab50 --- /dev/null +++ b/src/lib/state.svelte.ts @@ -0,0 +1,358 @@ +import type { Item, Manifest, Asset, AssetStore, Viewport, PositionFlag } from './types'; + +const STORAGE_KEY = 'buboard'; + +const DEFAULT_SHARED_CSS = `* { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +html, body { + width: 100%; + height: 100%; +} + +body { + font-family: 'Departure Mono', monospace; + color: #fff; + overflow: hidden; +}`; + +const DEFAULT_APP_CSS = `:root { + /* Theme */ + --bg: #1a1a1a; + --surface: #282c34; + --border: #333; + --accent: #4a9eff; + --text: #fff; + --text-dim: #666; + + /* Syntax */ + --cm-keyword: #c678dd; + --cm-variable: #e06c75; + --cm-function: #61afef; + --cm-string: #98c379; + --cm-comment: #7d8799; + --cm-number: #d19a66; + --cm-operator: #56b6c2; +}`; + +interface StoredAsset { + dataUrl: string; + filename: string; +} + +interface StoredState { + manifest: Manifest; + assets: Record; +} + +async function blobToDataUrl(blob: Blob): Promise { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onload = () => resolve(reader.result as string); + reader.onerror = reject; + reader.readAsDataURL(blob); + }); +} + +async function dataUrlToBlob(dataUrl: string): Promise { + const res = await fetch(dataUrl); + return res.blob(); +} + +function createState() { + let manifest = $state({ + version: 1, + items: [], + sharedCss: DEFAULT_SHARED_CSS, + appCss: DEFAULT_APP_CSS, + flags: {} + }); + let assets = $state({}); + let viewport = $state({ x: 0, y: 0, zoom: 1 }); + let selectedId = $state(null); + let editingId = $state(null); + let editingGlobal = $state(false); + let focusedId = $state(null); + + let saveTimeout: ReturnType | null = null; + let animationId: number | null = null; + + let maxZIndex = $derived( + manifest.items.length > 0 ? Math.max(...manifest.items.map((i) => i.zIndex)) : 0 + ); + + async function save() { + if (saveTimeout) clearTimeout(saveTimeout); + saveTimeout = setTimeout(async () => { + const storedAssets: Record = {}; + for (const [id, asset] of Object.entries(assets)) { + storedAssets[id] = { + dataUrl: await blobToDataUrl(asset.blob), + filename: asset.filename + }; + } + const stored: StoredState = { manifest, assets: storedAssets }; + try { + localStorage.setItem(STORAGE_KEY, JSON.stringify(stored)); + } catch { + // localStorage full or unavailable + } + }, 500); + } + + async function restore() { + try { + const raw = localStorage.getItem(STORAGE_KEY); + if (!raw) return; + const stored: StoredState = JSON.parse(raw); + if (stored.manifest.version !== 1) return; + + const restoredAssets: AssetStore = {}; + for (const [id, storedAsset] of Object.entries(stored.assets)) { + const blob = await dataUrlToBlob(storedAsset.dataUrl); + const url = URL.createObjectURL(blob); + restoredAssets[id] = { blob, url, filename: storedAsset.filename }; + } + + for (const item of stored.manifest.items) { + if (item.assetId && restoredAssets[item.assetId]) { + const newUrl = restoredAssets[item.assetId].url; + item.html = item.html.replace(/src="[^"]*"/g, `src="${newUrl}"`); + } + } + + manifest = { ...stored.manifest, flags: stored.manifest.flags ?? {} }; + assets = restoredAssets; + } catch { + // corrupted or missing data + } + } + + function addItem(item: Item) { + manifest.items.push(item); + save(); + } + + function updateItem(id: string, updates: Partial) { + const item = manifest.items.find((i) => i.id === id); + if (!item) return; + Object.assign(item, updates); + save(); + } + + function removeItem(id: string) { + const idx = manifest.items.findIndex((i) => i.id === id); + if (idx === -1) return; + const item = manifest.items[idx]; + if (item.assetId && assets[item.assetId]) { + URL.revokeObjectURL(assets[item.assetId].url); + delete assets[item.assetId]; + } + manifest.items.splice(idx, 1); + if (selectedId === id) selectedId = null; + if (editingId === id) editingId = null; + save(); + } + + function addAsset(id: string, asset: Asset) { + assets[id] = asset; + save(); + } + + function getItem(id: string): Item | undefined { + return manifest.items.find((i) => i.id === id); + } + + function select(id: string | null) { + selectedId = id; + } + + function edit(id: string | null) { + editingId = id; + if (id) editingGlobal = false; + } + + function editGlobal(editing: boolean) { + editingGlobal = editing; + if (editing) editingId = null; + } + + function focus(id: string | null) { + focusedId = id; + } + + function updateSharedCss(css: string) { + manifest.sharedCss = css; + save(); + } + + function updateAppCss(css: string) { + manifest.appCss = css; + save(); + } + + function bringToFront(id: string) { + const item = manifest.items.find((i) => i.id === id); + if (!item) return; + item.zIndex = maxZIndex + 1; + save(); + } + + function pan(dx: number, dy: number) { + viewport.x += dx; + viewport.y += dy; + } + + function zoomAt(factor: number, cx: number, cy: number) { + const newZoom = Math.max(0.1, Math.min(10, viewport.zoom * factor)); + const scale = newZoom / viewport.zoom; + viewport.x = cx - (cx - viewport.x) * scale; + viewport.y = cy - (cy - viewport.y) * scale; + viewport.zoom = newZoom; + } + + function setZoom(zoom: number) { + viewport.zoom = Math.max(0.1, Math.min(10, zoom)); + } + + function hasFlag(key: string): boolean { + return !!manifest.flags?.[key]; + } + + function setFlag(key: string) { + if (!manifest.flags) manifest.flags = {}; + manifest.flags[key] = { x: viewport.x, y: viewport.y, zoom: viewport.zoom }; + save(); + } + + function clearFlag(key: string) { + if (manifest.flags?.[key]) { + delete manifest.flags[key]; + save(); + } + } + + function easeInOutCubic(t: number): number { + return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2; + } + + function animateViewport(targetX: number, targetY: number, targetZoom: number) { + if (animationId) cancelAnimationFrame(animationId); + + const startX = viewport.x; + const startY = viewport.y; + const startZoom = viewport.zoom; + const startTime = performance.now(); + const duration = 600; + + function tick(now: number) { + const elapsed = now - startTime; + const t = Math.min(elapsed / duration, 1); + const eased = easeInOutCubic(t); + + viewport.x = startX + (targetX - startX) * eased; + viewport.y = startY + (targetY - startY) * eased; + viewport.zoom = startZoom + (targetZoom - startZoom) * eased; + + if (t < 1) { + animationId = requestAnimationFrame(tick); + } else { + animationId = null; + } + } + + animationId = requestAnimationFrame(tick); + } + + function gotoFlag(key: string) { + const flag = manifest.flags?.[key]; + if (flag) { + animateViewport(flag.x, flag.y, flag.zoom); + } + } + + function reset() { + Object.values(assets).forEach((a) => URL.revokeObjectURL(a.url)); + manifest = { + version: 1, + items: [], + sharedCss: DEFAULT_SHARED_CSS, + appCss: DEFAULT_APP_CSS, + flags: {} + }; + assets = {}; + viewport = { x: 0, y: 0, zoom: 1 }; + selectedId = null; + editingId = null; + editingGlobal = false; + focusedId = null; + localStorage.removeItem(STORAGE_KEY); + } + + function load(newManifest: Manifest, newAssets: AssetStore) { + Object.values(assets).forEach((a) => URL.revokeObjectURL(a.url)); + manifest = newManifest; + assets = newAssets; + viewport = { x: 0, y: 0, zoom: 1 }; + selectedId = null; + editingId = null; + editingGlobal = false; + focusedId = null; + save(); + } + + restore(); + + return { + get manifest() { + return manifest; + }, + get assets() { + return assets; + }, + get viewport() { + return viewport; + }, + get selectedId() { + return selectedId; + }, + get editingId() { + return editingId; + }, + get editingGlobal() { + return editingGlobal; + }, + get focusedId() { + return focusedId; + }, + get maxZIndex() { + return maxZIndex; + }, + addItem, + updateItem, + removeItem, + addAsset, + getItem, + select, + edit, + editGlobal, + focus, + updateSharedCss, + updateAppCss, + bringToFront, + pan, + zoomAt, + setZoom, + hasFlag, + setFlag, + clearFlag, + gotoFlag, + reset, + load + }; +} + +export const state = createState(); diff --git a/src/lib/theme.ts b/src/lib/theme.ts new file mode 100644 index 0000000..056a4b2 --- /dev/null +++ b/src/lib/theme.ts @@ -0,0 +1,131 @@ +import { EditorView } from '@codemirror/view'; +import { syntaxHighlighting, HighlightStyle } from '@codemirror/language'; +import { tags } from '@lezer/highlight'; + +function getVar(name: string, fallback: string): string { + const value = getComputedStyle(document.documentElement).getPropertyValue(name).trim(); + return value || fallback; +} + +export function createTheme() { + const surface = getVar('--surface', '#282c34'); + const border = getVar('--border', '#333'); + const accent = getVar('--accent', '#4a9eff'); + const text = getVar('--text', '#fff'); + const textDim = getVar('--text-dim', '#666'); + + const keyword = getVar('--cm-keyword', '#c678dd'); + const variable = getVar('--cm-variable', '#e06c75'); + const func = getVar('--cm-function', '#61afef'); + const string = getVar('--cm-string', '#98c379'); + const comment = getVar('--cm-comment', '#7d8799'); + const number = getVar('--cm-number', '#d19a66'); + const operator = getVar('--cm-operator', '#56b6c2'); + + const theme = EditorView.theme( + { + '&': { + backgroundColor: surface, + color: '#abb2bf', + height: '100%' + }, + '.cm-scroller': { + overflow: 'auto', + fontFamily: "'Departure Mono', monospace" + }, + '.cm-content': { + caretColor: accent + }, + '.cm-cursor, .cm-dropCursor': { + borderLeftColor: accent + }, + '&.cm-focused > .cm-scroller > .cm-selectionLayer .cm-selectionBackground, .cm-selectionBackground, .cm-content ::selection': + { + backgroundColor: '#3E4451' + }, + '.cm-panels': { + backgroundColor: surface, + color: '#abb2bf' + }, + '.cm-panels.cm-panels-top': { + borderBottom: `1px solid ${border}` + }, + '.cm-panels.cm-panels-bottom': { + borderTop: `1px solid ${border}` + }, + '.cm-searchMatch': { + backgroundColor: '#72a1ff59', + outline: `1px solid ${border}` + }, + '.cm-searchMatch.cm-searchMatch-selected': { + backgroundColor: '#6199ff2f' + }, + '.cm-activeLine': { + backgroundColor: '#2c313c50' + }, + '.cm-selectionMatch': { + backgroundColor: '#aafe661a' + }, + '&.cm-focused .cm-matchingBracket, &.cm-focused .cm-nonmatchingBracket': { + backgroundColor: '#bad0f847' + }, + '.cm-gutters': { + backgroundColor: surface, + color: textDim, + border: 'none' + }, + '.cm-activeLineGutter': { + backgroundColor: '#2c313c50' + }, + '.cm-foldPlaceholder': { + backgroundColor: 'transparent', + border: 'none', + color: textDim + }, + '.cm-tooltip': { + border: 'none', + backgroundColor: surface + }, + '.cm-tooltip .cm-tooltip-arrow:before': { + borderTopColor: 'transparent', + borderBottomColor: 'transparent' + }, + '.cm-tooltip .cm-tooltip-arrow:after': { + borderTopColor: surface, + borderBottomColor: surface + }, + '.cm-tooltip-autocomplete': { + '& > ul > li[aria-selected]': { + backgroundColor: accent, + color: text + } + } + }, + { dark: true } + ); + + const highlighting = HighlightStyle.define([ + { tag: tags.keyword, color: keyword }, + { tag: [tags.name, tags.deleted, tags.character, tags.propertyName, tags.macroName], color: variable }, + { tag: [tags.function(tags.variableName), tags.labelName], color: func }, + { tag: [tags.color, tags.constant(tags.name), tags.standard(tags.name)], color: number }, + { tag: [tags.definition(tags.name), tags.separator], color: '#abb2bf' }, + { tag: [tags.typeName, tags.className, tags.number, tags.changed, tags.annotation, tags.modifier, tags.self, tags.namespace], color: number }, + { tag: [tags.operator, tags.operatorKeyword, tags.url, tags.escape, tags.regexp, tags.link, tags.special(tags.string)], color: operator }, + { tag: [tags.meta, tags.comment], color: comment, fontStyle: 'italic' }, + { tag: tags.strong, fontWeight: 'bold' }, + { tag: tags.emphasis, fontStyle: 'italic' }, + { tag: tags.strikethrough, textDecoration: 'line-through' }, + { tag: tags.link, color: comment, textDecoration: 'underline' }, + { tag: tags.heading, fontWeight: 'bold', color: variable }, + { tag: [tags.atom, tags.bool, tags.special(tags.variableName)], color: number }, + { tag: [tags.processingInstruction, tags.string, tags.inserted], color: string }, + { tag: tags.invalid, color: '#ff0000' }, + { tag: tags.tagName, color: variable }, + { tag: tags.attributeName, color: number }, + { tag: tags.attributeValue, color: string }, + { tag: tags.propertyName, color: func } + ]); + + return [theme, syntaxHighlighting(highlighting)]; +} diff --git a/src/lib/types.ts b/src/lib/types.ts new file mode 100644 index 0000000..025bee5 --- /dev/null +++ b/src/lib/types.ts @@ -0,0 +1,42 @@ +export interface Item { + id: string; + x: number; + y: number; + width: number; + height: number; + rotation: number; + zIndex: number; + html: string; + css: string; + assetId?: string; +} + +export interface Manifest { + version: 1; + items: Item[]; + sharedCss: string; + appCss: string; + flags?: Record; +} + +export interface Asset { + blob: Blob; + url: string; + filename: string; +} + +export interface AssetStore { + [assetId: string]: Asset; +} + +export interface Viewport { + x: number; + y: number; + zoom: number; +} + +export interface PositionFlag { + x: number; + y: number; + zoom: number; +} diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..664a057 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,9 @@ +import { mount } from 'svelte' +import './app.css' +import App from './App.svelte' + +const app = mount(App, { + target: document.getElementById('app')!, +}) + +export default app diff --git a/svelte.config.js b/svelte.config.js new file mode 100644 index 0000000..96b3455 --- /dev/null +++ b/svelte.config.js @@ -0,0 +1,8 @@ +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' + +/** @type {import("@sveltejs/vite-plugin-svelte").SvelteConfig} */ +export default { + // Consult https://svelte.dev/docs#compile-time-svelte-preprocess + // for more information about preprocessors + preprocess: vitePreprocess(), +} diff --git a/tsconfig.app.json b/tsconfig.app.json new file mode 100644 index 0000000..31c18cf --- /dev/null +++ b/tsconfig.app.json @@ -0,0 +1,21 @@ +{ + "extends": "@tsconfig/svelte/tsconfig.json", + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "target": "ES2022", + "useDefineForClassFields": true, + "module": "ESNext", + "types": ["svelte", "vite/client"], + "noEmit": true, + /** + * Typecheck JS in `.svelte` and `.js` files by default. + * Disable checkJs if you'd like to use dynamic types in JS. + * Note that setting allowJs false does not prevent the use + * of JS in `.svelte` files. + */ + "allowJs": true, + "checkJs": true, + "moduleDetection": "force" + }, + "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte"] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..1ffef60 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..8a67f62 --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "target": "ES2023", + "lib": ["ES2023"], + "module": "ESNext", + "types": ["node"], + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..d32eba1 --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite' +import { svelte } from '@sveltejs/vite-plugin-svelte' + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [svelte()], +})