commit 2f5e10140cdbc1bbf53a11451383d4de063d6849 Author: Alois Date: Tue Mar 10 20:44:25 2026 +0100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b7077d0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules +packages/core/socket \ No newline at end of file diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..e24f579 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,6 @@ +node_modules +dist +coverage +.tmp +*.tsbuildinfo +bun.lock \ No newline at end of file diff --git a/bun.lock b/bun.lock new file mode 100644 index 0000000..c314563 --- /dev/null +++ b/bun.lock @@ -0,0 +1,1112 @@ +{ + "lockfileVersion": 1, + "configVersion": 1, + "workspaces": { + "": { + "name": "tensamin", + "devDependencies": { + "@eslint/js": "^10.0.1", + "@types/node": "^25.4.0", + "@typescript-eslint/parser": "^8.57.0", + "eslint": "^10.0.3", + "eslint-plugin-solid": "^0.14.5", + "globals": "^17.4.0", + "prettier": "^3.8.1", + "typescript": "^5.9.3", + "typescript-eslint": "^8.57.0", + }, + }, + "packages/chat": { + "name": "@tensamin/chat", + "version": "0.0.0", + "dependencies": { + "@solidjs/router": "^0.15.4", + "@tanstack/solid-query": "^5.90.23", + "@tanstack/solid-virtual": "^3.13.21", + "@tensamin/core-crypto": "workspace:*", + "@tensamin/core-storage": "workspace:*", + "@tensamin/core-user": "workspace:*", + "@tensamin/markdown": "workspace:*", + "@tensamin/shared": "workspace:*", + "@tensamin/ttp": "git+https://github.com/Tensamin/TTP.git", + "@tensamin/ui": "workspace:*", + "lucide-solid": "^0.564.0", + "solid-js": "^1.9.11", + "solid-sonner": "^0.2.8", + "zod": "^4.3.6", + }, + }, + "packages/core/crypto": { + "name": "@tensamin/core-crypto", + "version": "0.0.0", + "dependencies": { + "@noble/curves": "^2.0.1", + "@tensamin/ui": "workspace:*", + "comlink": "^4.4.2", + "solid-js": "^1.9.11", + }, + }, + "packages/core/markdown": { + "name": "@tensamin/markdown", + "version": "0.0.0", + "dependencies": { + "@codemirror/commands": "^6.10.2", + "@codemirror/lang-markdown": "^6.5.0", + "@codemirror/state": "^6.5.4", + "@codemirror/view": "^6.39.16", + "@tensamin/ui": "workspace:*", + "solid-js": "^1.9.11", + }, + }, + "packages/core/storage": { + "name": "@tensamin/core-storage", + "version": "0.0.0", + "dependencies": { + "@tensamin/shared": "workspace:*", + "@tensamin/ui": "workspace:*", + "solid-js": "^1.9.11", + }, + }, + "packages/core/user": { + "name": "@tensamin/core-user", + "version": "0.0.0", + "dependencies": { + "@tensamin/shared": "workspace:*", + "@tensamin/ttp": "git+https://github.com/Tensamin/TTP.git", + "solid-js": "^1.9.11", + "zod": "^4.3.6", + }, + }, + "packages/desktop": { + "name": "electrobun-hello-world", + "version": "1.0.0", + "dependencies": { + "@tensamin/shared": "workspace:*", + "electrobun": "1.15.1", + }, + "devDependencies": { + "@types/bun": "latest", + }, + }, + "packages/notifications": { + "name": "@tensamin/notifications", + "version": "0.0.0", + "dependencies": { + "@solidjs/router": "^0.15.4", + "@tensamin/ttp": "git+https://github.com/Tensamin/TTP.git", + "lucide-solid": "^0.564.0", + "solid-js": "^1.9.11", + "solid-sonner": "^0.2.8", + "zod": "^4.3.6", + }, + }, + "packages/shared": { + "name": "@tensamin/shared", + "version": "0.0.0", + "dependencies": { + "lucide-solid": "^0.564.0", + "solid-js": "^1.9.11", + "solid-sonner": "^0.2.8", + "zod": "^4.3.6", + }, + }, + "packages/ui": { + "name": "@tensamin/ui", + "version": "0.0.0", + "dependencies": { + "@ark-ui/solid": "^5.34.1", + "@corvu/drawer": "^0.2.4", + "@corvu/otp-field": "^0.1.4", + "@corvu/resizable": "^0.2.5", + "@kobalte/core": "^0.13.11", + "@tanstack/solid-virtual": "^3.13.21", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "cmdk-solid": "^1.1.2", + "embla-carousel-solid": "^8.6.0", + "lucide-solid": "^0.564.0", + "solid-js": "^1.9.11", + "solid-sonner": "^0.2.8", + "tailwind-merge": "^3.5.0", + }, + }, + "packages/web": { + "name": "@tensamin/web", + "version": "0.0.0", + "dependencies": { + "@ark-ui/solid": "^5.34.1", + "@corvu/drawer": "^0.2.4", + "@corvu/otp-field": "^0.1.4", + "@corvu/resizable": "^0.2.5", + "@kobalte/core": "^0.13.11", + "@noble/curves": "^2.0.1", + "@solidjs/router": "^0.15.4", + "@tailwindcss/vite": "^4.2.1", + "@tanstack/solid-virtual": "^3.13.21", + "@tensamin/chat": "workspace:*", + "@tensamin/core-crypto": "workspace:*", + "@tensamin/core-storage": "workspace:*", + "@tensamin/core-user": "workspace:*", + "@tensamin/shared": "workspace:*", + "@tensamin/ttp": "git+https://github.com/Tensamin/TTP.git", + "@tensamin/ui": "workspace:*", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "cmdk-solid": "^1.1.2", + "comlink": "^4.4.2", + "embla-carousel-solid": "^8.6.0", + "lucide-solid": "^0.564.0", + "solid-js": "^1.9.11", + "solid-sonner": "^0.2.8", + "tailwind-merge": "^3.5.0", + "tailwind-scrollbar-hide": "^4.0.0", + "tailwindcss": "^4.2.1", + "tw-animate-css": "^1.4.0", + "vite-tsconfig-paths": "^6.1.1", + "zod": "^4.3.6", + }, + "devDependencies": { + "@eslint/js": "^10.0.1", + "eslint": "^10.0.3", + "eslint-plugin-solid": "^0.14.5", + "globals": "^17.4.0", + "typescript": "~5.9.3", + "typescript-eslint": "^8.57.0", + "vite": "^7.3.1", + "vite-plugin-lucide-preprocess": "^1.4.8", + "vite-plugin-solid": "^2.11.10", + }, + }, + }, + "packages": { + "@ark-ui/solid": ["@ark-ui/solid@5.34.1", "", { "dependencies": { "@internationalized/date": "3.11.0", "@zag-js/accordion": "1.35.3", "@zag-js/anatomy": "1.35.3", "@zag-js/angle-slider": "1.35.3", "@zag-js/async-list": "1.35.3", "@zag-js/auto-resize": "1.35.3", "@zag-js/avatar": "1.35.3", "@zag-js/carousel": "1.35.3", "@zag-js/cascade-select": "1.35.3", "@zag-js/checkbox": "1.35.3", "@zag-js/clipboard": "1.35.3", "@zag-js/collapsible": "1.35.3", "@zag-js/collection": "1.35.3", "@zag-js/color-picker": "1.35.3", "@zag-js/color-utils": "1.35.3", "@zag-js/combobox": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/date-picker": "1.35.3", "@zag-js/date-utils": "1.35.3", "@zag-js/dialog": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/drawer": "1.35.3", "@zag-js/editable": "1.35.3", "@zag-js/file-upload": "1.35.3", "@zag-js/file-utils": "1.35.3", "@zag-js/floating-panel": "1.35.3", "@zag-js/focus-trap": "1.35.3", "@zag-js/highlight-word": "1.35.3", "@zag-js/hover-card": "1.35.3", "@zag-js/i18n-utils": "1.35.3", "@zag-js/image-cropper": "1.35.3", "@zag-js/json-tree-utils": "1.35.3", "@zag-js/listbox": "1.35.3", "@zag-js/marquee": "1.35.3", "@zag-js/menu": "1.35.3", "@zag-js/navigation-menu": "1.35.3", "@zag-js/number-input": "1.35.3", "@zag-js/pagination": "1.35.3", "@zag-js/password-input": "1.35.3", "@zag-js/pin-input": "1.35.3", "@zag-js/popover": "1.35.3", "@zag-js/presence": "1.35.3", "@zag-js/progress": "1.35.3", "@zag-js/qr-code": "1.35.3", "@zag-js/radio-group": "1.35.3", "@zag-js/rating-group": "1.35.3", "@zag-js/scroll-area": "1.35.3", "@zag-js/select": "1.35.3", "@zag-js/signature-pad": "1.35.3", "@zag-js/slider": "1.35.3", "@zag-js/solid": "1.35.3", "@zag-js/splitter": "1.35.3", "@zag-js/steps": "1.35.3", "@zag-js/switch": "1.35.3", "@zag-js/tabs": "1.35.3", "@zag-js/tags-input": "1.35.3", "@zag-js/timer": "1.35.3", "@zag-js/toast": "1.35.3", "@zag-js/toggle": "1.35.3", "@zag-js/toggle-group": "1.35.3", "@zag-js/tooltip": "1.35.3", "@zag-js/tour": "1.35.3", "@zag-js/tree-view": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" }, "peerDependencies": { "solid-js": ">=1.6.0" } }, "sha512-DMTAVtmibwcKC9B3iMhQfXfTvCsQYs43qTX2VZPArVsjQGNZlDXK3+oPmaw1FPoVBD5csi1bjGNkwruhbh1gAA=="], + + "@babel/code-frame": ["@babel/code-frame@7.29.0", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw=="], + + "@babel/compat-data": ["@babel/compat-data@7.29.0", "", {}, "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg=="], + + "@babel/core": ["@babel/core@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-module-transforms": "^7.28.6", "@babel/helpers": "^7.28.6", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA=="], + + "@babel/generator": ["@babel/generator@7.29.1", "", { "dependencies": { "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw=="], + + "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.28.6", "", { "dependencies": { "@babel/compat-data": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA=="], + + "@babel/helper-globals": ["@babel/helper-globals@7.28.0", "", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="], + + "@babel/helper-module-imports": ["@babel/helper-module-imports@7.28.6", "", { "dependencies": { "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw=="], + + "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.6", "", { "dependencies": { "@babel/helper-module-imports": "^7.28.6", "@babel/helper-validator-identifier": "^7.28.5", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA=="], + + "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.28.6", "", {}, "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug=="], + + "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], + + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="], + + "@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="], + + "@babel/helpers": ["@babel/helpers@7.28.6", "", { "dependencies": { "@babel/template": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw=="], + + "@babel/parser": ["@babel/parser@7.29.0", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww=="], + + "@babel/plugin-syntax-jsx": ["@babel/plugin-syntax-jsx@7.28.6", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w=="], + + "@babel/template": ["@babel/template@7.28.6", "", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ=="], + + "@babel/traverse": ["@babel/traverse@7.29.0", "", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/types": "^7.29.0", "debug": "^4.3.1" } }, "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA=="], + + "@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="], + + "@babylonjs/core": ["@babylonjs/core@7.54.3", "", {}, "sha512-P5ncXVd8GEUJLhwloP9V0oVwQYIrvZztguVeLlvd5Rx+9aQnenKjpV8auJ6SRsUlAmNZU4pFTKzwF6o2EUfhAw=="], + + "@codemirror/autocomplete": ["@codemirror/autocomplete@6.20.0", "", { "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.17.0", "@lezer/common": "^1.0.0" } }, "sha512-bOwvTOIJcG5FVo5gUUupiwYh8MioPLQ4UcqbcRf7UQ98X90tCa9E1kZ3Z7tqwpZxYyOvh1YTYbmZE9RTfTp5hg=="], + + "@codemirror/commands": ["@codemirror/commands@6.10.2", "", { "dependencies": { "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.4.0", "@codemirror/view": "^6.27.0", "@lezer/common": "^1.1.0" } }, "sha512-vvX1fsih9HledO1c9zdotZYUZnE4xV0m6i3m25s5DIfXofuprk6cRcLUZvSk3CASUbwjQX21tOGbkY2BH8TpnQ=="], + + "@codemirror/lang-css": ["@codemirror/lang-css@6.3.1", "", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/language": "^6.0.0", "@codemirror/state": "^6.0.0", "@lezer/common": "^1.0.2", "@lezer/css": "^1.1.7" } }, "sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg=="], + + "@codemirror/lang-html": ["@codemirror/lang-html@6.4.11", "", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/lang-css": "^6.0.0", "@codemirror/lang-javascript": "^6.0.0", "@codemirror/language": "^6.4.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.17.0", "@lezer/common": "^1.0.0", "@lezer/css": "^1.1.0", "@lezer/html": "^1.3.12" } }, "sha512-9NsXp7Nwp891pQchI7gPdTwBuSuT3K65NGTHWHNJ55HjYcHLllr0rbIZNdOzas9ztc1EUVBlHou85FFZS4BNnw=="], + + "@codemirror/lang-javascript": ["@codemirror/lang-javascript@6.2.4", "", { "dependencies": { "@codemirror/autocomplete": "^6.0.0", "@codemirror/language": "^6.6.0", "@codemirror/lint": "^6.0.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.17.0", "@lezer/common": "^1.0.0", "@lezer/javascript": "^1.0.0" } }, "sha512-0WVmhp1QOqZ4Rt6GlVGwKJN3KW7Xh4H2q8ZZNGZaP6lRdxXJzmjm4FqvmOojVj6khWJHIb9sp7U/72W7xQgqAA=="], + + "@codemirror/lang-markdown": ["@codemirror/lang-markdown@6.5.0", "", { "dependencies": { "@codemirror/autocomplete": "^6.7.1", "@codemirror/lang-html": "^6.0.0", "@codemirror/language": "^6.3.0", "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.0.0", "@lezer/common": "^1.2.1", "@lezer/markdown": "^1.0.0" } }, "sha512-0K40bZ35jpHya6FriukbgaleaqzBLZfOh7HuzqbMxBXkbYMJDxfF39c23xOgxFezR+3G+tR2/Mup+Xk865OMvw=="], + + "@codemirror/language": ["@codemirror/language@6.12.1", "", { "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.23.0", "@lezer/common": "^1.5.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0", "style-mod": "^4.0.0" } }, "sha512-Fa6xkSiuGKc8XC8Cn96T+TQHYj4ZZ7RdFmXA3i9xe/3hLHfwPZdM+dqfX0Cp0zQklBKhVD8Yzc8LS45rkqcwpQ=="], + + "@codemirror/lint": ["@codemirror/lint@6.9.4", "", { "dependencies": { "@codemirror/state": "^6.0.0", "@codemirror/view": "^6.35.0", "crelt": "^1.0.5" } }, "sha512-ABc9vJ8DEmvOWuH26P3i8FpMWPQkduD9Rvba5iwb6O3hxASgclm3T3krGo8NASXkHCidz6b++LWlzWIUfEPSWw=="], + + "@codemirror/state": ["@codemirror/state@6.5.4", "", { "dependencies": { "@marijn/find-cluster-break": "^1.0.0" } }, "sha512-8y7xqG/hpB53l25CIoit9/ngxdfoG+fx+V3SHBrinnhOtLvKHRyAJJuHzkWrR4YXXLX8eXBsejgAAxHUOdW1yw=="], + + "@codemirror/view": ["@codemirror/view@6.39.16", "", { "dependencies": { "@codemirror/state": "^6.5.0", "crelt": "^1.0.6", "style-mod": "^4.1.0", "w3c-keyname": "^2.2.4" } }, "sha512-m6S22fFpKtOWhq8HuhzsI1WzUP/hB9THbDj0Tl5KX4gbO6Y91hwBl7Yky33NdvB6IffuRFiBxf1R8kJMyXmA4Q=="], + + "@corvu/dialog": ["@corvu/dialog@0.2.4", "", { "dependencies": { "@corvu/utils": "~0.4.2", "solid-dismissible": "~0.1.1", "solid-focus-trap": "~0.1.8", "solid-presence": "~0.2.0", "solid-prevent-scroll": "~0.1.10" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-n54vJq+fOy8GVrnYBdJpD6JXNuyx7LOeMrRxwzAvZnYGpW8+AA12tnb/P/2emJj/HjOO5otheGKb0breshdFlA=="], + + "@corvu/drawer": ["@corvu/drawer@0.2.4", "", { "dependencies": { "@corvu/dialog": "~0.2.4", "@corvu/utils": "~0.4.2", "@solid-primitives/memo": "^1.4.1", "solid-transition-size": "~0.1.4" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-7jQoGZ8ROB9CmXam2nMY2wEskU3IoFwZQywkF/7vrBc/edGsPv7mOVQ1GN6G+4nd7nrMZ3UtqHAhmRh9V0azlw=="], + + "@corvu/otp-field": ["@corvu/otp-field@0.1.4", "", { "dependencies": { "@corvu/utils": "~0.4.2" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-3eG7OoUt6CfVqGujIYfqImdrhGR/s4DpKr5ZQT10zzw3nawIlcwVpqoHTam0v4cgv+NXXvl6I8DoA3J+WgW2YA=="], + + "@corvu/resizable": ["@corvu/resizable@0.2.5", "", { "dependencies": { "@corvu/utils": "~0.4.2" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-psax38DraM9SXtaNh/sfvizGO6xLCL4sqT4rWYlMZP5ZsUM05Q30tvXgnTo2roQFNOz2e06WofhDsBXTjY6g4A=="], + + "@corvu/utils": ["@corvu/utils@0.4.2", "", { "dependencies": { "@floating-ui/dom": "^1.6.11" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-Ox2kYyxy7NoXdKWdHeDEjZxClwzO4SKM8plAaVwmAJPxHMqA0rLOoAsa+hBDwRLpctf+ZRnAd/ykguuJidnaTA=="], + + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.3", "", { "os": "aix", "cpu": "ppc64" }, "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg=="], + + "@esbuild/android-arm": ["@esbuild/android-arm@0.27.3", "", { "os": "android", "cpu": "arm" }, "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA=="], + + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.3", "", { "os": "android", "cpu": "arm64" }, "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg=="], + + "@esbuild/android-x64": ["@esbuild/android-x64@0.27.3", "", { "os": "android", "cpu": "x64" }, "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ=="], + + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg=="], + + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg=="], + + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.3", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w=="], + + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA=="], + + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.3", "", { "os": "linux", "cpu": "arm" }, "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw=="], + + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg=="], + + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.3", "", { "os": "linux", "cpu": "ia32" }, "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg=="], + + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA=="], + + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw=="], + + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA=="], + + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.3", "", { "os": "linux", "cpu": "none" }, "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ=="], + + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw=="], + + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.3", "", { "os": "linux", "cpu": "x64" }, "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA=="], + + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA=="], + + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.3", "", { "os": "none", "cpu": "x64" }, "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA=="], + + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.3", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw=="], + + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.3", "", { "os": "openbsd", "cpu": "x64" }, "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ=="], + + "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.3", "", { "os": "none", "cpu": "arm64" }, "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g=="], + + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.3", "", { "os": "sunos", "cpu": "x64" }, "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA=="], + + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA=="], + + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q=="], + + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.3", "", { "os": "win32", "cpu": "x64" }, "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA=="], + + "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ=="], + + "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="], + + "@eslint/config-array": ["@eslint/config-array@0.23.3", "", { "dependencies": { "@eslint/object-schema": "^3.0.3", "debug": "^4.3.1", "minimatch": "^10.2.4" } }, "sha512-j+eEWmB6YYLwcNOdlwQ6L2OsptI/LO6lNBuLIqe5R7RetD658HLoF+Mn7LzYmAWWNNzdC6cqP+L6r8ujeYXWLw=="], + + "@eslint/config-helpers": ["@eslint/config-helpers@0.5.2", "", { "dependencies": { "@eslint/core": "^1.1.0" } }, "sha512-a5MxrdDXEvqnIq+LisyCX6tQMPF/dSJpCfBgBauY+pNZ28yCtSsTvyTYrMhaI+LK26bVyCJfJkT0u8KIj2i1dQ=="], + + "@eslint/core": ["@eslint/core@1.1.1", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-QUPblTtE51/7/Zhfv8BDwO0qkkzQL7P/aWWbqcf4xWLEYn1oKjdO0gglQBB4GAsu7u6wjijbCmzsUTy6mnk6oQ=="], + + "@eslint/js": ["@eslint/js@10.0.1", "", { "peerDependencies": { "eslint": "^10.0.0" }, "optionalPeers": ["eslint"] }, "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA=="], + + "@eslint/object-schema": ["@eslint/object-schema@3.0.3", "", {}, "sha512-iM869Pugn9Nsxbh/YHRqYiqd23AmIbxJOcpUMOuWCVNdoQJ5ZtwL6h3t0bcZzJUlC3Dq9jCFCESBZnX0GTv7iQ=="], + + "@eslint/plugin-kit": ["@eslint/plugin-kit@0.6.1", "", { "dependencies": { "@eslint/core": "^1.1.1", "levn": "^0.4.1" } }, "sha512-iH1B076HoAshH1mLpHMgwdGeTs0CYwL0SPMkGuSebZrwBp16v415e9NZXg2jtrqPVQjf6IANe2Vtlr5KswtcZQ=="], + + "@floating-ui/core": ["@floating-ui/core@1.7.5", "", { "dependencies": { "@floating-ui/utils": "^0.2.11" } }, "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ=="], + + "@floating-ui/dom": ["@floating-ui/dom@1.7.6", "", { "dependencies": { "@floating-ui/core": "^1.7.5", "@floating-ui/utils": "^0.2.11" } }, "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ=="], + + "@floating-ui/utils": ["@floating-ui/utils@0.2.11", "", {}, "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg=="], + + "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], + + "@humanfs/node": ["@humanfs/node@0.16.7", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ=="], + + "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="], + + "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], + + "@internationalized/date": ["@internationalized/date@3.11.0", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-BOx5huLAWhicM9/ZFs84CzP+V3gBW6vlpM02yzsdYC7TGlZJX1OJiEEHcSayF00Z+3jLlm4w79amvSt6RqKN3Q=="], + + "@internationalized/number": ["@internationalized/number@3.6.5", "", { "dependencies": { "@swc/helpers": "^0.5.0" } }, "sha512-6hY4Kl4HPBvtfS62asS/R22JzNNy8vi/Ssev7x6EobfCp+9QIB2hKvI2EtbdJ0VSQacxVNtqhE/NmF/NZ0gm6g=="], + + "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], + + "@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="], + + "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], + + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], + + "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="], + + "@kobalte/core": ["@kobalte/core@0.13.11", "", { "dependencies": { "@floating-ui/dom": "^1.5.1", "@internationalized/date": "^3.4.0", "@internationalized/number": "^3.2.1", "@kobalte/utils": "^0.9.1", "@solid-primitives/props": "^3.1.8", "@solid-primitives/resize-observer": "^2.0.26", "solid-presence": "^0.1.8", "solid-prevent-scroll": "^0.1.4" }, "peerDependencies": { "solid-js": "^1.8.15" } }, "sha512-hK7TYpdib/XDb/r/4XDBFaO9O+3ZHz4ZWryV4/3BfES+tSQVgg2IJupDnztKXB0BqbSRy/aWlHKw1SPtNPYCFQ=="], + + "@kobalte/utils": ["@kobalte/utils@0.9.1", "", { "dependencies": { "@solid-primitives/event-listener": "^2.2.14", "@solid-primitives/keyed": "^1.2.0", "@solid-primitives/map": "^0.4.7", "@solid-primitives/media": "^2.2.4", "@solid-primitives/props": "^3.1.8", "@solid-primitives/refs": "^1.0.5", "@solid-primitives/utils": "^6.2.1" }, "peerDependencies": { "solid-js": "^1.8.8" } }, "sha512-eeU60A3kprIiBDAfv9gUJX1tXGLuZiKMajUfSQURAF2pk4ZoMYiqIzmrMBvzcxP39xnYttgTyQEVLwiTZnrV4w=="], + + "@lezer/common": ["@lezer/common@1.5.1", "", {}, "sha512-6YRVG9vBkaY7p1IVxL4s44n5nUnaNnGM2/AckNgYOnxTG2kWh1vR8BMxPseWPjRNpb5VtXnMpeYAEAADoRV1Iw=="], + + "@lezer/css": ["@lezer/css@1.3.1", "", { "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.3.0" } }, "sha512-PYAKeUVBo3HFThruRyp/iK91SwiZJnzXh8QzkQlwijB5y+N5iB28+iLk78o2zmKqqV0uolNhCwFqB8LA7b0Svg=="], + + "@lezer/highlight": ["@lezer/highlight@1.2.3", "", { "dependencies": { "@lezer/common": "^1.3.0" } }, "sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g=="], + + "@lezer/html": ["@lezer/html@1.3.13", "", { "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.0.0", "@lezer/lr": "^1.0.0" } }, "sha512-oI7n6NJml729m7pjm9lvLvmXbdoMoi2f+1pwSDJkl9d68zGr7a9Btz8NdHTGQZtW2DA25ybeuv/SyDb9D5tseg=="], + + "@lezer/javascript": ["@lezer/javascript@1.5.4", "", { "dependencies": { "@lezer/common": "^1.2.0", "@lezer/highlight": "^1.1.3", "@lezer/lr": "^1.3.0" } }, "sha512-vvYx3MhWqeZtGPwDStM2dwgljd5smolYD2lR2UyFcHfxbBQebqx8yjmFmxtJ/E6nN6u1D9srOiVWm3Rb4tmcUA=="], + + "@lezer/lr": ["@lezer/lr@1.4.8", "", { "dependencies": { "@lezer/common": "^1.0.0" } }, "sha512-bPWa0Pgx69ylNlMlPvBPryqeLYQjyJjqPx+Aupm5zydLIF3NE+6MMLT8Yi23Bd9cif9VS00aUebn+6fDIGBcDA=="], + + "@lezer/markdown": ["@lezer/markdown@1.6.3", "", { "dependencies": { "@lezer/common": "^1.5.0", "@lezer/highlight": "^1.0.0" } }, "sha512-jpGm5Ps+XErS+xA4urw7ogEGkeZOahVQF21Z6oECF0sj+2liwZopd2+I8uH5I/vZsRuuze3OxBREIANLf6KKUw=="], + + "@malept/cross-spawn-promise": ["@malept/cross-spawn-promise@1.1.1", "", { "dependencies": { "cross-spawn": "^7.0.1" } }, "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ=="], + + "@marijn/find-cluster-break": ["@marijn/find-cluster-break@1.0.2", "", {}, "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g=="], + + "@noble/curves": ["@noble/curves@2.0.1", "", { "dependencies": { "@noble/hashes": "2.0.1" } }, "sha512-vs1Az2OOTBiP4q0pwjW5aF0xp9n4MxVrmkFBxc6EKZc6ddYx5gaZiAsZoq0uRRXWbi3AT/sBqn05eRPtn1JCPw=="], + + "@noble/hashes": ["@noble/hashes@2.0.1", "", {}, "sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw=="], + + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.57.1", "", { "os": "android", "cpu": "arm" }, "sha512-A6ehUVSiSaaliTxai040ZpZ2zTevHYbvu/lDoeAteHI8QnaosIzm4qwtezfRg1jOYaUmnzLX1AOD6Z+UJjtifg=="], + + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.57.1", "", { "os": "android", "cpu": "arm64" }, "sha512-dQaAddCY9YgkFHZcFNS/606Exo8vcLHwArFZ7vxXq4rigo2bb494/xKMMwRRQW6ug7Js6yXmBZhSBRuBvCCQ3w=="], + + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.57.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-crNPrwJOrRxagUYeMn/DZwqN88SDmwaJ8Cvi/TN1HnWBU7GwknckyosC2gd0IqYRsHDEnXf328o9/HC6OkPgOg=="], + + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.57.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-Ji8g8ChVbKrhFtig5QBV7iMaJrGtpHelkB3lsaKzadFBe58gmjfGXAOfI5FV0lYMH8wiqsxKQ1C9B0YTRXVy4w=="], + + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.57.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-R+/WwhsjmwodAcz65guCGFRkMb4gKWTcIeLy60JJQbXrJ97BOXHxnkPFrP+YwFlaS0m+uWJTstrUA9o+UchFug=="], + + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.57.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-IEQTCHeiTOnAUC3IDQdzRAGj3jOAYNr9kBguI7MQAAZK3caezRrg0GxAb6Hchg4lxdZEI5Oq3iov/w/hnFWY9Q=="], + + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.57.1", "", { "os": "linux", "cpu": "arm" }, "sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw=="], + + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.57.1", "", { "os": "linux", "cpu": "arm" }, "sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw=="], + + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.57.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g=="], + + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.57.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q=="], + + "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.57.1", "", { "os": "linux", "cpu": "none" }, "sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA=="], + + "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.57.1", "", { "os": "linux", "cpu": "none" }, "sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw=="], + + "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.57.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w=="], + + "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.57.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw=="], + + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.57.1", "", { "os": "linux", "cpu": "none" }, "sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A=="], + + "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.57.1", "", { "os": "linux", "cpu": "none" }, "sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw=="], + + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.57.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg=="], + + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.57.1", "", { "os": "linux", "cpu": "x64" }, "sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg=="], + + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.57.1", "", { "os": "linux", "cpu": "x64" }, "sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw=="], + + "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.57.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw=="], + + "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.57.1", "", { "os": "none", "cpu": "arm64" }, "sha512-4wYoDpNg6o/oPximyc/NG+mYUejZrCU2q+2w6YZqrAs2UcNUChIZXjtafAiiZSUc7On8v5NyNj34Kzj/Ltk6dQ=="], + + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.57.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-O54mtsV/6LW3P8qdTcamQmuC990HDfR71lo44oZMZlXU4tzLrbvTii87Ni9opq60ds0YzuAlEr/GNwuNluZyMQ=="], + + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.57.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-P3dLS+IerxCT/7D2q2FYcRdWRl22dNbrbBEtxdWhXrfIMPP9lQhb5h4Du04mdl5Woq05jVCDPCMF7Ub0NAjIew=="], + + "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.57.1", "", { "os": "win32", "cpu": "x64" }, "sha512-VMBH2eOOaKGtIJYleXsi2B8CPVADrh+TyNxJ4mWPnKfLB/DBUmzW+5m1xUrcwWoMfSLagIRpjUFeW5CO5hyciQ=="], + + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.57.1", "", { "os": "win32", "cpu": "x64" }, "sha512-mxRFDdHIWRxg3UfIIAwCm6NzvxG0jDX/wBN6KsQFTvKFqqg9vTrWUE68qEjHt19A5wwx5X5aUi2zuZT7YR0jrA=="], + + "@solid-primitives/deep": ["@solid-primitives/deep@0.2.10", "", { "dependencies": { "@solid-primitives/memo": "^1.3.10" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-uzhXr/cMABsGkTcV3yuviZjTDmj44wb2JetuJ5O8NCugz4Ug/6XlPjT8ISMPYV7eCbC/gFhgt7e60+TRpl2Upg=="], + + "@solid-primitives/event-listener": ["@solid-primitives/event-listener@2.4.5", "", { "dependencies": { "@solid-primitives/utils": "^6.4.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-nwRV558mIabl4yVAhZKY8cb6G+O1F0M6Z75ttTu5hk+SxdOnKSGj+eetDIu7Oax1P138ZdUU01qnBPR8rnxaEA=="], + + "@solid-primitives/keyed": ["@solid-primitives/keyed@1.5.3", "", { "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-zNadtyYBhJSOjXtogkGHmRxjGdz9KHc8sGGVAGlUABkE8BED2tbIZoxkwSqzOwde8OcUEH0bb5DLZUWIMvyBSA=="], + + "@solid-primitives/map": ["@solid-primitives/map@0.4.13", "", { "dependencies": { "@solid-primitives/trigger": "^1.1.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-B1zyFbsiTQvqPr+cuPCXO72sRuczG9Swncqk5P74NCGw1VE8qa/Ry9GlfI1e/VdeQYHjan+XkbE3rO2GW/qKew=="], + + "@solid-primitives/media": ["@solid-primitives/media@2.3.5", "", { "dependencies": { "@solid-primitives/event-listener": "^2.4.5", "@solid-primitives/rootless": "^1.5.3", "@solid-primitives/static-store": "^0.1.3", "@solid-primitives/utils": "^6.4.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-LX9fB5WDaK87FMDtUB1qokBOfT2et9Uobv/zZaKLH9caFSz4+P70MBKEIBHcZQy+9MV5M2XvGYLTbLskjkzMjA=="], + + "@solid-primitives/memo": ["@solid-primitives/memo@1.4.5", "", { "dependencies": { "@solid-primitives/scheduled": "^1.5.3", "@solid-primitives/utils": "^6.4.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-dMfFShNsyX5virETyDv/Uoy2HP+PL4k8cUTTLb2r4TfoqJb010KIaOuURqp/Qbdznp4ZkDuP57b28d45kaOueQ=="], + + "@solid-primitives/mutation-observer": ["@solid-primitives/mutation-observer@1.2.3", "", { "dependencies": { "@solid-primitives/utils": "^6.4.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-p69O/zwvR7fCT87KGN3hkDfsZyWAJH+bsCZrdmWHcM5/8lg1Ndh7NjxXX1G1Ugk6ru/Bx6MvSppbbfkdBlwzgQ=="], + + "@solid-primitives/props": ["@solid-primitives/props@3.2.3", "", { "dependencies": { "@solid-primitives/utils": "^6.4.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-XzG6en9gSFwmvbKcATm2BxL63HegZ+BAG5fmHi8jyBppQHcaths7ffz+6vYvwYy3nlgLa20ufJLj7tst+PcHFA=="], + + "@solid-primitives/refs": ["@solid-primitives/refs@1.1.3", "", { "dependencies": { "@solid-primitives/utils": "^6.4.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-aam02fjNKpBteewF/UliPSQCVJsIIGOLEWQOh+ll6R/QePzBOOBMcC4G+5jTaO75JuUS1d/14Q1YXT3X0Ow6iA=="], + + "@solid-primitives/resize-observer": ["@solid-primitives/resize-observer@2.1.5", "", { "dependencies": { "@solid-primitives/event-listener": "^2.4.5", "@solid-primitives/rootless": "^1.5.3", "@solid-primitives/static-store": "^0.1.3", "@solid-primitives/utils": "^6.4.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-AiyTknKcNBaKHbcSMuxtSNM8FjIuiSuFyFghdD0TcCMU9hKi9EmsC5pjfjDwxE+5EueB1a+T/34PLRI5vbBbKw=="], + + "@solid-primitives/rootless": ["@solid-primitives/rootless@1.5.3", "", { "dependencies": { "@solid-primitives/utils": "^6.4.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-N8cIDAHbWcLahNRLr0knAAQvXyEdEMoAZvIMZKmhNb1mlx9e2UOv9BRD5YNwQUJwbNoYVhhLwFOEOcVXFx0HqA=="], + + "@solid-primitives/scheduled": ["@solid-primitives/scheduled@1.5.3", "", { "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-oNwLE6E6lxJAWrc8QXuwM0k2oU1BnANnkChwMw82aK1j3+mWGJkG1IFe5gCwbV+afYmjI76t9JJV3md/8tLw+g=="], + + "@solid-primitives/static-store": ["@solid-primitives/static-store@0.1.3", "", { "dependencies": { "@solid-primitives/utils": "^6.4.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-uxez7SXnr5GiRnzqO2IEDjOJRIXaG+0LZLBizmUA1FwSi+hrpuMzVBwyk70m4prcl8X6FDDXUl9O8hSq8wHbBQ=="], + + "@solid-primitives/trigger": ["@solid-primitives/trigger@1.2.3", "", { "dependencies": { "@solid-primitives/utils": "^6.4.0" }, "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-Za2JebEiDyfamjmDwRaESYqBBYOlgYGzB8kHYH0QrkXyLf2qNADlKdGN+z3vWSLCTDcKxChS43Kssjuc0OZhng=="], + + "@solid-primitives/utils": ["@solid-primitives/utils@6.4.0", "", { "peerDependencies": { "solid-js": "^1.6.12" } }, "sha512-AeGTBg8Wtkh/0s+evyLtP8piQoS4wyqqQaAFs2HJcFMMjYAtUgo+ZPduRXLjPlqKVc2ejeR544oeqpbn8Egn8A=="], + + "@solidjs/router": ["@solidjs/router@0.15.4", "", { "peerDependencies": { "solid-js": "^1.8.6" } }, "sha512-WOpgg9a9T638cR+5FGbFi/IV4l2FpmBs1GpIMSPa0Ce9vyJN7Wts+X2PqMf9IYn0zUj2MlSJtm1gp7/HI/n5TQ=="], + + "@swc/helpers": ["@swc/helpers@0.5.19", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-QamiFeIK3txNjgUTNppE6MiG3p7TdninpZu0E0PbqVh1a9FNLT2FRhisaa4NcaX52XVhA5l7Pk58Ft7Sqi/2sA=="], + + "@tailwindcss/node": ["@tailwindcss/node@4.2.1", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "enhanced-resolve": "^5.19.0", "jiti": "^2.6.1", "lightningcss": "1.31.1", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.2.1" } }, "sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg=="], + + "@tailwindcss/oxide": ["@tailwindcss/oxide@4.2.1", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.2.1", "@tailwindcss/oxide-darwin-arm64": "4.2.1", "@tailwindcss/oxide-darwin-x64": "4.2.1", "@tailwindcss/oxide-freebsd-x64": "4.2.1", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.1", "@tailwindcss/oxide-linux-arm64-gnu": "4.2.1", "@tailwindcss/oxide-linux-arm64-musl": "4.2.1", "@tailwindcss/oxide-linux-x64-gnu": "4.2.1", "@tailwindcss/oxide-linux-x64-musl": "4.2.1", "@tailwindcss/oxide-wasm32-wasi": "4.2.1", "@tailwindcss/oxide-win32-arm64-msvc": "4.2.1", "@tailwindcss/oxide-win32-x64-msvc": "4.2.1" } }, "sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw=="], + + "@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.2.1", "", { "os": "android", "cpu": "arm64" }, "sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg=="], + + "@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.2.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw=="], + + "@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.2.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw=="], + + "@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.2.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA=="], + + "@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.2.1", "", { "os": "linux", "cpu": "arm" }, "sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw=="], + + "@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.2.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ=="], + + "@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.2.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ=="], + + "@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g=="], + + "@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.2.1", "", { "os": "linux", "cpu": "x64" }, "sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g=="], + + "@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.2.1", "", { "dependencies": { "@emnapi/core": "^1.8.1", "@emnapi/runtime": "^1.8.1", "@emnapi/wasi-threads": "^1.1.0", "@napi-rs/wasm-runtime": "^1.1.1", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.8.1" }, "cpu": "none" }, "sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q=="], + + "@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.2.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA=="], + + "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.2.1", "", { "os": "win32", "cpu": "x64" }, "sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ=="], + + "@tailwindcss/vite": ["@tailwindcss/vite@4.2.1", "", { "dependencies": { "@tailwindcss/node": "4.2.1", "@tailwindcss/oxide": "4.2.1", "tailwindcss": "4.2.1" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-TBf2sJjYeb28jD2U/OhwdW0bbOsxkWPwQ7SrqGf9sVcoYwZj7rkXljroBO9wKBut9XnmQLXanuDUeqQK0lGg/w=="], + + "@tanstack/query-core": ["@tanstack/query-core@5.90.20", "", {}, "sha512-OMD2HLpNouXEfZJWcKeVKUgQ5n+n3A2JFmBaScpNDUqSrQSjiveC7dKMe53uJUg1nDG16ttFPz2xfilz6i2uVg=="], + + "@tanstack/solid-query": ["@tanstack/solid-query@5.90.23", "", { "dependencies": { "@tanstack/query-core": "5.90.20" }, "peerDependencies": { "solid-js": "^1.6.0" } }, "sha512-pbZc4+Kgm7ktzIuu01R3KOWfazQKgNp4AZvW0RSvv+sNMpYoileUDAkXEcjDJe6RJmb3fVvTR4LlcSL5pxDElQ=="], + + "@tanstack/solid-virtual": ["@tanstack/solid-virtual@3.13.21", "", { "dependencies": { "@tanstack/virtual-core": "3.13.21" }, "peerDependencies": { "solid-js": "^1.3.0" } }, "sha512-SOwgCLVFHzousW9TnbkRMlUxdCHWP8xmp+v9ay2S6aaNT4MgEp6w3/EAFPQuXGVoRgyh8i4M+KZKpmliyTsNfw=="], + + "@tanstack/virtual-core": ["@tanstack/virtual-core@3.13.21", "", {}, "sha512-ww+fmLHyCbPSf7JNbWZP3g7wl6SdNo3ah5Aiw+0e9FDErkVHLKprYUrwTm7dF646FtEkN/KkAKPYezxpmvOjxw=="], + + "@tensamin/chat": ["@tensamin/chat@workspace:packages/chat"], + + "@tensamin/core-crypto": ["@tensamin/core-crypto@workspace:packages/core/crypto"], + + "@tensamin/core-storage": ["@tensamin/core-storage@workspace:packages/core/storage"], + + "@tensamin/core-user": ["@tensamin/core-user@workspace:packages/core/user"], + + "@tensamin/markdown": ["@tensamin/markdown@workspace:packages/core/markdown"], + + "@tensamin/notifications": ["@tensamin/notifications@workspace:packages/notifications"], + + "@tensamin/shared": ["@tensamin/shared@workspace:packages/shared"], + + "@tensamin/ttp": ["@tensamin/ttp@github:Tensamin/TTP#58a5e2b", { "dependencies": { "@solidjs/router": "^0.15.4", "@tensamin/core-crypto": "workspace:*", "@tensamin/core-storage": "workspace:*", "@tensamin/shared": "workspace:*", "@tensamin/ui": "workspace:*", "solid-js": "^1.9.10", "zod": "^4.3.6" } }, "Tensamin-TTP-58a5e2b"], + + "@tensamin/ui": ["@tensamin/ui@workspace:packages/ui"], + + "@tensamin/web": ["@tensamin/web@workspace:packages/web"], + + "@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="], + + "@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="], + + "@types/babel__template": ["@types/babel__template@7.4.4", "", { "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A=="], + + "@types/babel__traverse": ["@types/babel__traverse@7.28.0", "", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="], + + "@types/bun": ["@types/bun@1.3.10", "", { "dependencies": { "bun-types": "1.3.10" } }, "sha512-0+rlrUrOrTSskibryHbvQkDOWRJwJZqZlxrUs1u4oOoTln8+WIXBPmAuCF35SWB2z4Zl3E84Nl/D0P7803nigQ=="], + + "@types/esrecurse": ["@types/esrecurse@4.3.1", "", {}, "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw=="], + + "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], + + "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], + + "@types/node": ["@types/node@25.4.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-9wLpoeWuBlcbBpOY3XmzSTG3oscB6xjBEEtn+pYXTfhyXhIxC5FsBer2KTopBlvKEiW9l13po9fq+SJY/5lkhw=="], + + "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.57.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.57.0", "@typescript-eslint/type-utils": "8.57.0", "@typescript-eslint/utils": "8.57.0", "@typescript-eslint/visitor-keys": "8.57.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.57.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-qeu4rTHR3/IaFORbD16gmjq9+rEs9fGKdX0kF6BKSfi+gCuG3RCKLlSBYzn/bGsY9Tj7KE/DAQStbp8AHJGHEQ=="], + + "@typescript-eslint/parser": ["@typescript-eslint/parser@8.57.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.57.0", "@typescript-eslint/types": "8.57.0", "@typescript-eslint/typescript-estree": "8.57.0", "@typescript-eslint/visitor-keys": "8.57.0", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-XZzOmihLIr8AD1b9hL9ccNMzEMWt/dE2u7NyTY9jJG6YNiNthaD5XtUHVF2uCXZ15ng+z2hT3MVuxnUYhq6k1g=="], + + "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.57.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.57.0", "@typescript-eslint/types": "^8.57.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-pR+dK0BlxCLxtWfaKQWtYr7MhKmzqZxuii+ZjuFlZlIGRZm22HnXFqa2eY+90MUz8/i80YJmzFGDUsi8dMOV5w=="], + + "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.57.0", "", { "dependencies": { "@typescript-eslint/types": "8.57.0", "@typescript-eslint/visitor-keys": "8.57.0" } }, "sha512-nvExQqAHF01lUM66MskSaZulpPL5pgy5hI5RfrxviLgzZVffB5yYzw27uK/ft8QnKXI2X0LBrHJFr1TaZtAibw=="], + + "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.57.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-LtXRihc5ytjJIQEH+xqjB0+YgsV4/tW35XKX3GTZHpWtcC8SPkT/d4tqdf1cKtesryHm2bgp6l555NYcT2NLvA=="], + + "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.57.0", "", { "dependencies": { "@typescript-eslint/types": "8.57.0", "@typescript-eslint/typescript-estree": "8.57.0", "@typescript-eslint/utils": "8.57.0", "debug": "^4.4.3", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-yjgh7gmDcJ1+TcEg8x3uWQmn8ifvSupnPfjP21twPKrDP/pTHlEQgmKcitzF/rzPSmv7QjJ90vRpN4U+zoUjwQ=="], + + "@typescript-eslint/types": ["@typescript-eslint/types@8.57.0", "", {}, "sha512-dTLI8PEXhjUC7B9Kre+u0XznO696BhXcTlOn0/6kf1fHaQW8+VjJAVHJ3eTI14ZapTxdkOmc80HblPQLaEeJdg=="], + + "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.57.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.57.0", "@typescript-eslint/tsconfig-utils": "8.57.0", "@typescript-eslint/types": "8.57.0", "@typescript-eslint/visitor-keys": "8.57.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-m7faHcyVg0BT3VdYTlX8GdJEM7COexXxS6KqGopxdtkQRvBanK377QDHr4W/vIPAR+ah9+B/RclSW5ldVniO1Q=="], + + "@typescript-eslint/utils": ["@typescript-eslint/utils@8.56.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.56.0", "@typescript-eslint/types": "8.56.0", "@typescript-eslint/typescript-estree": "8.56.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-RZ3Qsmi2nFGsS+n+kjLAYDPVlrzf7UhTffrDIKr+h2yzAlYP/y5ZulU0yeDEPItos2Ph46JAL5P/On3pe7kDIQ=="], + + "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.57.0", "", { "dependencies": { "@typescript-eslint/types": "8.57.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-zm6xx8UT/Xy2oSr2ZXD0pZo7Jx2XsCoID2IUh9YSTFRu7z+WdwYTRk6LhUftm1crwqbuoF6I8zAFeCMw0YjwDg=="], + + "@zag-js/accordion": ["@zag-js/accordion@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-wmw6yo5Zr6ShiKGTc5ICEOJCurWAOSGubIpGISiHi3cZ4tlxKF/vpATIUT3eq8xzdB56YK57yKCujs/WmwqqoA=="], + + "@zag-js/anatomy": ["@zag-js/anatomy@1.35.3", "", {}, "sha512-oqU9iLNNylrtJMBX5Xu4DsxnPNvtZLiobryv2oNtsDI1mi1Fca/XHghQC9K5aYT0qNsmHj1M3W5WAWTaOtPLkQ=="], + + "@zag-js/angle-slider": ["@zag-js/angle-slider@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/rect-utils": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-HXRlmsbNEJSBT53fq9XQKL/vwZWwJC3nprskI7s4f/jy8a4uXPTlv7N7zuBYjew+ScTMzZah6fLWzUztBehmSg=="], + + "@zag-js/aria-hidden": ["@zag-js/aria-hidden@1.35.3", "", { "dependencies": { "@zag-js/dom-query": "1.35.3" } }, "sha512-dk5POebn10WneQfLrEgbTzwolaXWpCSHL6F3jCTinW9IbOx7BXghzJD21iU5Iun+y9CorqJPW3p7LplYNUMO5Q=="], + + "@zag-js/async-list": ["@zag-js/async-list@1.35.3", "", { "dependencies": { "@zag-js/core": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-SXX3wGzLK/maKS1PJ3XfLIGWbu0022f/OhcFsT1PbiHnoFZTH7h2fBhirrCBfy2TYFQ6r5uxgjkhPUNkuaeYnA=="], + + "@zag-js/auto-resize": ["@zag-js/auto-resize@1.35.3", "", { "dependencies": { "@zag-js/dom-query": "1.35.3" } }, "sha512-ufG8HSqzLd9h5rnos8aumj8iORlRskeR/gbpJu1NHrnHBWIrpuXm6KJJR2oZhTFY1BUMMk8eYIBA2QkVuiJzWA=="], + + "@zag-js/avatar": ["@zag-js/avatar@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-lbQ2Q4Va8AAScKULOHw2tCQez+0JRYGHSMFq6i+dJmeT3dlSgRanm69ra6K2po6hM9E4v6pRe+xOVE+9QMDnuA=="], + + "@zag-js/carousel": ["@zag-js/carousel@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/scroll-snap": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-F+b8HzUeZfB+xUkAkLG4r0Ubui8pj7pSgZhi26ZiWgsM7tsd7cD+xRMXkvPEITN5Fd5QCe3KlVBuE00w5byjmg=="], + + "@zag-js/cascade-select": ["@zag-js/cascade-select@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/collection": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dismissable": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/focus-visible": "1.35.3", "@zag-js/popper": "1.35.3", "@zag-js/rect-utils": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-Nifdx77hEuAdXqr1wpZSPjLXqygRhq/WvnPjGhCeSqFPpy62uT4JZ3avyjUZ4I0UhvIpkleUcXtFwQ3cSMh4ww=="], + + "@zag-js/checkbox": ["@zag-js/checkbox@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/focus-visible": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-8XBt/Wg2zSQWqV2ZFqZBQUjYRkOYHA2O3IEi0VVYtds3S1n7Pu/HqkZT5qDw+E/SY2+X9Uyx4hO7h2XrlsiZQQ=="], + + "@zag-js/clipboard": ["@zag-js/clipboard@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-obTwynBpp6c17fLHe5tg//FQ497QsyCEry+K3bTdlrivWW200wvfHxZ6RKVbKwDAwhH+ye0bI1xkYAId8j7sdA=="], + + "@zag-js/collapsible": ["@zag-js/collapsible@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-IweG8JOBCerJwLO6QzTZGEMlsYUmQfQSeD0jniFguMM8vcunvGVSrM+AaL8pDbmXd+snXokaGyJpGO3vzMW6Fw=="], + + "@zag-js/collection": ["@zag-js/collection@1.35.3", "", { "dependencies": { "@zag-js/utils": "1.35.3" } }, "sha512-BYoWJ4b7ma2PgiuQbRSnP603f2DlK6se5JtViUHTamZScLLLWnWHuQ6zFa1KS5kiIkbb7CFM6/bJ3WNYLch8Ig=="], + + "@zag-js/color-picker": ["@zag-js/color-picker@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/color-utils": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dismissable": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/popper": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-i9roSgtqeA1b4Q+jWqnxjXB//BQXMP5m1FQ4YcZVq/0yT14A53JIknchuqrh3wC3yPsJMXFqCoKg+NET2+OVig=="], + + "@zag-js/color-utils": ["@zag-js/color-utils@1.35.3", "", { "dependencies": { "@zag-js/utils": "1.35.3" } }, "sha512-vxkEVgz4YdSbdaPvjiRI1VsJAdwzu/dUNvzqOaiVcPDrHr/FFgmUbv0SOFjnfSb2QWGI8EDEMn02RW9ym+BzGw=="], + + "@zag-js/combobox": ["@zag-js/combobox@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/aria-hidden": "1.35.3", "@zag-js/collection": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dismissable": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/focus-visible": "1.35.3", "@zag-js/popper": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-s1qmttTGJTMjlDakL+uvWSEggpafKr1vhOeZCh8j+N4eFt9bLAwaffjuh/1JzWBvzovw7WoMVkizdTXPlN8oYg=="], + + "@zag-js/core": ["@zag-js/core@1.35.3", "", { "dependencies": { "@zag-js/dom-query": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-fGAHyqOYSEFmo52t7wI4dvbFfLyJmUlyf7wknsiUlzUHlrn3yv5PAZYZ2TibpOD1hwXIp4AoCjbiIPPZBxirZw=="], + + "@zag-js/date-picker": ["@zag-js/date-picker@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/date-utils": "1.35.3", "@zag-js/dismissable": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/live-region": "1.35.3", "@zag-js/popper": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" }, "peerDependencies": { "@internationalized/date": ">=3.0.0" } }, "sha512-4G10h6pzzLbd84SE2CKtqi6Z9wEBhSyx4GRSxxy3tsf5wAxnz4anRFat9CGwn2YVUYcUJpD+umYgBMPt6zGDnA=="], + + "@zag-js/date-utils": ["@zag-js/date-utils@1.35.3", "", { "peerDependencies": { "@internationalized/date": ">=3.0.0" } }, "sha512-1co0FPpZ6nO5dN8sZtECkMYaf+3E5zu0KSIJZpZiXb4TgsZMDyHu7K7IsiKFHk9qmhuF6AdPpNxBju91pSXMFg=="], + + "@zag-js/dialog": ["@zag-js/dialog@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/aria-hidden": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dismissable": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/focus-trap": "1.35.3", "@zag-js/remove-scroll": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-byosV+aBHH5LoFKnjEgC7WdqJid7bP9UhgWLSC7+IXbxrif9Czg1YVp6ZlQM6Nx6uD1vnty4touI3P7D7CTKcw=="], + + "@zag-js/dismissable": ["@zag-js/dismissable@1.35.3", "", { "dependencies": { "@zag-js/dom-query": "1.35.3", "@zag-js/interact-outside": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-XPk+lqmsZp2Z1yMb5K1yj/e7Sobv4D7zK66B1GS97lk9Xzz8vuSgsimcLy0p7RXQl3KL6H5L69inSuQa2exybQ=="], + + "@zag-js/dom-query": ["@zag-js/dom-query@1.35.3", "", { "dependencies": { "@zag-js/types": "1.35.3" } }, "sha512-1RbFZoT4CjlHN9TUNse1++ZVOyKo45ktucTIT349o6HMsoWWKmTJDPvFkMBbmu/qY6XXn4dT+LJEp4bL3DR+Qw=="], + + "@zag-js/drawer": ["@zag-js/drawer@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/aria-hidden": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dismissable": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/focus-trap": "1.35.3", "@zag-js/remove-scroll": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-DN5bwa7bDCDaUSbNzFxMc2U/WmbLcXvPSQjyOpKI6CC3VbW2kKaOnjJ5qQG+W5YBO0FpmJBtaxRV7lke4sZH2w=="], + + "@zag-js/editable": ["@zag-js/editable@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/interact-outside": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-HcjeacS61vQXfNT9IalZj/+oS45yW5bIDO2NjJWV7zNe5AG29NCceUnvBhy+hrUKPnKcjfDocdW5rCL+Lvs/CQ=="], + + "@zag-js/file-upload": ["@zag-js/file-upload@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/file-utils": "1.35.3", "@zag-js/i18n-utils": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-oIYwnDct4ERo2mfmcxsBIJnlmpzjrzYx82SQsXWD3NGKx3cgdh2lwBX+ebItaLH1jkgzBa3z0TWxc6rfvcUXbw=="], + + "@zag-js/file-utils": ["@zag-js/file-utils@1.35.3", "", { "dependencies": { "@zag-js/i18n-utils": "1.35.3" } }, "sha512-Tb05RCzx4swc156hd4jLiO7z+Gxg/HQ+JCds03jgTbrFJAz2D56YaMeI7gSDc1m4Xre3nyqQpSo9AeX5nzbE/w=="], + + "@zag-js/floating-panel": ["@zag-js/floating-panel@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/popper": "1.35.3", "@zag-js/rect-utils": "1.35.3", "@zag-js/store": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-nTZypcS0X46Oo1kpCQTnP5UlzjhypOAj3B4dq2z/3bAOC0TntYTnFkj8PbEJtExk7364xfMyxfgZOiv7Aqq01w=="], + + "@zag-js/focus-trap": ["@zag-js/focus-trap@1.35.3", "", { "dependencies": { "@zag-js/dom-query": "1.35.3" } }, "sha512-evErLlGFdDVCI8xipNS5k0rAvO+KFRA9g273bbfWAL1+mT54mcB/XHa85nC3QpPgMNrSh+6LUNq9fapyOGoyYg=="], + + "@zag-js/focus-visible": ["@zag-js/focus-visible@1.35.3", "", { "dependencies": { "@zag-js/dom-query": "1.35.3" } }, "sha512-g4F8PRGIoFoKBrHiQ1HQh5AjCS7brFRXHvpbDNb9+T11FGlF5Turb+6OVRoNV8MmiuqMltO2I28l36YsGc//uQ=="], + + "@zag-js/highlight-word": ["@zag-js/highlight-word@1.35.3", "", {}, "sha512-K+mvEBbf3SUFjQeMeJQYb3cjri3x6sPaPhcKWayalelSLB/StWEGqcpmz+a6uUYrCUAK5kEi3Hn0YLGfn0GOig=="], + + "@zag-js/hover-card": ["@zag-js/hover-card@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dismissable": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/popper": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-xVoKOtvrnzhYzciZ1csgiV76IQ4DRtx1lsJeFSrfg5MH0kYWeC/pcmm3yCd2+Qh/45J7DbSXeZneqxpyiF5Vvw=="], + + "@zag-js/i18n-utils": ["@zag-js/i18n-utils@1.35.3", "", { "dependencies": { "@zag-js/dom-query": "1.35.3" } }, "sha512-k7UcNxbnC2jvGwCoHYAkFD3ZaRSMQNVHfuy8TujZQ+ci3IJovwgWLveZoRfFbXHkTLfhmbpE2tFXBdpwOVZutg=="], + + "@zag-js/image-cropper": ["@zag-js/image-cropper@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-1PH6bg8JAQESHzNqjka2TJ0QGNBGBAO6rb7AZ+9CaCCLw0pIzbUJhqPMkwd9GhdWGKGP+e7wFitnjcT4W5Js8g=="], + + "@zag-js/interact-outside": ["@zag-js/interact-outside@1.35.3", "", { "dependencies": { "@zag-js/dom-query": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-tOcuo/IztzpU7UKXtjVrLZtXzzcbhP4n2WynKwDRkTkq3mRCp61xXJp1csIBycI3JHm/CMeAEcPdRIioxIT/Zw=="], + + "@zag-js/json-tree-utils": ["@zag-js/json-tree-utils@1.35.3", "", {}, "sha512-nOv2dPJf+1mxsobYiSlYt96hR1MK7iHKG1iDLoO5wLggS6GQA3ix1BerHJK0zdehoEZ71R45el5ghCG1HB9VzQ=="], + + "@zag-js/listbox": ["@zag-js/listbox@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/collection": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/focus-visible": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-FE6FOuBr6aWtOb8U8oDvAvcUzD6JKLXAe8WngiLFG+b2yyW4nlaz2AcKRG1bjjB066UMxMo9/+2p4D0Kf5Id1Q=="], + + "@zag-js/live-region": ["@zag-js/live-region@1.35.3", "", {}, "sha512-64rWcfggYpyr2Fn4pdrB/lljMgm3quwn9is+vdDN85Vv3WShKWoz08T4njidm0hwcIbzas0bRqQYWDLLsAoSJQ=="], + + "@zag-js/marquee": ["@zag-js/marquee@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-bKZVpmAJWPDORP7WOWnS+65W5ZQBQmRs8zvV33ZfCpFbkXjhRiqKSzIj223/VOc2NEDjyWagz2vioAxrFYVzww=="], + + "@zag-js/menu": ["@zag-js/menu@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dismissable": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/focus-visible": "1.35.3", "@zag-js/popper": "1.35.3", "@zag-js/rect-utils": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-KyY0EZXkIU57Mjt+Lg+pupiePk3LcnQcB3Gl05Vva61bNjBjdKV71qwCQru/OxPZEwYgPo46L7TDIb56kfK/VQ=="], + + "@zag-js/navigation-menu": ["@zag-js/navigation-menu@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dismissable": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-8cCHx0X/KjEpr2BaMOxJS5LiA6fs/CNqVTF/sTTgZAv7Dm+MH0yNuKm4kpPvcLaVeBpVE09bnyCHrNKzZes+Fw=="], + + "@zag-js/number-input": ["@zag-js/number-input@1.35.3", "", { "dependencies": { "@internationalized/number": "3.6.5", "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-uqawVybAcLcefVEHMVONuAA5kDSDPP5TsROr5PnAyFlhM1iD85+r3KAfCueoDX5w2X4ibbu9o2tdV6zTFKD/nQ=="], + + "@zag-js/pagination": ["@zag-js/pagination@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-fKm4s5KAd12RiCI/EDmmGKjPQ+i2qS/UsJPdMe65yb/4mY5OibwV2zyHcVeFsOD4gBZpnU6kYlDAGSttmLWLlQ=="], + + "@zag-js/password-input": ["@zag-js/password-input@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-etd0gm6ELAm3y+cFhPU+TYm8khm9cL5Mg5m2DcZxu1Mqpj7JY0LsXZ8SFOdCZgTIHuMEhKBiYfnuyMAd4CJztA=="], + + "@zag-js/pin-input": ["@zag-js/pin-input@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-ZFt+WIHMdVlSg29BrQLFq5ijabiUO3tXMhoKhjjzTSe/tLqfNeu3UxFB6y/FYpn8+Cvn6xwvhu3lgnORYmI0zQ=="], + + "@zag-js/popover": ["@zag-js/popover@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/aria-hidden": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dismissable": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/focus-trap": "1.35.3", "@zag-js/popper": "1.35.3", "@zag-js/remove-scroll": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-+MIEENPsbKPxzoNuDI/C5d5ZN9uxnfZ+MBDc5C5XSgjjg9FcvMXClNq7IFM1aZi24peRXg9cMNf//lApVRT37w=="], + + "@zag-js/popper": ["@zag-js/popper@1.35.3", "", { "dependencies": { "@floating-ui/dom": "^1.7.5", "@zag-js/dom-query": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-gpB7Xn9WtlfrUsIVbSgNQGDwgNOL/cSGt0Id3wEQKArmqVC704EWtPvXzOMMybBEdm8YW2hQrXuo+o66abI1Sg=="], + + "@zag-js/presence": ["@zag-js/presence@1.35.3", "", { "dependencies": { "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/types": "1.35.3" } }, "sha512-ev5E7+U9IZAGvEaflpdVLHaZl8ZaQMhGB3ypd0yKhPwXeM51obV8w3+5HjzTqHPl8TKuoHWL31YaiUBd5EuS6w=="], + + "@zag-js/progress": ["@zag-js/progress@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-u0GxQN1AfXMAgzYOUMxKQA12DyuAP0svh2S//KvOorTSv7d5hAa8nZXi2cEv5abYsyfKJ6/bc1Z56byzW1jVZw=="], + + "@zag-js/qr-code": ["@zag-js/qr-code@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3", "proxy-memoize": "3.0.1", "uqr": "0.1.2" } }, "sha512-t0Ehwogr49vTNtWyNdQU2tYex7uJyfAn7N/5LgD7FXw8aa+RBMWZWlqjCUvHqJ929tVMrn+LIrQnZCcwNunalA=="], + + "@zag-js/radio-group": ["@zag-js/radio-group@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/focus-visible": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-kOzocjqWk3dXuRfyfsHwfw63Z99NHbc7rvVUutSsfXANXi+DFYZHuqdPUwMt+29LfaL15XTOfuGV+yUXDCgQHQ=="], + + "@zag-js/rating-group": ["@zag-js/rating-group@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-BmhJZdbaTnd3nFWMY+nR+HF952UhWXfaXXxiBWptSLMBfAYImQTWBMrLgTHCSnVfmFATj4Gb7xQe79FQU8T5fA=="], + + "@zag-js/rect-utils": ["@zag-js/rect-utils@1.35.3", "", {}, "sha512-mt/oD3RXdyaX6ZPSd8BO13vvPBJ7QpVWieubE3O0WM3OPhU7ykDMRp/tR7cYMQrzUm04GlY9pbkmSSw2uABxlA=="], + + "@zag-js/remove-scroll": ["@zag-js/remove-scroll@1.35.3", "", { "dependencies": { "@zag-js/dom-query": "1.35.3" } }, "sha512-e59z9SbEpPiw0qwNQa2cB5/h30ZCLREaHsCw1TKTANFhwg7v85k9Lq1H/G/49li1CAjmiaOU9BNGlDvbzpNETQ=="], + + "@zag-js/scroll-area": ["@zag-js/scroll-area@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-IQwdUws/AckRIHK1z/wHdHurnOeGd8h8Dmspfh3VT7NkwTnxeJ4SW9di9smuD+d25eXkJRuX5zGEDHAyx2IaPQ=="], + + "@zag-js/scroll-snap": ["@zag-js/scroll-snap@1.35.3", "", { "dependencies": { "@zag-js/dom-query": "1.35.3" } }, "sha512-NVa2yRm2DQnF6hTV9k7Xz7l8YCZBagZTiqSwNvWKUulKD1csjt2fpBxvUt2cK+1iQnLOey2ydhs7MMsAnXPbJA=="], + + "@zag-js/select": ["@zag-js/select@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/collection": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dismissable": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/focus-visible": "1.35.3", "@zag-js/popper": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-ztszGHWvlbBDE0YT5LYPH+sMd6VH1ct5pH/M9VSzIUO6C5PARkW0NwSVQ1rCQJMj4sfvSE1gC1/r7urRzqEcUQ=="], + + "@zag-js/signature-pad": ["@zag-js/signature-pad@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3", "perfect-freehand": "^1.2.3" } }, "sha512-jvtxxzAQ8fre11zWUh6HflG4Ycr5z83Wba4pONRJbUE/vNgkJQ7yJgfyUl1QTlkn8Arfg2Zwoxu9GIq80HLZWg=="], + + "@zag-js/slider": ["@zag-js/slider@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-Th142JO4Fqla5AWhGrTW6CQicwvTw87PdVpur/WotQ7brlZIww5HipzEMh5eQJSWfwpKD4PI2bYK9V/ZE/mpXA=="], + + "@zag-js/solid": ["@zag-js/solid@1.35.3", "", { "dependencies": { "@solid-primitives/keyed": "^1.5.3", "@zag-js/core": "1.35.3", "@zag-js/store": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" }, "peerDependencies": { "solid-js": ">=1.1.3" } }, "sha512-Gp6jFWwLeToD+Y0lcEwi15XIHSmJbyPhl/klxKQWWpr7+p3OAoNWwOQbxkhRU7M9hhJrYYsENfSETwG9QhMfBQ=="], + + "@zag-js/splitter": ["@zag-js/splitter@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-IsIbRwzjr5amGANEDsZDSToaSn8wHUWvS2l0XHmf3BiiguVApaZgQTlfqthVQC9hBHMOaGIXIW1CFUOrQYkvUQ=="], + + "@zag-js/steps": ["@zag-js/steps@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-TYIrqV+v9/ULhvrTRBtQFFvJQPPTWOmjFXxlIxDwozek5R4dCIyeUYt1/ChJEc2mNETocbfDVSTxRO1dwCFpwQ=="], + + "@zag-js/store": ["@zag-js/store@1.35.3", "", { "dependencies": { "proxy-compare": "3.0.1" } }, "sha512-7kEV4T/20DU36UIfVMzuDlLhWSSEy/vabmpiB700tcdD9BBBODTiSg3ZeljW17dQbvE545vZOFEjVf/cQ5LVGA=="], + + "@zag-js/switch": ["@zag-js/switch@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/focus-visible": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-EP/2cJ46sd+6C5x5+89jn/9NOpM05CRESYB4RMhOnTe/WFtcS4IpiYtVHFhikdXkvJoibm67O2EHep2Pm/Xj4w=="], + + "@zag-js/tabs": ["@zag-js/tabs@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-lZKlDmxE25miCikj9QZCCnL02SVV2K14KZy5bn7+XDgrWlfSNTpNTj8r5E3zGlSgio5pkTGou57ASqS7WaPDWg=="], + + "@zag-js/tags-input": ["@zag-js/tags-input@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/auto-resize": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/interact-outside": "1.35.3", "@zag-js/live-region": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-HqyoQ3DZFhByOGnDShFfxi6u0bIf7aSVTlwmAvcL+b2ZhyU6/wIMGc4WJE7BMx1NYWM/jNLHedvGExAI8R0kXQ=="], + + "@zag-js/timer": ["@zag-js/timer@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-edmgitbRgsq+msxvVB4wc17Q5d5k63zMWaLJnWjUdDGAgEtM6/HNxwGb3riv46S2U3RgYxaaHTNZ/M7EE5mvYw=="], + + "@zag-js/toast": ["@zag-js/toast@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dismissable": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-whlR791GHdnMD21nNPsl2Dbql8+qu1wBZl75QzwYrjR8FlKjp8bhr3gXKzQEddcBXe9GPEFGvUs4iCyXsuTbpg=="], + + "@zag-js/toggle": ["@zag-js/toggle@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-aFfHKuR4sKzglhkmWLA+0RTNPs9dfeqwtc96qljawGYfAYWJXkEPYK9dFfVa+arZ7L84xBi24QSLiTg7LGSFLw=="], + + "@zag-js/toggle-group": ["@zag-js/toggle-group@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-Gn6JHzkQ4tlttjZcE0ZjIdxYkFeVp9VHrcMVizjJTkGZRmQ+kPZ5G/wOsZhIrvLX3Dw6Y0NkuBcP+jDHz/o3TA=="], + + "@zag-js/tooltip": ["@zag-js/tooltip@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/focus-visible": "1.35.3", "@zag-js/popper": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-/pImDGYl79MfLdvEphj3rSvNdj2tLW4GwGEncgdLM/GKwQiEUjfi/9EJOfLYP23M4lOOnoW7orehJ9xeaXOAkA=="], + + "@zag-js/tour": ["@zag-js/tour@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dismissable": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/focus-trap": "1.35.3", "@zag-js/interact-outside": "1.35.3", "@zag-js/popper": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-DI2aCXmZaE9KcPZDs9itc2BO7ixLApJ/yVRfM69pXwVOrucdSeDDNPFkfbhj5XwB+9VjjZEkqWFHKntRIyPl5g=="], + + "@zag-js/tree-view": ["@zag-js/tree-view@1.35.3", "", { "dependencies": { "@zag-js/anatomy": "1.35.3", "@zag-js/collection": "1.35.3", "@zag-js/core": "1.35.3", "@zag-js/dom-query": "1.35.3", "@zag-js/types": "1.35.3", "@zag-js/utils": "1.35.3" } }, "sha512-DbHaLxSNa1goE3o3IsXxEdzp8P5dvmkk1rVWgNUUIhpA+44idEjSSNXJkHPl18Mk5blqSMVjK1EX91oqai01Vw=="], + + "@zag-js/types": ["@zag-js/types@1.35.3", "", { "dependencies": { "csstype": "3.2.3" } }, "sha512-Fnm3AMs1lfb55hlkip/eJeWHOjFB3gSi1JkZlkkdltG2l7y/zsHkumPSe6jIKy+DRRIFKRCyXVTatbPN27bO3w=="], + + "@zag-js/utils": ["@zag-js/utils@1.35.3", "", {}, "sha512-LHcC+9y6TFhDsIz9I3koYxONl2JFfx5yQDzc6ZEQO2cqzXedRcN0R9IPqNGCX7JuhGt14ctDkVCm1JWGP2J6Wg=="], + + "acorn": ["acorn@8.16.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], + + "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], + + "ajv": ["ajv@6.14.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw=="], + + "babel-plugin-jsx-dom-expressions": ["babel-plugin-jsx-dom-expressions@0.40.5", "", { "dependencies": { "@babel/helper-module-imports": "7.18.6", "@babel/plugin-syntax-jsx": "^7.18.6", "@babel/types": "^7.20.7", "html-entities": "2.3.3", "parse5": "^7.1.2" }, "peerDependencies": { "@babel/core": "^7.20.12" } }, "sha512-8TFKemVLDYezqqv4mWz+PhRrkryTzivTGu0twyLrOkVZ0P63COx2Y04eVsUjFlwSOXui1z3P3Pn209dokWnirg=="], + + "babel-preset-solid": ["babel-preset-solid@1.9.10", "", { "dependencies": { "babel-plugin-jsx-dom-expressions": "^0.40.3" }, "peerDependencies": { "@babel/core": "^7.0.0", "solid-js": "^1.9.10" }, "optionalPeers": ["solid-js"] }, "sha512-HCelrgua/Y+kqO8RyL04JBWS/cVdrtUv/h45GntgQY+cJl4eBcKkCDV3TdMjtKx1nXwRaR9QXslM/Npm1dxdZQ=="], + + "balanced-match": ["balanced-match@4.0.3", "", {}, "sha512-1pHv8LX9CpKut1Zp4EXey7Z8OfH11ONNH6Dhi2WDUt31VVZFXZzKwXcysBgqSumFCmR+0dqjMK5v5JiFHzi0+g=="], + + "baseline-browser-mapping": ["baseline-browser-mapping@2.10.0", "", { "bin": { "baseline-browser-mapping": "dist/cli.cjs" } }, "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA=="], + + "brace-expansion": ["brace-expansion@5.0.2", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-Pdk8c9poy+YhOgVWw1JNN22/HcivgKWwpxKq04M/jTmHyCZn12WPJebZxdjSa5TmBqISrUSgNYU3eRORljfCCw=="], + + "browserslist": ["browserslist@4.28.1", "", { "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", "electron-to-chromium": "^1.5.263", "node-releases": "^2.0.27", "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" } }, "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA=="], + + "bun-types": ["bun-types@1.3.10", "", { "dependencies": { "@types/node": "*" } }, "sha512-tcpfCCl6XWo6nCVnpcVrxQ+9AYN1iqMIzgrSKYMB/fjLtV2eyAVEg7AxQJuCq/26R6HpKWykQXuSOq/21RYcbg=="], + + "caniuse-lite": ["caniuse-lite@1.0.30001770", "", {}, "sha512-x/2CLQ1jHENRbHg5PSId2sXq1CIO1CISvwWAj027ltMVG2UNgW+w9oH2+HzgEIRFembL8bUlXtfbBHR1fCg2xw=="], + + "class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="], + + "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], + + "cmdk-solid": ["cmdk-solid@1.1.2", "", { "dependencies": { "@kobalte/core": "^0.12.4", "@kobalte/utils": "^0.9.0", "@solid-primitives/deep": "^0.2.7", "@solid-primitives/mutation-observer": "^1.1.17" }, "peerDependencies": { "solid-js": "^1.8.0" } }, "sha512-E0g6bwr2Z92Ib1K2WHwGsq6xsrkVVSN1oe5YTg8LCV3iIwtyZORwmR+8n0xrecqycdhgAar8vWUjtB1OJt9tiA=="], + + "comlink": ["comlink@4.4.2", "", {}, "sha512-OxGdvBmJuNKSCMO4NTl1L47VRp6xn2wG4F/2hYzB6tiCb709otOxtEYCSvK80PtjODfXXZu8ds+Nw5kVCjqd2g=="], + + "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], + + "crelt": ["crelt@1.0.6", "", {}, "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g=="], + + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + + "cross-spawn-windows-exe": ["cross-spawn-windows-exe@1.2.0", "", { "dependencies": { "@malept/cross-spawn-promise": "^1.1.0", "is-wsl": "^2.2.0", "which": "^2.0.2" } }, "sha512-mkLtJJcYbDCxEG7Js6eUnUNndWjyUZwJ3H7bErmmtOYU/Zb99DyUkpamuIZE0b3bhmJyZ7D90uS6f+CGxRRjOw=="], + + "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], + + "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + + "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], + + "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], + + "electrobun": ["electrobun@1.15.1", "", { "dependencies": { "@babylonjs/core": "^7.45.0", "@types/bun": "^1.3.8", "png-to-ico": "^2.1.8", "rcedit": "^4.0.1", "three": "^0.165.0" }, "bin": { "electrobun": "bin/electrobun.cjs" } }, "sha512-FJ7XaTzbCPuH2ABK615WJyrfacoMdYR33tHJ0j/2JIw2srK4lHN9iSjPpvRVL1UveIQB7zRQ2pmVjeI4evwJ+g=="], + + "electrobun-hello-world": ["electrobun-hello-world@workspace:packages/desktop"], + + "electron-to-chromium": ["electron-to-chromium@1.5.286", "", {}, "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A=="], + + "embla-carousel": ["embla-carousel@8.6.0", "", {}, "sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA=="], + + "embla-carousel-reactive-utils": ["embla-carousel-reactive-utils@8.6.0", "", { "peerDependencies": { "embla-carousel": "8.6.0" } }, "sha512-fMVUDUEx0/uIEDM0Mz3dHznDhfX+znCCDCeIophYb1QGVM7YThSWX+wz11zlYwWFOr74b4QLGg0hrGPJeG2s4A=="], + + "embla-carousel-solid": ["embla-carousel-solid@8.6.0", "", { "dependencies": { "embla-carousel": "8.6.0", "embla-carousel-reactive-utils": "8.6.0" }, "peerDependencies": { "solid-js": "^1.0.0" } }, "sha512-xQQjPZL+CQ4n2KemoeTu0BD9mk8tkVuSMOe/GEnzKM0lAoXY/akSYBNZ4dvJDE7TMeUCAuI6D9742TTLglGq/A=="], + + "enhanced-resolve": ["enhanced-resolve@5.19.0", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.0" } }, "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg=="], + + "entities": ["entities@6.0.1", "", {}, "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g=="], + + "esbuild": ["esbuild@0.27.3", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.3", "@esbuild/android-arm": "0.27.3", "@esbuild/android-arm64": "0.27.3", "@esbuild/android-x64": "0.27.3", "@esbuild/darwin-arm64": "0.27.3", "@esbuild/darwin-x64": "0.27.3", "@esbuild/freebsd-arm64": "0.27.3", "@esbuild/freebsd-x64": "0.27.3", "@esbuild/linux-arm": "0.27.3", "@esbuild/linux-arm64": "0.27.3", "@esbuild/linux-ia32": "0.27.3", "@esbuild/linux-loong64": "0.27.3", "@esbuild/linux-mips64el": "0.27.3", "@esbuild/linux-ppc64": "0.27.3", "@esbuild/linux-riscv64": "0.27.3", "@esbuild/linux-s390x": "0.27.3", "@esbuild/linux-x64": "0.27.3", "@esbuild/netbsd-arm64": "0.27.3", "@esbuild/netbsd-x64": "0.27.3", "@esbuild/openbsd-arm64": "0.27.3", "@esbuild/openbsd-x64": "0.27.3", "@esbuild/openharmony-arm64": "0.27.3", "@esbuild/sunos-x64": "0.27.3", "@esbuild/win32-arm64": "0.27.3", "@esbuild/win32-ia32": "0.27.3", "@esbuild/win32-x64": "0.27.3" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg=="], + + "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], + + "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], + + "eslint": ["eslint@10.0.3", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.2", "@eslint/config-array": "^0.23.3", "@eslint/config-helpers": "^0.5.2", "@eslint/core": "^1.1.1", "@eslint/plugin-kit": "^0.6.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^9.1.2", "eslint-visitor-keys": "^5.0.1", "espree": "^11.1.1", "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "minimatch": "^10.2.4", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-COV33RzXZkqhG9P2rZCFl9ZmJ7WL+gQSCRzE7RhkbclbQPtLAWReL7ysA0Sh4c8Im2U9ynybdR56PV0XcKvqaQ=="], + + "eslint-plugin-solid": ["eslint-plugin-solid@0.14.5", "", { "dependencies": { "@typescript-eslint/utils": "^7.13.1 || ^8.0.0", "estraverse": "^5.3.0", "is-html": "^2.0.0", "kebab-case": "^1.0.2", "known-css-properties": "^0.30.0", "style-to-object": "^1.0.6" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", "typescript": ">=4.8.4" } }, "sha512-nfuYK09ah5aJG/oEN6P1qziy1zLgW4PDWe75VNPi4CEFYk1x2AEqwFeQfEPR7gNn0F2jOeqKhx2E+5oNCOBYWQ=="], + + "eslint-scope": ["eslint-scope@9.1.2", "", { "dependencies": { "@types/esrecurse": "^4.3.1", "@types/estree": "^1.0.8", "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ=="], + + "eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="], + + "espree": ["espree@11.2.0", "", { "dependencies": { "acorn": "^8.16.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^5.0.1" } }, "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw=="], + + "esquery": ["esquery@1.7.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g=="], + + "esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], + + "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], + + "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], + + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], + + "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], + + "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], + + "fdir": ["fdir@6.5.0", "", { "peerDependencies": { "picomatch": "^3 || ^4" }, "optionalPeers": ["picomatch"] }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], + + "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], + + "find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], + + "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], + + "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="], + + "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + + "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="], + + "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], + + "globals": ["globals@17.4.0", "", {}, "sha512-hjrNztw/VajQwOLsMNT1cbJiH2muO3OROCHnbehc8eY5JyD2gqz4AcMHPqgaOR59DjgUjYAYLeH699g/eWi2jw=="], + + "globrex": ["globrex@0.1.2", "", {}, "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg=="], + + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + + "html-entities": ["html-entities@2.3.3", "", {}, "sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA=="], + + "html-tags": ["html-tags@3.3.1", "", {}, "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ=="], + + "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], + + "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], + + "inline-style-parser": ["inline-style-parser@0.2.7", "", {}, "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA=="], + + "is-docker": ["is-docker@2.2.1", "", { "bin": { "is-docker": "cli.js" } }, "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ=="], + + "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + + "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + + "is-html": ["is-html@2.0.0", "", { "dependencies": { "html-tags": "^3.0.0" } }, "sha512-S+OpgB5i7wzIue/YSE5hg0e5ZYfG3hhpNh9KGl6ayJ38p7ED6wxQLd1TV91xHpcTvw90KMJ9EwN3F/iNflHBVg=="], + + "is-what": ["is-what@4.1.16", "", {}, "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A=="], + + "is-wsl": ["is-wsl@2.2.0", "", { "dependencies": { "is-docker": "^2.0.0" } }, "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww=="], + + "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + + "jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], + + "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], + + "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], + + "json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], + + "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], + + "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], + + "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], + + "kebab-case": ["kebab-case@1.0.2", "", {}, "sha512-7n6wXq4gNgBELfDCpzKc+mRrZFs7D+wgfF5WRFLNAr4DA/qtr9Js8uOAVAfHhuLMfAcQ0pRKqbpjx+TcJVdE1Q=="], + + "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], + + "known-css-properties": ["known-css-properties@0.30.0", "", {}, "sha512-VSWXYUnsPu9+WYKkfmJyLKtIvaRJi1kXUqVmBACORXZQxT5oZDsoZ2vQP+bQFDnWtpI/4eq3MLoRMjI2fnLzTQ=="], + + "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], + + "lightningcss": ["lightningcss@1.31.1", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.31.1", "lightningcss-darwin-arm64": "1.31.1", "lightningcss-darwin-x64": "1.31.1", "lightningcss-freebsd-x64": "1.31.1", "lightningcss-linux-arm-gnueabihf": "1.31.1", "lightningcss-linux-arm64-gnu": "1.31.1", "lightningcss-linux-arm64-musl": "1.31.1", "lightningcss-linux-x64-gnu": "1.31.1", "lightningcss-linux-x64-musl": "1.31.1", "lightningcss-win32-arm64-msvc": "1.31.1", "lightningcss-win32-x64-msvc": "1.31.1" } }, "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ=="], + + "lightningcss-android-arm64": ["lightningcss-android-arm64@1.31.1", "", { "os": "android", "cpu": "arm64" }, "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg=="], + + "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.31.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg=="], + + "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.31.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA=="], + + "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.31.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A=="], + + "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.31.1", "", { "os": "linux", "cpu": "arm" }, "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g=="], + + "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg=="], + + "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.31.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg=="], + + "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA=="], + + "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.31.1", "", { "os": "linux", "cpu": "x64" }, "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA=="], + + "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.31.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w=="], + + "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.31.1", "", { "os": "win32", "cpu": "x64" }, "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw=="], + + "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], + + "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], + + "lucide-solid": ["lucide-solid@0.564.0", "", { "peerDependencies": { "solid-js": "^1.4.7" } }, "sha512-gZdibdRlnooRdKek2zhNGnep/N5TSlOSMWgUXiVtglys728zLLRupyaI7IfZ3USS/p6MG5eu2RKM2CARRYiXVg=="], + + "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + + "merge-anything": ["merge-anything@5.1.7", "", { "dependencies": { "is-what": "^4.1.8" } }, "sha512-eRtbOb1N5iyH0tkQDAoQ4Ipsp/5qSR79Dzrz8hEPxRX10RWWR/iQXdoKmBSRCThY1Fh5EhISDtpSc93fpxUniQ=="], + + "minimatch": ["minimatch@10.2.4", "", { "dependencies": { "brace-expansion": "^5.0.2" } }, "sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg=="], + + "minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], + + "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], + + "node-releases": ["node-releases@2.0.27", "", {}, "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA=="], + + "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], + + "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], + + "p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], + + "parse5": ["parse5@7.3.0", "", { "dependencies": { "entities": "^6.0.0" } }, "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw=="], + + "path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], + + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + + "perfect-freehand": ["perfect-freehand@1.2.3", "", {}, "sha512-bHZSfqDHGNlPpgH2yxXgPHlQSPpEbo+qg7li0M78J9vNAi2yjwLeA4x79BEQhX44lEWpCLSFCeRZwpw0niiXPA=="], + + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], + + "png-to-ico": ["png-to-ico@2.1.8", "", { "dependencies": { "@types/node": "^17.0.36", "minimist": "^1.2.6", "pngjs": "^6.0.0" }, "bin": { "png-to-ico": "bin/cli.js" } }, "sha512-Nf+IIn/cZ/DIZVdGveJp86NG5uNib1ZXMiDd/8x32HCTeKSvgpyg6D/6tUBn1QO/zybzoMK0/mc3QRgAyXdv9w=="], + + "pngjs": ["pngjs@6.0.0", "", {}, "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg=="], + + "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], + + "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], + + "prettier": ["prettier@3.8.1", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg=="], + + "proxy-compare": ["proxy-compare@3.0.1", "", {}, "sha512-V9plBAt3qjMlS1+nC8771KNf6oJ12gExvaxnNzN/9yVRLdTv/lc+oJlnSzrdYDAvBfTStPCoiaCOTmTs0adv7Q=="], + + "proxy-memoize": ["proxy-memoize@3.0.1", "", { "dependencies": { "proxy-compare": "^3.0.0" } }, "sha512-VDdG/VYtOgdGkWJx7y0o7p+zArSf2383Isci8C+BP3YXgMYDoPd3cCBjw0JdWb6YBb9sFiOPbAADDVTPJnh+9g=="], + + "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], + + "rcedit": ["rcedit@4.0.1", "", { "dependencies": { "cross-spawn-windows-exe": "^1.1.0" } }, "sha512-bZdaQi34krFWhrDn+O53ccBDw0MkAT2Vhu75SqhtvhQu4OPyFM4RoVheyYiVQYdjhUi6EJMVWQ0tR6bCIYVkUg=="], + + "rollup": ["rollup@4.57.1", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.57.1", "@rollup/rollup-android-arm64": "4.57.1", "@rollup/rollup-darwin-arm64": "4.57.1", "@rollup/rollup-darwin-x64": "4.57.1", "@rollup/rollup-freebsd-arm64": "4.57.1", "@rollup/rollup-freebsd-x64": "4.57.1", "@rollup/rollup-linux-arm-gnueabihf": "4.57.1", "@rollup/rollup-linux-arm-musleabihf": "4.57.1", "@rollup/rollup-linux-arm64-gnu": "4.57.1", "@rollup/rollup-linux-arm64-musl": "4.57.1", "@rollup/rollup-linux-loong64-gnu": "4.57.1", "@rollup/rollup-linux-loong64-musl": "4.57.1", "@rollup/rollup-linux-ppc64-gnu": "4.57.1", "@rollup/rollup-linux-ppc64-musl": "4.57.1", "@rollup/rollup-linux-riscv64-gnu": "4.57.1", "@rollup/rollup-linux-riscv64-musl": "4.57.1", "@rollup/rollup-linux-s390x-gnu": "4.57.1", "@rollup/rollup-linux-x64-gnu": "4.57.1", "@rollup/rollup-linux-x64-musl": "4.57.1", "@rollup/rollup-openbsd-x64": "4.57.1", "@rollup/rollup-openharmony-arm64": "4.57.1", "@rollup/rollup-win32-arm64-msvc": "4.57.1", "@rollup/rollup-win32-ia32-msvc": "4.57.1", "@rollup/rollup-win32-x64-gnu": "4.57.1", "@rollup/rollup-win32-x64-msvc": "4.57.1", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-oQL6lgK3e2QZeQ7gcgIkS2YZPg5slw37hYufJ3edKlfQSGGm8ICoxswK15ntSzF/a8+h7ekRy7k7oWc3BQ7y8A=="], + + "semver": ["semver@7.7.4", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], + + "seroval": ["seroval@1.5.0", "", {}, "sha512-OE4cvmJ1uSPrKorFIH9/w/Qwuvi/IMcGbv5RKgcJ/zjA/IohDLU6SVaxFN9FwajbP7nsX0dQqMDes1whk3y+yw=="], + + "seroval-plugins": ["seroval-plugins@1.5.0", "", { "peerDependencies": { "seroval": "^1.0" } }, "sha512-EAHqADIQondwRZIdeW2I636zgsODzoBDwb3PT/+7TLDWyw1Dy/Xv7iGUIEXXav7usHDE9HVhOU61irI3EnyyHA=="], + + "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], + + "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], + + "solid-dismissible": ["solid-dismissible@0.1.1", "", { "dependencies": { "@corvu/utils": "~0.4.1" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-9kcKBJIMdS+586cA1g63HYWxKh3h89leeNHbPZ1csYjuni+NvPBtNr11l0iEX2AKKEt6FHk6qNhc/gjoYAW1pA=="], + + "solid-focus-trap": ["solid-focus-trap@0.1.9", "", { "dependencies": { "@corvu/utils": "~0.4.2" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-LTyNki6GUJPRLXV5uMWPkYClB07SUMubbr2EkAddiR0CJCF/I283txilMU9RURSr/P8EewMfXWu2o3aWrK7A5A=="], + + "solid-js": ["solid-js@1.9.11", "", { "dependencies": { "csstype": "^3.1.0", "seroval": "~1.5.0", "seroval-plugins": "~1.5.0" } }, "sha512-WEJtcc5mkh/BnHA6Yrg4whlF8g6QwpmXXRg4P2ztPmcKeHHlH4+djYecBLhSpecZY2RRECXYUwIc/C2r3yzQ4Q=="], + + "solid-presence": ["solid-presence@0.1.8", "", { "dependencies": { "@corvu/utils": "~0.4.0" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-pWGtXUFWYYUZNbg5YpG5vkQJyOtzn2KXhxYaMx/4I+lylTLYkITOLevaCwMRN+liCVk0pqB6EayLWojNqBFECA=="], + + "solid-prevent-scroll": ["solid-prevent-scroll@0.1.10", "", { "dependencies": { "@corvu/utils": "~0.4.1" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-KplGPX2GHiWJLZ6AXYRql4M127PdYzfwvLJJXMkO+CMb8Np4VxqDAg5S8jLdwlEuBis/ia9DKw2M8dFx5u8Mhw=="], + + "solid-refresh": ["solid-refresh@0.6.3", "", { "dependencies": { "@babel/generator": "^7.23.6", "@babel/helper-module-imports": "^7.22.15", "@babel/types": "^7.23.6" }, "peerDependencies": { "solid-js": "^1.3" } }, "sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA=="], + + "solid-sonner": ["solid-sonner@0.2.8", "", { "peerDependencies": { "solid-js": "^1.6.0" } }, "sha512-EQ2EIznvHHpAmkYh2CTu0AdCgmPJRJWLGFRWygE8j+vMEfvIV2wotHU5qgWzqzVTG1SODGsay2Lwq6ENWx/rPA=="], + + "solid-transition-size": ["solid-transition-size@0.1.4", "", { "dependencies": { "@corvu/utils": "~0.3.2" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-ocHVnbfy23CgfaH4cEUR/AFg0Y3CEL8Oh3n9Qv8OHFJgPh+zkmERKZQfi/xH5XvxDCizg8VjPrVUhiHB1Gza8g=="], + + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + + "style-mod": ["style-mod@4.1.3", "", {}, "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ=="], + + "style-to-object": ["style-to-object@1.0.14", "", { "dependencies": { "inline-style-parser": "0.2.7" } }, "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw=="], + + "tailwind-merge": ["tailwind-merge@3.5.0", "", {}, "sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A=="], + + "tailwind-scrollbar-hide": ["tailwind-scrollbar-hide@4.0.0", "", { "peerDependencies": { "tailwindcss": ">=3.0.0 || >= 4.0.0 || >= 4.0.0-beta.8 || >= 4.0.0-alpha.20" } }, "sha512-gobtvVcThB2Dxhy0EeYSS1RKQJ5baDFkamkhwBvzvevwX6L4XQfpZ3me9s25Ss1ecFVT5jPYJ50n+7xTBJG9WQ=="], + + "tailwindcss": ["tailwindcss@4.2.1", "", {}, "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw=="], + + "tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="], + + "three": ["three@0.165.0", "", {}, "sha512-cc96IlVYGydeceu0e5xq70H8/yoVT/tXBxV/W8A/U6uOq7DXc4/s1Mkmnu6SqoYGhSRWWYFOhVwvq6V0VtbplA=="], + + "tinyglobby": ["tinyglobby@0.2.15", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], + + "ts-api-utils": ["ts-api-utils@2.4.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA=="], + + "tsconfck": ["tsconfck@3.1.6", "", { "peerDependencies": { "typescript": "^5.0.0" }, "optionalPeers": ["typescript"], "bin": { "tsconfck": "bin/tsconfck.js" } }, "sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w=="], + + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "tw-animate-css": ["tw-animate-css@1.4.0", "", {}, "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ=="], + + "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], + + "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], + + "typescript-eslint": ["typescript-eslint@8.57.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.57.0", "@typescript-eslint/parser": "8.57.0", "@typescript-eslint/typescript-estree": "8.57.0", "@typescript-eslint/utils": "8.57.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-W8GcigEMEeB07xEZol8oJ26rigm3+bfPHxHvwbYUlu1fUDsGuQ7Hiskx5xGW/xM4USc9Ephe3jtv7ZYPQntHeA=="], + + "undici-types": ["undici-types@7.18.2", "", {}, "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w=="], + + "update-browserslist-db": ["update-browserslist-db@1.2.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="], + + "uqr": ["uqr@0.1.2", "", {}, "sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA=="], + + "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], + + "vite": ["vite@7.3.1", "", { "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.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" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA=="], + + "vite-plugin-lucide-preprocess": ["vite-plugin-lucide-preprocess@1.4.8", "", { "dependencies": { "magic-string": "^0.30.0" }, "peerDependencies": { "rolldown": ">=0.1", "rollup": ">=1", "vite": ">=2" }, "optionalPeers": ["rolldown", "rollup"] }, "sha512-wIQ1fchys+WD/brwNjJTpy+GoHysPRDI7PFl4Qb6WNleifeC0fHGISMoyXdCjlcbx9wMMWOCPsZOygtk09mMfw=="], + + "vite-plugin-solid": ["vite-plugin-solid@2.11.10", "", { "dependencies": { "@babel/core": "^7.23.3", "@types/babel__core": "^7.20.4", "babel-preset-solid": "^1.8.4", "merge-anything": "^5.1.7", "solid-refresh": "^0.6.3", "vitefu": "^1.0.4" }, "peerDependencies": { "@testing-library/jest-dom": "^5.16.6 || ^5.17.0 || ^6.*", "solid-js": "^1.7.2", "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" }, "optionalPeers": ["@testing-library/jest-dom"] }, "sha512-Yr1dQybmtDtDAHkii6hXuc1oVH9CPcS/Zb2jN/P36qqcrkNnVPsMTzQ06jyzFPFjj3U1IYKMVt/9ZqcwGCEbjw=="], + + "vite-tsconfig-paths": ["vite-tsconfig-paths@6.1.1", "", { "dependencies": { "debug": "^4.1.1", "globrex": "^0.1.2", "tsconfck": "^3.0.3" }, "peerDependencies": { "vite": "*" } }, "sha512-2cihq7zliibCCZ8P9cKJrQBkfgdvcFkOOc3Y02o3GWUDLgqjWsZudaoiuOwO/gzTzy17cS5F7ZPo4bsnS4DGkg=="], + + "vitefu": ["vitefu@1.1.1", "", { "peerDependencies": { "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" }, "optionalPeers": ["vite"] }, "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ=="], + + "w3c-keyname": ["w3c-keyname@2.2.8", "", {}, "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ=="], + + "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + + "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], + + "yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], + + "yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], + + "zod": ["zod@4.3.6", "", {}, "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg=="], + + "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "@codemirror/autocomplete/@codemirror/view": ["@codemirror/view@6.39.15", "", { "dependencies": { "@codemirror/state": "^6.5.0", "crelt": "^1.0.6", "style-mod": "^4.1.0", "w3c-keyname": "^2.2.4" } }, "sha512-aCWjgweIIXLBHh7bY6cACvXuyrZ0xGafjQ2VInjp4RM4gMfscK5uESiNdrH0pE+e1lZr2B4ONGsjchl2KsKZzg=="], + + "@codemirror/commands/@codemirror/view": ["@codemirror/view@6.39.15", "", { "dependencies": { "@codemirror/state": "^6.5.0", "crelt": "^1.0.6", "style-mod": "^4.1.0", "w3c-keyname": "^2.2.4" } }, "sha512-aCWjgweIIXLBHh7bY6cACvXuyrZ0xGafjQ2VInjp4RM4gMfscK5uESiNdrH0pE+e1lZr2B4ONGsjchl2KsKZzg=="], + + "@codemirror/lang-html/@codemirror/view": ["@codemirror/view@6.39.15", "", { "dependencies": { "@codemirror/state": "^6.5.0", "crelt": "^1.0.6", "style-mod": "^4.1.0", "w3c-keyname": "^2.2.4" } }, "sha512-aCWjgweIIXLBHh7bY6cACvXuyrZ0xGafjQ2VInjp4RM4gMfscK5uESiNdrH0pE+e1lZr2B4ONGsjchl2KsKZzg=="], + + "@codemirror/lang-javascript/@codemirror/view": ["@codemirror/view@6.39.15", "", { "dependencies": { "@codemirror/state": "^6.5.0", "crelt": "^1.0.6", "style-mod": "^4.1.0", "w3c-keyname": "^2.2.4" } }, "sha512-aCWjgweIIXLBHh7bY6cACvXuyrZ0xGafjQ2VInjp4RM4gMfscK5uESiNdrH0pE+e1lZr2B4ONGsjchl2KsKZzg=="], + + "@codemirror/lang-markdown/@codemirror/view": ["@codemirror/view@6.39.15", "", { "dependencies": { "@codemirror/state": "^6.5.0", "crelt": "^1.0.6", "style-mod": "^4.1.0", "w3c-keyname": "^2.2.4" } }, "sha512-aCWjgweIIXLBHh7bY6cACvXuyrZ0xGafjQ2VInjp4RM4gMfscK5uESiNdrH0pE+e1lZr2B4ONGsjchl2KsKZzg=="], + + "@codemirror/language/@codemirror/view": ["@codemirror/view@6.39.15", "", { "dependencies": { "@codemirror/state": "^6.5.0", "crelt": "^1.0.6", "style-mod": "^4.1.0", "w3c-keyname": "^2.2.4" } }, "sha512-aCWjgweIIXLBHh7bY6cACvXuyrZ0xGafjQ2VInjp4RM4gMfscK5uESiNdrH0pE+e1lZr2B4ONGsjchl2KsKZzg=="], + + "@codemirror/lint/@codemirror/view": ["@codemirror/view@6.39.15", "", { "dependencies": { "@codemirror/state": "^6.5.0", "crelt": "^1.0.6", "style-mod": "^4.1.0", "w3c-keyname": "^2.2.4" } }, "sha512-aCWjgweIIXLBHh7bY6cACvXuyrZ0xGafjQ2VInjp4RM4gMfscK5uESiNdrH0pE+e1lZr2B4ONGsjchl2KsKZzg=="], + + "@corvu/dialog/solid-presence": ["solid-presence@0.2.0", "", { "dependencies": { "@corvu/utils": "~0.4.2" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-YM92o+jvpzX3XGaD4rLYmq/Kc2ZVh47GSCLEufHBFQQIurvZTs8SoGJxO8BJGNDxBKdcS8F3dYhW1SDXp4BNjA=="], + + "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + + "@eslint/config-helpers/@eslint/core": ["@eslint/core@1.1.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-/nr9K9wkr3P1EzFTdFdMoLuo1PmIxjmwvPozwoSodjNBdefGujXQUF93u1DDZpEaTuDvMsIQddsd35BwtrW9Xw=="], + + "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.8.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg=="], + + "@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.8.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg=="], + + "@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="], + + "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.1", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" }, "bundled": true }, "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A=="], + + "@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], + + "@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "@typescript-eslint/eslint-plugin/@typescript-eslint/utils": ["@typescript-eslint/utils@8.57.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.57.0", "@typescript-eslint/types": "8.57.0", "@typescript-eslint/typescript-estree": "8.57.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-5iIHvpD3CZe06riAsbNxxreP+MuYgVUsV0n4bwLH//VJmgtt54sQeY2GszntJ4BjYCpMzrfVh2SBnUQTtys2lQ=="], + + "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], + + "@typescript-eslint/type-utils/@typescript-eslint/utils": ["@typescript-eslint/utils@8.57.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.57.0", "@typescript-eslint/types": "8.57.0", "@typescript-eslint/typescript-estree": "8.57.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-5iIHvpD3CZe06riAsbNxxreP+MuYgVUsV0n4bwLH//VJmgtt54sQeY2GszntJ4BjYCpMzrfVh2SBnUQTtys2lQ=="], + + "@typescript-eslint/utils/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.56.0", "", { "dependencies": { "@typescript-eslint/types": "8.56.0", "@typescript-eslint/visitor-keys": "8.56.0" } }, "sha512-7UiO/XwMHquH+ZzfVCfUNkIXlp/yQjjnlYUyYz7pfvlK3/EyyN6BK+emDmGNyQLBtLGaYrTAI6KOw8tFucWL2w=="], + + "@typescript-eslint/utils/@typescript-eslint/types": ["@typescript-eslint/types@8.56.0", "", {}, "sha512-DBsLPs3GsWhX5HylbP9HNG15U0bnwut55Lx12bHB9MpXxQ+R5GC8MwQe+N1UFXxAeQDvEsEDY6ZYwX03K7Z6HQ=="], + + "@typescript-eslint/utils/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.56.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.56.0", "@typescript-eslint/tsconfig-utils": "8.56.0", "@typescript-eslint/types": "8.56.0", "@typescript-eslint/visitor-keys": "8.56.0", "debug": "^4.4.3", "minimatch": "^9.0.5", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.4.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ex1nTUMWrseMltXUHmR2GAQ4d+WjkZCT4f+4bVsps8QEdh0vlBsaCokKTPlnqBFqqGaxilDNJG7b8dolW2m43Q=="], + + "babel-plugin-jsx-dom-expressions/@babel/helper-module-imports": ["@babel/helper-module-imports@7.18.6", "", { "dependencies": { "@babel/types": "^7.18.6" } }, "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA=="], + + "bun-types/@types/node": ["@types/node@25.3.0", "", { "dependencies": { "undici-types": "~7.18.0" } }, "sha512-4K3bqJpXpqfg2XKGK9bpDTc6xO/xoUP/RBWS7AtRMug6zZFaRekiLzjVtAoZMquxoAbzBvy5nxQ7veS5eYzf8A=="], + + "cmdk-solid/@kobalte/core": ["@kobalte/core@0.12.6", "", { "dependencies": { "@floating-ui/dom": "^1.5.1", "@internationalized/date": "^3.4.0", "@internationalized/number": "^3.2.1", "@kobalte/utils": "^0.9.0", "solid-prevent-scroll": "^0.1.4" }, "peerDependencies": { "solid-js": "^1.8.15" } }, "sha512-+Ta2o2wEqZ2fCqLMkvjT40VHNmcFKdGe8TNDVQbbMPk66qoU6g/DDRFR/Ib7eAjb+C95VoIyk6zaafos2VOo0w=="], + + "png-to-ico/@types/node": ["@types/node@17.0.45", "", {}, "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw=="], + + "solid-transition-size/@corvu/utils": ["@corvu/utils@0.3.2", "", { "dependencies": { "@floating-ui/dom": "^1.6.7" }, "peerDependencies": { "solid-js": "^1.8" } }, "sha512-ZWlyWEE8qV9+CB9OAyo2bTrZGXQN9ZeM+JfYv89zoR+lRACKTDuoOZEdiyL8Uc7U5dUSH1uTqKhTTnaHWb+wZA=="], + + "typescript-eslint/@typescript-eslint/utils": ["@typescript-eslint/utils@8.57.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.57.0", "@typescript-eslint/types": "8.57.0", "@typescript-eslint/typescript-estree": "8.57.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-5iIHvpD3CZe06riAsbNxxreP+MuYgVUsV0n4bwLH//VJmgtt54sQeY2GszntJ4BjYCpMzrfVh2SBnUQTtys2lQ=="], + + "@typescript-eslint/utils/@typescript-eslint/scope-manager/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.56.0", "", { "dependencies": { "@typescript-eslint/types": "8.56.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-q+SL+b+05Ud6LbEE35qe4A99P+htKTKVbyiNEe45eCbJFyh/HVK9QXwlrbz+Q4L8SOW4roxSVwXYj4DMBT7Ieg=="], + + "@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.56.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.56.0", "@typescript-eslint/types": "^8.56.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-M3rnyL1vIQOMeWxTWIW096/TtVP+8W3p/XnaFflhmcFp+U4zlxUxWj4XwNs6HbDeTtN4yun0GNTTDBw/SvufKg=="], + + "@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.56.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-bSJoIIt4o3lKXD3xmDh9chZcjCz5Lk8xS7Rxn+6l5/pKrDpkCwtQNQQwZ2qRPk7TkUYhrq3WPIHXOXlbXP0itg=="], + + "@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.56.0", "", { "dependencies": { "@typescript-eslint/types": "8.56.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-q+SL+b+05Ud6LbEE35qe4A99P+htKTKVbyiNEe45eCbJFyh/HVK9QXwlrbz+Q4L8SOW4roxSVwXYj4DMBT7Ieg=="], + + "@typescript-eslint/utils/@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "@typescript-eslint/utils/@typescript-eslint/scope-manager/@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@5.0.0", "", {}, "sha512-A0XeIi7CXU7nPlfHS9loMYEKxUaONu/hTEzHTGba9Huu94Cq1hPivf+DE5erJozZOky0LfvXAyrV/tcswpLI0Q=="], + + "@typescript-eslint/utils/@typescript-eslint/typescript-estree/@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@5.0.0", "", {}, "sha512-A0XeIi7CXU7nPlfHS9loMYEKxUaONu/hTEzHTGba9Huu94Cq1hPivf+DE5erJozZOky0LfvXAyrV/tcswpLI0Q=="], + + "@typescript-eslint/utils/@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + + "@typescript-eslint/utils/@typescript-eslint/typescript-estree/minimatch/brace-expansion/balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + } +} diff --git a/eslint.config.ts b/eslint.config.ts new file mode 100644 index 0000000..fe986f5 --- /dev/null +++ b/eslint.config.ts @@ -0,0 +1,24 @@ +import js from "@eslint/js"; +import globals from "globals"; +import tseslint from "typescript-eslint"; +import solid from "eslint-plugin-solid/configs/typescript"; +import * as tsParser from "@typescript-eslint/parser"; + +export default [ + { + ignores: ["**/dist/**", "**/node_modules/**", "**/.tmp/**"], + }, + js.configs.recommended, + ...tseslint.configs.recommended, + { + files: ["**/*.{ts,tsx}"], + ...solid, + languageOptions: { + parser: tsParser, + globals: { + ...globals.browser, + ...globals.node, + }, + }, + }, +]; diff --git a/package.json b/package.json new file mode 100644 index 0000000..ffdea6f --- /dev/null +++ b/package.json @@ -0,0 +1,28 @@ +{ + "name": "tensamin", + "private": true, + "workspaces": [ + "packages/*", + "packages/core/*" + ], + "type": "module", + "scripts": { + "format": "bunx prettier --write .", + "lint": "bun scripts/lint-packages.ts", + "build:packages": "bun scripts/build-packages.ts", + "install:packages": "bun scripts/install-packages.ts", + "update:packages": "bun scripts/update-packages.ts", + "dev": "cd packages/web && bun dev" + }, + "devDependencies": { + "@eslint/js": "^10.0.1", + "@types/node": "^25.4.0", + "@typescript-eslint/parser": "^8.57.0", + "eslint": "^10.0.3", + "eslint-plugin-solid": "^0.14.5", + "globals": "^17.4.0", + "prettier": "^3.8.1", + "typescript": "^5.9.3", + "typescript-eslint": "^8.57.0" + } +} diff --git a/packages/chat/package.json b/packages/chat/package.json new file mode 100644 index 0000000..4881851 --- /dev/null +++ b/packages/chat/package.json @@ -0,0 +1,33 @@ +{ + "name": "@tensamin/chat", + "private": true, + "version": "0.0.0", + "type": "module", + "exports": { + "./context": "./src/context.tsx", + "./screen": "./src/screen.tsx", + "./behaviour-conversation": "./src/behaviour/conversation.ts", + "./behaviour-community": "./src/behaviour/community.ts" + }, + "scripts": { + "format": "bunx prettier --write .", + "lint": "eslint src", + "build": "tsc -p tsconfig.json --noEmit" + }, + "dependencies": { + "@solidjs/router": "^0.15.4", + "@tanstack/solid-query": "^5.90.23", + "@tanstack/solid-virtual": "^3.13.21", + "@tensamin/core-crypto": "workspace:*", + "@tensamin/ttp": "git+https://github.com/Tensamin/TTP.git", + "@tensamin/core-storage": "workspace:*", + "@tensamin/core-user": "workspace:*", + "@tensamin/markdown": "workspace:*", + "@tensamin/shared": "workspace:*", + "@tensamin/ui": "workspace:*", + "lucide-solid": "^0.564.0", + "solid-js": "^1.9.11", + "solid-sonner": "^0.2.8", + "zod": "^4.3.6" + } +} diff --git a/packages/chat/src/behaviour/community.ts b/packages/chat/src/behaviour/community.ts new file mode 100644 index 0000000..1340103 --- /dev/null +++ b/packages/chat/src/behaviour/community.ts @@ -0,0 +1,3 @@ +export function getMessages() { + return 0; +} diff --git a/packages/chat/src/behaviour/conversation.ts b/packages/chat/src/behaviour/conversation.ts new file mode 100644 index 0000000..e6977e2 --- /dev/null +++ b/packages/chat/src/behaviour/conversation.ts @@ -0,0 +1,22 @@ +import { useSocket } from "@tensamin/ttp/context"; +import type { RawMessages } from "../values"; + +export async function getMessages( + amount: number, + offset: number, + user_id: number, +): Promise { + const { send } = useSocket(); + + const messages = await send("messages_get", { + amount: amount, + offset: offset, + user_id: user_id, + }); + + if (messages.type.startsWith("error")) { + throw new Error(messages.type); + } + + return messages.data.messages; +} diff --git a/packages/chat/src/components/input.tsx b/packages/chat/src/components/input.tsx new file mode 100644 index 0000000..830dad4 --- /dev/null +++ b/packages/chat/src/components/input.tsx @@ -0,0 +1,103 @@ +import Input from "@tensamin/markdown/input"; +import { Card, CardHeader } from "@tensamin/ui/card"; +import { useStorage } from "@tensamin/core-storage/context"; +import { createEffect, createSignal } from "solid-js"; +import { Button } from "@tensamin/ui/button"; + +import { Plus, Laugh, Clapperboard } from "lucide-solid"; +import { useChat } from "../context"; +import { useSocket } from "@tensamin/ttp/context"; +import { useCrypto } from "@tensamin/core-crypto/context"; +import { log, toast } from "@tensamin/shared/log"; + +export default function InputComponent() { + const [value, setValue] = createSignal(""); + const [invertEnterBehavior, setInvertEnterBehavior] = createSignal(false); + + const { encrypt } = useCrypto(); + const { send } = useSocket(); + const { addLiveMessage, sharedSecret, userId } = useChat(); + const { load } = useStorage(); + + createEffect(() => { + void load("chat_invert_enter_behaviour").then((shouldInvert) => { + setInvertEnterBehavior(shouldInvert); + }); + }); + + async function handleSubmit() { + if (value().trim() === "") return; + + const time = Date.now(); + const currentValue = value(); + const currentUserId = userId(); + + addLiveMessage({ + height: 0, + not_encrypted: true, + timestamp: time, + content: currentValue, + sent_by_self: true, + }); + + const encryptedContext = await encrypt(sharedSecret(), currentValue); + + send("message_send", { + height: 0, + content: encryptedContext, + receiver_id: currentUserId, + send_time: time, + }).catch((e) => { + log(0, "Chat", "red", "Failed to send message", e, { + content: currentValue, + encryptedContext, + receiver_id: currentUserId, + send_time: time, + }); + toast("error", "Failed to send message"); + }); + + setValue(""); + } + + return ( + + + +
+
+ +
+

Files list

+
+
+
+ + +
+
+
+
+ ); +} diff --git a/packages/chat/src/components/message.tsx b/packages/chat/src/components/message.tsx new file mode 100644 index 0000000..c2b4c94 --- /dev/null +++ b/packages/chat/src/components/message.tsx @@ -0,0 +1,80 @@ +import { useCrypto } from "@tensamin/core-crypto/context"; +import { createEffect, createSignal, onCleanup, Show } from "solid-js"; +import { useChat } from "../context"; +import type { RawMessage } from "../values"; +import { log } from "@tensamin/shared/log"; +import Text from "@tensamin/markdown/text"; + +export default function Message(props: { + message: RawMessage; + notEncrypted?: boolean; +}) { + const { sharedSecret } = useChat(); + const { decrypt } = useCrypto(); + + const message = () => props.message; + const [decodedContent, setDecodedContent] = createSignal(""); + const [isReady, setIsReady] = createSignal(false); + + createEffect(() => { + if (props.notEncrypted) { + setDecodedContent(message().content); + setIsReady(true); + return; + } + + const content = message().content; + const secret = sharedSecret(); + let active = true; + + if (!secret) { + setIsReady(false); + return; + } + + setIsReady(false); + + decrypt(secret, content) + .then((value) => { + if (!active) { + return; + } + + setDecodedContent(value); + setIsReady(true); + }) + .catch((e) => { + if (!active) { + return; + } + + log(0, "Chat", "red", "Failed to decrypt message", e, { + content, + secret, + }); + + setDecodedContent("Failed to decrypt"); + setIsReady(true); + }); + + onCleanup(() => { + active = false; + }); + }); + + return ( +
+
+ + + +
+
+ ); +} diff --git a/packages/chat/src/context.tsx b/packages/chat/src/context.tsx new file mode 100644 index 0000000..7b4f2d0 --- /dev/null +++ b/packages/chat/src/context.tsx @@ -0,0 +1,108 @@ +import { + createContext, + createEffect, + createSignal, + useContext, +} from "solid-js"; +import type { ParentProps } from "solid-js"; +import { QueryClient, QueryClientProvider } from "@tanstack/solid-query"; +import type { RawMessage, RawMessages } from "./values"; +import { useSearchParams } from "@solidjs/router"; +import { useCrypto } from "@tensamin/core-crypto/context"; +import { useUser } from "@tensamin/core-user/context"; +import { useStorage } from "@tensamin/core-storage/context"; + +export const context = createContext(); + +const queryClient = new QueryClient(); + +export default function Provider( + props: ParentProps & { + getMessages: ( + amount: number, + offset: number, + user_id: number, + ) => Promise; + }, +) { + const { get_shared_secret } = useCrypto(); + const { get } = useUser(); + const { load } = useStorage(); + + const [liveMessages, setLiveMessages] = createSignal([]); + const [currentSharedSecret, setCurrentSharedSecret] = createSignal(""); + + const [searchParams] = useSearchParams(); + const userId = () => Number(searchParams.id ?? 0); + + createEffect(() => { + const recipientId = userId(); + + if (!recipientId) { + setCurrentSharedSecret(""); + return; + } + + get(recipientId).then(async (recipientData) => { + const ownId = await load("user_id"); + const privateKey = await load("private_key"); + const ownData = await get(ownId); + const sharedSecret = await get_shared_secret( + privateKey, + ownData.public_key, + recipientData.public_key, + ); + + setCurrentSharedSecret(sharedSecret); + }); + }); + + async function customGetMessages(amount: number, offset: number) { + const messages = await props.getMessages(amount, offset, userId()); + const sorted = [...messages].sort((a, b) => a.timestamp - b.timestamp); + + return sorted; + } + + function addLiveMessage(message: RawMessage) { + setLiveMessages((prev) => [...prev, message]); + } + + function clearLiveMessages() { + setLiveMessages([]); + } + + return ( + + + {props.children} + + + ); +} + +type contextType = { + getMessages: (amount: number, offset: number) => Promise; + liveMessages: () => RawMessages; + addLiveMessage: (message: RawMessage) => void; + clearLiveMessages: () => void; + sharedSecret: () => string; + userId: () => number; +}; + +export function useChat(): contextType { + const ctx = useContext(context); + if (!ctx) { + throw new Error("useChat must be used within a ChatProvider"); + } + return ctx; +} diff --git a/packages/chat/src/screen.tsx b/packages/chat/src/screen.tsx new file mode 100644 index 0000000..ce936d8 --- /dev/null +++ b/packages/chat/src/screen.tsx @@ -0,0 +1,204 @@ +import { createVirtualizer } from "@tanstack/solid-virtual"; +import { useInfiniteQuery } from "@tanstack/solid-query"; +import { useChat } from "./context"; +import { createEffect, createMemo, createSignal, For } from "solid-js"; + +import InputComponent from "./components/input"; +import Message from "./components/message"; + +const PAGE_SIZE = 50; + +export default function Screen() { + const { getMessages, liveMessages, clearLiveMessages, userId } = useChat(); + + // eslint-disable-next-line no-unassigned-vars + let scrollRef!: HTMLDivElement; + + const [hasScrolledToBottomInitially, setHasScrolledToBottomInitially] = + createSignal(false); + const [lastLiveMessageCount, setLastLiveMessageCount] = createSignal(0); + const [prependAnchor, setPrependAnchor] = createSignal<{ + totalSize: number; + scrollTop: number; + } | null>(null); + + const messagesQuery = useInfiniteQuery(() => ({ + queryKey: ["chat-messages", String(userId())], + initialPageParam: 0, + queryFn: ({ pageParam }) => getMessages(PAGE_SIZE, pageParam), + getNextPageParam: (lastPage, allPages) => { + if (lastPage.length < PAGE_SIZE) { + return undefined; + } + + return allPages.length * PAGE_SIZE; + }, + })); + + const historicalMessages = createMemo(() => { + const pages = messagesQuery.data?.pages ?? []; + return [...pages].reverse().flat(); + }); + + createEffect(() => { + userId(); + clearLiveMessages(); + setHasScrolledToBottomInitially(false); + setLastLiveMessageCount(0); + setPrependAnchor(null); + }); + + const messages = createMemo(() => [ + ...historicalMessages(), + ...liveMessages(), + ]); + + async function onScroll() { + if (!scrollRef) { + return; + } + + if (scrollRef.scrollTop > 96) { + return; + } + + if (messagesQuery.isFetchingNextPage || !messagesQuery.hasNextPage) { + return; + } + + setPrependAnchor({ + totalSize: virtualizer.getTotalSize(), + scrollTop: scrollRef.scrollTop, + }); + + await messagesQuery.fetchNextPage(); + } + + const virtualizer = createVirtualizer({ + get count() { + return messages().length; + }, + getScrollElement: () => scrollRef, + estimateSize: (index) => { + const message = messages()[index]; + + if (!message) { + return 56; + } + + let decodedContent = message.content; + try { + decodedContent = atob(message.content); + } catch { + /* noop */ + } + + const lineCount = decodedContent.split("\n").length; + const wrappedLineCount = Math.ceil(decodedContent.length / 42); + const fileCount = message.files?.length ?? 0; + + return 28 + Math.max(lineCount, wrappedLineCount) * 20 + fileCount * 20; + }, + overscan: 6, + }); + + createEffect(() => { + const currentMessages = messages(); + + if ( + !scrollRef || + hasScrolledToBottomInitially() || + currentMessages.length === 0 + ) { + return; + } + + queueMicrotask(() => { + if (!scrollRef) { + return; + } + + scrollRef.scrollTop = scrollRef.scrollHeight; + setHasScrolledToBottomInitially(true); + }); + }); + + createEffect(() => { + const count = liveMessages().length; + + if (!scrollRef) { + return; + } + + if (count > lastLiveMessageCount()) { + queueMicrotask(() => { + if (!scrollRef) { + return; + } + + scrollRef.scrollTop = scrollRef.scrollHeight; + }); + } + + setLastLiveMessageCount(count); + }); + + createEffect(() => { + const anchor = prependAnchor(); + + if (!scrollRef || !anchor || messagesQuery.isFetchingNextPage) { + return; + } + + queueMicrotask(() => { + if (!scrollRef) { + return; + } + + const delta = virtualizer.getTotalSize() - anchor.totalSize; + scrollRef.scrollTop = anchor.scrollTop + delta; + setPrependAnchor(null); + }); + }); + + return ( +
+
+
+ + {(virtualRow) => ( +
+ +
+ )} +
+
+
+ +
+ ); +} diff --git a/packages/chat/src/values.ts b/packages/chat/src/values.ts new file mode 100644 index 0000000..76ad12e --- /dev/null +++ b/packages/chat/src/values.ts @@ -0,0 +1,8 @@ +import { z } from "zod"; +import { socket } from "@tensamin/shared/data"; + +export type RawMessages = z.infer< + typeof socket.messages_get.response +>["messages"]; + +export type RawMessage = RawMessages[number]; diff --git a/packages/chat/tsconfig.json b/packages/chat/tsconfig.json new file mode 100644 index 0000000..ad45124 --- /dev/null +++ b/packages/chat/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "jsx": "preserve", + "jsxImportSource": "solid-js", + "strict": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": ["src"] +} diff --git a/packages/core/crypto/package.json b/packages/core/crypto/package.json new file mode 100644 index 0000000..1128952 --- /dev/null +++ b/packages/core/crypto/package.json @@ -0,0 +1,21 @@ +{ + "name": "@tensamin/core-crypto", + "private": true, + "version": "0.0.0", + "type": "module", + "exports": { + "./context": "./src/context.tsx", + "./worker": "./src/worker.ts" + }, + "scripts": { + "format": "bunx prettier --write .", + "lint": "eslint src", + "build": "tsc -p tsconfig.json --noEmit" + }, + "dependencies": { + "@noble/curves": "^2.0.1", + "@tensamin/ui": "workspace:*", + "comlink": "^4.4.2", + "solid-js": "^1.9.11" + } +} diff --git a/packages/core/crypto/src/context.tsx b/packages/core/crypto/src/context.tsx new file mode 100644 index 0000000..87fd1bd --- /dev/null +++ b/packages/core/crypto/src/context.tsx @@ -0,0 +1,107 @@ +import { + createContext, + onMount, + onCleanup, + createSignal, + Show, + useContext, +} from "solid-js"; +import type { ParentProps } from "solid-js"; + +import * as Comlink from "comlink"; +import Loading from "@tensamin/ui/screens/loading"; + +export const context = createContext(); + +export default function Provider(props: ParentProps) { + let apiRef: ApiRef | null = null; + const [isWorkerReady, setIsWorkerReady] = createSignal(false); + + const { encrypt, decrypt, get_shared_secret } = createCryptoActions( + () => apiRef, + ); + + onMount(() => { + const worker = new Worker(new URL("./worker.ts", import.meta.url), { + type: "module", + }); + apiRef = Comlink.wrap(worker); + setIsWorkerReady(true); + + onCleanup(() => { + apiRef = null; + worker.terminate(); + }); + }); + + return ( + }> + + {props.children} + + + ); +} + +type contextType = { + decrypt: (secret: string, data: string) => Promise; + encrypt: (secret: string, data: string) => Promise; + get_shared_secret: ( + ownPrivateKey: string, + ownPublicKey: string, + otherPublicKey: string, + ) => Promise; +}; + +type ApiRef = { + encrypt: (secret: string, message: string) => Promise; + decrypt: (secret: string, encryptedMessage: string) => Promise; + get_shared_secret: ( + own_private_key: string, + own_public_key: string, + other_public_key: string, + ) => Promise; +}; + +export function createCryptoActions( + getApiRef: () => ApiRef | null, +): contextType { + const encrypt = async (secret: string, message: string): Promise => { + const apiRef = getApiRef(); + if (!apiRef) throw "API not initialized"; + return await apiRef.encrypt(secret, message); + }; + + const decrypt = async ( + secret: string, + encryptedMessage: string, + ): Promise => { + const apiRef = getApiRef(); + if (!apiRef) throw "API not initialized"; + return await apiRef.decrypt(secret, encryptedMessage); + }; + + const get_shared_secret = async ( + own_private_key: string, + own_public_key: string, + other_public_key: string, + ): Promise => { + const apiRef = getApiRef(); + if (!apiRef) throw "API not initialized"; + return await apiRef.get_shared_secret( + own_private_key, + own_public_key, + other_public_key, + ); + }; + + return { encrypt, decrypt, get_shared_secret }; +} + +export function useCrypto(): contextType { + const ctx = useContext(context); + if (!ctx) { + throw new Error("useCrypto must be used within a CryptoProvider"); + } + return ctx; +} diff --git a/packages/core/crypto/src/worker.ts b/packages/core/crypto/src/worker.ts new file mode 100644 index 0000000..4a25e67 --- /dev/null +++ b/packages/core/crypto/src/worker.ts @@ -0,0 +1,364 @@ +import * as Comlink from "comlink"; + +type Base64URLString = string; + +type JWK = { + kty: string; + crv: string; + x?: string; + d?: string; +}; + +const textEncoder = new TextEncoder(); +const crypto = globalThis.crypto; + +export async function encrypt( + password: string, + input: string, +): Promise { + const sharedSecret = new Uint8Array( + password.match(/.{1,2}/g)!.map((byte) => parseInt(byte, 16)), + ); + + const hkdfKey = await crypto.subtle.importKey( + "raw", + sharedSecret, + "HKDF", + false, + ["deriveBits"], + ); + + const okm = await crypto.subtle.deriveBits( + { + name: "HKDF", + hash: "SHA-256", + salt: new Uint8Array([]), + info: textEncoder.encode("x448-aes-gcm-no-overhead"), + }, + hkdfKey, + 44 * 8, + ); + + const okmBytes = new Uint8Array(okm); + const keyBytes = okmBytes.slice(0, 32); + const nonce = okmBytes.slice(32, 44); + + const aesKey = await crypto.subtle.importKey( + "raw", + keyBytes, + { name: "AES-GCM" }, + false, + ["encrypt"], + ); + + const encryptedBuffer = await crypto.subtle.encrypt( + { name: "AES-GCM", iv: nonce }, + aesKey, + textEncoder.encode(input), + ); + + return btoa(String.fromCharCode(...new Uint8Array(encryptedBuffer))); +} + +export async function decrypt( + password: string, + input: Base64URLString | string, +): Promise { + const sharedSecret = new Uint8Array( + password.match(/.{1,2}/g)!.map((byte) => parseInt(byte, 16)), + ); + + const ciphertext = Uint8Array.from(atob(input), (c) => c.charCodeAt(0)); + + const hkdfKey = await crypto.subtle.importKey( + "raw", + sharedSecret, + "HKDF", + false, + ["deriveBits"], + ); + + const okm = await crypto.subtle.deriveBits( + { + name: "HKDF", + hash: "SHA-256", + salt: new Uint8Array([]), + info: textEncoder.encode("x448-aes-gcm-no-overhead"), + }, + hkdfKey, + 44 * 8, + ); + + const okmBytes = new Uint8Array(okm); + const keyBytes = okmBytes.slice(0, 32); + const nonce = okmBytes.slice(32, 44); + + const aesKey = await crypto.subtle.importKey( + "raw", + keyBytes, + { name: "AES-GCM" }, + false, + ["decrypt"], + ); + + const decryptedBuffer = await crypto.subtle.decrypt( + { + name: "AES-GCM", + iv: nonce, + }, + aesKey, + ciphertext, + ); + + return new TextDecoder().decode(decryptedBuffer); +} + +export async function get_shared_secret( + own_private_key: string, + own_public_key: string, + other_public_key: string, +): Promise { + const other_jwk: JWK = { kty: "OKP", crv: "X448", x: other_public_key }; + const own_jwk: JWK = { + kty: "OKP", + crv: "X448", + x: own_public_key, + d: own_private_key, + }; + + const bytesToHex = (u8: Uint8Array): string => + Array.from(u8, (b) => b.toString(16).padStart(2, "0")).join(""); + + const b64ToBytes = (s: Base64URLString): Uint8Array => { + const bin = atob(s); + const out = new Uint8Array(bin.length); + for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i); + return out; + }; + + const b64uToBytes = (s: Base64URLString): Uint8Array => { + const b64 = + s.replace(/-/g, "+").replace(/_/g, "/") + "===".slice((s.length + 3) % 4); + return b64ToBytes(b64); + }; + + const bytesToB64u = (u8: Uint8Array): string => { + const b64 = btoa(String.fromCharCode(...u8)); + return b64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, ""); + }; + + const decodeBase64Auto = (s: string): Uint8Array => + /[-_]/.test(s) ? b64uToBytes(s) : b64ToBytes(s); + + const readTLV = (view: Uint8Array, off: number) => { + const tag = view[off++]; + if (off >= view.length) throw new Error("DER: truncated"); + let len = view[off++]; + if (len & 0x80) { + const n = len & 0x7f; + if (n === 0) throw new Error("DER: indefinite length not supported"); + if (off + n > view.length) throw new Error("DER: truncated length"); + len = 0; + for (let i = 0; i < n; i++) len = (len << 8) | view[off++]; + } + const start = off; + const end = off + len; + if (end > view.length) throw new Error("DER: content truncated"); + return { tag, len, start, end }; + }; + + const ensureOidX448 = (view: Uint8Array, start: number): boolean => { + const oid = readTLV(view, start); + if (oid.tag !== 0x06) return false; + const len = oid.end - oid.start; + if (len !== 3) return false; + return ( + view[oid.start] === 0x2b && + view[oid.start + 1] === 0x65 && + view[oid.start + 2] === 0x6f + ); + }; + + const extractRawX448FromSPKI = (spkiBytes: Uint8Array): Uint8Array => { + const view = spkiBytes; + const outer = readTLV(view, 0); + if (outer.tag !== 0x30) throw new Error("SPKI: expected SEQUENCE"); + const alg = readTLV(view, outer.start); + if (alg.tag !== 0x30) throw new Error("SPKI: expected AlgorithmIdentifier"); + if (!ensureOidX448(view, alg.start)) throw new Error("SPKI: not X448"); + const bitstr = readTLV(view, alg.end); + if (bitstr.tag !== 0x03) throw new Error("SPKI: expected BIT STRING"); + const unusedBits = view[bitstr.start]; + if (unusedBits !== 0x00) throw new Error("SPKI: unexpected unused bits"); + const raw = view.subarray(bitstr.start + 1, bitstr.end); + if (raw.length !== 56) + throw new Error("SPKI: X448 public key must be 56 bytes"); + return raw; + }; + + const extractRawX448FromPKCS8 = (pkcs8Bytes: Uint8Array): Uint8Array => { + const view = pkcs8Bytes; + const outer = readTLV(view, 0); + if (outer.tag !== 0x30) throw new Error("PKCS8: expected SEQUENCE"); + let off = outer.start; + + const version = readTLV(view, off); + if (version.tag !== 0x02) + throw new Error("PKCS8: expected version INTEGER"); + off = version.end; + + const alg = readTLV(view, off); + if (alg.tag !== 0x30) + throw new Error("PKCS8: expected AlgorithmIdentifier"); + if (!ensureOidX448(view, alg.start)) throw new Error("PKCS8: not X448"); + off = alg.end; + + const priv = readTLV(view, off); + if (priv.tag !== 0x04) + throw new Error("PKCS8: expected privateKey OCTET STRING"); + let raw = view.subarray(priv.start, priv.end); + + // Some encoders nest another OCTET STRING inside + if (raw[0] === 0x04) { + const inner = readTLV(raw, 0); + if (inner.tag === 0x04) { + raw = raw.subarray(inner.start, inner.end); + } + } + if (raw.length !== 56) + throw new Error("PKCS8: X448 private key must be 56 bytes"); + return raw; + }; + + const normalizeOkpX448Jwk = (jwk: JWK, label: string): JWK => { + if (!jwk || jwk.kty !== "OKP" || jwk.crv !== "X448") { + throw new Error(`${label}: expected OKP JWK with crv "X448"`); + } + const out = { ...jwk }; + + if (out.x) { + const xBytes = decodeBase64Auto(out.x); + let rawX: Uint8Array; + try { + rawX = extractRawX448FromSPKI(xBytes); + } catch { + if (xBytes.length !== 56) { + throw new Error( + `${label}: "x" is not a valid X448 SPKI or raw 56-byte key`, + ); + } + rawX = xBytes; + } + out.x = bytesToB64u(rawX); + } + + if (out.d) { + const dBytes = decodeBase64Auto(out.d); + let rawD: Uint8Array; + try { + rawD = extractRawX448FromPKCS8(dBytes); + } catch { + if (dBytes.length !== 56) { + throw new Error( + `${label}: "d" is not a valid X448 PKCS#8 or raw 56-byte key`, + ); + } + rawD = dBytes; + } + out.d = bytesToB64u(rawD); + } + + return out; + }; + + const getSubtle = () => globalThis.crypto?.subtle; + + { + /* + const hkdfAesGcmFromShared = async ( + sharedSecret: BufferSource, + infoStr: string + ): Promise => { + const subtle = getSubtle(); + if (!subtle) throw new Error("WebCrypto subtle not available"); + const info = textEncoder.encode(infoStr); + const baseKey = await subtle.importKey( + "raw", + sharedSecret, + "HKDF", + false, + ["deriveKey"] + ); + return await subtle.deriveKey( + { + name: "HKDF", + hash: "SHA-256", + salt: new Uint8Array(0), + info, + }, + baseKey, + { name: "AES-GCM", length: 256 }, + false, + ["encrypt", "decrypt"] + ); + }; + */ + } + + const myJwk: JWK = normalizeOkpX448Jwk(own_jwk, "own_jwk"); + const peerJwk: JWK = normalizeOkpX448Jwk(other_jwk, "other_jwk"); + + const subtle = getSubtle(); + //const infoStr = `ECDH-X448-AES-GCM-v1|my=${myJwk.x}|peer=${peerJwk.x}`; + + if (subtle) { + const algorithms = [{ name: "ECDH", namedCurve: "X448" }, { name: "X448" }]; + + for (const algorithm of algorithms) { + try { + const [myPriv, peerPub] = await Promise.all([ + subtle.importKey("jwk", myJwk, algorithm, false, ["deriveBits"]), + subtle.importKey("jwk", peerJwk, algorithm, false, []), + ]); + + const sharedBits = await subtle.deriveBits( + { name: algorithm.name, public: peerPub }, + myPriv, + 448, + ); + + const sharedSecret = new Uint8Array(sharedBits); + //const aeadKey = await hkdfAesGcmFromShared(sharedSecret, infoStr); + + return bytesToHex(sharedSecret); + } catch { + // Browser doesn't support this algorithm, try next or fall through to software fallback + } + } + } + + const { d: dMyB64u } = myJwk; + //const { x: xMyB64u, d: dMyB64u } = myJwk; + const { x: xPeerB64u } = peerJwk; + + if (!dMyB64u || !xPeerB64u) { + return "Failed to get shared secret due to missing keys"; + } + + const [dRaw, xRawPeer] = [b64uToBytes(dMyB64u), b64uToBytes(xPeerB64u)]; + if (dRaw.length !== 56 || xRawPeer.length !== 56) { + return "Failed to get shared secret due to invalid key lengths"; + } + + const { x448 } = await import("@noble/curves/ed448.js"); + const sharedSecret = new Uint8Array(x448.getSharedSecret(dRaw, xRawPeer)); + //const aeadKey = await hkdfAesGcmFromShared(sharedSecret, infoStr); + + return bytesToHex(sharedSecret); +} + +Comlink.expose({ + encrypt, + decrypt, + get_shared_secret, +}); diff --git a/packages/core/crypto/tsconfig.json b/packages/core/crypto/tsconfig.json new file mode 100644 index 0000000..ad45124 --- /dev/null +++ b/packages/core/crypto/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "jsx": "preserve", + "jsxImportSource": "solid-js", + "strict": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": ["src"] +} diff --git a/packages/core/markdown/package.json b/packages/core/markdown/package.json new file mode 100644 index 0000000..8515f2b --- /dev/null +++ b/packages/core/markdown/package.json @@ -0,0 +1,23 @@ +{ + "name": "@tensamin/markdown", + "private": true, + "version": "0.0.0", + "type": "module", + "exports": { + "./text": "./src/text.tsx", + "./input": "./src/input.tsx" + }, + "scripts": { + "format": "bunx prettier --write .", + "lint": "eslint src", + "build": "tsc -p tsconfig.json --noEmit" + }, + "dependencies": { + "@codemirror/commands": "^6.10.2", + "@codemirror/lang-markdown": "^6.5.0", + "@codemirror/state": "^6.5.4", + "@codemirror/view": "^6.39.16", + "@tensamin/ui": "workspace:*", + "solid-js": "^1.9.11" + } +} diff --git a/packages/core/markdown/src/input.tsx b/packages/core/markdown/src/input.tsx new file mode 100644 index 0000000..2e2cddb --- /dev/null +++ b/packages/core/markdown/src/input.tsx @@ -0,0 +1,364 @@ +import { markdown } from "@codemirror/lang-markdown"; +import { + EditorState, + type Extension, + type Range, + type SelectionRange, +} from "@codemirror/state"; +import { + Decoration, + EditorView, + keymap, + placeholder, + ViewPlugin, + type DecorationSet, + type ViewUpdate, +} from "@codemirror/view"; +import { + defaultKeymap, + history, + historyKeymap, + indentWithTab, +} from "@codemirror/commands"; +import { + createEffect, + createMemo, + onCleanup, + onMount, + type Setter, +} from "solid-js"; + +import { collectInlineRanges, ensureMarkdownStyles } from "./markdown"; + +export type InputProps = { + ref?: HTMLDivElement; + placeholder?: string; + value: string; + setValue: Setter; + onSubmit?: () => void; + invertEnterBehavior?: boolean; +}; + +type TokenRange = { + from: number; + to: number; +}; + +const hiddenTokenDecoration = Decoration.mark({ class: "tm-md-hidden-token" }); +const strongDecoration = Decoration.mark({ class: "tm-md-strong" }); +const emDecoration = Decoration.mark({ class: "tm-md-em" }); +const delDecoration = Decoration.mark({ class: "tm-md-del" }); +const codeDecoration = Decoration.mark({ class: "tm-md-code" }); +const linkDecoration = Decoration.mark({ class: "tm-md-link" }); +const codeLineDecoration = Decoration.line({ class: "tm-md-code-line" }); + +/** + * Builds markdown styling decorations every time the document or cursor selection changes. + * Token delimiters are hidden unless the cursor is currently intersecting that token range. + */ +const markdownDecorations = ViewPlugin.fromClass( + class { + decorations: DecorationSet; + + constructor(view: EditorView) { + this.decorations = buildDecorations(view); + } + + update(update: ViewUpdate) { + if (update.docChanged || update.selectionSet || update.viewportChanged) { + this.decorations = buildDecorations(update.view); + } + } + }, + { + decorations: (instance: { decorations: DecorationSet }) => + instance.decorations, + }, +); + +export default function Input(props: InputProps) { + ensureMarkdownStyles(); + + // eslint-disable-next-line no-unassigned-vars + let element: HTMLDivElement | undefined; + let view: EditorView | undefined; + let ignoreSync = false; + + const externalValue = createMemo(() => props.value); + + onMount(() => { + if (!element) return; + + const state = EditorState.create({ + doc: props.value, + extensions: createEditorExtensions( + (value) => { + ignoreSync = true; + props.setValue(value); + }, + () => props.placeholder, + () => Boolean(props.invertEnterBehavior), + () => props.onSubmit?.(), + ), + }); + + view = new EditorView({ + state, + parent: element, + }); + }); + + createEffect(() => { + const editor = view; + if (!editor) return; + + const next = externalValue(); + const current = editor.state.doc.toString(); + + if (ignoreSync) { + ignoreSync = false; + return; + } + + if (next === current) return; + + editor.dispatch({ + changes: { + from: 0, + to: current.length, + insert: next, + }, + }); + }); + + onCleanup(() => { + view?.destroy(); + view = undefined; + }); + + return
; +} + +function createEditorExtensions( + onChange: (value: string) => void, + getPlaceholder: () => string | undefined, + getInvertEnterBehavior: () => boolean, + onSubmit: () => void, +): Extension[] { + const customEnterKeymap = keymap.of([ + { + key: "Shift-Enter", + run: () => { + if (!getInvertEnterBehavior()) { + return false; + } + + onSubmit(); + return true; + }, + }, + { + key: "Enter", + run: () => { + if (getInvertEnterBehavior()) { + return false; + } + + onSubmit(); + return true; + }, + }, + ]); + + return [ + history(), + markdown(), + customEnterKeymap, + keymap.of([...defaultKeymap, ...historyKeymap, indentWithTab]), + EditorView.lineWrapping, + placeholder(getPlaceholder() ?? ""), + EditorView.updateListener.of((update: ViewUpdate) => { + if (!update.docChanged) return; + onChange(update.state.doc.toString()); + }), + EditorView.theme({ + "&": { + fontSize: "1rem", + }, + "&.cm-editor": { + width: "100%", + }, + }), + EditorView.editorAttributes.of({ + class: "tm-md-editor", + spellcheck: "true", + "aria-label": "Markdown input", + }), + markdownDecorations, + ]; +} + +function buildDecorations(view: EditorView): DecorationSet { + const builder: Range[] = []; + const selections = view.state.selection.ranges.map( + (range: SelectionRange) => ({ + from: range.from, + to: range.to, + }), + ); + + let codeFenceOpen = false; + + for ( + let lineNumber = 1; + lineNumber <= view.state.doc.lines; + lineNumber += 1 + ) { + const line = view.state.doc.line(lineNumber); + const text = line.text; + const lineFrom = line.from; + const trimmed = text.trim(); + + const fence = text.match(/^```\s*([^`]*)$/); + if (fence) { + const ticksStart = lineFrom + text.indexOf("```"); + const ticksEnd = ticksStart + 3; + addHiddenToken(builder, selections, { from: ticksStart, to: ticksEnd }); + if (trimmed.length > 3) { + addHiddenToken(builder, selections, { + from: ticksEnd, + to: line.to, + }); + } + codeFenceOpen = !codeFenceOpen; + continue; + } + + if (codeFenceOpen) { + builder.push(codeLineDecoration.range(lineFrom)); + continue; + } + + const heading = text.match(/^(#{1,6})\s+/); + if (heading) { + const markerLength = heading[0].length; + addHiddenToken(builder, selections, { + from: lineFrom, + to: lineFrom + markerLength, + }); + + const level = heading[1].length; + const headingClass = Decoration.mark({ + class: `tm-md-heading tm-md-h${String(level)}`, + }); + const contentFrom = lineFrom + markerLength; + if (contentFrom < line.to) { + builder.push(headingClass.range(contentFrom, line.to)); + } + } + + const quote = text.match(/^>\s?/); + if (quote) { + addHiddenToken(builder, selections, { + from: lineFrom, + to: lineFrom + quote[0].length, + }); + } + + const unordered = text.match(/^(\s*)([-+*])\s+(?:\[( |x|X)\]\s+)?/); + if (unordered) { + const markerStart = lineFrom + unordered[1].length; + const markerEnd = markerStart + unordered[2].length + 1; + addHiddenToken(builder, selections, { from: markerStart, to: markerEnd }); + + const checkbox = unordered[0].match(/\[( |x|X)\]\s+$/); + if (checkbox) { + const checkboxStart = lineFrom + unordered[0].lastIndexOf("["); + addHiddenToken(builder, selections, { + from: checkboxStart, + to: checkboxStart + checkbox[0].length, + }); + } + } + + const ordered = text.match(/^(\s*)(\d+\.)\s+/); + if (ordered) { + const markerStart = lineFrom + ordered[1].length; + addHiddenToken(builder, selections, { + from: markerStart, + to: markerStart + ordered[2].length + 1, + }); + } + + if (/^(?:\*\s*){3,}$|^(?:-\s*){3,}$|^(?:_\s*){3,}$/.test(trimmed)) { + if (lineFrom < line.to) { + builder.push( + Decoration.mark({ class: "tm-md-hr" }).range(lineFrom, line.to), + ); + } + continue; + } + + const tableSeparator = /^\|?\s*:?-{3,}:?\s*(?:\|\s*:?-{3,}:?\s*)+\|?$/.test( + text, + ); + if (tableSeparator) { + if (lineFrom < line.to) { + builder.push( + Decoration.mark({ class: "tm-md-del" }).range(lineFrom, line.to), + ); + } + continue; + } + + const { styleRanges, tokenRanges } = collectInlineRanges(text, lineFrom); + + for (const range of styleRanges) { + if (range.from >= range.to) continue; + + if (range.className === "tm-md-strong") { + builder.push(strongDecoration.range(range.from, range.to)); + } else if (range.className === "tm-md-em") { + builder.push(emDecoration.range(range.from, range.to)); + } else if (range.className === "tm-md-del") { + builder.push(delDecoration.range(range.from, range.to)); + } else if (range.className === "tm-md-code") { + builder.push(codeDecoration.range(range.from, range.to)); + } else if (range.className === "tm-md-link") { + builder.push(linkDecoration.range(range.from, range.to)); + } + } + + for (const token of tokenRanges) { + addHiddenToken(builder, selections, token); + } + } + + return Decoration.set(builder, true); +} + +/** + * Keeps markdown syntax visible only when user selection intersects the token. + * This preserves cursor predictability and cross-token selection while still hiding syntax during reading. + */ +function addHiddenToken( + builder: Range[], + selections: ReadonlyArray<{ from: number; to: number }>, + token: TokenRange, +): void { + if (token.from >= token.to) return; + + const overlapsSelection = selections.some((selection) => { + const selectionFrom = Math.min(selection.from, selection.to); + const selectionTo = Math.max(selection.from, selection.to); + + if (selectionFrom === selectionTo) { + return selectionFrom >= token.from && selectionFrom <= token.to; + } + + return selectionFrom < token.to && selectionTo > token.from; + }); + + if (overlapsSelection) return; + builder.push(hiddenTokenDecoration.range(token.from, token.to)); +} diff --git a/packages/core/markdown/src/markdown.tsx b/packages/core/markdown/src/markdown.tsx new file mode 100644 index 0000000..ddb896b --- /dev/null +++ b/packages/core/markdown/src/markdown.tsx @@ -0,0 +1,623 @@ +import { For, Index, type JSX } from "solid-js"; + +type InlineNode = + | { type: "text"; value: string } + | { type: "strong"; value: string } + | { type: "em"; value: string } + | { type: "del"; value: string } + | { type: "code"; value: string } + | { type: "link"; label: string; href: string } + | { type: "image"; alt: string; src: string }; + +type InlineDecorationRange = { + from: number; + to: number; + className: string; +}; + +type InlineTokenRange = { + from: number; + to: number; +}; + +type ParagraphBlock = { + type: "paragraph"; + text: string; +}; + +type HeadingBlock = { + type: "heading"; + level: number; + text: string; +}; + +type HrBlock = { + type: "hr"; +}; + +type BlockQuoteBlock = { + type: "blockquote"; + text: string; +}; + +type CodeBlock = { + type: "code"; + language: string; + code: string; +}; + +type ListItem = { + text: string; + checked: boolean | null; +}; + +type ListBlock = { + type: "list"; + ordered: boolean; + items: ListItem[]; +}; + +type TableBlock = { + type: "table"; + headers: string[]; + rows: string[][]; +}; + +type MarkdownBlock = + | ParagraphBlock + | HeadingBlock + | HrBlock + | BlockQuoteBlock + | CodeBlock + | ListBlock + | TableBlock; + +const INLINE_TOKEN_REGEX = + /!\[([^\]]*)\]\(([^)\s]+(?:\s+"[^"]*")?)\)|\[([^\]]+)\]\(([^)\s]+(?:\s+"[^"]*")?)\)|`([^`\n]+)`|~~([^~\n]+)~~|\*\*([^*\n]+)\*\*|__([^_\n]+)__|\*([^*\n]+)\*|_([^_\n]+)_/g; + +export function parseInlineNodes(input: string): InlineNode[] { + const nodes: InlineNode[] = []; + + let cursor = 0; + let match = INLINE_TOKEN_REGEX.exec(input); + + while (match) { + const index = match.index; + const raw = match[0]; + + if (index > cursor) { + nodes.push({ type: "text", value: input.slice(cursor, index) }); + } + + if (match[1] !== undefined && match[2] !== undefined) { + nodes.push({ type: "image", alt: match[1], src: normalizeUrl(match[2]) }); + } else if (match[3] !== undefined && match[4] !== undefined) { + nodes.push({ + type: "link", + label: match[3], + href: normalizeUrl(match[4]), + }); + } else if (match[5] !== undefined) { + nodes.push({ type: "code", value: match[5] }); + } else if (match[6] !== undefined) { + nodes.push({ type: "del", value: match[6] }); + } else if (match[7] !== undefined || match[8] !== undefined) { + nodes.push({ type: "strong", value: match[7] ?? match[8] ?? "" }); + } else if (match[9] !== undefined || match[10] !== undefined) { + nodes.push({ type: "em", value: match[9] ?? match[10] ?? "" }); + } else { + nodes.push({ type: "text", value: raw }); + } + + cursor = index + raw.length; + match = INLINE_TOKEN_REGEX.exec(input); + } + + if (cursor < input.length) { + nodes.push({ type: "text", value: input.slice(cursor) }); + } + + INLINE_TOKEN_REGEX.lastIndex = 0; + return nodes; +} + +export function collectInlineRanges( + input: string, + offset = 0, +): { + styleRanges: InlineDecorationRange[]; + tokenRanges: InlineTokenRange[]; +} { + const styleRanges: InlineDecorationRange[] = []; + const tokenRanges: InlineTokenRange[] = []; + + let match = INLINE_TOKEN_REGEX.exec(input); + + while (match) { + const raw = match[0]; + const start = offset + match.index; + const end = start + raw.length; + + if (match[1] !== undefined && match[2] !== undefined) { + const openLength = 2; + const closeLength = raw.endsWith(")") ? 1 : 0; + + const imageEnd = start + openLength + match[1].length; + tokenRanges.push({ from: start, to: start + openLength }); + tokenRanges.push({ from: imageEnd, to: imageEnd + 1 }); + + const srcStart = imageEnd + 1; + const srcEnd = end - closeLength; + tokenRanges.push({ from: srcStart, to: srcStart + 1 }); + tokenRanges.push({ from: srcEnd, to: srcEnd + closeLength }); + } else if (match[3] !== undefined && match[4] !== undefined) { + const label = match[3]; + const labelStart = start + 1; + const labelEnd = labelStart + label.length; + + tokenRanges.push({ from: start, to: start + 1 }); + tokenRanges.push({ from: labelEnd, to: labelEnd + 1 }); + tokenRanges.push({ from: labelEnd + 1, to: labelEnd + 2 }); + tokenRanges.push({ from: end - 1, to: end }); + + styleRanges.push({ + from: labelStart, + to: labelEnd, + className: "tm-md-link", + }); + } else if (match[5] !== undefined) { + const codeStart = start + 1; + const codeEnd = end - 1; + + tokenRanges.push({ from: start, to: start + 1 }); + tokenRanges.push({ from: end - 1, to: end }); + styleRanges.push({ + from: codeStart, + to: codeEnd, + className: "tm-md-code", + }); + } else if (match[6] !== undefined) { + const contentStart = start + 2; + const contentEnd = end - 2; + + tokenRanges.push({ from: start, to: start + 2 }); + tokenRanges.push({ from: end - 2, to: end }); + styleRanges.push({ + from: contentStart, + to: contentEnd, + className: "tm-md-del", + }); + } else if (match[7] !== undefined || match[8] !== undefined) { + const contentStart = start + 2; + const contentEnd = end - 2; + + tokenRanges.push({ from: start, to: start + 2 }); + tokenRanges.push({ from: end - 2, to: end }); + styleRanges.push({ + from: contentStart, + to: contentEnd, + className: "tm-md-strong", + }); + } else if (match[9] !== undefined || match[10] !== undefined) { + const contentStart = start + 1; + const contentEnd = end - 1; + + tokenRanges.push({ from: start, to: start + 1 }); + tokenRanges.push({ from: end - 1, to: end }); + styleRanges.push({ + from: contentStart, + to: contentEnd, + className: "tm-md-em", + }); + } + + match = INLINE_TOKEN_REGEX.exec(input); + } + + INLINE_TOKEN_REGEX.lastIndex = 0; + return { styleRanges, tokenRanges }; +} + +export function parseMarkdownBlocks(markdown: string): MarkdownBlock[] { + const lines = markdown.replace(/\r\n/g, "\n").split("\n"); + const blocks: MarkdownBlock[] = []; + + let index = 0; + + while (index < lines.length) { + const line = lines[index]; + + if (!line.trim()) { + index += 1; + continue; + } + + const codeFence = line.match(/^```\s*([^`]*)$/); + if (codeFence) { + const language = (codeFence[1] ?? "").trim(); + const codeLines: string[] = []; + index += 1; + + while (index < lines.length && !/^```\s*$/.test(lines[index])) { + codeLines.push(lines[index]); + index += 1; + } + + if (index < lines.length) { + index += 1; + } + + blocks.push({ type: "code", language, code: codeLines.join("\n") }); + continue; + } + + if (/^(?:\*\s*){3,}$|^(?:-\s*){3,}$|^(?:_\s*){3,}$/.test(line.trim())) { + blocks.push({ type: "hr" }); + index += 1; + continue; + } + + const heading = line.match(/^(#{1,6})\s+(.+)$/); + if (heading) { + blocks.push({ + type: "heading", + level: heading[1].length, + text: heading[2], + }); + index += 1; + continue; + } + + const quote = line.match(/^>\s?(.*)$/); + if (quote) { + const quoteLines: string[] = [quote[1]]; + index += 1; + + while (index < lines.length) { + const next = lines[index].match(/^>\s?(.*)$/); + if (!next) break; + quoteLines.push(next[1]); + index += 1; + } + + blocks.push({ type: "blockquote", text: quoteLines.join("\n") }); + continue; + } + + const tableCandidate = readTable(lines, index); + if (tableCandidate) { + blocks.push(tableCandidate.block); + index = tableCandidate.nextIndex; + continue; + } + + const unordered = line.match(/^\s*[-*+]\s+(.*)$/); + const ordered = line.match(/^\s*\d+\.\s+(.*)$/); + if (unordered || ordered) { + const orderedList = Boolean(ordered); + const items: ListItem[] = []; + + while (index < lines.length) { + const current = lines[index]; + const match = orderedList + ? current.match(/^\s*\d+\.\s+(.*)$/) + : current.match(/^\s*[-*+]\s+(.*)$/); + + if (!match) break; + + const task = match[1].match(/^\[( |x|X)\]\s+(.*)$/); + if (task) { + items.push({ + text: task[2], + checked: task[1].toLowerCase() === "x", + }); + } else { + items.push({ text: match[1], checked: null }); + } + + index += 1; + } + + blocks.push({ type: "list", ordered: orderedList, items }); + continue; + } + + const paragraphLines = [line]; + index += 1; + + while ( + index < lines.length && + lines[index].trim() && + !/^(#{1,6})\s+/.test(lines[index]) && + !/^```\s*/.test(lines[index]) && + !/^>\s?/.test(lines[index]) && + !/^\s*[-*+]\s+/.test(lines[index]) && + !/^\s*\d+\.\s+/.test(lines[index]) && + !/^(?:\*\s*){3,}$|^(?:-\s*){3,}$|^(?:_\s*){3,}$/.test(lines[index].trim()) + ) { + paragraphLines.push(lines[index]); + index += 1; + } + + blocks.push({ type: "paragraph", text: paragraphLines.join("\n") }); + } + + return blocks; +} + +export function renderInline(nodes: InlineNode[]): JSX.Element[] { + return nodes.map((node) => { + if (node.type === "text") { + return node.value; + } + + if (node.type === "strong") { + return {node.value}; + } + + if (node.type === "em") { + return {node.value}; + } + + if (node.type === "del") { + return {node.value}; + } + + if (node.type === "code") { + return {node.value}; + } + + if (node.type === "link") { + return ( + + {node.label} + + ); + } + + return ( + {node.alt} + ); + }); +} + +export function renderBlocks(blocks: MarkdownBlock[]): JSX.Element { + return ( + + {(block) => { + if (block.type === "heading") { + const className = `tm-md-heading tm-md-h${String(block.level)}`; + if (block.level === 1) + return ( +

+ {renderInline(parseInlineNodes(block.text))} +

+ ); + if (block.level === 2) + return ( +

+ {renderInline(parseInlineNodes(block.text))} +

+ ); + if (block.level === 3) + return ( +

+ {renderInline(parseInlineNodes(block.text))} +

+ ); + if (block.level === 4) + return ( +

+ {renderInline(parseInlineNodes(block.text))} +

+ ); + if (block.level === 5) + return ( +
+ {renderInline(parseInlineNodes(block.text))} +
+ ); + return ( +
+ {renderInline(parseInlineNodes(block.text))} +
+ ); + } + + if (block.type === "blockquote") { + return ( +
+ + {(line) =>

{renderInline(parseInlineNodes(line))}

} +
+
+ ); + } + + if (block.type === "code") { + return ( +
+              
+                {block.code}
+              
+            
+ ); + } + + if (block.type === "list") { + const Tag = block.ordered ? "ol" : "ul"; + return ( + + + {(item) => ( +
  • + {item.checked !== null ? ( + + ) : null} + {renderInline(parseInlineNodes(item.text))} +
  • + )} +
    +
    + ); + } + + if (block.type === "table") { + return ( +
    + + + + + {(header) => ( + + )} + + + + + + {(row) => ( + + + {(cell) => ( + + )} + + + )} + + +
    {renderInline(parseInlineNodes(header))}
    {renderInline(parseInlineNodes(cell))}
    +
    + ); + } + + if (block.type === "hr") { + return
    ; + } + + return ( +

    + + {(line, idx) => ( + <> + {idx > 0 ?
    : null} + {renderInline(parseInlineNodes(line()))} + + )} +
    +

    + ); + }} +
    + ); +} + +function normalizeUrl(input: string): string { + const value = input.trim(); + if (/^(https?:|mailto:|tel:|\/)/i.test(value)) { + return value; + } + + return "#"; +} + +function splitTableRow(row: string): string[] { + const cleaned = row.trim().replace(/^\|/, "").replace(/\|$/, ""); + return cleaned.split("|").map((cell) => cell.trim()); +} + +function readTable( + lines: string[], + index: number, +): { block: TableBlock; nextIndex: number } | null { + const header = lines[index] ?? ""; + const separator = lines[index + 1] ?? ""; + + if (!header.includes("|") || !separator.includes("|")) { + return null; + } + + const separatorCells = splitTableRow(separator); + const isSeparator = separatorCells.every((cell) => /^:?-{3,}:?$/.test(cell)); + if (!isSeparator) { + return null; + } + + const headers = splitTableRow(header); + const rows: string[][] = []; + let cursor = index + 2; + + while (cursor < lines.length && lines[cursor].includes("|")) { + rows.push(splitTableRow(lines[cursor])); + cursor += 1; + } + + return { + block: { type: "table", headers, rows }, + nextIndex: cursor, + }; +} + +export const markdownStyles = ` +.tm-md-root { color: var(--foreground); line-height: 1.55; font-size: 0.95rem; } +.tm-md-root * { box-sizing: border-box; } +.tm-md-heading { margin: 0.2rem 0 0.35rem; font-weight: 700; line-height: 1.25; } +.tm-md-h1 { font-size: 1.65rem; } +.tm-md-h2 { font-size: 1.45rem; } +.tm-md-h3 { font-size: 1.25rem; } +.tm-md-h4 { font-size: 1.1rem; } +.tm-md-h5 { font-size: 1rem; } +.tm-md-h6 { font-size: 0.95rem; opacity: 0.9; } +.tm-md-p { margin: 0.25rem 0; } +.tm-md-blockquote { margin: 0.45rem 0; padding-left: 0.75rem; border-left: 2px solid var(--border); opacity: 0.95; } +.tm-md-blockquote p { margin: 0.2rem 0; } +.tm-md-pre { margin: 0.45rem 0; padding: 0.65rem 0.75rem; border: 1px solid var(--border); border-radius: 0.5rem; background: var(--muted); overflow-x: auto; } +.tm-md-code, .tm-md-codeblock { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; } +.tm-md-code { padding: 0.08rem 0.32rem; border-radius: 0.28rem; background: var(--muted); } +.tm-md-strong { font-weight: 700; } +.tm-md-em { font-style: italic; } +.tm-md-del { text-decoration: line-through; } +.tm-md-link { color: var(--primary); text-decoration: underline; text-underline-offset: 0.14rem; } +.tm-md-image { display: block; max-width: 100%; border-radius: 0.4rem; margin: 0.5rem 0; } +.tm-md-ul, .tm-md-ol { margin: 0.3rem 0 0.35rem 1.2rem; padding: 0; } +.tm-md-li { margin: 0.2rem 0; } +.tm-md-checkbox { margin-right: 0.5rem; vertical-align: middle; } +.tm-md-table-wrap { overflow-x: auto; margin: 0.45rem 0; } +.tm-md-table { border-collapse: collapse; width: 100%; min-width: 16rem; } +.tm-md-table th, .tm-md-table td { border: 1px solid var(--border); padding: 0.4rem 0.5rem; text-align: left; } +.tm-md-table th { background: var(--muted); font-weight: 600; } +.tm-md-hr { border: 0; border-top: 1px solid var(--border); margin: 0.55rem 0; } + +.cm-editor.tm-md-editor { border: 1px solid var(--border); border-radius: 0.65rem; background: var(--background); } +.cm-editor.tm-md-editor.cm-focused { outline: 2px solid var(--ring); outline-offset: 1px; } +.cm-editor.tm-md-editor .cm-scroller { font-family: inherit; line-height: 1.55; max-height: 30vh; overflow-y: auto; overflow-x: hidden; } +.cm-editor.tm-md-editor .cm-content { padding: 0.7rem 0.85rem; min-height: 2.75rem; } +.cm-editor.tm-md-editor .cm-line { padding: 0 1px; } +.cm-editor.tm-md-editor .tm-md-hidden-token { color: transparent; opacity: 0; font-size: inherit; } +.cm-editor.tm-md-editor .tm-md-code-line { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; background: var(--muted); border-radius: 0.3rem; } +`; + +export function ensureMarkdownStyles(): void { + if (typeof document === "undefined") return; + + const styleId = "tensamin-markdown-styles"; + if (document.getElementById(styleId)) return; + + const style = document.createElement("style"); + style.id = styleId; + style.textContent = markdownStyles; + document.head.appendChild(style); +} diff --git a/packages/core/markdown/src/text.tsx b/packages/core/markdown/src/text.tsx new file mode 100644 index 0000000..4e42d50 --- /dev/null +++ b/packages/core/markdown/src/text.tsx @@ -0,0 +1,19 @@ +import { createMemo } from "solid-js"; + +import { + ensureMarkdownStyles, + parseMarkdownBlocks, + renderBlocks, +} from "./markdown"; + +export type TextProps = { + value: string; +}; + +export default function Text(props: TextProps) { + ensureMarkdownStyles(); + + const blocks = createMemo(() => parseMarkdownBlocks(props.value)); + + return
    {renderBlocks(blocks())}
    ; +} diff --git a/packages/core/markdown/tsconfig.json b/packages/core/markdown/tsconfig.json new file mode 100644 index 0000000..ad45124 --- /dev/null +++ b/packages/core/markdown/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "jsx": "preserve", + "jsxImportSource": "solid-js", + "strict": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": ["src"] +} diff --git a/packages/core/storage/package.json b/packages/core/storage/package.json new file mode 100644 index 0000000..e61b42b --- /dev/null +++ b/packages/core/storage/package.json @@ -0,0 +1,20 @@ +{ + "name": "@tensamin/core-storage", + "private": true, + "version": "0.0.0", + "type": "module", + "exports": { + "./context": "./src/context.tsx", + "./indexed-db": "./src/indexed-db.ts" + }, + "scripts": { + "format": "bunx prettier --write .", + "lint": "eslint src", + "build": "tsc -p tsconfig.json --noEmit" + }, + "dependencies": { + "@tensamin/shared": "workspace:*", + "@tensamin/ui": "workspace:*", + "solid-js": "^1.9.11" + } +} diff --git a/packages/core/storage/src/context.tsx b/packages/core/storage/src/context.tsx new file mode 100644 index 0000000..f10445f --- /dev/null +++ b/packages/core/storage/src/context.tsx @@ -0,0 +1,131 @@ +import { + createContext, + createSignal, + Show, + useContext, + type ParentProps, +} from "solid-js"; +import { + type Storage as StorageSchema, + storageDefaults as defaults, +} from "@tensamin/shared/data"; +import { getEntry, setEntry, deleteEntry } from "./indexed-db"; +import ErrorScreen from "@tensamin/ui/screens/error"; +import { createStore } from "solid-js/store"; +import { log } from "@tensamin/shared/log"; + +interface StorageContextValue { + load(key: K): Promise; + save( + key: K, + value: StorageSchema[K], + ): Promise; + clear: () => Promise; +} + +const StorageContext = createContext(); + +const isIndexedDBSupported = typeof indexedDB !== "undefined"; + +export default function StorageProvider(props: ParentProps) { + const [storage, setStorage] = createStore(defaults); + + const [error, setError] = createSignal(""); + const [errorDescription, setErrorDescription] = createSignal(""); + + async function loadIO( + key: K, + ): Promise { + let stored; + try { + stored = await getEntry(key); + } catch (err) { + setError("Failed to load data"); + setErrorDescription( + "An error occurred while loading data from IndexedDB. Please try again.", + ); + log(0, "Storage", "red", err); + } + if (stored !== undefined) { + setStorage(key, stored); + return stored; + } + return defaults[key]; + } + + async function saveIO( + key: K, + value: StorageSchema[K], + ): Promise { + if (JSON.stringify(value) === JSON.stringify(defaults[key])) { + await deleteEntry(key); + setStorage(key, defaults[key]); + } else { + await setEntry(key, value); + setStorage(key, value); + } + } + + const value: StorageContextValue = { + async load( + key: K, + ): Promise { + if ( + storage[key] === undefined || + JSON.stringify(storage[key]) === JSON.stringify(defaults[key]) + ) { + const value = await loadIO(key); + setStorage(key, value); + } + + return storage[key]; + }, + + async save( + key: K, + value: StorageSchema[K], + ): Promise { + await saveIO(key, value); + setStorage(key, value); + }, + + async clear() { + const keys = Object.keys(defaults) as (keyof StorageSchema)[]; + await Promise.all(keys.map((key) => deleteEntry(key))); + }, + }; + + // @ts-expect-error development utility + window.save = value.save; + + return ( + + } + > + + {props.children} + + + } + > + + + ); +} + +export function useStorage(): StorageContextValue { + const context = useContext(StorageContext); + if (!context) { + throw new Error("useStorage must be used within a StorageProvider"); + } + return context; +} diff --git a/packages/core/storage/src/indexed-db.ts b/packages/core/storage/src/indexed-db.ts new file mode 100644 index 0000000..3cb2b7e --- /dev/null +++ b/packages/core/storage/src/indexed-db.ts @@ -0,0 +1,71 @@ +import type { Storage as StorageSchema } from "@tensamin/shared/data"; + +const DB_NAME = "tensamin"; +const DB_VERSION = 1; +const STORE_NAME = "storage"; + +let dbPromise: Promise | null = null; + +function openDB(): Promise { + if (dbPromise) return dbPromise; + + dbPromise = new Promise((resolve, reject) => { + const request = indexedDB.open(DB_NAME, DB_VERSION); + + request.onupgradeneeded = () => { + const db = request.result; + if (!db.objectStoreNames.contains(STORE_NAME)) { + db.createObjectStore(STORE_NAME); + } + }; + + request.onsuccess = () => resolve(request.result); + request.onerror = () => reject(request.error); + }); + + return dbPromise; +} + +export async function getEntry( + key: K, +): Promise { + const db = await openDB(); + return new Promise((resolve, reject) => { + const tx = db.transaction(STORE_NAME, "readonly"); + const store = tx.objectStore(STORE_NAME); + const request = store.get(key as string); + + request.onsuccess = () => + resolve(request.result as StorageSchema[K] | undefined); + request.onerror = () => reject(request.error); + }); +} + +export async function setEntry( + key: K, + value: StorageSchema[K], +): Promise { + const db = await openDB(); + return new Promise((resolve, reject) => { + const tx = db.transaction(STORE_NAME, "readwrite"); + const store = tx.objectStore(STORE_NAME); + const request = store.put(value, key as string); + + request.onsuccess = () => resolve(); + request.onerror = () => reject(request.error); + }); +} + +export async function deleteEntry( + key: K, +): Promise { + const db = await openDB(); + return new Promise((resolve, reject) => { + const tx = db.transaction(STORE_NAME, "readwrite"); + const store = tx.objectStore(STORE_NAME); + const request = store.delete(key as string); + + request.onsuccess = () => resolve(); + request.onerror = () => reject(request.error); + }); +} diff --git a/packages/core/storage/tsconfig.json b/packages/core/storage/tsconfig.json new file mode 100644 index 0000000..ad45124 --- /dev/null +++ b/packages/core/storage/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "jsx": "preserve", + "jsxImportSource": "solid-js", + "strict": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": ["src"] +} diff --git a/packages/core/user/package.json b/packages/core/user/package.json new file mode 100644 index 0000000..c693cd4 --- /dev/null +++ b/packages/core/user/package.json @@ -0,0 +1,22 @@ +{ + "name": "@tensamin/core-user", + "private": true, + "version": "0.0.0", + "type": "module", + "exports": { + "./context": "./src/context.tsx", + "./wrapper": "./src/wrapper.tsx", + "./values": "./src/values.ts" + }, + "scripts": { + "format": "bunx prettier --write .", + "lint": "eslint src", + "build": "tsc -p tsconfig.json --noEmit" + }, + "dependencies": { + "@tensamin/ttp": "git+https://github.com/Tensamin/TTP.git", + "@tensamin/shared": "workspace:*", + "solid-js": "^1.9.11", + "zod": "^4.3.6" + } +} diff --git a/packages/core/user/src/context.tsx b/packages/core/user/src/context.tsx new file mode 100644 index 0000000..6b37977 --- /dev/null +++ b/packages/core/user/src/context.tsx @@ -0,0 +1,54 @@ +import { createContext, useContext, type ParentProps } from "solid-js"; +import { createStore } from "solid-js/store"; +import { useSocket } from "@tensamin/ttp/context"; + +import { socket as schemas } from "@tensamin/shared/data"; +import type z from "zod"; +import { failedUser } from "./values"; + +export type User = z.infer; + +interface contextValue { + get(userId: number): Promise; +} + +const UserContext = createContext(); + +export default function UserProvider(props: ParentProps) { + const [storage, setStorage] = createStore>({}); + + const { send } = useSocket(); + + async function get(userId: number): Promise { + if (storage[userId] === undefined) { + try { + const userData = await send("get_user_data", { user_id: userId }); + + // Temp, add base64 stuff + userData.data.avatar = userData.data.avatar + ? `data:image/png;base64,${userData.data.avatar}` + : undefined; + // Temp end + + setStorage(userId, userData.data); + } catch { + setStorage(userId, failedUser); + } + } + return storage[userId]; + } + + return ( + + {props.children} + + ); +} + +export function useUser(): contextValue { + const context = useContext(UserContext); + if (!context) { + throw new Error("useUser must be used within a UserProvider"); + } + return context; +} diff --git a/packages/core/user/src/values.ts b/packages/core/user/src/values.ts new file mode 100644 index 0000000..fb8970b --- /dev/null +++ b/packages/core/user/src/values.ts @@ -0,0 +1,13 @@ +import type { User } from "./context"; + +export const failedUser: User = { + user_id: 0, + display: "Failed", + iota_id: 0, + omikron_connections: [], + online_status: "user_offline", + public_key: "", + sub_end: 0, + sub_level: 0, + username: "failed", +}; diff --git a/packages/core/user/src/wrapper.tsx b/packages/core/user/src/wrapper.tsx new file mode 100644 index 0000000..a4188d4 --- /dev/null +++ b/packages/core/user/src/wrapper.tsx @@ -0,0 +1,16 @@ +import { createEffect, createSignal, type JSX } from "solid-js"; +import { useUser, type User } from "./context"; + +export default function Wrapper(props: { + userId: number; + component: (user: User) => JSX.Element; +}) { + const { get } = useUser(); + const [user, setUser] = createSignal(null); + + createEffect(() => { + get(props.userId).then(setUser); + }); + + return <>{user() ? props.component(user() as User) : null}; +} diff --git a/packages/core/user/tsconfig.json b/packages/core/user/tsconfig.json new file mode 100644 index 0000000..ad45124 --- /dev/null +++ b/packages/core/user/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "jsx": "preserve", + "jsxImportSource": "solid-js", + "strict": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": ["src"] +} diff --git a/packages/desktop/.gitignore b/packages/desktop/.gitignore new file mode 100644 index 0000000..c795b05 --- /dev/null +++ b/packages/desktop/.gitignore @@ -0,0 +1 @@ +build \ No newline at end of file diff --git a/packages/desktop/electrobun.config.ts b/packages/desktop/electrobun.config.ts new file mode 100644 index 0000000..6433cf7 --- /dev/null +++ b/packages/desktop/electrobun.config.ts @@ -0,0 +1,37 @@ +import type { ElectrobunConfig } from "electrobun"; + +import { version } from "@tensamin/shared/package.json"; + +export default { + app: { + name: "tensamin", + identifier: "client.tensamin.net", + version: version, + }, + build: { + views: { + mainview: { + entrypoint: "src/mainview/index.ts", + }, + }, + copy: { + "../web/dist/": "views/mainview/", + }, + mac: { + defaultRenderer: "cef", + bundleCEF: true, + }, + linux: { + defaultRenderer: "cef", + bundleCEF: true, + chromiumFlags: { + "enable-features": "UseOzonePlatform", + "ozone-platform": "wayland", + }, + }, + win: { + defaultRenderer: "cef", + bundleCEF: true, + }, + }, +} satisfies ElectrobunConfig; diff --git a/packages/desktop/llms.txt b/packages/desktop/llms.txt new file mode 100644 index 0000000..74e7715 --- /dev/null +++ b/packages/desktop/llms.txt @@ -0,0 +1,24 @@ +# Electrobun Project + +This is an Electrobun desktop application. + +IMPORTANT: Electrobun is NOT Electron. Do not use Electron APIs or patterns. + +## Documentation + +Full API reference: https://blackboard.sh/electrobun/llms.txt +Getting started: https://blackboard.sh/electrobun/docs/ + +## Quick Reference + +Import patterns: +- Main process (Bun): `import { BrowserWindow } from "electrobun/bun"` +- Browser context: `import { Electroview } from "electrobun/view"` + +Use `views://` URLs to load bundled assets (e.g., `url: "views://mainview/index.html"`). +Views must be configured in `electrobun.config.ts` to be built and copied into the bundle. + +## About + +Electrobun is built by Blackboard (https://blackboard.sh), an innovation lab building +tools and funding teams that define the next generation of technology. diff --git a/packages/desktop/package.json b/packages/desktop/package.json new file mode 100644 index 0000000..089c55b --- /dev/null +++ b/packages/desktop/package.json @@ -0,0 +1,19 @@ +{ + "name": "electrobun-hello-world", + "version": "1.0.0", + "description": "A simple Electrobun app showcasing core features", + "scripts": { + "format": "bunx prettier --write .", + "lint": "echo desktop lint skipped", + "build": "echo desktop build skipped", + "start": "electrobun dev", + "dev": "electrobun dev --watch" + }, + "dependencies": { + "electrobun": "1.15.1", + "@tensamin/shared": "workspace:*" + }, + "devDependencies": { + "@types/bun": "latest" + } +} diff --git a/packages/desktop/shell.nix b/packages/desktop/shell.nix new file mode 100644 index 0000000..854b915 --- /dev/null +++ b/packages/desktop/shell.nix @@ -0,0 +1,41 @@ +{pkgs ? import {}}: let + libs = with pkgs; [ + nspr + nss + libxcb + libxkbcommon + wayland + libdecor + dbus + atk + glib + gtk3 + cups + libx11 + libxcomposite + libxdamage + libxext + libxfixes + libxrandr + libgbm + expat + cairo + pango + alsa-lib + + webkitgtk_4_1 + libsoup_3 + libayatana-appindicator + gdk-pixbuf + ]; +in + pkgs.mkShell { + buildInputs = [pkgs.bun] ++ libs; + + shellHook = '' + export LD_LIBRARY_PATH=${pkgs.lib.makeLibraryPath libs}:$LD_LIBRARY_PATH + export GDK_BACKEND=wayland + export OZONE_PLATFORM=wayland + export XDG_SESSION_TYPE=wayland + ''; + } diff --git a/packages/desktop/src/bun/index.ts b/packages/desktop/src/bun/index.ts new file mode 100644 index 0000000..fa76ca6 --- /dev/null +++ b/packages/desktop/src/bun/index.ts @@ -0,0 +1,18 @@ +import { BrowserWindow } from "electrobun/bun"; + +// Create the main application window +const mainWindow = new BrowserWindow({ + title: "Hello Electrobun!", + url: "views://mainview/index.html", + renderer: "cef", + frame: { + width: 800, + height: 800, + x: 200, + y: 200, + }, +}); + +mainWindow.url = "views://mainview/index.html"; + +console.log("Hello Electrobun app started!"); diff --git a/packages/desktop/src/mainview/index.css b/packages/desktop/src/mainview/index.css new file mode 100644 index 0000000..7a4d9ac --- /dev/null +++ b/packages/desktop/src/mainview/index.css @@ -0,0 +1,126 @@ +* { + box-sizing: border-box; +} + +body { + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, + Cantarell, sans-serif; + margin: 0; + padding: 0; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: #333; + min-height: 100vh; +} + +.container { + max-width: 800px; + margin: 0 auto; + padding: 40px 20px; +} + +h1 { + color: white; + font-size: 3rem; + text-align: center; + margin-bottom: 8px; + text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3); +} + +.subtitle { + color: rgba(255, 255, 255, 0.9); + font-size: 1.25rem; + text-align: center; + margin-top: 0; + margin-bottom: 40px; + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); +} + +.welcome-section { + background: white; + border-radius: 12px; + padding: 30px; + margin: 30px 0; + box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15); + line-height: 1.6; +} + +h2 { + color: #2563eb; + margin-top: 30px; + margin-bottom: 15px; +} + +ul { + margin: 20px 0; + padding-left: 20px; +} + +li { + margin: 8px 0; +} + +.links { + display: flex; + gap: 15px; + margin: 25px 0; + flex-wrap: wrap; +} + +.doc-link { + display: inline-block; + background: #2563eb; + color: white; + text-decoration: none; + padding: 12px 20px; + border-radius: 8px; + font-weight: 500; + transition: all 0.2s ease; + box-shadow: 0 2px 4px rgba(37, 99, 235, 0.2); +} + +.doc-link:hover { + background: #1d4ed8; + transform: translateY(-1px); + box-shadow: 0 4px 8px rgba(37, 99, 235, 0.3); +} + +code { + background: #f1f5f9; + color: #475569; + padding: 2px 6px; + border-radius: 4px; + font-family: "Monaco", "Menlo", "Ubuntu Mono", monospace; + font-size: 0.9em; +} + +.footer { + text-align: center; + color: rgba(255, 255, 255, 0.8); + margin-top: 40px; + padding: 20px; + background: rgba(255, 255, 255, 0.1); + border-radius: 8px; + backdrop-filter: blur(10px); +} + +.footer p { + margin: 8px 0; +} + +/* Dark mode support */ +@media (prefers-color-scheme: dark) { + .welcome-section { + background: #1f2937; + color: #f3f4f6; + } + + h2 { + color: #60a5fa; + } + + code { + background: #374151; + color: #d1d5db; + } +} diff --git a/packages/desktop/src/mainview/index.html b/packages/desktop/src/mainview/index.html new file mode 100644 index 0000000..6197add --- /dev/null +++ b/packages/desktop/src/mainview/index.html @@ -0,0 +1,64 @@ + + + + + + Hello Electrobun! + + + +
    +

    Hello Electrobun! 🎉

    +

    A fast, cross-platform desktop app framework

    + +
    +

    + Welcome to your first Electrobun app! This framework combines the + power of Bun with native desktop capabilities. +

    + +

    What is Electrobun?

    +
      +
    • + Fast: Built on Bun's lightning-fast JavaScript + runtime +
    • +
    • + Native: Access to system APIs like menus, trays, + and file dialogs +
    • +
    • + Cross-platform: Works on macOS, Windows, and Linux +
    • +
    • + Web-based UI: Use familiar HTML, CSS, and + JavaScript for your interface +
    • +
    + +

    Get Started

    +

    + Ready to build something amazing? Check out the documentation and + examples: +

    + + +
    + + +
    + + diff --git a/packages/desktop/src/mainview/index.ts b/packages/desktop/src/mainview/index.ts new file mode 100644 index 0000000..0403408 --- /dev/null +++ b/packages/desktop/src/mainview/index.ts @@ -0,0 +1 @@ +console.log("Hello Electrobun view loaded!"); diff --git a/packages/desktop/tsconfig.json b/packages/desktop/tsconfig.json new file mode 100644 index 0000000..1d8d7b9 --- /dev/null +++ b/packages/desktop/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "lib": ["ESNext", "DOM"], + "target": "ESNext", + "module": "ESNext", + "moduleDetection": "force", + "jsx": "react-jsx", + "allowJs": true, + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "noEmit": true, + "strict": true, + "skipLibCheck": true, + "noFallthroughCasesInSwitch": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noPropertyAccessFromIndexSignature": true + }, + "include": ["src/**/*", "./electrobun.config.ts"], + "exclude": ["node_modules", "dist", "build", "../../package/dist"] +} diff --git a/packages/notifications/package.json b/packages/notifications/package.json new file mode 100644 index 0000000..a41c5a3 --- /dev/null +++ b/packages/notifications/package.json @@ -0,0 +1,22 @@ +{ + "name": "@tensamin/notifications", + "private": true, + "version": "0.0.0", + "type": "module", + "exports": { + "./context": "./src/context.tsx" + }, + "scripts": { + "format": "bunx prettier --write .", + "lint": "eslint src", + "build": "tsc -p tsconfig.json --noEmit" + }, + "dependencies": { + "@tensamin/ttp": "git+https://github.com/Tensamin/TTP.git", + "@solidjs/router": "^0.15.4", + "lucide-solid": "^0.564.0", + "solid-js": "^1.9.11", + "solid-sonner": "^0.2.8", + "zod": "^4.3.6" + } +} diff --git a/packages/notifications/src/context.tsx b/packages/notifications/src/context.tsx new file mode 100644 index 0000000..32b2136 --- /dev/null +++ b/packages/notifications/src/context.tsx @@ -0,0 +1,26 @@ +import { createContext, useContext } from "solid-js"; +import type { ParentProps } from "solid-js"; + +export const context = createContext(); + +export default function Provider(props: ParentProps) { + // live_messages + + return ( + {} }}> + {props.children} + + ); +} + +type contextType = { + test: () => void; +}; + +export function useNotifications(): contextType { + const ctx = useContext(context); + if (!ctx) { + throw new Error("useNotifications must be used within a ChatProvider"); + } + return ctx; +} diff --git a/packages/notifications/tsconfig.json b/packages/notifications/tsconfig.json new file mode 100644 index 0000000..ad45124 --- /dev/null +++ b/packages/notifications/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "jsx": "preserve", + "jsxImportSource": "solid-js", + "strict": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": ["src"] +} diff --git a/packages/shared/package.json b/packages/shared/package.json new file mode 100644 index 0000000..7b67b59 --- /dev/null +++ b/packages/shared/package.json @@ -0,0 +1,23 @@ +{ + "name": "@tensamin/shared", + "private": true, + "version": "0.0.0", + "type": "module", + "exports": { + "./data": "./src/data.ts", + "./log": "./src/log.tsx", + "./features/legal/schema": "./src/features/legal/schema.ts", + "./features/conversation/schema": "./src/features/conversation/schema.ts" + }, + "scripts": { + "format": "bunx prettier --write .", + "lint": "eslint src", + "build": "tsc -p tsconfig.json --noEmit" + }, + "dependencies": { + "lucide-solid": "^0.564.0", + "solid-js": "^1.9.11", + "solid-sonner": "^0.2.8", + "zod": "^4.3.6" + } +} diff --git a/packages/shared/src/data.ts b/packages/shared/src/data.ts new file mode 100644 index 0000000..1d4ffd9 --- /dev/null +++ b/packages/shared/src/data.ts @@ -0,0 +1,164 @@ +import { z } from "zod"; + +import { legalDocsSchema } from "./features/legal/schema"; +import { community, conversation } from "./features/conversation/schema"; + +const fileFromMessage = z.object({ + name: z.string(), + id: z.uuidv4(), + type: z.enum(["image", "image_top_right", "file"]), +}); + +const message = z.object({ + height: z.number(), + not_encrypted: z.boolean().optional(), + sent_by_self: z.boolean(), + timestamp: z.number(), + content: z.base64(), + files: z.array(fileFromMessage).optional(), + tint: z.string().length(7).startsWith("#").optional(), + avatar: z.boolean().optional(), + display: z.boolean().optional(), +}); + +// Socket +export const socket = { + identification: { + request: z.object({ + user_id: z.number(), + }), + response: z.object({ + challenge: z.string(), + public_key: z.base64(), + }), + }, + get_user_data: { + request: z.object({ + user_id: z.number(), + }), + response: z.object({ + about: z.string().max(255).optional(), + avatar: z.string().optional(), + display: z.string().max(15), + iota_id: z.number(), + omikron_connections: z.array(z.number()), + omikron_id: z.number().optional(), + online_status: z.enum([ + "user_offline", + "user_online", + "user_dnd", + "user_idle", + "user_wc", + "user_borked", + "iota_offline", + "iota_online", + "iota_borked", + ]), + public_key: z.base64(), + status: z.string().max(15).optional(), + sub_end: z.number(), + sub_level: z.number(), + user_id: z.number(), + username: z.string().max(15), + }), + }, + challenge_response: { + request: z.object({ + challenge: z.base64(), + }), + response: z.object({}), + }, + ping: { + request: z.object({ + last_ping: z.number(), + }), + response: z.object({ + ping_iota: z.number(), + }), + }, + get_chats: { + request: z.object({}), + response: z.object({ + user_ids: z.array(conversation), + }), + }, + get_communities: { + request: z.object({}), + response: z.object({ + communities: z.array(community), + }), + }, + live_message: { + request: z.object({}), + response: z.object({ + sender_id: z.number(), + send_time: z.number(), + message, + }), + }, + messages_get: { + request: z.object({ + user_id: z.number(), + amount: z.number(), + offset: z.number(), + }), + response: z.object({ + messages: z.array(message), + }), + }, + message_send: { + request: z.object({ + height: z.number(), + content: z.base64(), + receiver_id: z.number(), + send_time: z.number(), + files: z.array(fileFromMessage).optional(), + }), + response: z.object({}), + }, +} satisfies Record; + +export type Socket = typeof socket; + +// Storage +export interface Storage { + user_id: number; + private_key: string; + ppandtos_done: boolean; + accepted_terms_of_service: boolean; + accepted_privacy_policy: boolean; + analytics_crash_reports: boolean; + analytics_usage_data: boolean; + analytics_done: boolean; + legal_docs: z.infer; + chat_invert_enter_behaviour: boolean; +} + +export const storageDefaults: Storage = { + user_id: 0, + private_key: "", + ppandtos_done: false, + accepted_terms_of_service: false, + accepted_privacy_policy: false, + analytics_crash_reports: true, + analytics_usage_data: true, + analytics_done: false, + legal_docs: { + eula: { + version: "0.0", + hash: "000000000000", + unix: 0, + }, + tos: { + version: "0.0", + hash: "000000000000", + unix: 0, + }, + pp: { + version: "0.0", + hash: "000000000000", + unix: 0, + }, + }, + chat_invert_enter_behaviour: false, +}; diff --git a/packages/shared/src/features/conversation/schema.ts b/packages/shared/src/features/conversation/schema.ts new file mode 100644 index 0000000..57c97e3 --- /dev/null +++ b/packages/shared/src/features/conversation/schema.ts @@ -0,0 +1,16 @@ +import { z } from "zod"; + +export const conversation = z.object({ + user_id: z.number(), + calls: z.array(z.uuidv4()).optional(), + last_message_at: z.number(), +}); + +export const community = z.object({ + community_address: z.string(), + community_title: z.string(), + position: z.string(), +}); + +export type Conversation = z.infer; +export type Community = z.infer; diff --git a/packages/shared/src/features/legal/schema.ts b/packages/shared/src/features/legal/schema.ts new file mode 100644 index 0000000..cbdbf4e --- /dev/null +++ b/packages/shared/src/features/legal/schema.ts @@ -0,0 +1,13 @@ +import { z } from "zod"; + +const legalDocSchema = z.object({ + version: z.string().regex(/^\d+\.\d+$/), + hash: z.string().regex(/^[a-f0-9]{12}$/), + unix: z.number().int().positive(), +}); + +export const legalDocsSchema = z.object({ + eula: legalDocSchema, + tos: legalDocSchema, + pp: legalDocSchema, +}); diff --git a/packages/shared/src/log.tsx b/packages/shared/src/log.tsx new file mode 100644 index 0000000..df882c9 --- /dev/null +++ b/packages/shared/src/log.tsx @@ -0,0 +1,52 @@ +import { toast as sonnerToast } from "solid-sonner"; +import { Ban, Check, Info, TriangleAlert } from "lucide-solid"; + +export function log( + logLevel: number, + logger: string, + color: "red" | "green" | "yellow" | "purple" | "blue", + ...args: unknown[] +) { + const currentLogLevel = Number(localStorage.getItem("log_level") || 0); + + if (logLevel > currentLogLevel) return; + + const colorCodes: Record = { + red: "\x1b[31m", + green: "\x1b[32m", + yellow: "\x1b[33m", + purple: "\x1b[35m", + blue: "\x1b[34m", + }; + const resetCode = "\x1b[0m"; + console.log(`${colorCodes[color]}[${logger}]${resetCode}`, ...args); +} + +const size = 20; +export function toast( + type: "error" | "info" | "warn" | "success", + message: string, +) { + switch (type) { + case "error": + sonnerToast(message, { + icon: , + }); + break; + case "info": + sonnerToast(message, { + icon: , + }); + break; + case "warn": + sonnerToast(message, { + icon: , + }); + break; + case "success": + sonnerToast(message, { + icon: , + }); + break; + } +} diff --git a/packages/shared/tsconfig.json b/packages/shared/tsconfig.json new file mode 100644 index 0000000..ad45124 --- /dev/null +++ b/packages/shared/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "moduleResolution": "bundler", + "jsx": "preserve", + "jsxImportSource": "solid-js", + "strict": true, + "skipLibCheck": true, + "noEmit": true + }, + "include": ["src"] +} diff --git a/packages/ui/package.json b/packages/ui/package.json new file mode 100644 index 0000000..1c4045f --- /dev/null +++ b/packages/ui/package.json @@ -0,0 +1,32 @@ +{ + "name": "@tensamin/ui", + "private": true, + "version": "0.0.0", + "type": "module", + "exports": { + "./*": "./src/ui/*.tsx", + "./screens/*": "./src/screens/*.tsx", + "./link": "./src/link.tsx" + }, + "scripts": { + "format": "bunx prettier --write .", + "lint": "eslint src", + "build": "tsc -p tsconfig.json --noEmit" + }, + "dependencies": { + "@ark-ui/solid": "^5.34.1", + "@corvu/drawer": "^0.2.4", + "@corvu/otp-field": "^0.1.4", + "@corvu/resizable": "^0.2.5", + "@kobalte/core": "^0.13.11", + "@tanstack/solid-virtual": "^3.13.21", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "cmdk-solid": "^1.1.2", + "embla-carousel-solid": "^8.6.0", + "lucide-solid": "^0.564.0", + "solid-js": "^1.9.11", + "solid-sonner": "^0.2.8", + "tailwind-merge": "^3.5.0" + } +} diff --git a/packages/ui/src/libs/cn.ts b/packages/ui/src/libs/cn.ts new file mode 100644 index 0000000..4f31bb0 --- /dev/null +++ b/packages/ui/src/libs/cn.ts @@ -0,0 +1,5 @@ +import type { ClassValue } from "clsx"; +import clsx from "clsx"; +import { twMerge } from "tailwind-merge"; + +export const cn = (...classLists: ClassValue[]) => twMerge(clsx(classLists)); diff --git a/packages/ui/src/link.tsx b/packages/ui/src/link.tsx new file mode 100644 index 0000000..40cd1e9 --- /dev/null +++ b/packages/ui/src/link.tsx @@ -0,0 +1,13 @@ +import { ExternalLink } from "lucide-solid"; + +export default function Link(props: { link: string; label: string }) { + return ( + + {props.label} + + ); +} diff --git a/packages/ui/src/screens/error.tsx b/packages/ui/src/screens/error.tsx new file mode 100644 index 0000000..0a1ec59 --- /dev/null +++ b/packages/ui/src/screens/error.tsx @@ -0,0 +1,13 @@ +import Link from "../link"; + +export default function Screen(props: { error: string; description: string }) { + return ( +
    +

    {props.error}

    +

    + {props.description} +

    + +
    + ); +} diff --git a/packages/ui/src/screens/loading.tsx b/packages/ui/src/screens/loading.tsx new file mode 100644 index 0000000..8f9c8fc --- /dev/null +++ b/packages/ui/src/screens/loading.tsx @@ -0,0 +1,45 @@ +import { createSignal, createEffect, on } from "solid-js"; + +const DELAY = 250; + +export default function Screen(props: { progress: number }) { + const [displayProgress, setDisplayProgress] = createSignal(0); + + // Animation + createEffect( + on( + () => props.progress, + (target) => { + const start = displayProgress(); + const delta = target - start; + if (delta === 0) return; + + const duration = DELAY; + const startTime = performance.now(); + + function animate(now: number) { + const elapsed = now - startTime; + const t = Math.min(elapsed / duration, 1); + const eased = 1 - Math.pow(1 - t, 3); + setDisplayProgress(start + delta * eased); + if (t < 1) requestAnimationFrame(animate); + } + + requestAnimationFrame(animate); + }, + ), + ); + + return ( +
    +
    +
    +
    +
    + ); +} diff --git a/packages/ui/src/ui/accordion.tsx b/packages/ui/src/ui/accordion.tsx new file mode 100644 index 0000000..4d8ed2a --- /dev/null +++ b/packages/ui/src/ui/accordion.tsx @@ -0,0 +1,97 @@ +import { cn } from "../libs/cn"; +import type { + AccordionContentProps, + AccordionItemProps, + AccordionTriggerProps, +} from "@kobalte/core/accordion"; +import { Accordion as AccordionPrimitive } from "@kobalte/core/accordion"; +import type { PolymorphicProps } from "@kobalte/core/polymorphic"; +import { type ParentProps, type ValidComponent, splitProps } from "solid-js"; + +export const Accordion = AccordionPrimitive; + +type accordionItemProps = + AccordionItemProps & { + class?: string; + }; + +export const AccordionItem = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as accordionItemProps, ["class"]); + + return ( + + ); +}; + +type accordionTriggerProps = ParentProps< + AccordionTriggerProps & { + class?: string; + } +>; + +export const AccordionTrigger = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as accordionTriggerProps, [ + "class", + "children", + ]); + + return ( + + svg]:rotate-180", + local.class, + )} + {...rest} + > + {local.children} + + + Arrow + + + + ); +}; + +type accordionContentProps = ParentProps< + AccordionContentProps & { + class?: string; + } +>; + +export const AccordionContent = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as accordionContentProps, [ + "class", + "children", + ]); + + return ( + +
    {local.children}
    +
    + ); +}; diff --git a/packages/ui/src/ui/alert-dialog.tsx b/packages/ui/src/ui/alert-dialog.tsx new file mode 100644 index 0000000..a968ea6 --- /dev/null +++ b/packages/ui/src/ui/alert-dialog.tsx @@ -0,0 +1,152 @@ +import { cn } from "../libs/cn"; +import type { + AlertDialogCloseButtonProps, + AlertDialogContentProps, + AlertDialogDescriptionProps, + AlertDialogTitleProps, +} from "@kobalte/core/alert-dialog"; +import { AlertDialog as AlertDialogPrimitive } from "@kobalte/core/alert-dialog"; +import type { PolymorphicProps } from "@kobalte/core/polymorphic"; +import type { ComponentProps, ParentProps, ValidComponent } from "solid-js"; +import { splitProps } from "solid-js"; +import { buttonVariants } from "./button"; + +export const AlertDialog = AlertDialogPrimitive; +export const AlertDialogTrigger = AlertDialogPrimitive.Trigger; + +type alertDialogContentProps = ParentProps< + AlertDialogContentProps & { + class?: string; + } +>; + +export const AlertDialogContent = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as alertDialogContentProps, [ + "class", + "children", + ]); + + return ( + + + + {local.children} + + + ); +}; + +export const AlertDialogHeader = (props: ComponentProps<"div">) => { + const [local, rest] = splitProps(props, ["class"]); + + return ( +
    + ); +}; + +export const AlertDialogFooter = (props: ComponentProps<"div">) => { + const [local, rest] = splitProps(props, ["class"]); + + return ( +
    + ); +}; + +type alertDialogTitleProps = + AlertDialogTitleProps & { + class?: string; + }; + +export const AlertDialogTitle = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as alertDialogTitleProps, ["class"]); + + return ( + + ); +}; + +type alertDialogDescriptionProps = + AlertDialogDescriptionProps & { + class?: string; + }; + +export const AlertDialogDescription = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as alertDialogDescriptionProps, [ + "class", + ]); + + return ( + + ); +}; + +type alertDialogCloseProps = + AlertDialogCloseButtonProps & { + class?: string; + }; + +export const AlertDialogClose = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as alertDialogCloseProps, ["class"]); + + return ( + + ); +}; + +export const AlertDialogAction = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as alertDialogCloseProps, ["class"]); + + return ( + + ); +}; diff --git a/packages/ui/src/ui/alert.tsx b/packages/ui/src/ui/alert.tsx new file mode 100644 index 0000000..00ae2cc --- /dev/null +++ b/packages/ui/src/ui/alert.tsx @@ -0,0 +1,66 @@ +import { cn } from "../libs/cn"; +import type { AlertRootProps } from "@kobalte/core/alert"; +import { Alert as AlertPrimitive } from "@kobalte/core/alert"; +import type { PolymorphicProps } from "@kobalte/core/polymorphic"; +import type { VariantProps } from "class-variance-authority"; +import { cva } from "class-variance-authority"; +import type { ComponentProps, ValidComponent } from "solid-js"; +import { splitProps } from "solid-js"; + +export const alertVariants = cva( + "relative w-full rounded-lg border px-4 py-3 text-sm [&:has(svg)]:pl-11 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground", + { + variants: { + variant: { + default: "bg-background text-foreground", + destructive: + "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive", + }, + }, + defaultVariants: { + variant: "default", + }, + }, +); + +type alertProps = AlertRootProps & + VariantProps & { + class?: string; + }; + +export const Alert = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as alertProps, ["class", "variant"]); + + return ( + + ); +}; + +export const AlertTitle = (props: ComponentProps<"div">) => { + const [local, rest] = splitProps(props, ["class"]); + + return ( +
    + ); +}; + +export const AlertDescription = (props: ComponentProps<"div">) => { + const [local, rest] = splitProps(props, ["class"]); + + return ( +
    + ); +}; diff --git a/packages/ui/src/ui/avatar.tsx b/packages/ui/src/ui/avatar.tsx new file mode 100644 index 0000000..15557de --- /dev/null +++ b/packages/ui/src/ui/avatar.tsx @@ -0,0 +1,10 @@ +import { Avatar as ArkAvatar } from "@ark-ui/solid/avatar"; + +export default function Avatar(props: { img?: string; fallback: string }) { + return ( + + {props.fallback} + + + ); +} diff --git a/packages/ui/src/ui/badge.tsx b/packages/ui/src/ui/badge.tsx new file mode 100644 index 0000000..dbb8a6a --- /dev/null +++ b/packages/ui/src/ui/badge.tsx @@ -0,0 +1,42 @@ +import { cn } from "../libs/cn"; +import type { VariantProps } from "class-variance-authority"; +import { cva } from "class-variance-authority"; +import { type ComponentProps, splitProps } from "solid-js"; + +export const badgeVariants = cva( + "inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-shadow focus-visible:outline-none focus-visible:ring-[1.5px] focus-visible:ring-ring", + { + variants: { + variant: { + default: + "border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80", + secondary: + "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", + destructive: + "border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80", + outline: "text-foreground", + }, + }, + defaultVariants: { + variant: "default", + }, + }, +); + +export const Badge = ( + props: ComponentProps<"div"> & VariantProps, +) => { + const [local, rest] = splitProps(props, ["class", "variant"]); + + return ( +
    + ); +}; diff --git a/packages/ui/src/ui/button.tsx b/packages/ui/src/ui/button.tsx new file mode 100644 index 0000000..2f374e8 --- /dev/null +++ b/packages/ui/src/ui/button.tsx @@ -0,0 +1,66 @@ +import { cn } from "../libs/cn"; +import type { ButtonRootProps } from "@kobalte/core/button"; +import { Button as ButtonPrimitive } from "@kobalte/core/button"; +import type { PolymorphicProps } from "@kobalte/core/polymorphic"; +import type { VariantProps } from "class-variance-authority"; +import { cva } from "class-variance-authority"; +import type { ValidComponent } from "solid-js"; +import { splitProps } from "solid-js"; + +export const buttonVariants = cva( + "inline-flex items-center justify-center rounded-md text-sm font-medium transition-[color,background-color,box-shadow] focus-visible:outline-none focus-visible:ring-[1.5px] focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50", + { + variants: { + variant: { + default: + "bg-primary text-primary-foreground shadow hover:bg-primary/90", + destructive: + "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90", + outline: + "border bg-card shadow-sm hover:bg-accent hover:text-accent-foreground", + secondary: + "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-9 px-4 py-2", + sm: "h-8 rounded-md px-3 text-xs", + lg: "h-10 rounded-md px-8", + icon: "h-9 w-9", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + }, +); + +type buttonProps = ButtonRootProps & + VariantProps & { + class?: string; + }; + +export const Button = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as buttonProps, [ + "class", + "variant", + "size", + ]); + + return ( + + ); +}; diff --git a/packages/ui/src/ui/card.tsx b/packages/ui/src/ui/card.tsx new file mode 100644 index 0000000..4e7675b --- /dev/null +++ b/packages/ui/src/ui/card.tsx @@ -0,0 +1,60 @@ +import { cn } from "../libs/cn"; +import type { ComponentProps, ParentComponent } from "solid-js"; +import { splitProps } from "solid-js"; + +export const Card = (props: ComponentProps<"div">) => { + const [local, rest] = splitProps(props, ["class"]); + + return ( +
    + ); +}; + +export const CardHeader = (props: ComponentProps<"div">) => { + const [local, rest] = splitProps(props, ["class"]); + + return ( +
    + ); +}; + +export const CardTitle: ParentComponent> = (props) => { + const [local, rest] = splitProps(props, ["class"]); + + return ( +

    + ); +}; + +export const CardDescription: ParentComponent> = ( + props, +) => { + const [local, rest] = splitProps(props, ["class"]); + + return ( +

    + ); +}; + +export const CardContent = (props: ComponentProps<"div">) => { + const [local, rest] = splitProps(props, ["class"]); + + return
    ; +}; + +export const CardFooter = (props: ComponentProps<"div">) => { + const [local, rest] = splitProps(props, ["class"]); + + return ( +
    + ); +}; diff --git a/packages/ui/src/ui/carousel.tsx b/packages/ui/src/ui/carousel.tsx new file mode 100644 index 0000000..7438968 --- /dev/null +++ b/packages/ui/src/ui/carousel.tsx @@ -0,0 +1,272 @@ +import { cn } from "../libs/cn"; +import type { CreateEmblaCarouselType } from "embla-carousel-solid"; +import createEmblaCarousel from "embla-carousel-solid"; +import type { + Accessor, + ComponentProps, + ParentProps, + VoidProps, +} from "solid-js"; +import { + createContext, + createEffect, + createMemo, + createSignal, + mergeProps, + onCleanup, + splitProps, + useContext, +} from "solid-js"; +import { Button } from "./button"; + +export type CarouselApi = CreateEmblaCarouselType[1]; +type UseCarouselParameters = Parameters; +type CarouselOptions = NonNullable; +type CarouselPlugin = NonNullable; + +type CarouselProps = { + opts?: ReturnType; + plugins?: ReturnType; + orientation?: "horizontal" | "vertical"; + setApi?: (api: CarouselApi) => void; +}; + +type CarouselContextProps = { + carouselRef: ReturnType[0]; + api: ReturnType[1]; + scrollPrev: () => void; + scrollNext: () => void; + canScrollPrev: Accessor; + canScrollNext: Accessor; +} & CarouselProps; + +const CarouselContext = createContext | null>( + null, +); + +const useCarousel = () => { + const context = useContext(CarouselContext); + + if (!context) { + throw new Error("useCarousel must be used within a "); + } + + return context(); +}; + +export const Carousel = (props: ComponentProps<"div"> & CarouselProps) => { + const merge = mergeProps< + ParentProps & CarouselProps>[] + >({ orientation: "horizontal" }, props); + + const [local, rest] = splitProps(merge, [ + "orientation", + "opts", + "setApi", + "plugins", + "class", + "children", + ]); + + const [carouselRef, api] = createEmblaCarousel( + () => ({ + ...local.opts, + axis: local.orientation === "horizontal" ? "x" : "y", + }), + () => (local.plugins === undefined ? [] : local.plugins), + ); + const [canScrollPrev, setCanScrollPrev] = createSignal(false); + const [canScrollNext, setCanScrollNext] = createSignal(false); + + const onSelect = (api: NonNullable>) => { + setCanScrollPrev(api.canScrollPrev()); + setCanScrollNext(api.canScrollNext()); + }; + + const scrollPrev = () => api()?.scrollPrev(); + + const scrollNext = () => api()?.scrollNext(); + + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === "ArrowLeft") { + event.preventDefault(); + scrollPrev(); + } else if (event.key === "ArrowRight") { + event.preventDefault(); + scrollNext(); + } + }; + + createEffect(() => { + if (!api() || !local.setApi) return; + + local.setApi(api); + }); + + createEffect(() => { + const _api = api(); + if (_api === undefined) return; + + onSelect(_api); + _api.on("reInit", onSelect); + _api.on("select", onSelect); + + onCleanup(() => { + _api.off("select", onSelect); + }); + }); + + const value = createMemo( + () => + ({ + carouselRef, + api, + opts: local.opts, + orientation: + local.orientation || + (local.opts?.axis === "y" ? "vertical" : "horizontal"), + scrollPrev, + scrollNext, + canScrollPrev, + canScrollNext, + }) satisfies CarouselContextProps, + ); + + return ( + +
    + {local.children} +
    +
    + ); +}; + +export const CarouselContent = (props: ComponentProps<"div">) => { + const [local, rest] = splitProps(props, ["class"]); + const { carouselRef, orientation } = useCarousel(); + + return ( +
    +
    +
    + ); +}; + +export const CarouselItem = (props: ComponentProps<"div">) => { + const [local, rest] = splitProps(props, ["class"]); + const { orientation } = useCarousel(); + + return ( +
    + ); +}; + +export const CarouselPrevious = ( + props: VoidProps>, +) => { + const merge = mergeProps[]>>( + { variant: "outline", size: "icon" }, + props, + ); + const [local, rest] = splitProps(merge, ["class", "variant", "size"]); + const { orientation, scrollPrev, canScrollPrev } = useCarousel(); + + return ( + + ); +}; + +export const CarouselNext = ( + props: VoidProps>, +) => { + const merge = mergeProps[]>>( + { variant: "outline", size: "icon" }, + props, + ); + const [local, rest] = splitProps(merge, ["class", "variant", "size"]); + const { orientation, scrollNext, canScrollNext } = useCarousel(); + + return ( + + ); +}; diff --git a/packages/ui/src/ui/checkbox.tsx b/packages/ui/src/ui/checkbox.tsx new file mode 100644 index 0000000..be78dc4 --- /dev/null +++ b/packages/ui/src/ui/checkbox.tsx @@ -0,0 +1,55 @@ +import { cn } from "../libs/cn"; +import type { CheckboxControlProps } from "@kobalte/core/checkbox"; +import { Checkbox as CheckboxPrimitive } from "@kobalte/core/checkbox"; +import type { PolymorphicProps } from "@kobalte/core/polymorphic"; +import type { ValidComponent, VoidProps } from "solid-js"; +import { splitProps } from "solid-js"; + +export const CheckboxLabel = CheckboxPrimitive.Label; +export const Checkbox = CheckboxPrimitive; +export const CheckboxErrorMessage = CheckboxPrimitive.ErrorMessage; +export const CheckboxDescription = CheckboxPrimitive.Description; + +type checkboxControlProps = VoidProps< + CheckboxControlProps & { class?: string } +>; + +export const CheckboxControl = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as checkboxControlProps, [ + "class", + "children", + ]); + + return ( + <> + + + + + + Checkbox + + + + + ); +}; diff --git a/packages/ui/src/ui/collapsible.tsx b/packages/ui/src/ui/collapsible.tsx new file mode 100644 index 0000000..b1d75fd --- /dev/null +++ b/packages/ui/src/ui/collapsible.tsx @@ -0,0 +1,31 @@ +import { cn } from "../libs/cn"; +import type { CollapsibleContentProps } from "@kobalte/core/collapsible"; +import { Collapsible as CollapsiblePrimitive } from "@kobalte/core/collapsible"; +import type { PolymorphicProps } from "@kobalte/core/polymorphic"; +import type { ValidComponent } from "solid-js"; +import { splitProps } from "solid-js"; + +export const Collapsible = CollapsiblePrimitive; + +export const CollapsibleTrigger = CollapsiblePrimitive.Trigger; + +type collapsibleContentProps = + CollapsibleContentProps & { + class?: string; + }; + +export const CollapsibleContent = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as collapsibleContentProps, ["class"]); + + return ( + + ); +}; diff --git a/packages/ui/src/ui/combobox.tsx b/packages/ui/src/ui/combobox.tsx new file mode 100644 index 0000000..d8b55d1 --- /dev/null +++ b/packages/ui/src/ui/combobox.tsx @@ -0,0 +1,156 @@ +import { cn } from "../libs/cn"; +import type { + ComboboxContentProps, + ComboboxInputProps, + ComboboxItemProps, + ComboboxTriggerProps, +} from "@kobalte/core/combobox"; +import { Combobox as ComboboxPrimitive } from "@kobalte/core/combobox"; +import type { PolymorphicProps } from "@kobalte/core/polymorphic"; +import type { ParentProps, ValidComponent, VoidProps } from "solid-js"; +import { splitProps } from "solid-js"; + +export const Combobox = ComboboxPrimitive; +export const ComboboxDescription = ComboboxPrimitive.Description; +export const ComboboxErrorMessage = ComboboxPrimitive.ErrorMessage; +export const ComboboxItemDescription = ComboboxPrimitive.ItemDescription; +export const ComboboxHiddenSelect = ComboboxPrimitive.HiddenSelect; + +type comboboxInputProps = VoidProps< + ComboboxInputProps & { + class?: string; + } +>; + +export const ComboboxInput = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as comboboxInputProps, ["class"]); + + return ( + + ); +}; + +type comboboxTriggerProps = ParentProps< + ComboboxTriggerProps & { + class?: string; + } +>; + +export const ComboboxTrigger = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as comboboxTriggerProps, [ + "class", + "children", + ]); + + return ( + + + {local.children} + + + + Arrow + + + + + ); +}; + +type comboboxContentProps = + ComboboxContentProps & { + class?: string; + }; + +export const ComboboxContent = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as comboboxContentProps, ["class"]); + + return ( + + + + + + ); +}; + +type comboboxItemProps = ParentProps< + ComboboxItemProps & { + class?: string; + } +>; + +export const ComboboxItem = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as comboboxItemProps, [ + "class", + "children", + ]); + + return ( + + + + + Checked + + + + {local.children} + + + ); +}; diff --git a/packages/ui/src/ui/command.tsx b/packages/ui/src/ui/command.tsx new file mode 100644 index 0000000..2a51efe --- /dev/null +++ b/packages/ui/src/ui/command.tsx @@ -0,0 +1,151 @@ +import { cn } from "../libs/cn"; +import type { + CommandDialogProps, + CommandEmptyProps, + CommandGroupProps, + CommandInputProps, + CommandItemProps, + CommandListProps, + CommandRootProps, +} from "cmdk-solid"; +import { Command as CommandPrimitive } from "cmdk-solid"; +import type { ComponentProps, VoidProps } from "solid-js"; +import { splitProps } from "solid-js"; +import { Dialog, DialogContent } from "./dialog"; + +export const Command = (props: CommandRootProps) => { + const [local, rest] = splitProps(props, ["class"]); + + return ( + + ); +}; + +export const CommandList = (props: CommandListProps) => { + const [local, rest] = splitProps(props, ["class"]); + + return ( + + ); +}; + +export const CommandInput = (props: VoidProps) => { + const [local, rest] = splitProps(props, ["class"]); + + return ( +
    + + + Search + + +
    + ); +}; + +export const CommandItem = (props: CommandItemProps) => { + const [local, rest] = splitProps(props, ["class"]); + + return ( + + ); +}; + +export const CommandShortcut = (props: ComponentProps<"span">) => { + const [local, rest] = splitProps(props, ["class"]); + + return ( + + ); +}; + +export const CommandDialog = (props: CommandDialogProps) => { + const [local, rest] = splitProps(props, ["children"]); + + return ( + + + + {local.children} + + + + ); +}; + +export const CommandEmpty = (props: CommandEmptyProps) => { + const [local, rest] = splitProps(props, ["class"]); + + return ( + + ); +}; + +export const CommandGroup = (props: CommandGroupProps) => { + const [local, rest] = splitProps(props, ["class"]); + + return ( + + ); +}; + +export const CommandSeparator = (props: CommandEmptyProps) => { + const [local, rest] = splitProps(props, ["class"]); + + return ( + + ); +}; diff --git a/packages/ui/src/ui/context-menu.tsx b/packages/ui/src/ui/context-menu.tsx new file mode 100644 index 0000000..7b661b8 --- /dev/null +++ b/packages/ui/src/ui/context-menu.tsx @@ -0,0 +1,327 @@ +import { cn } from "../libs/cn"; +import type { + ContextMenuCheckboxItemProps, + ContextMenuContentProps, + ContextMenuGroupLabelProps, + ContextMenuItemLabelProps, + ContextMenuItemProps, + ContextMenuRadioItemProps, + ContextMenuSeparatorProps, + ContextMenuSubContentProps, + ContextMenuSubTriggerProps, +} from "@kobalte/core/context-menu"; +import { ContextMenu as ContextMenuPrimitive } from "@kobalte/core/context-menu"; +import type { PolymorphicProps } from "@kobalte/core/polymorphic"; +import type { + ComponentProps, + ParentProps, + ValidComponent, + VoidProps, +} from "solid-js"; +import { splitProps } from "solid-js"; + +export const ContextMenu = ContextMenuPrimitive; +export const ContextMenuTrigger = ContextMenuPrimitive.Trigger; +export const ContextMenuGroup = ContextMenuPrimitive.Group; +export const ContextMenuSub = ContextMenuPrimitive.Sub; +export const ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup; + +type contextMenuSubTriggerProps = ParentProps< + ContextMenuSubTriggerProps & { + class?: string; + inset?: boolean; + } +>; + +export const ContextMenuSubTrigger = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as contextMenuSubTriggerProps, [ + "class", + "children", + "inset", + ]); + + return ( + + {local.children} + + + Arrow + + + ); +}; + +type contextMenuSubContentProps = + ContextMenuSubContentProps & { + class?: string; + }; + +export const ContextMenuSubContent = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as contextMenuSubContentProps, [ + "class", + ]); + + return ( + + + + ); +}; + +type contextMenuContentProps = + ContextMenuContentProps & { + class?: string; + }; + +export const ContextMenuContent = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as contextMenuContentProps, ["class"]); + + return ( + + + + ); +}; + +type contextMenuItemProps = + ContextMenuItemProps & { + class?: string; + inset?: boolean; + }; + +export const ContextMenuItem = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as contextMenuItemProps, [ + "class", + "inset", + ]); + + return ( + + ); +}; + +type contextMenuCheckboxItemProps = + ParentProps< + ContextMenuCheckboxItemProps & { + class?: string; + } + >; + +export const ContextMenuCheckboxItem = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as contextMenuCheckboxItemProps, [ + "class", + "children", + ]); + + return ( + + + + + Checkbox + + + {local.children} + + ); +}; + +type contextMenuRadioItemProps = ParentProps< + ContextMenuRadioItemProps & { + class?: string; + } +>; + +export const ContextMenuRadioItem = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as contextMenuRadioItemProps, [ + "class", + "children", + ]); + + return ( + + + + + + + + Radio + + + {local.children} + + ); +}; + +type contextMenuItemLabelProps = + ContextMenuItemLabelProps & { + class?: string; + inset?: boolean; + }; + +export const ContextMenuItemLabel = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as contextMenuItemLabelProps, [ + "class", + "inset", + ]); + + return ( + + ); +}; + +type contextMenuGroupLabelProps = + ContextMenuGroupLabelProps & { + class?: string; + inset?: boolean; + }; + +export const ContextMenuGroupLabel = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as contextMenuGroupLabelProps, [ + "class", + "inset", + ]); + + return ( + + ); +}; + +type contextMenuSeparatorProps = VoidProps< + ContextMenuSeparatorProps & { + class?: string; + } +>; + +export const ContextMenuSeparator = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as contextMenuSeparatorProps, [ + "class", + ]); + + return ( + + ); +}; + +export const ContextMenuShortcut = (props: ComponentProps<"span">) => { + const [local, rest] = splitProps(props, ["class"]); + + return ( + + ); +}; diff --git a/packages/ui/src/ui/dialog.tsx b/packages/ui/src/ui/dialog.tsx new file mode 100644 index 0000000..2160abb --- /dev/null +++ b/packages/ui/src/ui/dialog.tsx @@ -0,0 +1,128 @@ +import { cn } from "../libs/cn"; +import type { + DialogContentProps, + DialogDescriptionProps, + DialogTitleProps, +} from "@kobalte/core/dialog"; +import { Dialog as DialogPrimitive } from "@kobalte/core/dialog"; +import type { PolymorphicProps } from "@kobalte/core/polymorphic"; +import type { ComponentProps, ParentProps, ValidComponent } from "solid-js"; +import { splitProps } from "solid-js"; + +export const Dialog = DialogPrimitive; +export const DialogTrigger = DialogPrimitive.Trigger; + +type dialogContentProps = ParentProps< + DialogContentProps & { + class?: string; + } +>; + +export const DialogContent = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as dialogContentProps, [ + "class", + "children", + ]); + + return ( + + + + {local.children} + + + + Close + + + + + ); +}; + +type dialogTitleProps = DialogTitleProps & { + class?: string; +}; + +export const DialogTitle = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as dialogTitleProps, ["class"]); + + return ( + + ); +}; + +type dialogDescriptionProps = + DialogDescriptionProps & { + class?: string; + }; + +export const DialogDescription = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as dialogDescriptionProps, ["class"]); + + return ( + + ); +}; + +export const DialogHeader = (props: ComponentProps<"div">) => { + const [local, rest] = splitProps(props, ["class"]); + + return ( +
    + ); +}; + +export const DialogFooter = (props: ComponentProps<"div">) => { + const [local, rest] = splitProps(props, ["class"]); + + return ( +
    + ); +}; diff --git a/packages/ui/src/ui/drawer.tsx b/packages/ui/src/ui/drawer.tsx new file mode 100644 index 0000000..7aa07b0 --- /dev/null +++ b/packages/ui/src/ui/drawer.tsx @@ -0,0 +1,107 @@ +import { cn } from "../libs/cn"; +import type { + ContentProps, + DescriptionProps, + DynamicProps, + LabelProps, +} from "@corvu/drawer"; +import DrawerPrimitive from "@corvu/drawer"; +import type { ComponentProps, ParentProps, ValidComponent } from "solid-js"; +import { splitProps } from "solid-js"; + +export const Drawer = DrawerPrimitive; +export const DrawerTrigger = DrawerPrimitive.Trigger; +export const DrawerClose = DrawerPrimitive.Close; + +type drawerContentProps = ParentProps< + ContentProps & { + class?: string; + } +>; + +export const DrawerContent = ( + props: DynamicProps>, +) => { + const [local, rest] = splitProps(props as drawerContentProps, [ + "class", + "children", + ]); + const ctx = DrawerPrimitive.useContext(); + + return ( + + + +
    + {local.children} + + + ); +}; + +export const DrawerHeader = (props: ComponentProps<"div">) => { + const [local, rest] = splitProps(props, ["class"]); + + return ( +
    + ); +}; + +export const DrawerFooter = (props: ComponentProps<"div">) => { + const [local, rest] = splitProps(props, ["class"]); + + return ( +
    + ); +}; + +type DrawerLabelProps = LabelProps & { + class?: string; +}; + +export const DrawerLabel = ( + props: DynamicProps, +) => { + const [local, rest] = splitProps(props as DrawerLabelProps, ["class"]); + + return ( + + ); +}; + +type DrawerDescriptionProps = DescriptionProps & { + class?: string; +}; + +export const DrawerDescription = ( + props: DynamicProps, +) => { + const [local, rest] = splitProps(props as DrawerDescriptionProps, ["class"]); + + return ( + + ); +}; diff --git a/packages/ui/src/ui/dropdown-menu.tsx b/packages/ui/src/ui/dropdown-menu.tsx new file mode 100644 index 0000000..36cea11 --- /dev/null +++ b/packages/ui/src/ui/dropdown-menu.tsx @@ -0,0 +1,320 @@ +import { cn } from "../libs/cn"; +import type { + DropdownMenuCheckboxItemProps, + DropdownMenuContentProps, + DropdownMenuGroupLabelProps, + DropdownMenuItemLabelProps, + DropdownMenuItemProps, + DropdownMenuRadioItemProps, + DropdownMenuRootProps, + DropdownMenuSeparatorProps, + DropdownMenuSubTriggerProps, +} from "@kobalte/core/dropdown-menu"; +import { DropdownMenu as DropdownMenuPrimitive } from "@kobalte/core/dropdown-menu"; +import type { PolymorphicProps } from "@kobalte/core/polymorphic"; +import type { ComponentProps, ParentProps, ValidComponent } from "solid-js"; +import { mergeProps, splitProps } from "solid-js"; + +export const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger; +export const DropdownMenuGroup = DropdownMenuPrimitive.Group; +export const DropdownMenuSub = DropdownMenuPrimitive.Sub; +export const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup; + +export const DropdownMenu = (props: DropdownMenuRootProps) => { + const merge = mergeProps( + { + gutter: 4, + flip: false, + }, + props, + ); + + return ; +}; + +type dropdownMenuContentProps = + DropdownMenuContentProps & { + class?: string; + }; + +export const DropdownMenuContent = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as dropdownMenuContentProps, [ + "class", + ]); + + return ( + + + + ); +}; + +type dropdownMenuItemProps = + DropdownMenuItemProps & { + class?: string; + inset?: boolean; + }; + +export const DropdownMenuItem = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as dropdownMenuItemProps, [ + "class", + "inset", + ]); + + return ( + + ); +}; + +type dropdownMenuGroupLabelProps = + DropdownMenuGroupLabelProps & { + class?: string; + }; + +export const DropdownMenuGroupLabel = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as dropdownMenuGroupLabelProps, [ + "class", + ]); + + return ( + + ); +}; + +type dropdownMenuItemLabelProps = + DropdownMenuItemLabelProps & { + class?: string; + }; + +export const DropdownMenuItemLabel = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as dropdownMenuItemLabelProps, [ + "class", + ]); + + return ( + + ); +}; + +type dropdownMenuSeparatorProps = + DropdownMenuSeparatorProps & { + class?: string; + }; + +export const DropdownMenuSeparator = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as dropdownMenuSeparatorProps, [ + "class", + ]); + + return ( + + ); +}; + +export const DropdownMenuShortcut = (props: ComponentProps<"span">) => { + const [local, rest] = splitProps(props, ["class"]); + + return ( + + ); +}; + +type dropdownMenuSubTriggerProps = + ParentProps< + DropdownMenuSubTriggerProps & { + class?: string; + } + >; + +export const DropdownMenuSubTrigger = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as dropdownMenuSubTriggerProps, [ + "class", + "children", + ]); + + return ( + + {local.children} + + + Arrow + + + ); +}; + +type dropdownMenuSubContentProps = + DropdownMenuSubTriggerProps & { + class?: string; + }; + +export const DropdownMenuSubContent = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as dropdownMenuSubContentProps, [ + "class", + ]); + + return ( + + + + ); +}; + +type dropdownMenuCheckboxItemProps = + ParentProps< + DropdownMenuCheckboxItemProps & { + class?: string; + } + >; + +export const DropdownMenuCheckboxItem = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as dropdownMenuCheckboxItemProps, [ + "class", + "children", + ]); + + return ( + + + + + Checkbox + + + {props.children} + + ); +}; + +type dropdownMenuRadioItemProps = ParentProps< + DropdownMenuRadioItemProps & { + class?: string; + } +>; + +export const DropdownMenuRadioItem = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as dropdownMenuRadioItemProps, [ + "class", + "children", + ]); + + return ( + + + + + + + + Radio + + + {props.children} + + ); +}; diff --git a/packages/ui/src/ui/hover-card.tsx b/packages/ui/src/ui/hover-card.tsx new file mode 100644 index 0000000..08f56b5 --- /dev/null +++ b/packages/ui/src/ui/hover-card.tsx @@ -0,0 +1,32 @@ +import { cn } from "../libs/cn"; +import type { HoverCardContentProps } from "@kobalte/core/hover-card"; +import { HoverCard as HoverCardPrimitive } from "@kobalte/core/hover-card"; +import type { PolymorphicProps } from "@kobalte/core/polymorphic"; +import type { ValidComponent } from "solid-js"; +import { splitProps } from "solid-js"; + +export const HoverCard = HoverCardPrimitive; +export const HoverCardTrigger = HoverCardPrimitive.Trigger; + +type hoverCardContentProps = + HoverCardContentProps & { + class?: string; + }; + +export const HoverCardContent = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as hoverCardContentProps, ["class"]); + + return ( + + + + ); +}; diff --git a/packages/ui/src/ui/image.tsx b/packages/ui/src/ui/image.tsx new file mode 100644 index 0000000..add09b2 --- /dev/null +++ b/packages/ui/src/ui/image.tsx @@ -0,0 +1,68 @@ +import { cn } from "../libs/cn"; +import type { + ImageFallbackProps, + ImageImgProps, + ImageRootProps, +} from "@kobalte/core/image"; +import { Image as ImagePrimitive } from "@kobalte/core/image"; +import type { PolymorphicProps } from "@kobalte/core/polymorphic"; +import type { ValidComponent } from "solid-js"; +import { splitProps } from "solid-js"; + +type imageRootProps = ImageRootProps & { + class?: string; +}; + +export const ImageRoot = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as imageRootProps, ["class"]); + + return ( + + ); +}; + +type imageProps = ImageImgProps & { + class?: string; +}; + +export const Image = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as imageProps, ["class"]); + + return ( + + ); +}; + +type imageFallbackProps = + ImageFallbackProps & { + class?: string; + }; + +export const ImageFallback = ( + props: PolymorphicProps>, +) => { + const [local, rest] = splitProps(props as imageFallbackProps, ["class"]); + + return ( + + ); +}; diff --git a/packages/ui/src/ui/input.tsx b/packages/ui/src/ui/input.tsx new file mode 100644 index 0000000..0b3a75b --- /dev/null +++ b/packages/ui/src/ui/input.tsx @@ -0,0 +1,27 @@ +import { splitProps, type JSX } from "solid-js"; + +import { cn } from "../libs/cn"; + +interface InputProps extends JSX.HTMLAttributes { + type?: string; +} + +function Input(props: InputProps) { + const [local, others] = splitProps(props, ["class", "type"]); + + return ( + + ); +} + +export { Input }; diff --git a/packages/ui/src/ui/label.tsx b/packages/ui/src/ui/label.tsx new file mode 100644 index 0000000..2ffd0e3 --- /dev/null +++ b/packages/ui/src/ui/label.tsx @@ -0,0 +1,20 @@ +import { cn } from "../libs/cn"; +import type { Component, JSX } from "solid-js"; +import { splitProps } from "solid-js"; + +const Label: Component> = (props) => { + const [local, others] = splitProps(props, ["class"]); + + return ( +