diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index 8f322f0..0000000 --- a/.dockerignore +++ /dev/null @@ -1,35 +0,0 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js - -# testing -/coverage - -# next.js -/.next/ -/out/ - -# production -/build - -# misc -.DS_Store -*.pem - -# debug -npm-debug.log* -yarn-debug.log* -yarn-error.log* - -# local env files -.env*.local - -# vercel -.vercel - -# typescript -*.tsbuildinfo -next-env.d.ts diff --git a/.idea/copilot.data.migration.ask.xml b/.idea/copilot.data.migration.ask.xml new file mode 100644 index 0000000..7ef04e2 --- /dev/null +++ b/.idea/copilot.data.migration.ask.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/copilot.data.migration.ask2agent.xml b/.idea/copilot.data.migration.ask2agent.xml new file mode 100644 index 0000000..1f2ea11 --- /dev/null +++ b/.idea/copilot.data.migration.ask2agent.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/copilotDiffState.xml b/.idea/copilotDiffState.xml new file mode 100644 index 0000000..66475ce --- /dev/null +++ b/.idea/copilotDiffState.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/biome.json b/biome.json index 828ca02..5b99e54 100644 --- a/biome.json +++ b/biome.json @@ -1,24 +1,42 @@ { - "$schema": "https://biomejs.dev/schemas/1.5.1/schema.json", - "organizeImports": { - "enabled": true - }, - "linter": { - "enabled": true, - "rules": { - "recommended": true - }, - "ignore": [".next/", "out/", ".wrangler/", ".open-next/"] - }, - "formatter": { - "enabled": true, - "indentWidth": 4, - "indentStyle": "tab", - "ignore": [".next/", "out/", ".wrangler/", ".open-next/"], - }, - "javascript": { - "formatter": { - "bracketSpacing": true - } - } + "$schema": "https://biomejs.dev/schemas/2.2.0/schema.json", + "vcs": { + "enabled": true, + "clientKind": "git", + "useIgnoreFile": true + }, + "files": { + "ignoreUnknown": true, + "includes": ["**", "!node_modules", "!.next", "!dist", "!build"] + }, + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 2 + }, + "css": { + "parser": { + "tailwindDirectives": true + } + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "suspicious": { + "noUnknownAtRules": "off" + } + }, + "domains": { + "next": "recommended", + "react": "recommended" + } + }, + "assist": { + "actions": { + "source": { + "organizeImports": "on" + } + } + } } diff --git a/bun.lock b/bun.lock new file mode 100644 index 0000000..a42ebf8 --- /dev/null +++ b/bun.lock @@ -0,0 +1,1337 @@ +{ + "lockfileVersion": 1, + "workspaces": { + "": { + "name": "mikn-dev", + "dependencies": { + "@c15t/nextjs": "^1.7.1", + "@c15t/scripts": "^1.0.0", + "@pixiv/three-vrm": "^3.3.4", + "@pixiv/three-vrm-animation": "^3.3.4", + "@radix-ui/react-slot": "^1.2.3", + "@react-three/drei": "^10.7.6", + "@react-three/fiber": "^9.4.0", + "@swetrix/nextjs": "^1.0.1", + "@tailwindcss/postcss": "^4.1.7", + "@types/three": "^0.176.0", + "babel-plugin-react-compiler": "^1.0.0", + "caniuse-lite": "^1.0.30001664", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "daisyui": "^5.0.0", + "gsap": "^3.13.0", + "lucide-react": "^0.548.0", + "maath": "^0.10.8", + "motion": "^12.23.24", + "next": "^16.0.0", + "next-intl": "^4.4.0", + "next-themes": "^0.4.4", + "postcss": "^8.5.3", + "radix-ui": "^1.4.3", + "react": "^19.2.0", + "react-dom": "^19.2.0", + "react-icons": "^5.2.1", + "react-use": "^17.6.0", + "sharp": "^0.33.5", + "shiki": "^1.24.4", + "sonner": "^1.7.1", + "tailwind-merge": "^3.3.1", + "tailwind-variants": "^3.1.1", + "tailwindcss-animate": "^1.0.7", + "three": "^0.180.0", + "tw-animate-css": "^1.4.0", + }, + "devDependencies": { + "@biomejs/biome": "^2.3.1", + "@types/node": "^20", + "@types/react": "^19.2.2", + "@types/react-dom": "^18", + "tailwindcss": "^4.1.7", + "typescript": "^5", + }, + }, + }, + "packages": { + "@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="], + + "@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/runtime": ["@babel/runtime@7.28.4", "", {}, "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ=="], + + "@babel/types": ["@babel/types@7.28.5", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA=="], + + "@biomejs/biome": ["@biomejs/biome@2.3.1", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.3.1", "@biomejs/cli-darwin-x64": "2.3.1", "@biomejs/cli-linux-arm64": "2.3.1", "@biomejs/cli-linux-arm64-musl": "2.3.1", "@biomejs/cli-linux-x64": "2.3.1", "@biomejs/cli-linux-x64-musl": "2.3.1", "@biomejs/cli-win32-arm64": "2.3.1", "@biomejs/cli-win32-x64": "2.3.1" }, "bin": { "biome": "bin/biome" } }, "sha512-A29evf1R72V5bo4o2EPxYMm5mtyGvzp2g+biZvRFx29nWebGyyeOSsDWGx3tuNNMFRepGwxmA9ZQ15mzfabK2w=="], + + "@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.3.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ombSf3MnTUueiYGN1SeI9tBCsDUhpWzOwS63Dove42osNh0PfE1cUtHFx6eZ1+MYCCLwXzlFlYFdrJ+U7h6LcA=="], + + "@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.3.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-pcOfwyoQkrkbGvXxRvZNe5qgD797IowpJPovPX5biPk2FwMEV+INZqfCaz4G5bVq9hYnjwhRMamg11U4QsRXrQ=="], + + "@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.3.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-td5O8pFIgLs8H1sAZsD6v+5quODihyEw4nv2R8z7swUfIK1FKk+15e4eiYVLcAE4jUqngvh4j3JCNgg0Y4o4IQ=="], + + "@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.3.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-+DZYv8l7FlUtTrWs1Tdt1KcNCAmRO87PyOnxKGunbWm5HKg1oZBSbIIPkjrCtDZaeqSG1DiGx7qF+CPsquQRcg=="], + + "@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.3.1", "", { "os": "linux", "cpu": "x64" }, "sha512-PYWgEO7up7XYwSAArOpzsVCiqxBCXy53gsReAb1kKYIyXaoAlhBaBMvxR/k2Rm9aTuZ662locXUmPk/Aj+Xu+Q=="], + + "@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.3.1", "", { "os": "linux", "cpu": "x64" }, "sha512-Y3Ob4nqgv38Mh+6EGHltuN+Cq8aj/gyMTJYzkFZV2AEj+9XzoXB9VNljz9pjfFNHUxvLEV4b55VWyxozQTBaUQ=="], + + "@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.3.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-RHIG/zgo+69idUqVvV3n8+j58dKYABRpMyDmfWu2TITC+jwGPiEaT0Q3RKD+kQHiS80mpBrST0iUGeEXT0bU9A=="], + + "@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.3.1", "", { "os": "win32", "cpu": "x64" }, "sha512-izl30JJ5Dp10mi90Eko47zhxE6pYyWPcnX1NQxKpL/yMhXxf95oLTzfpu4q+MDBh/gemNqyJEwjBpe0MT5iWPA=="], + + "@c15t/backend": ["@c15t/backend@1.7.1", "", { "dependencies": { "@c15t/logger": "1.0.0", "@c15t/translations": "1.7.0", "@opentelemetry/api": "1.9.0", "@opentelemetry/resources": "^2.0.1", "@opentelemetry/sdk-node": "^0.203.0", "@opentelemetry/sdk-trace-base": "^2.0.1", "@orpc/contract": "1.8.1", "@orpc/openapi": "1.8.1", "@orpc/otel": "^1.8.1", "@orpc/server": "1.8.1", "@orpc/zod": "1.8.1", "base-x": "^5.0.1", "defu": "^6.1.4", "drizzle-orm": "^0.44.6", "fumadb": "^0.1.1", "kysely": "^0.27.6", "neverthrow": "^8.2.0", "superjson": "^2.2.2", "zod": "^4.0.17" } }, "sha512-oO+UM7fI93qb1KC+r02FCPeva+cUEySZ0S3MPbUWM5OG5vc/tz6JaPeAK9wEc1TTXszvv5zuNKrK1FYgYNcNdQ=="], + + "@c15t/logger": ["@c15t/logger@1.0.0", "", { "dependencies": { "chalk": "^5.4.1", "neverthrow": "^8.2.0", "picocolors": "^1.1.1" } }, "sha512-z2RrUnvO5bbEg/qd9iD/TqdBi04vfvALf2uovDVLJiQTNfOVUb7FM/GkPH5mugiDwErlrtVhAW8hW/2VmBXbUA=="], + + "@c15t/nextjs": ["@c15t/nextjs@1.7.1", "", { "dependencies": { "@c15t/react": "1.7.1", "@c15t/translations": "1.7.0" }, "peerDependencies": { "next": "^15.0.0 || ^14.0.0 || ^13.0.0", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-TNs9x5eKQ+vkJ9LY0h54DyGZqa4GeUMqnTSS5PC7hczA/QkyoUJkyj7agRUzZsPVBeQEVw7xXbJEhuwr8p+C5Q=="], + + "@c15t/react": ["@c15t/react@1.7.1", "", { "dependencies": { "@radix-ui/react-accordion": "1.2.4", "@radix-ui/react-slot": "1.2.0", "@radix-ui/react-switch": "1.1.4", "c15t": "1.7.1", "clsx": "2.1.1", "zustand": "^5.0.3" }, "peerDependencies": { "react": "^19.0.0 || ^19.0.0-rc || ^18.0.0 || ^17.0.0 || ^16.8.0", "react-dom": "^19.0.0 || ^19.0.0-rc || ^18.0.0 || ^17.0.0 || ^16.8.0" } }, "sha512-Ey6SUOxhf3nEiomYhRR9Axiy4Ku47zrSIDIvJ+amhHEhCS8jyJNQBdclUAggUFzvB8xVJQfGuniU6X6IzjL39Q=="], + + "@c15t/scripts": ["@c15t/scripts@1.0.0", "", {}, "sha512-mMV9BC5HqRvMm1sLzMk3B7XOfaihTfPg1eZr6XJNml5XsKtyrQgbTPHNK5bFH0HBK4jAZYKLGI87qaCJtuQURQ=="], + + "@c15t/translations": ["@c15t/translations@1.7.0", "", {}, "sha512-irrJAni2Cei56wHLmGoIoPHoXk/ygXllWs4dBF9LL0D/Ns7bvcBi/CAPCnCD1hw4FnoJ9amPqYtVKQ3sT++JaQ=="], + + "@clack/core": ["@clack/core@0.5.0", "", { "dependencies": { "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-p3y0FIOwaYRUPRcMO7+dlmLh8PSRcrjuTndsiA0WAFbWES0mLZlrjVoBRZ9DzkPFJZG6KGkJmoEAY0ZcVWTkow=="], + + "@clack/prompts": ["@clack/prompts@0.11.0", "", { "dependencies": { "@clack/core": "0.5.0", "picocolors": "^1.0.0", "sisteransi": "^1.0.5" } }, "sha512-pMN5FcrEw9hUkZA4f+zLlzivQSeQf5dRGJjSUbvVYDLvpKCdQx5OaknvKzgbtXOizhP+SJJJjqEbOe55uKKfAw=="], + + "@dimforge/rapier3d-compat": ["@dimforge/rapier3d-compat@0.12.0", "", {}, "sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow=="], + + "@emnapi/runtime": ["@emnapi/runtime@1.6.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-obtUmAHTMjll499P+D9A3axeJFlhdjOWdKUNs/U6QIGT7V5RjcUW1xToAzjvmgTSQhDbYn/NwfTRoJcQ2rNBxA=="], + + "@floating-ui/core": ["@floating-ui/core@1.7.3", "", { "dependencies": { "@floating-ui/utils": "^0.2.10" } }, "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w=="], + + "@floating-ui/dom": ["@floating-ui/dom@1.7.4", "", { "dependencies": { "@floating-ui/core": "^1.7.3", "@floating-ui/utils": "^0.2.10" } }, "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA=="], + + "@floating-ui/react-dom": ["@floating-ui/react-dom@2.1.6", "", { "dependencies": { "@floating-ui/dom": "^1.7.4" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw=="], + + "@floating-ui/utils": ["@floating-ui/utils@0.2.10", "", {}, "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ=="], + + "@formatjs/ecma402-abstract": ["@formatjs/ecma402-abstract@2.3.6", "", { "dependencies": { "@formatjs/fast-memoize": "2.2.7", "@formatjs/intl-localematcher": "0.6.2", "decimal.js": "^10.4.3", "tslib": "^2.8.0" } }, "sha512-HJnTFeRM2kVFVr5gr5kH1XP6K0JcJtE7Lzvtr3FS/so5f1kpsqqqxy5JF+FRaO6H2qmcMfAUIox7AJteieRtVw=="], + + "@formatjs/fast-memoize": ["@formatjs/fast-memoize@2.2.7", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-Yabmi9nSvyOMrlSeGGWDiH7rf3a7sIwplbvo/dlz9WCIjzIQAfy1RMf4S0X3yG724n5Ghu2GmEl5NJIV6O9sZQ=="], + + "@formatjs/icu-messageformat-parser": ["@formatjs/icu-messageformat-parser@2.11.4", "", { "dependencies": { "@formatjs/ecma402-abstract": "2.3.6", "@formatjs/icu-skeleton-parser": "1.8.16", "tslib": "^2.8.0" } }, "sha512-7kR78cRrPNB4fjGFZg3Rmj5aah8rQj9KPzuLsmcSn4ipLXQvC04keycTI1F7kJYDwIXtT2+7IDEto842CfZBtw=="], + + "@formatjs/icu-skeleton-parser": ["@formatjs/icu-skeleton-parser@1.8.16", "", { "dependencies": { "@formatjs/ecma402-abstract": "2.3.6", "tslib": "^2.8.0" } }, "sha512-H13E9Xl+PxBd8D5/6TVUluSpxGNvFSlN/b3coUp0e0JpuWXXnQDiavIpY3NnvSp4xhEMoXyyBvVfdFX8jglOHQ=="], + + "@formatjs/intl-localematcher": ["@formatjs/intl-localematcher@0.5.10", "", { "dependencies": { "tslib": "2" } }, "sha512-af3qATX+m4Rnd9+wHcjJ4w2ijq+rAVP3CCinJQvFv1kgSu1W6jypUmvleJxcewdxmutM8dmIRZFxO/IQBZmP2Q=="], + + "@grpc/grpc-js": ["@grpc/grpc-js@1.14.0", "", { "dependencies": { "@grpc/proto-loader": "^0.8.0", "@js-sdsl/ordered-map": "^4.4.2" } }, "sha512-N8Jx6PaYzcTRNzirReJCtADVoq4z7+1KQ4E70jTg/koQiMoUSN1kbNjPOqpPbhMFhfU1/l7ixspPl8dNY+FoUg=="], + + "@grpc/proto-loader": ["@grpc/proto-loader@0.8.0", "", { "dependencies": { "lodash.camelcase": "^4.3.0", "long": "^5.0.0", "protobufjs": "^7.5.3", "yargs": "^17.7.2" }, "bin": { "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" } }, "sha512-rc1hOQtjIWGxcxpb9aHAfLpIctjEnsDehj0DAiVfBlmT84uvR0uUtN2hEi/ecvWVjXUGf5qPF4qEgiLOx1YIMQ=="], + + "@img/colour": ["@img/colour@1.0.0", "", {}, "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw=="], + + "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.0.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ=="], + + "@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.0.4" }, "os": "darwin", "cpu": "x64" }, "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q=="], + + "@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.0.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg=="], + + "@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.0.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ=="], + + "@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.0.5", "", { "os": "linux", "cpu": "arm" }, "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g=="], + + "@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA=="], + + "@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.2.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg=="], + + "@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.0.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA=="], + + "@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw=="], + + "@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA=="], + + "@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw=="], + + "@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.0.5" }, "os": "linux", "cpu": "arm" }, "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ=="], + + "@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA=="], + + "@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.2.3" }, "os": "linux", "cpu": "ppc64" }, "sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ=="], + + "@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.0.4" }, "os": "linux", "cpu": "s390x" }, "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q=="], + + "@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA=="], + + "@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" }, "os": "linux", "cpu": "arm64" }, "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g=="], + + "@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.0.4" }, "os": "linux", "cpu": "x64" }, "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw=="], + + "@img/sharp-wasm32": ["@img/sharp-wasm32@0.33.5", "", { "dependencies": { "@emnapi/runtime": "^1.2.0" }, "cpu": "none" }, "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg=="], + + "@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.34.4", "", { "os": "win32", "cpu": "arm64" }, "sha512-2Q250do/5WXTwxW3zjsEuMSv5sUU4Tq9VThWKlU2EYLm4MB7ZeMwF+SFJutldYODXF6jzc6YEOC+VfX0SZQPqA=="], + + "@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.33.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ=="], + + "@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.33.5", "", { "os": "win32", "cpu": "x64" }, "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg=="], + + "@isaacs/cliui": ["@isaacs/cliui@8.0.2", "", { "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", "strip-ansi": "^7.0.1", "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", "wrap-ansi": "^8.1.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" } }, "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA=="], + + "@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=="], + + "@js-sdsl/ordered-map": ["@js-sdsl/ordered-map@4.4.2", "", {}, "sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw=="], + + "@mediapipe/tasks-vision": ["@mediapipe/tasks-vision@0.10.17", "", {}, "sha512-CZWV/q6TTe8ta61cZXjfnnHsfWIdFhms03M9T7Cnd5y2mdpylJM0rF1qRq+wsQVRMLz1OYPVEBU9ph2Bx8cxrg=="], + + "@monogrid/gainmap-js": ["@monogrid/gainmap-js@3.1.0", "", { "dependencies": { "promise-worker-transferable": "^1.0.4" }, "peerDependencies": { "three": ">= 0.159.0" } }, "sha512-Obb0/gEd/HReTlg8ttaYk+0m62gQJmCblMOjHSMHRrBP2zdfKMHLCRbh/6ex9fSUJMKdjjIEiohwkbGD3wj2Nw=="], + + "@next/env": ["@next/env@16.0.0", "", {}, "sha512-s5j2iFGp38QsG1LWRQaE2iUY3h1jc014/melHFfLdrsMJPqxqDQwWNwyQTcNoUSGZlCVZuM7t7JDMmSyRilsnA=="], + + "@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.0.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-/CntqDCnk5w2qIwMiF0a9r6+9qunZzFmU0cBX4T82LOflE72zzH6gnOjCwUXYKOBlQi8OpP/rMj8cBIr18x4TA=="], + + "@next/swc-darwin-x64": ["@next/swc-darwin-x64@16.0.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-hB4GZnJGKa8m4efvTGNyii6qs76vTNl+3dKHTCAUaksN6KjYy4iEO3Q5ira405NW2PKb3EcqWiRaL9DrYJfMHg=="], + + "@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@16.0.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-E2IHMdE+C1k+nUgndM13/BY/iJY9KGCphCftMh7SXWcaQqExq/pJU/1Hgn8n/tFwSoLoYC/yUghOv97tAsIxqg=="], + + "@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@16.0.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-xzgl7c7BVk4+7PDWldU+On2nlwnGgFqJ1siWp3/8S0KBBLCjonB6zwJYPtl4MUY7YZJrzzumdUpUoquu5zk8vg=="], + + "@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@16.0.0", "", { "os": "linux", "cpu": "x64" }, "sha512-sdyOg4cbiCw7YUr0F/7ya42oiVBXLD21EYkSwN+PhE4csJH4MSXUsYyslliiiBwkM+KsuQH/y9wuxVz6s7Nstg=="], + + "@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@16.0.0", "", { "os": "linux", "cpu": "x64" }, "sha512-IAXv3OBYqVaNOgyd3kxR4L3msuhmSy1bcchPHxDOjypG33i2yDWvGBwFD94OuuTjjTt/7cuIKtAmoOOml6kfbg=="], + + "@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@16.0.0", "", { "os": "win32", "cpu": "arm64" }, "sha512-bmo3ncIJKUS9PWK1JD9pEVv0yuvp1KPuOsyJTHXTv8KDrEmgV/K+U0C75rl9rhIaODcS7JEb6/7eJhdwXI0XmA=="], + + "@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@16.0.0", "", { "os": "win32", "cpu": "x64" }, "sha512-O1cJbT+lZp+cTjYyZGiDwsOjO3UHHzSqobkPNipdlnnuPb1swfcuY6r3p8dsKU4hAIEO4cO67ZCfVVH/M1ETXA=="], + + "@noble/hashes": ["@noble/hashes@1.8.0", "", {}, "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A=="], + + "@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="], + + "@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.203.0", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-9B9RU0H7Ya1Dx/Rkyc4stuBZSGVQF27WigitInx2QQoj6KUpEFYPKoWjdFTunJYxmXmh17HeBvbMa1EhGyPmqQ=="], + + "@opentelemetry/context-async-hooks": ["@opentelemetry/context-async-hooks@2.0.1", "", { "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-XuY23lSI3d4PEqKA+7SLtAgwqIfc6E/E9eAQWLN1vlpC53ybO3o6jW4BsXo1xvz9lYyyWItfQDDLzezER01mCw=="], + + "@opentelemetry/core": ["@opentelemetry/core@2.2.0", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-FuabnnUm8LflnieVxs6eP7Z383hgQU4W1e3KJS6aOG3RxWxcHyBxH8fDMHNgu/gFx/M2jvTOW/4/PHhLz6bjWw=="], + + "@opentelemetry/exporter-logs-otlp-grpc": ["@opentelemetry/exporter-logs-otlp-grpc@0.203.0", "", { "dependencies": { "@grpc/grpc-js": "^1.7.1", "@opentelemetry/core": "2.0.1", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-grpc-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0", "@opentelemetry/sdk-logs": "0.203.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-g/2Y2noc/l96zmM+g0LdeuyYKINyBwN6FJySoU15LHPLcMN/1a0wNk2SegwKcxrRdE7Xsm7fkIR5n6XFe3QpPw=="], + + "@opentelemetry/exporter-logs-otlp-http": ["@opentelemetry/exporter-logs-otlp-http@0.203.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.203.0", "@opentelemetry/core": "2.0.1", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0", "@opentelemetry/sdk-logs": "0.203.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-s0hys1ljqlMTbXx2XiplmMJg9wG570Z5lH7wMvrZX6lcODI56sG4HL03jklF63tBeyNwK2RV1/ntXGo3HgG4Qw=="], + + "@opentelemetry/exporter-logs-otlp-proto": ["@opentelemetry/exporter-logs-otlp-proto@0.203.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.203.0", "@opentelemetry/core": "2.0.1", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-logs": "0.203.0", "@opentelemetry/sdk-trace-base": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-nl/7S91MXn5R1aIzoWtMKGvqxgJgepB/sH9qW0rZvZtabnsjbf8OQ1uSx3yogtvLr0GzwD596nQKz2fV7q2RBw=="], + + "@opentelemetry/exporter-metrics-otlp-grpc": ["@opentelemetry/exporter-metrics-otlp-grpc@0.203.0", "", { "dependencies": { "@grpc/grpc-js": "^1.7.1", "@opentelemetry/core": "2.0.1", "@opentelemetry/exporter-metrics-otlp-http": "0.203.0", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-grpc-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-metrics": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-FCCj9nVZpumPQSEI57jRAA89hQQgONuoC35Lt+rayWY/mzCAc6BQT7RFyFaZKJ2B7IQ8kYjOCPsF/HGFWjdQkQ=="], + + "@opentelemetry/exporter-metrics-otlp-http": ["@opentelemetry/exporter-metrics-otlp-http@0.203.0", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-metrics": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-HFSW10y8lY6BTZecGNpV3GpoSy7eaO0Z6GATwZasnT4bEsILp8UJXNG5OmEsz4SdwCSYvyCbTJdNbZP3/8LGCQ=="], + + "@opentelemetry/exporter-metrics-otlp-proto": ["@opentelemetry/exporter-metrics-otlp-proto@0.203.0", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/exporter-metrics-otlp-http": "0.203.0", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-metrics": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-OZnhyd9npU7QbyuHXFEPVm3LnjZYifuKpT3kTnF84mXeEQ84pJJZgyLBpU4FSkSwUkt/zbMyNAI7y5+jYTWGIg=="], + + "@opentelemetry/exporter-prometheus": ["@opentelemetry/exporter-prometheus@0.203.0", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-metrics": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-2jLuNuw5m4sUj/SncDf/mFPabUxMZmmYetx5RKIMIQyPnl6G6ooFzfeE8aXNRf8YD1ZXNlCnRPcISxjveGJHNg=="], + + "@opentelemetry/exporter-trace-otlp-grpc": ["@opentelemetry/exporter-trace-otlp-grpc@0.203.0", "", { "dependencies": { "@grpc/grpc-js": "^1.7.1", "@opentelemetry/core": "2.0.1", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-grpc-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-trace-base": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-322coOTf81bm6cAA8+ML6A+m4r2xTCdmAZzGNTboPXRzhwPt4JEmovsFAs+grpdarObd68msOJ9FfH3jxM6wqA=="], + + "@opentelemetry/exporter-trace-otlp-http": ["@opentelemetry/exporter-trace-otlp-http@0.203.0", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-trace-base": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-ZDiaswNYo0yq/cy1bBLJFe691izEJ6IgNmkjm4C6kE9ub/OMQqDXORx2D2j8fzTBTxONyzusbaZlqtfmyqURPw=="], + + "@opentelemetry/exporter-trace-otlp-proto": ["@opentelemetry/exporter-trace-otlp-proto@0.203.0", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-trace-base": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-1xwNTJ86L0aJmWRwENCJlH4LULMG2sOXWIVw+Szta4fkqKVY50Eo4HoVKKq6U9QEytrWCr8+zjw0q/ZOeXpcAQ=="], + + "@opentelemetry/exporter-zipkin": ["@opentelemetry/exporter-zipkin@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-trace-base": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": "^1.0.0" } }, "sha512-a9eeyHIipfdxzCfc2XPrE+/TI3wmrZUDFtG2RRXHSbZZULAny7SyybSvaDvS77a7iib5MPiAvluwVvbGTsHxsw=="], + + "@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.203.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.203.0", "import-in-the-middle": "^1.8.1", "require-in-the-middle": "^7.1.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-ke1qyM+3AK2zPuBPb6Hk/GCsc5ewbLvPNkEuELx/JmANeEp6ZjnZ+wypPAJSucTw0wvCGrUaibDSdcrGFoWxKQ=="], + + "@opentelemetry/otlp-exporter-base": ["@opentelemetry/otlp-exporter-base@0.203.0", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/otlp-transformer": "0.203.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-Wbxf7k+87KyvxFr5D7uOiSq/vHXWommvdnNE7vECO3tAhsA2GfOlpWINCMWUEPdHZ7tCXxw6Epp3vgx3jU7llQ=="], + + "@opentelemetry/otlp-grpc-exporter-base": ["@opentelemetry/otlp-grpc-exporter-base@0.203.0", "", { "dependencies": { "@grpc/grpc-js": "^1.7.1", "@opentelemetry/core": "2.0.1", "@opentelemetry/otlp-exporter-base": "0.203.0", "@opentelemetry/otlp-transformer": "0.203.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-te0Ze1ueJF+N/UOFl5jElJW4U0pZXQ8QklgSfJ2linHN0JJsuaHG8IabEUi2iqxY8ZBDlSiz1Trfv5JcjWWWwQ=="], + + "@opentelemetry/otlp-transformer": ["@opentelemetry/otlp-transformer@0.203.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.203.0", "@opentelemetry/core": "2.0.1", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-logs": "0.203.0", "@opentelemetry/sdk-metrics": "2.0.1", "@opentelemetry/sdk-trace-base": "2.0.1", "protobufjs": "^7.3.0" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-Y8I6GgoCna0qDQ2W6GCRtaF24SnvqvA8OfeTi7fqigD23u8Jpb4R5KFv/pRvrlGagcCLICMIyh9wiejp4TXu/A=="], + + "@opentelemetry/propagator-b3": ["@opentelemetry/propagator-b3@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-Hc09CaQ8Tf5AGLmf449H726uRoBNGPBL4bjr7AnnUpzWMvhdn61F78z9qb6IqB737TffBsokGAK1XykFEZ1igw=="], + + "@opentelemetry/propagator-jaeger": ["@opentelemetry/propagator-jaeger@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-7PMdPBmGVH2eQNb/AtSJizQNgeNTfh6jQFqys6lfhd6P4r+m/nTh3gKPPpaCXVdRQ+z93vfKk+4UGty390283w=="], + + "@opentelemetry/resources": ["@opentelemetry/resources@2.2.0", "", { "dependencies": { "@opentelemetry/core": "2.2.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-1pNQf/JazQTMA0BiO5NINUzH0cbLbbl7mntLa4aJNmCCXSj0q03T5ZXXL0zw4G55TjdL9Tz32cznGClf+8zr5A=="], + + "@opentelemetry/sdk-logs": ["@opentelemetry/sdk-logs@0.203.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.203.0", "@opentelemetry/core": "2.0.1", "@opentelemetry/resources": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": ">=1.4.0 <1.10.0" } }, "sha512-vM2+rPq0Vi3nYA5akQD2f3QwossDnTDLvKbea6u/A2NZ3XDkPxMfo/PNrDoXhDUD/0pPo2CdH5ce/thn9K0kLw=="], + + "@opentelemetry/sdk-metrics": ["@opentelemetry/sdk-metrics@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/resources": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": ">=1.9.0 <1.10.0" } }, "sha512-wf8OaJoSnujMAHWR3g+/hGvNcsC16rf9s1So4JlMiFaFHiE4HpIA3oUh+uWZQ7CNuK8gVW/pQSkgoa5HkkOl0g=="], + + "@opentelemetry/sdk-node": ["@opentelemetry/sdk-node@0.203.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.203.0", "@opentelemetry/core": "2.0.1", "@opentelemetry/exporter-logs-otlp-grpc": "0.203.0", "@opentelemetry/exporter-logs-otlp-http": "0.203.0", "@opentelemetry/exporter-logs-otlp-proto": "0.203.0", "@opentelemetry/exporter-metrics-otlp-grpc": "0.203.0", "@opentelemetry/exporter-metrics-otlp-http": "0.203.0", "@opentelemetry/exporter-metrics-otlp-proto": "0.203.0", "@opentelemetry/exporter-prometheus": "0.203.0", "@opentelemetry/exporter-trace-otlp-grpc": "0.203.0", "@opentelemetry/exporter-trace-otlp-http": "0.203.0", "@opentelemetry/exporter-trace-otlp-proto": "0.203.0", "@opentelemetry/exporter-zipkin": "2.0.1", "@opentelemetry/instrumentation": "0.203.0", "@opentelemetry/propagator-b3": "2.0.1", "@opentelemetry/propagator-jaeger": "2.0.1", "@opentelemetry/resources": "2.0.1", "@opentelemetry/sdk-logs": "0.203.0", "@opentelemetry/sdk-metrics": "2.0.1", "@opentelemetry/sdk-trace-base": "2.0.1", "@opentelemetry/sdk-trace-node": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-zRMvrZGhGVMvAbbjiNQW3eKzW/073dlrSiAKPVWmkoQzah9wfynpVPeL55f9fVIm0GaBxTLcPeukWGy0/Wj7KQ=="], + + "@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.2.0", "", { "dependencies": { "@opentelemetry/core": "2.2.0", "@opentelemetry/resources": "2.2.0", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-xWQgL0Bmctsalg6PaXExmzdedSp3gyKV8mQBwK/j9VGdCDu2fmXIb2gAehBKbkXCpJ4HPkgv3QfoJWRT4dHWbw=="], + + "@opentelemetry/sdk-trace-node": ["@opentelemetry/sdk-trace-node@2.0.1", "", { "dependencies": { "@opentelemetry/context-async-hooks": "2.0.1", "@opentelemetry/core": "2.0.1", "@opentelemetry/sdk-trace-base": "2.0.1" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-UhdbPF19pMpBtCWYP5lHbTogLWx9N0EBxtdagvkn5YtsAnCBZzL7SjktG+ZmupRgifsHMjwUaCCaVmqGfSADmA=="], + + "@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.37.0", "", {}, "sha512-JD6DerIKdJGmRp4jQyX5FlrQjA4tjOw1cvfsPAZXfOOEErMUHjPcPSICS+6WnM0nB0efSFARh0KAZss+bvExOA=="], + + "@orpc/client": ["@orpc/client@1.8.1", "", { "dependencies": { "@orpc/shared": "1.8.1", "@orpc/standard-server": "1.8.1", "@orpc/standard-server-fetch": "1.8.1", "@orpc/standard-server-peer": "1.8.1" } }, "sha512-ewofUqn46yHQxnAOFLwZspQD1k3DPTUCnkqP6aFO1alUMHgLFNb03BKd1rgwUXSWaxWltKD8Db07HNxgltdk4A=="], + + "@orpc/contract": ["@orpc/contract@1.8.1", "", { "dependencies": { "@orpc/client": "1.8.1", "@orpc/shared": "1.8.1", "@standard-schema/spec": "^1.0.0", "openapi-types": "^12.1.3" } }, "sha512-zw0xgRxOyR/otX+4UeGEm0VjuMH/AeVbEuWvPNRJC8xxvQpaPJFo8Nr8eaywqSUZo1DnIS+pkwsdipa7GgFl7A=="], + + "@orpc/interop": ["@orpc/interop@1.8.1", "", {}, "sha512-TA2AQREo3tKQheHPvVs5PY1PqDnNUFGO3c8eb6lrX53npOD6lMi6IPedzeEHaZCqb17bRZ9Skc9Fg1FZ30ckug=="], + + "@orpc/json-schema": ["@orpc/json-schema@1.8.1", "", { "dependencies": { "@orpc/contract": "1.8.1", "@orpc/interop": "1.8.1", "@orpc/openapi": "1.8.1", "@orpc/server": "1.8.1", "@orpc/shared": "1.8.1" } }, "sha512-i3qaaW0iKreD8tgRCqQbqn69LZT2f3f80+idLUeq7zHmHtbhoYlPEmtCfz29+casM719gWkI6QDRtMhDpfQlgw=="], + + "@orpc/openapi": ["@orpc/openapi@1.8.1", "", { "dependencies": { "@orpc/client": "1.8.1", "@orpc/contract": "1.8.1", "@orpc/interop": "1.8.1", "@orpc/openapi-client": "1.8.1", "@orpc/server": "1.8.1", "@orpc/shared": "1.8.1", "@orpc/standard-server": "1.8.1", "rou3": "^0.7.3" } }, "sha512-G1qMCjpVGxJYrU0vMdYOr2WxSiX9C6ZhvafgKN7vOGqC7O5s1D+Ph/cSUe1R9OPZZPouhw75MNjTtKYP5lOrcA=="], + + "@orpc/openapi-client": ["@orpc/openapi-client@1.8.1", "", { "dependencies": { "@orpc/client": "1.8.1", "@orpc/contract": "1.8.1", "@orpc/shared": "1.8.1", "@orpc/standard-server": "1.8.1" } }, "sha512-DlBdRcn0lz2lzBis+d6zfVD8tZ7hM5S0uCjL3jNLNp/3T7RMSbhz/6egBCQW1vRh+kXhBjVyGs1mYEYd7ZWEZw=="], + + "@orpc/otel": ["@orpc/otel@1.10.2", "", { "dependencies": { "@orpc/shared": "1.10.2" }, "peerDependencies": { "@opentelemetry/api": ">=1.9.0", "@opentelemetry/instrumentation": ">=0.203.0" } }, "sha512-0FQ14GTRAaVRdGml2xFqHBcgPR2SH61H/f8RQ0Bo+xGIvKlZIKCzti0KQKwYwfUP3SqxzuuhZJXecpmSm/jhrw=="], + + "@orpc/server": ["@orpc/server@1.8.1", "", { "dependencies": { "@orpc/client": "1.8.1", "@orpc/contract": "1.8.1", "@orpc/interop": "1.8.1", "@orpc/shared": "1.8.1", "@orpc/standard-server": "1.8.1", "@orpc/standard-server-aws-lambda": "1.8.1", "@orpc/standard-server-fetch": "1.8.1", "@orpc/standard-server-node": "1.8.1", "@orpc/standard-server-peer": "1.8.1", "cookie": "^1.0.2" }, "peerDependencies": { "crossws": ">=0.3.4", "ws": ">=8.18.1" }, "optionalPeers": ["crossws", "ws"] }, "sha512-Aei7KJSMG9daNdubREeDYKCnmSRTnZT7V1Cx0NFLYDYqx8Bdil2J2InJghsio6AZdJUWLNq/zMm6QDu3NN2E6g=="], + + "@orpc/shared": ["@orpc/shared@1.8.1", "", { "dependencies": { "radash": "^12.1.1", "type-fest": "^4.39.1" }, "peerDependencies": { "@opentelemetry/api": ">=1.9.0" }, "optionalPeers": ["@opentelemetry/api"] }, "sha512-tlKvjSpqV54tG7tWwBjBcg/RziszZhWNp4Md2ERpLn+hnzgp8XyD0TEFLjWRm1RBAsZptqe/OlYIVEqNa3rg2g=="], + + "@orpc/standard-server": ["@orpc/standard-server@1.8.1", "", { "dependencies": { "@orpc/shared": "1.8.1" } }, "sha512-SgVoxnmRAhrF0usZcz72F8FcneM4Rp+UYMhggwwnCEtjKtKXddg89J/to2bkpH/P5x8JMVI/uE2YXRG8CtU6Cg=="], + + "@orpc/standard-server-aws-lambda": ["@orpc/standard-server-aws-lambda@1.8.1", "", { "dependencies": { "@orpc/shared": "1.8.1", "@orpc/standard-server": "1.8.1", "@orpc/standard-server-fetch": "1.8.1", "@orpc/standard-server-node": "1.8.1" } }, "sha512-5db2k1nhdySkYXMMXCxMuZIXDgo04rrZ6qqIEr1cvKnW5OHadcvxysfMa60WMA4Mzm3pypl2WJKGy36mdm6R8Q=="], + + "@orpc/standard-server-fetch": ["@orpc/standard-server-fetch@1.8.1", "", { "dependencies": { "@orpc/shared": "1.8.1", "@orpc/standard-server": "1.8.1" } }, "sha512-HZNTuLitB6X2nVPBfpbKvHRPNL7LV4J9+mQxr+Xi/hU2I6Fr2KWjNmAxcH1Fn6cOsJ09q9RFIaikUC88CQMnlA=="], + + "@orpc/standard-server-node": ["@orpc/standard-server-node@1.8.1", "", { "dependencies": { "@orpc/shared": "1.8.1", "@orpc/standard-server": "1.8.1", "@orpc/standard-server-fetch": "1.8.1" } }, "sha512-+hKShhdAM2ljCbfvFjZQVhcpZjVXCgrz3ysTNKRsIR+E3aiYXffylL6RDOjLAjfvQyRy7wsPVxPjyqUHGXX4vg=="], + + "@orpc/standard-server-peer": ["@orpc/standard-server-peer@1.8.1", "", { "dependencies": { "@orpc/shared": "1.8.1", "@orpc/standard-server": "1.8.1" } }, "sha512-QDGfi/P0HKxFQCoDUOsIaIfO1KK10qoXDmd6ZfZF9DwFKrnqE6AEpMgz/TVDqLb6mFUzMtvdjrPga8uO9QdnbQ=="], + + "@orpc/zod": ["@orpc/zod@1.8.1", "", { "dependencies": { "@orpc/json-schema": "1.8.1", "@orpc/openapi": "1.8.1", "@orpc/shared": "1.8.1", "escape-string-regexp": "^5.0.0", "wildcard-match": "^5.1.3" }, "peerDependencies": { "@orpc/contract": "1.8.1", "@orpc/server": "1.8.1", "zod": ">=3.25.0" } }, "sha512-2tVvLnPx5xxb2H93FYWfAGFA9N7IrVf8/Bv5aUEg11LiHaYBzDEBwyssiOXQL7/57RJ8RQbpvKYmr19hVrmj8g=="], + + "@paralleldrive/cuid2": ["@paralleldrive/cuid2@2.3.1", "", { "dependencies": { "@noble/hashes": "^1.1.5" } }, "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw=="], + + "@pixiv/three-vrm": ["@pixiv/three-vrm@3.4.3", "", { "dependencies": { "@pixiv/three-vrm-core": "3.4.3", "@pixiv/three-vrm-materials-hdr-emissive-multiplier": "3.4.3", "@pixiv/three-vrm-materials-mtoon": "3.4.3", "@pixiv/three-vrm-materials-v0compat": "3.4.3", "@pixiv/three-vrm-node-constraint": "3.4.3", "@pixiv/three-vrm-springbone": "3.4.3" }, "peerDependencies": { "three": ">=0.137" } }, "sha512-meTTL5WRIsuoVsdbfHcMVUcgnTF/T0C7bPCuWnV6mImHGkImdOS/1+w79arOfabdBQLuKZjvGHtCtdAheLpnKg=="], + + "@pixiv/three-vrm-animation": ["@pixiv/three-vrm-animation@3.4.3", "", { "dependencies": { "@pixiv/three-vrm-core": "3.4.3", "@pixiv/types-vrmc-vrm-1.0": "3.4.3", "@pixiv/types-vrmc-vrm-animation-1.0": "3.4.3" }, "peerDependencies": { "three": ">=0.137" } }, "sha512-gT9WQe/N4J4SL2NQrl7RMfFJ2u1LNKVbG0GCVSCC1V0aUM/vpg6pB+BU99VAjF7btZZBjGaliQUnrs3TVasRjA=="], + + "@pixiv/three-vrm-core": ["@pixiv/three-vrm-core@3.4.3", "", { "dependencies": { "@pixiv/types-vrm-0.0": "3.4.3", "@pixiv/types-vrmc-vrm-1.0": "3.4.3" }, "peerDependencies": { "three": ">=0.137" } }, "sha512-GS6Q0k+rSoOz/v2j79IReVdy95w+cO1WTGXwN4zMk1qH2KyLWLVfWD0eIZ7sF3ZpNjxOAQ/ibr4Oj8Zl+mrBcw=="], + + "@pixiv/three-vrm-materials-hdr-emissive-multiplier": ["@pixiv/three-vrm-materials-hdr-emissive-multiplier@3.4.3", "", { "dependencies": { "@pixiv/types-vrmc-materials-hdr-emissive-multiplier-1.0": "3.4.3" }, "peerDependencies": { "three": ">=0.137" } }, "sha512-HtQJ9Qy+VvdaBDZuNdQVGxi/59H88LHOGYhs7gUJCbf/U69rNkDx4sXBaqIvrF+r2GLphbl51sVSe6M+FBEqMw=="], + + "@pixiv/three-vrm-materials-mtoon": ["@pixiv/three-vrm-materials-mtoon@3.4.3", "", { "dependencies": { "@pixiv/types-vrm-0.0": "3.4.3", "@pixiv/types-vrmc-materials-mtoon-1.0": "3.4.3" }, "peerDependencies": { "three": ">=0.137" } }, "sha512-DvC3Vq+Xud6ipFlMQeXbL9pWXEythEjszOeJTgDmhuzd5ACdMvny9ClWe7sy9T5dtsjVGF36kuNQNXTsXz6UPw=="], + + "@pixiv/three-vrm-materials-v0compat": ["@pixiv/three-vrm-materials-v0compat@3.4.3", "", { "dependencies": { "@pixiv/types-vrm-0.0": "3.4.3", "@pixiv/types-vrmc-materials-mtoon-1.0": "3.4.3" }, "peerDependencies": { "three": ">=0.137" } }, "sha512-xtGSnatekG+1kfe2OG8w58+0MDsjj590qg2M0Yys+KXgSDyGDYX2kR+aS0oIFRfyuHy6wjSmYI04FGbPAEPi9Q=="], + + "@pixiv/three-vrm-node-constraint": ["@pixiv/three-vrm-node-constraint@3.4.3", "", { "dependencies": { "@pixiv/types-vrmc-node-constraint-1.0": "3.4.3" }, "peerDependencies": { "three": ">=0.137" } }, "sha512-YuxIhyCMGqvn78jh87SLDANF0nkBZrSUzCEJEy5iK3QMyxGXjMGiKAcNkWtLAONsG8ivHGSd5Wt5QhiafN55MQ=="], + + "@pixiv/three-vrm-springbone": ["@pixiv/three-vrm-springbone@3.4.3", "", { "dependencies": { "@pixiv/types-vrm-0.0": "3.4.3", "@pixiv/types-vrmc-springbone-1.0": "3.4.3", "@pixiv/types-vrmc-springbone-extended-collider-1.0": "3.4.3" }, "peerDependencies": { "three": ">=0.137" } }, "sha512-p68HDhKhdR55C53k4YSKIUs3OFthDMPsk87f8INOiRBXC7YBfvMFqmjyafNPildJ+G4VWWjurkLaPdNts41iFg=="], + + "@pixiv/types-vrm-0.0": ["@pixiv/types-vrm-0.0@3.4.3", "", {}, "sha512-7px2JNCc4SQvLMOzUaeZbvPYY+WV9AKNVEVg5VwcA6VmL95knkrSRwKpOr2D+WhfI0pjELXfv6r/6BBDOQ6fjQ=="], + + "@pixiv/types-vrmc-materials-hdr-emissive-multiplier-1.0": ["@pixiv/types-vrmc-materials-hdr-emissive-multiplier-1.0@3.4.3", "", {}, "sha512-EGlyBeQEipAuD+ITNIbVwmI/poAkF57tA2Vq8P0JIFIa3Uo7zQuIBLtoeMHWWJZA1zFqDu/J3pSYnlFC4POSeA=="], + + "@pixiv/types-vrmc-materials-mtoon-1.0": ["@pixiv/types-vrmc-materials-mtoon-1.0@3.4.3", "", {}, "sha512-BWIuCyz0pznwZRiUrVs/hcXDHVnLi8tsQyoyamo4GzthLXOjKmxE/De9vZULVlTl+5Iy/COlLkUBixqDONWlYg=="], + + "@pixiv/types-vrmc-node-constraint-1.0": ["@pixiv/types-vrmc-node-constraint-1.0@3.4.3", "", {}, "sha512-VrJ6V+gLjZSu1B1UKNI0kl+0GHTvcNgSiZFhkd/AC70HOp/wTSGf6oIVE5e0g8unXXMczUgED/BAPk5ppTPKbQ=="], + + "@pixiv/types-vrmc-springbone-1.0": ["@pixiv/types-vrmc-springbone-1.0@3.4.3", "", {}, "sha512-RLnZnV/0frGE9XaYsO5rFtqQ0q69vWvdJot/V3E7EXgU5tSUPsqA8hPPpKXafYDJ7KyqYREMoiAc8SGMOENV1w=="], + + "@pixiv/types-vrmc-springbone-extended-collider-1.0": ["@pixiv/types-vrmc-springbone-extended-collider-1.0@3.4.3", "", {}, "sha512-BTOLufH42uj8dyRsUVY10XLYhwVVoXH9TqasELyqy5aFzL0ELe9mbzvWdfqva3gsgZNkrqfvTkAwwlLzz48VJg=="], + + "@pixiv/types-vrmc-vrm-1.0": ["@pixiv/types-vrmc-vrm-1.0@3.4.3", "", {}, "sha512-6ucxefth1KW+0nkSV5b2DRIR3RIZRNa+g4RBsOCwwill/tLaNKxqsfAdvbvIi7OsxnwSMDWB53relBdIlsoW0w=="], + + "@pixiv/types-vrmc-vrm-animation-1.0": ["@pixiv/types-vrmc-vrm-animation-1.0@3.4.3", "", { "dependencies": { "@pixiv/types-vrmc-vrm-1.0": "2.0.3" } }, "sha512-NuYgMxmA5JI+yWXSlUBHLWsbdQFV9mJC3rr0jDUxF0n+vdN3b8KlVALp8OlYC/rTrW0cflePAVlxzl3teah62w=="], + + "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], + + "@protobufjs/aspromise": ["@protobufjs/aspromise@1.1.2", "", {}, "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ=="], + + "@protobufjs/base64": ["@protobufjs/base64@1.1.2", "", {}, "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="], + + "@protobufjs/codegen": ["@protobufjs/codegen@2.0.4", "", {}, "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg=="], + + "@protobufjs/eventemitter": ["@protobufjs/eventemitter@1.1.0", "", {}, "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q=="], + + "@protobufjs/fetch": ["@protobufjs/fetch@1.1.0", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" } }, "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ=="], + + "@protobufjs/float": ["@protobufjs/float@1.0.2", "", {}, "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ=="], + + "@protobufjs/inquire": ["@protobufjs/inquire@1.1.0", "", {}, "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q=="], + + "@protobufjs/path": ["@protobufjs/path@1.1.2", "", {}, "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA=="], + + "@protobufjs/pool": ["@protobufjs/pool@1.1.0", "", {}, "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw=="], + + "@protobufjs/utf8": ["@protobufjs/utf8@1.1.0", "", {}, "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw=="], + + "@radix-ui/number": ["@radix-ui/number@1.1.1", "", {}, "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="], + + "@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="], + + "@radix-ui/react-accessible-icon": ["@radix-ui/react-accessible-icon@1.1.7", "", { "dependencies": { "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-XM+E4WXl0OqUJFovy6GjmxxFyx9opfCAIUku4dlKRd5YEPqt4kALOkQOp0Of6reHuUkJuiPBEc5k0o4z4lTC8A=="], + + "@radix-ui/react-accordion": ["@radix-ui/react-accordion@1.2.12", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collapsible": "1.1.12", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA=="], + + "@radix-ui/react-alert-dialog": ["@radix-ui/react-alert-dialog@1.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dialog": "1.1.15", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-oTVLkEw5GpdRe29BqJ0LSDFWI3qu0vR1M0mUkOQWDIUnY/QIkLpgDMWuKxP94c2NAC2LGcgVhG1ImF3jkZ5wXw=="], + + "@radix-ui/react-arrow": ["@radix-ui/react-arrow@1.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w=="], + + "@radix-ui/react-aspect-ratio": ["@radix-ui/react-aspect-ratio@1.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Yq6lvO9HQyPwev1onK1daHCHqXVLzPhSVjmsNjCa2Zcxy2f7uJD2itDtxknv6FzAKCwD1qQkeVDmX/cev13n/g=="], + + "@radix-ui/react-avatar": ["@radix-ui/react-avatar@1.1.10", "", { "dependencies": { "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-is-hydrated": "0.1.0", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-V8piFfWapM5OmNCXTzVQY+E1rDa53zY+MQ4Y7356v4fFz6vqCyUtIz2rUD44ZEdwg78/jKmMJHj07+C/Z/rcog=="], + + "@radix-ui/react-checkbox": ["@radix-ui/react-checkbox@1.3.3", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-wBbpv+NQftHDdG86Qc0pIyXk5IR3tM8Vd0nWLKDcX8nNn4nXFOFwsKuqw2okA/1D/mpaAkmuyndrPJTYDNZtFw=="], + + "@radix-ui/react-collapsible": ["@radix-ui/react-collapsible@1.1.12", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA=="], + + "@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw=="], + + "@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg=="], + + "@radix-ui/react-context": ["@radix-ui/react-context@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA=="], + + "@radix-ui/react-context-menu": ["@radix-ui/react-context-menu@2.2.16", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-menu": "2.1.16", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-O8morBEW+HsVG28gYDZPTrT9UUovQUlJue5YO836tiTJhuIWBm/zQHc7j388sHWtdH/xUZurK9olD2+pcqx5ww=="], + + "@radix-ui/react-dialog": ["@radix-ui/react-dialog@1.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw=="], + + "@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw=="], + + "@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-escape-keydown": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg=="], + + "@radix-ui/react-dropdown-menu": ["@radix-ui/react-dropdown-menu@2.1.16", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-menu": "2.1.16", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw=="], + + "@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.3", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw=="], + + "@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw=="], + + "@radix-ui/react-form": ["@radix-ui/react-form@0.1.8", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-label": "2.1.7", "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-QM70k4Zwjttifr5a4sZFts9fn8FzHYvQ5PiB19O2HsYibaHSVt9fH9rzB0XZo/YcM+b7t/p7lYCT/F5eOeF5yQ=="], + + "@radix-ui/react-hover-card": ["@radix-ui/react-hover-card@1.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-qgTkjNT1CfKMoP0rcasmlH2r1DAiYicWsDsufxl940sT2wHNEWWv6FMWIQXWhVdmC1d/HYfbhQx60KYyAtKxjg=="], + + "@radix-ui/react-id": ["@radix-ui/react-id@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg=="], + + "@radix-ui/react-label": ["@radix-ui/react-label@2.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ=="], + + "@radix-ui/react-menu": ["@radix-ui/react-menu@2.1.16", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-callback-ref": "1.1.1", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg=="], + + "@radix-ui/react-menubar": ["@radix-ui/react-menubar@1.1.16", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-menu": "2.1.16", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-EB1FktTz5xRRi2Er974AUQZWg2yVBb1yjip38/lgwtCVRd3a+maUoGHN/xs9Yv8SY8QwbSEb+YrxGadVWbEutA=="], + + "@radix-ui/react-navigation-menu": ["@radix-ui/react-navigation-menu@1.2.14", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-YB9mTFQvCOAQMHU+C/jVl96WmuWeltyUEpRJJky51huhds5W2FQr1J8D/16sQlf0ozxkPK8uF3niQMdUwZPv5w=="], + + "@radix-ui/react-one-time-password-field": ["@radix-ui/react-one-time-password-field@0.1.8", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-is-hydrated": "0.1.0", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-ycS4rbwURavDPVjCb5iS3aG4lURFDILi6sKI/WITUMZ13gMmn/xGjpLoqBAalhJaDk8I3UbCM5GzKHrnzwHbvg=="], + + "@radix-ui/react-password-toggle-field": ["@radix-ui/react-password-toggle-field@0.1.3", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-is-hydrated": "0.1.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-/UuCrDBWravcaMix4TdT+qlNdVwOM1Nck9kWx/vafXsdfj1ChfhOdfi3cy9SGBpWgTXwYCuboT/oYpJy3clqfw=="], + + "@radix-ui/react-popover": ["@radix-ui/react-popover@1.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA=="], + + "@radix-ui/react-popper": ["@radix-ui/react-popper@1.2.8", "", { "dependencies": { "@floating-ui/react-dom": "^2.0.0", "@radix-ui/react-arrow": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-rect": "1.1.1", "@radix-ui/react-use-size": "1.1.1", "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw=="], + + "@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.9", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ=="], + + "@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.5", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ=="], + + "@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], + + "@radix-ui/react-progress": ["@radix-ui/react-progress@1.1.7", "", { "dependencies": { "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-vPdg/tF6YC/ynuBIJlk1mm7Le0VgW6ub6J2UWnTQ7/D23KXcPI1qy+0vBkgKgd38RCMJavBXpB83HPNFMTb0Fg=="], + + "@radix-ui/react-radio-group": ["@radix-ui/react-radio-group@1.3.8", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ=="], + + "@radix-ui/react-roving-focus": ["@radix-ui/react-roving-focus@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA=="], + + "@radix-ui/react-scroll-area": ["@radix-ui/react-scroll-area@1.2.10", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A=="], + + "@radix-ui/react-select": ["@radix-ui/react-select@2.2.6", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-visually-hidden": "1.2.3", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ=="], + + "@radix-ui/react-separator": ["@radix-ui/react-separator@1.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA=="], + + "@radix-ui/react-slider": ["@radix-ui/react-slider@1.3.6", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw=="], + + "@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], + + "@radix-ui/react-switch": ["@radix-ui/react-switch@1.2.6", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ=="], + + "@radix-ui/react-tabs": ["@radix-ui/react-tabs@1.1.13", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A=="], + + "@radix-ui/react-toast": ["@radix-ui/react-toast@1.2.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-3OSz3TacUWy4WtOXV38DggwxoqJK4+eDkNMl5Z/MJZaoUPaP4/9lf81xXMe1I2ReTAptverZUpbPY4wWwWyL5g=="], + + "@radix-ui/react-toggle": ["@radix-ui/react-toggle@1.1.10", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-lS1odchhFTeZv3xwHH31YPObmJn8gOg7Lq12inrr0+BH/l3Tsq32VfjqH1oh80ARM3mlkfMic15n0kg4sD1poQ=="], + + "@radix-ui/react-toggle-group": ["@radix-ui/react-toggle-group@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-toggle": "1.1.10", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-5umnS0T8JQzQT6HbPyO7Hh9dgd82NmS36DQr+X/YJ9ctFNCiiQd6IJAYYZ33LUwm8M+taCz5t2ui29fHZc4Y6Q=="], + + "@radix-ui/react-toolbar": ["@radix-ui/react-toolbar@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-separator": "1.1.7", "@radix-ui/react-toggle-group": "1.1.11" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-4ol06/1bLoFu1nwUqzdD4Y5RZ9oDdKeiHIsntug54Hcr1pgaHiPqHFEaXI1IFP/EsOfROQZ8Mig9VTIRza6Tjg=="], + + "@radix-ui/react-tooltip": ["@radix-ui/react-tooltip@1.2.8", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg=="], + + "@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg=="], + + "@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.2.2", "", { "dependencies": { "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg=="], + + "@radix-ui/react-use-effect-event": ["@radix-ui/react-use-effect-event@0.0.2", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA=="], + + "@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.1", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g=="], + + "@radix-ui/react-use-is-hydrated": ["@radix-ui/react-use-is-hydrated@0.1.0", "", { "dependencies": { "use-sync-external-store": "^1.5.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA=="], + + "@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="], + + "@radix-ui/react-use-previous": ["@radix-ui/react-use-previous@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ=="], + + "@radix-ui/react-use-rect": ["@radix-ui/react-use-rect@1.1.1", "", { "dependencies": { "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w=="], + + "@radix-ui/react-use-size": ["@radix-ui/react-use-size@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ=="], + + "@radix-ui/react-visually-hidden": ["@radix-ui/react-visually-hidden@1.2.3", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug=="], + + "@radix-ui/rect": ["@radix-ui/rect@1.1.1", "", {}, "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="], + + "@react-three/drei": ["@react-three/drei@10.7.6", "", { "dependencies": { "@babel/runtime": "^7.26.0", "@mediapipe/tasks-vision": "0.10.17", "@monogrid/gainmap-js": "^3.0.6", "@use-gesture/react": "^10.3.1", "camera-controls": "^3.1.0", "cross-env": "^7.0.3", "detect-gpu": "^5.0.56", "glsl-noise": "^0.0.0", "hls.js": "^1.5.17", "maath": "^0.10.8", "meshline": "^3.3.1", "stats-gl": "^2.2.8", "stats.js": "^0.17.0", "suspend-react": "^0.1.3", "three-mesh-bvh": "^0.8.3", "three-stdlib": "^2.35.6", "troika-three-text": "^0.52.4", "tunnel-rat": "^0.1.2", "use-sync-external-store": "^1.4.0", "utility-types": "^3.11.0", "zustand": "^5.0.1" }, "peerDependencies": { "@react-three/fiber": "^9.0.0", "react": "^19", "react-dom": "^19", "three": ">=0.159" }, "optionalPeers": ["react-dom"] }, "sha512-ZSFwRlRaa4zjtB7yHO6Q9xQGuyDCzE7whXBhum92JslcMRC3aouivp0rAzszcVymIoJx6PXmibyP+xr+zKdwLg=="], + + "@react-three/fiber": ["@react-three/fiber@9.4.0", "", { "dependencies": { "@babel/runtime": "^7.17.8", "@types/react-reconciler": "^0.32.0", "@types/webxr": "*", "base64-js": "^1.5.1", "buffer": "^6.0.3", "its-fine": "^2.0.0", "react-reconciler": "^0.31.0", "react-use-measure": "^2.1.7", "scheduler": "^0.25.0", "suspend-react": "^0.1.3", "use-sync-external-store": "^1.4.0", "zustand": "^5.0.3" }, "peerDependencies": { "expo": ">=43.0", "expo-asset": ">=8.4", "expo-file-system": ">=11.0", "expo-gl": ">=11.0", "react": "^19.0.0", "react-dom": "^19.0.0", "react-native": ">=0.78", "three": ">=0.156" }, "optionalPeers": ["expo", "expo-asset", "expo-file-system", "expo-gl", "react-dom", "react-native"] }, "sha512-k4iu1R6e5D54918V4sqmISUkI5OgTw3v7/sDRKEC632Wd5g2WBtUS5gyG63X0GJO/HZUj1tsjSXfyzwrUHZl1g=="], + + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.52.5", "", { "os": "linux", "cpu": "x64" }, "sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q=="], + + "@schummar/icu-type-parser": ["@schummar/icu-type-parser@1.21.5", "", {}, "sha512-bXHSaW5jRTmke9Vd0h5P7BtWZG9Znqb8gSDxZnxaGSJnGwPLDPfS+3g0BKzeWqzgZPsIVZkM7m2tbo18cm5HBw=="], + + "@shikijs/core": ["@shikijs/core@1.29.2", "", { "dependencies": { "@shikijs/engine-javascript": "1.29.2", "@shikijs/engine-oniguruma": "1.29.2", "@shikijs/types": "1.29.2", "@shikijs/vscode-textmate": "^10.0.1", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.4" } }, "sha512-vju0lY9r27jJfOY4Z7+Rt/nIOjzJpZ3y+nYpqtUZInVoXQ/TJZcfGnNOGnKjFdVZb8qexiCuSlZRKcGfhhTTZQ=="], + + "@shikijs/engine-javascript": ["@shikijs/engine-javascript@1.29.2", "", { "dependencies": { "@shikijs/types": "1.29.2", "@shikijs/vscode-textmate": "^10.0.1", "oniguruma-to-es": "^2.2.0" } }, "sha512-iNEZv4IrLYPv64Q6k7EPpOCE/nuvGiKl7zxdq0WFuRPF5PAE9PRo2JGq/d8crLusM59BRemJ4eOqrFrC4wiQ+A=="], + + "@shikijs/engine-oniguruma": ["@shikijs/engine-oniguruma@1.29.2", "", { "dependencies": { "@shikijs/types": "1.29.2", "@shikijs/vscode-textmate": "^10.0.1" } }, "sha512-7iiOx3SG8+g1MnlzZVDYiaeHe7Ez2Kf2HrJzdmGwkRisT7r4rak0e655AcM/tF9JG/kg5fMNYlLLKglbN7gBqA=="], + + "@shikijs/langs": ["@shikijs/langs@1.29.2", "", { "dependencies": { "@shikijs/types": "1.29.2" } }, "sha512-FIBA7N3LZ+223U7cJDUYd5shmciFQlYkFXlkKVaHsCPgfVLiO+e12FmQE6Tf9vuyEsFe3dIl8qGWKXgEHL9wmQ=="], + + "@shikijs/themes": ["@shikijs/themes@1.29.2", "", { "dependencies": { "@shikijs/types": "1.29.2" } }, "sha512-i9TNZlsq4uoyqSbluIcZkmPL9Bfi3djVxRnofUHwvx/h6SRW3cwgBC5SML7vsDcWyukY0eCzVN980rqP6qNl9g=="], + + "@shikijs/types": ["@shikijs/types@1.29.2", "", { "dependencies": { "@shikijs/vscode-textmate": "^10.0.1", "@types/hast": "^3.0.4" } }, "sha512-VJjK0eIijTZf0QSTODEXCqinjBn0joAHQ+aPSBzrv4O2d/QSbsMw+ZeSRx03kV34Hy7NzUvV/7NqfYGRLrASmw=="], + + "@shikijs/vscode-textmate": ["@shikijs/vscode-textmate@10.0.2", "", {}, "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg=="], + + "@sqltools/formatter": ["@sqltools/formatter@1.2.5", "", {}, "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw=="], + + "@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="], + + "@swc/helpers": ["@swc/helpers@0.5.15", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g=="], + + "@swetrix/nextjs": ["@swetrix/nextjs@1.0.1", "", { "dependencies": { "swetrix": "^1.3.1" }, "peerDependencies": { "next": "^10 || ^11 || ^12", "react": "^16 || ^17 || ^18" } }, "sha512-GmqFWPHJuSz4POD427KHBE/Zw/9cimEg5Tq1Q5vMYx9ribT9bn1sW32tjoMhSpOyO9xep3lBmO5uMrYnziDfGQ=="], + + "@tailwindcss/node": ["@tailwindcss/node@4.1.16", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "enhanced-resolve": "^5.18.3", "jiti": "^2.6.1", "lightningcss": "1.30.2", "magic-string": "^0.30.19", "source-map-js": "^1.2.1", "tailwindcss": "4.1.16" } }, "sha512-BX5iaSsloNuvKNHRN3k2RcCuTEgASTo77mofW0vmeHkfrDWaoFAFvNHpEgtu0eqyypcyiBkDWzSMxJhp3AUVcw=="], + + "@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.16", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.16", "@tailwindcss/oxide-darwin-arm64": "4.1.16", "@tailwindcss/oxide-darwin-x64": "4.1.16", "@tailwindcss/oxide-freebsd-x64": "4.1.16", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.16", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.16", "@tailwindcss/oxide-linux-arm64-musl": "4.1.16", "@tailwindcss/oxide-linux-x64-gnu": "4.1.16", "@tailwindcss/oxide-linux-x64-musl": "4.1.16", "@tailwindcss/oxide-wasm32-wasi": "4.1.16", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.16", "@tailwindcss/oxide-win32-x64-msvc": "4.1.16" } }, "sha512-2OSv52FRuhdlgyOQqgtQHuCgXnS8nFSYRp2tJ+4WZXKgTxqPy7SMSls8c3mPT5pkZ17SBToGM5LHEJBO7miEdg=="], + + "@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.16", "", { "os": "android", "cpu": "arm64" }, "sha512-8+ctzkjHgwDJ5caq9IqRSgsP70xhdhJvm+oueS/yhD5ixLhqTw9fSL1OurzMUhBwE5zK26FXLCz2f/RtkISqHA=="], + + "@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.16", "", { "os": "darwin", "cpu": "arm64" }, "sha512-C3oZy5042v2FOALBZtY0JTDnGNdS6w7DxL/odvSny17ORUnaRKhyTse8xYi3yKGyfnTUOdavRCdmc8QqJYwFKA=="], + + "@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.16", "", { "os": "darwin", "cpu": "x64" }, "sha512-vjrl/1Ub9+JwU6BP0emgipGjowzYZMjbWCDqwA2Z4vCa+HBSpP4v6U2ddejcHsolsYxwL5r4bPNoamlV0xDdLg=="], + + "@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.16", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TSMpPYpQLm+aR1wW5rKuUuEruc/oOX3C7H0BTnPDn7W/eMw8W+MRMpiypKMkXZfwH8wqPIRKppuZoedTtNj2tg=="], + + "@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.16", "", { "os": "linux", "cpu": "arm" }, "sha512-p0GGfRg/w0sdsFKBjMYvvKIiKy/LNWLWgV/plR4lUgrsxFAoQBFrXkZ4C0w8IOXfslB9vHK/JGASWD2IefIpvw=="], + + "@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.16", "", { "os": "linux", "cpu": "arm64" }, "sha512-DoixyMmTNO19rwRPdqviTrG1rYzpxgyYJl8RgQvdAQUzxC1ToLRqtNJpU/ATURSKgIg6uerPw2feW0aS8SNr/w=="], + + "@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.16", "", { "os": "linux", "cpu": "arm64" }, "sha512-H81UXMa9hJhWhaAUca6bU2wm5RRFpuHImrwXBUvPbYb+3jo32I9VIwpOX6hms0fPmA6f2pGVlybO6qU8pF4fzQ=="], + + "@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.16", "", { "os": "linux", "cpu": "x64" }, "sha512-ZGHQxDtFC2/ruo7t99Qo2TTIvOERULPl5l0K1g0oK6b5PGqjYMga+FcY1wIUnrUxY56h28FxybtDEla+ICOyew=="], + + "@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.16", "", { "os": "linux", "cpu": "x64" }, "sha512-Oi1tAaa0rcKf1Og9MzKeINZzMLPbhxvm7rno5/zuP1WYmpiG0bEHq4AcRUiG2165/WUzvxkW4XDYCscZWbTLZw=="], + + "@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.1.16", "", { "dependencies": { "@emnapi/core": "^1.5.0", "@emnapi/runtime": "^1.5.0", "@emnapi/wasi-threads": "^1.1.0", "@napi-rs/wasm-runtime": "^1.0.7", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.4.0" }, "cpu": "none" }, "sha512-B01u/b8LteGRwucIBmCQ07FVXLzImWESAIMcUU6nvFt/tYsQ6IHz8DmZ5KtvmwxD+iTYBtM1xwoGXswnlu9v0Q=="], + + "@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.16", "", { "os": "win32", "cpu": "arm64" }, "sha512-zX+Q8sSkGj6HKRTMJXuPvOcP8XfYON24zJBRPlszcH1Np7xuHXhWn8qfFjIujVzvH3BHU+16jBXwgpl20i+v9A=="], + + "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.16", "", { "os": "win32", "cpu": "x64" }, "sha512-m5dDFJUEejbFqP+UXVstd4W/wnxA4F61q8SoL+mqTypId2T2ZpuxosNSgowiCnLp2+Z+rivdU0AqpfgiD7yCBg=="], + + "@tailwindcss/postcss": ["@tailwindcss/postcss@4.1.16", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "@tailwindcss/node": "4.1.16", "@tailwindcss/oxide": "4.1.16", "postcss": "^8.4.41", "tailwindcss": "4.1.16" } }, "sha512-Qn3SFGPXYQMKR/UtqS+dqvPrzEeBZHrFA92maT4zijCVggdsXnDBMsPFJo1eArX3J+O+Gi+8pV4PkqjLCNBk3A=="], + + "@tweenjs/tween.js": ["@tweenjs/tween.js@23.1.3", "", {}, "sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA=="], + + "@types/draco3d": ["@types/draco3d@1.4.10", "", {}, "sha512-AX22jp8Y7wwaBgAixaSvkoG4M/+PlAcm3Qs4OW8yT9DM4xUpWKeFhLueTAyZF39pviAdcDdeJoACapiAceqNcw=="], + + "@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="], + + "@types/js-cookie": ["@types/js-cookie@2.2.7", "", {}, "sha512-aLkWa0C0vO5b4Sr798E26QgOkss68Un0bLjs7u9qxzPT5CG+8DuNTffWES58YzJs3hrVAOs1wonycqEBqNJubA=="], + + "@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="], + + "@types/node": ["@types/node@20.19.23", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-yIdlVVVHXpmqRhtyovZAcSy0MiPcYWGkoO4CGe/+jpP0hmNuihm4XhHbADpK++MsiLHP5MVlv+bcgdF99kSiFQ=="], + + "@types/offscreencanvas": ["@types/offscreencanvas@2019.7.3", "", {}, "sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A=="], + + "@types/react": ["@types/react@19.2.2", "", { "dependencies": { "csstype": "^3.0.2" } }, "sha512-6mDvHUFSjyT2B2yeNx2nUgMxh9LtOWvkhIU3uePn2I2oyNymUAX1NIsdgviM4CH+JSrp2D2hsMvJOkxY+0wNRA=="], + + "@types/react-dom": ["@types/react-dom@18.3.7", "", { "peerDependencies": { "@types/react": "^18.0.0" } }, "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ=="], + + "@types/react-reconciler": ["@types/react-reconciler@0.32.2", "", { "peerDependencies": { "@types/react": "*" } }, "sha512-gjcm6O0aUknhYaogEl8t5pecPfiOTD8VQkbjOhgbZas/E6qGY+veW9iuJU/7p4Y1E0EuQ0mArga7VEOUWSlVRA=="], + + "@types/stats.js": ["@types/stats.js@0.17.4", "", {}, "sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA=="], + + "@types/three": ["@types/three@0.176.0", "", { "dependencies": { "@dimforge/rapier3d-compat": "^0.12.0", "@tweenjs/tween.js": "~23.1.3", "@types/stats.js": "*", "@types/webxr": "*", "@webgpu/types": "*", "fflate": "~0.8.2", "meshoptimizer": "~0.18.1" } }, "sha512-FwfPXxCqOtP7EdYMagCFePNKoG1AGBDUEVKtluv2BTVRpSt7b+X27xNsirPCTCqY1pGYsPUzaM3jgWP7dXSxlw=="], + + "@types/unist": ["@types/unist@3.0.3", "", {}, "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q=="], + + "@types/webxr": ["@types/webxr@0.5.24", "", {}, "sha512-h8fgEd/DpoS9CBrjEQXR+dIDraopAEfu4wYVNY2tEPwk60stPWhvZMf4Foo5FakuQ7HFZoa8WceaWFervK2Ovg=="], + + "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="], + + "@use-gesture/core": ["@use-gesture/core@10.3.1", "", {}, "sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw=="], + + "@use-gesture/react": ["@use-gesture/react@10.3.1", "", { "dependencies": { "@use-gesture/core": "10.3.1" }, "peerDependencies": { "react": ">= 16.8.0" } }, "sha512-Yy19y6O2GJq8f7CHf7L0nxL8bf4PZCPaVOCgJrusOeFHY1LvHgYXnmnXg6N5iwAnbgbZCDjo60SiM6IPJi9C5g=="], + + "@webgpu/types": ["@webgpu/types@0.1.66", "", {}, "sha512-YA2hLrwLpDsRueNDXIMqN9NTzD6bCDkuXbOSe0heS+f8YE8usA6Gbv1prj81pzVHrbaAma7zObnIC+I6/sXJgA=="], + + "@xobotyi/scrollbar-width": ["@xobotyi/scrollbar-width@1.9.5", "", {}, "sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ=="], + + "acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="], + + "acorn-import-attributes": ["acorn-import-attributes@1.9.5", "", { "peerDependencies": { "acorn": "^8" } }, "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ=="], + + "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + + "ansis": ["ansis@3.17.0", "", {}, "sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg=="], + + "app-root-path": ["app-root-path@3.1.0", "", {}, "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA=="], + + "aria-hidden": ["aria-hidden@1.2.6", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA=="], + + "available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="], + + "babel-plugin-react-compiler": ["babel-plugin-react-compiler@1.0.0", "", { "dependencies": { "@babel/types": "^7.26.0" } }, "sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw=="], + + "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "base-x": ["base-x@5.0.1", "", {}, "sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg=="], + + "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], + + "bidi-js": ["bidi-js@1.0.3", "", { "dependencies": { "require-from-string": "^2.0.2" } }, "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw=="], + + "brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + + "buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], + + "c15t": ["c15t@1.7.1", "", { "dependencies": { "@c15t/backend": "1.7.1", "@c15t/translations": "1.7.0", "@orpc/client": "1.8.1", "@orpc/server": "1.8.1", "zustand": "^5.0.3" } }, "sha512-MXQt0zsqTRbUs+9dNc9PivauJWc9232akbotS3NmUXnkMLBxYsCduSvqe560HDVVj0uhIQmYx0Yp0JbvHp/5yw=="], + + "call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="], + + "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], + + "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="], + + "camera-controls": ["camera-controls@3.1.1", "", { "peerDependencies": { "three": ">=0.126.1" } }, "sha512-zC3DcoQPJ0CbTZ8WHthzi8nMvVF71cppOTBcH4cMLreMkU3y3fzBPViGvz1BefWPo9+kv9BP41tvIsabsXTz+Q=="], + + "caniuse-lite": ["caniuse-lite@1.0.30001751", "", {}, "sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw=="], + + "ccount": ["ccount@2.0.1", "", {}, "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg=="], + + "chalk": ["chalk@5.6.2", "", {}, "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA=="], + + "character-entities-html4": ["character-entities-html4@2.1.0", "", {}, "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA=="], + + "character-entities-legacy": ["character-entities-legacy@3.0.0", "", {}, "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ=="], + + "cjs-module-lexer": ["cjs-module-lexer@1.4.3", "", {}, "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q=="], + + "class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="], + + "client-only": ["client-only@0.0.1", "", {}, "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="], + + "cliui": ["cliui@8.0.1", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="], + + "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], + + "color": ["color@4.2.3", "", { "dependencies": { "color-convert": "^2.0.1", "color-string": "^1.9.0" } }, "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A=="], + + "color-convert": ["color-convert@2.0.1", "", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], + + "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + + "color-string": ["color-string@1.9.1", "", { "dependencies": { "color-name": "^1.0.0", "simple-swizzle": "^0.2.2" } }, "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg=="], + + "comma-separated-tokens": ["comma-separated-tokens@2.0.3", "", {}, "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg=="], + + "commander": ["commander@14.0.2", "", {}, "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ=="], + + "cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="], + + "copy-anything": ["copy-anything@4.0.5", "", { "dependencies": { "is-what": "^5.2.0" } }, "sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA=="], + + "copy-to-clipboard": ["copy-to-clipboard@3.3.3", "", { "dependencies": { "toggle-selection": "^1.0.6" } }, "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA=="], + + "cross-env": ["cross-env@7.0.3", "", { "dependencies": { "cross-spawn": "^7.0.1" }, "bin": { "cross-env": "src/bin/cross-env.js", "cross-env-shell": "src/bin/cross-env-shell.js" } }, "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw=="], + + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + + "css-in-js-utils": ["css-in-js-utils@3.1.0", "", { "dependencies": { "hyphenate-style-name": "^1.0.3" } }, "sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A=="], + + "css-tree": ["css-tree@1.1.3", "", { "dependencies": { "mdn-data": "2.0.14", "source-map": "^0.6.1" } }, "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q=="], + + "csstype": ["csstype@3.1.3", "", {}, "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="], + + "daisyui": ["daisyui@5.3.10", "", {}, "sha512-vmjyPmm0hvFhA95KB6uiGmWakziB2pBv6CUcs5Ka/3iMBMn9S+C3SZYx9G9l2JrgTZ1EFn61F/HrPcwaUm2kLQ=="], + + "dayjs": ["dayjs@1.11.18", "", {}, "sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA=="], + + "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + + "decimal.js": ["decimal.js@10.6.0", "", {}, "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg=="], + + "dedent": ["dedent@1.7.0", "", { "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, "optionalPeers": ["babel-plugin-macros"] }, "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ=="], + + "define-data-property": ["define-data-property@1.1.4", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="], + + "defu": ["defu@6.1.4", "", {}, "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg=="], + + "dequal": ["dequal@2.0.3", "", {}, "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA=="], + + "detect-gpu": ["detect-gpu@5.0.70", "", { "dependencies": { "webgl-constants": "^1.1.1" } }, "sha512-bqerEP1Ese6nt3rFkwPnGbsUF9a4q+gMmpTVVOEzoCyeCc+y7/RvJnQZJx1JwhgQI5Ntg0Kgat8Uu7XpBqnz1w=="], + + "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], + + "detect-node-es": ["detect-node-es@1.1.0", "", {}, "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="], + + "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], + + "dotenv": ["dotenv@16.6.1", "", {}, "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow=="], + + "draco3d": ["draco3d@1.5.7", "", {}, "sha512-m6WCKt/erDXcw+70IJXnG7M3awwQPAsZvJGX5zY7beBqpELw6RDGkYVU0W43AFxye4pDZ5i2Lbyc/NNGqwjUVQ=="], + + "drizzle-orm": ["drizzle-orm@0.44.7", "", { "peerDependencies": { "@aws-sdk/client-rds-data": ">=3", "@cloudflare/workers-types": ">=4", "@electric-sql/pglite": ">=0.2.0", "@libsql/client": ">=0.10.0", "@libsql/client-wasm": ">=0.10.0", "@neondatabase/serverless": ">=0.10.0", "@op-engineering/op-sqlite": ">=2", "@opentelemetry/api": "^1.4.1", "@planetscale/database": ">=1.13", "@prisma/client": "*", "@tidbcloud/serverless": "*", "@types/better-sqlite3": "*", "@types/pg": "*", "@types/sql.js": "*", "@upstash/redis": ">=1.34.7", "@vercel/postgres": ">=0.8.0", "@xata.io/client": "*", "better-sqlite3": ">=7", "bun-types": "*", "expo-sqlite": ">=14.0.0", "gel": ">=2", "knex": "*", "kysely": "*", "mysql2": ">=2", "pg": ">=8", "postgres": ">=3", "sql.js": ">=1", "sqlite3": ">=5" }, "optionalPeers": ["@aws-sdk/client-rds-data", "@cloudflare/workers-types", "@electric-sql/pglite", "@libsql/client", "@libsql/client-wasm", "@neondatabase/serverless", "@op-engineering/op-sqlite", "@opentelemetry/api", "@planetscale/database", "@prisma/client", "@tidbcloud/serverless", "@types/better-sqlite3", "@types/pg", "@types/sql.js", "@upstash/redis", "@vercel/postgres", "@xata.io/client", "better-sqlite3", "bun-types", "expo-sqlite", "gel", "knex", "kysely", "mysql2", "pg", "postgres", "sql.js", "sqlite3"] }, "sha512-quIpnYznjU9lHshEOAYLoZ9s3jweleHlZIAWR/jX9gAWNg/JhQ1wj0KGRf7/Zm+obRrYd9GjPVJg790QY9N5AQ=="], + + "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], + + "eastasianwidth": ["eastasianwidth@0.2.0", "", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="], + + "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "emoji-regex-xs": ["emoji-regex-xs@1.0.0", "", {}, "sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg=="], + + "enhanced-resolve": ["enhanced-resolve@5.18.3", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww=="], + + "error-stack-parser": ["error-stack-parser@2.1.4", "", { "dependencies": { "stackframe": "^1.3.4" } }, "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ=="], + + "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], + + "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], + + "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="], + + "escalade": ["escalade@3.2.0", "", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], + + "escape-string-regexp": ["escape-string-regexp@5.0.0", "", {}, "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="], + + "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], + + "fast-shallow-equal": ["fast-shallow-equal@1.0.0", "", {}, "sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw=="], + + "fastest-stable-stringify": ["fastest-stable-stringify@2.0.2", "", {}, "sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q=="], + + "fflate": ["fflate@0.8.2", "", {}, "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="], + + "for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="], + + "foreground-child": ["foreground-child@3.3.1", "", { "dependencies": { "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" } }, "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw=="], + + "framer-motion": ["framer-motion@12.23.24", "", { "dependencies": { "motion-dom": "^12.23.23", "motion-utils": "^12.23.6", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-HMi5HRoRCTou+3fb3h9oTLyJGBxHfW+HnNE25tAXOvVx/IvwMHK0cx7IR4a2ZU6sh3IX1Z+4ts32PcYBOqka8w=="], + + "fumadb": ["fumadb@0.1.1", "", { "dependencies": { "@clack/prompts": "^0.11.0", "@paralleldrive/cuid2": "^2.2.2", "commander": "^14.0.0", "kysely": "^0.28.3", "kysely-typeorm": "^0.3.0", "semver": "^7.7.2", "zod": "^4.0.5" }, "peerDependencies": { "convex": "^1.25.0", "drizzle-orm": "^0.44.0", "mongodb": "6.x.x", "prisma": "6.x.x", "typeorm": "0.x.x" }, "optionalPeers": ["convex", "drizzle-orm", "mongodb", "prisma", "typeorm"] }, "sha512-p2+qTHEP+8J+hyCmDXQIib1eXNvr3pIIqRcbKkbYEgN/upBOPr6/kfgYCLipdXie73ryYWubom+kWgL010zwkQ=="], + + "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], + + "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="], + + "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], + + "get-nonce": ["get-nonce@1.0.1", "", {}, "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q=="], + + "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], + + "glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="], + + "glsl-noise": ["glsl-noise@0.0.0", "", {}, "sha512-b/ZCF6amfAUb7dJM/MxRs7AetQEahYzJ8PtgfrmEdtw6uyGOr+ZSGtgjFm6mfsBkxJ4d2W7kg+Nlqzqvn3Bc0w=="], + + "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], + + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + + "gsap": ["gsap@3.13.0", "", {}, "sha512-QL7MJ2WMjm1PHWsoFrAQH/J8wUeqZvMtHO58qdekHpCfhvhSL4gSiz6vJf5EeMP0LOn3ZCprL2ki/gjED8ghVw=="], + + "has-property-descriptors": ["has-property-descriptors@1.0.2", "", { "dependencies": { "es-define-property": "^1.0.0" } }, "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg=="], + + "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="], + + "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="], + + "hasown": ["hasown@2.0.2", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ=="], + + "hast-util-to-html": ["hast-util-to-html@9.0.5", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/unist": "^3.0.0", "ccount": "^2.0.0", "comma-separated-tokens": "^2.0.0", "hast-util-whitespace": "^3.0.0", "html-void-elements": "^3.0.0", "mdast-util-to-hast": "^13.0.0", "property-information": "^7.0.0", "space-separated-tokens": "^2.0.0", "stringify-entities": "^4.0.0", "zwitch": "^2.0.4" } }, "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw=="], + + "hast-util-whitespace": ["hast-util-whitespace@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw=="], + + "hls.js": ["hls.js@1.6.13", "", {}, "sha512-hNEzjZNHf5bFrUNvdS4/1RjIanuJ6szpWNfTaX5I6WfGynWXGT7K/YQLYtemSvFExzeMdgdE4SsyVLJbd5PcZA=="], + + "html-void-elements": ["html-void-elements@3.0.0", "", {}, "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg=="], + + "hyphenate-style-name": ["hyphenate-style-name@1.1.0", "", {}, "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw=="], + + "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], + + "immediate": ["immediate@3.0.6", "", {}, "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ=="], + + "import-in-the-middle": ["import-in-the-middle@1.15.0", "", { "dependencies": { "acorn": "^8.14.0", "acorn-import-attributes": "^1.9.5", "cjs-module-lexer": "^1.2.2", "module-details-from-path": "^1.0.3" } }, "sha512-bpQy+CrsRmYmoPMAE/0G33iwRqwW4ouqdRg8jgbH3aKuCtOc8lxgmYXg2dMM92CRiGP660EtBcymH/eVUpCSaA=="], + + "inherits": ["inherits@2.0.4", "", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], + + "inline-style-prefixer": ["inline-style-prefixer@7.0.1", "", { "dependencies": { "css-in-js-utils": "^3.1.0" } }, "sha512-lhYo5qNTQp3EvSSp3sRvXMbVQTLrvGV6DycRMJ5dm2BLMiJ30wpXKdDdgX+GmJZ5uQMucwRKHamXSst3Sj/Giw=="], + + "intl-messageformat": ["intl-messageformat@10.7.18", "", { "dependencies": { "@formatjs/ecma402-abstract": "2.3.6", "@formatjs/fast-memoize": "2.2.7", "@formatjs/icu-messageformat-parser": "2.11.4", "tslib": "^2.8.0" } }, "sha512-m3Ofv/X/tV8Y3tHXLohcuVuhWKo7BBq62cqY15etqmLxg2DZ34AGGgQDeR+SCta2+zICb1NX83af0GJmbQ1++g=="], + + "is-arrayish": ["is-arrayish@0.3.4", "", {}, "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA=="], + + "is-callable": ["is-callable@1.2.7", "", {}, "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="], + + "is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="], + + "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + + "is-promise": ["is-promise@2.2.2", "", {}, "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ=="], + + "is-typed-array": ["is-typed-array@1.1.15", "", { "dependencies": { "which-typed-array": "^1.1.16" } }, "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ=="], + + "is-what": ["is-what@5.5.0", "", {}, "sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw=="], + + "isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="], + + "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + + "its-fine": ["its-fine@2.0.0", "", { "dependencies": { "@types/react-reconciler": "^0.28.9" }, "peerDependencies": { "react": "^19.0.0" } }, "sha512-KLViCmWx94zOvpLwSlsx6yOCeMhZYaxrJV87Po5k/FoZzcPSahvK5qJ7fYhS61sZi5ikmh2S3Hz55A2l3U69ng=="], + + "jackspeak": ["jackspeak@3.4.3", "", { "dependencies": { "@isaacs/cliui": "^8.0.2" }, "optionalDependencies": { "@pkgjs/parseargs": "^0.11.0" } }, "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw=="], + + "jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], + + "js-cookie": ["js-cookie@2.2.1", "", {}, "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ=="], + + "kysely": ["kysely@0.27.6", "", {}, "sha512-FIyV/64EkKhJmjgC0g2hygpBv5RNWVPyNCqSAD7eTCv6eFWNIi4PN1UvdSJGicN/o35bnevgis4Y0UDC0qi8jQ=="], + + "kysely-typeorm": ["kysely-typeorm@0.3.0", "", { "peerDependencies": { "kysely": ">= 0.24.0 < 1", "typeorm": ">= 0.3.0 < 0.4.0" } }, "sha512-xQDx6+HagVmtXeuYd3Sz2CPYc/jOo7JO1ALldYPdwRrbiwSs9GFyNPp5JbElkfZB+T4DRb+A53pKWKYjlgSFeA=="], + + "lie": ["lie@3.3.0", "", { "dependencies": { "immediate": "~3.0.5" } }, "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ=="], + + "lightningcss": ["lightningcss@1.30.2", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.30.2", "lightningcss-darwin-arm64": "1.30.2", "lightningcss-darwin-x64": "1.30.2", "lightningcss-freebsd-x64": "1.30.2", "lightningcss-linux-arm-gnueabihf": "1.30.2", "lightningcss-linux-arm64-gnu": "1.30.2", "lightningcss-linux-arm64-musl": "1.30.2", "lightningcss-linux-x64-gnu": "1.30.2", "lightningcss-linux-x64-musl": "1.30.2", "lightningcss-win32-arm64-msvc": "1.30.2", "lightningcss-win32-x64-msvc": "1.30.2" } }, "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ=="], + + "lightningcss-android-arm64": ["lightningcss-android-arm64@1.30.2", "", { "os": "android", "cpu": "arm64" }, "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A=="], + + "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA=="], + + "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.30.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ=="], + + "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.30.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA=="], + + "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.30.2", "", { "os": "linux", "cpu": "arm" }, "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA=="], + + "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.30.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A=="], + + "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.30.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA=="], + + "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.30.2", "", { "os": "linux", "cpu": "x64" }, "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w=="], + + "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.30.2", "", { "os": "linux", "cpu": "x64" }, "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA=="], + + "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.30.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ=="], + + "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.2", "", { "os": "win32", "cpu": "x64" }, "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw=="], + + "lodash.camelcase": ["lodash.camelcase@4.3.0", "", {}, "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA=="], + + "long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="], + + "lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], + + "lucide-react": ["lucide-react@0.548.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-63b16z63jM9yc1MwxajHeuu0FRZFsDtljtDjYm26Kd86UQ5HQzu9ksEtoUUw4RBuewodw/tGFmvipePvRsKeDA=="], + + "maath": ["maath@0.10.8", "", { "peerDependencies": { "@types/three": ">=0.134.0", "three": ">=0.134.0" } }, "sha512-tRvbDF0Pgqz+9XUa4jjfgAQ8/aPKmQdWXilFu2tMy4GWj4NOsx99HlULO4IeREfbO3a0sA145DZYyvXPkybm0g=="], + + "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], + + "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], + + "mdast-util-to-hast": ["mdast-util-to-hast@13.2.0", "", { "dependencies": { "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "@ungap/structured-clone": "^1.0.0", "devlop": "^1.0.0", "micromark-util-sanitize-uri": "^2.0.0", "trim-lines": "^3.0.0", "unist-util-position": "^5.0.0", "unist-util-visit": "^5.0.0", "vfile": "^6.0.0" } }, "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA=="], + + "mdn-data": ["mdn-data@2.0.14", "", {}, "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow=="], + + "meshline": ["meshline@3.3.1", "", { "peerDependencies": { "three": ">=0.137" } }, "sha512-/TQj+JdZkeSUOl5Mk2J7eLcYTLiQm2IDzmlSvYm7ov15anEcDJ92GHqqazxTSreeNgfnYu24kiEvvv0WlbCdFQ=="], + + "meshoptimizer": ["meshoptimizer@0.18.1", "", {}, "sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw=="], + + "micromark-util-character": ["micromark-util-character@2.1.1", "", { "dependencies": { "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0" } }, "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q=="], + + "micromark-util-encode": ["micromark-util-encode@2.0.1", "", {}, "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw=="], + + "micromark-util-sanitize-uri": ["micromark-util-sanitize-uri@2.0.1", "", { "dependencies": { "micromark-util-character": "^2.0.0", "micromark-util-encode": "^2.0.0", "micromark-util-symbol": "^2.0.0" } }, "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ=="], + + "micromark-util-symbol": ["micromark-util-symbol@2.0.1", "", {}, "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q=="], + + "micromark-util-types": ["micromark-util-types@2.0.2", "", {}, "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA=="], + + "minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], + + "module-details-from-path": ["module-details-from-path@1.0.4", "", {}, "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w=="], + + "motion": ["motion@12.23.24", "", { "dependencies": { "framer-motion": "^12.23.24", "tslib": "^2.4.0" }, "peerDependencies": { "@emotion/is-prop-valid": "*", "react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0 || ^19.0.0" }, "optionalPeers": ["@emotion/is-prop-valid", "react", "react-dom"] }, "sha512-Rc5E7oe2YZ72N//S3QXGzbnXgqNrTESv8KKxABR20q2FLch9gHLo0JLyYo2hZ238bZ9Gx6cWhj9VO0IgwbMjCw=="], + + "motion-dom": ["motion-dom@12.23.23", "", { "dependencies": { "motion-utils": "^12.23.6" } }, "sha512-n5yolOs0TQQBRUFImrRfs/+6X4p3Q4n1dUEqt/H58Vx7OW6RF+foWEgmTVDhIWJIMXOuNNL0apKH2S16en9eiA=="], + + "motion-utils": ["motion-utils@12.23.6", "", {}, "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "nano-css": ["nano-css@5.6.2", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15", "css-tree": "^1.1.2", "csstype": "^3.1.2", "fastest-stable-stringify": "^2.0.2", "inline-style-prefixer": "^7.0.1", "rtl-css-js": "^1.16.1", "stacktrace-js": "^2.0.2", "stylis": "^4.3.0" }, "peerDependencies": { "react": "*", "react-dom": "*" } }, "sha512-+6bHaC8dSDGALM1HJjOHVXpuastdu2xFoZlC77Jh4cg+33Zcgm+Gxd+1xsnpZK14eyHObSp82+ll5y3SX75liw=="], + + "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], + + "negotiator": ["negotiator@1.0.0", "", {}, "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg=="], + + "neverthrow": ["neverthrow@8.2.0", "", { "optionalDependencies": { "@rollup/rollup-linux-x64-gnu": "^4.24.0" } }, "sha512-kOCT/1MCPAxY5iUV3wytNFUMUolzuwd/VF/1KCx7kf6CutrOsTie+84zTGTpgQycjvfLdBBdvBvFLqFD2c0wkQ=="], + + "next": ["next@16.0.0", "", { "dependencies": { "@next/env": "16.0.0", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "16.0.0", "@next/swc-darwin-x64": "16.0.0", "@next/swc-linux-arm64-gnu": "16.0.0", "@next/swc-linux-arm64-musl": "16.0.0", "@next/swc-linux-x64-gnu": "16.0.0", "@next/swc-linux-x64-musl": "16.0.0", "@next/swc-win32-arm64-msvc": "16.0.0", "@next/swc-win32-x64-msvc": "16.0.0", "sharp": "^0.34.4" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-nYohiNdxGu4OmBzggxy9rczmjIGI+TpR5vbKTsE1HqYwNm1B+YSiugSrFguX6omMOKnDHAmBPY4+8TNJk0Idyg=="], + + "next-intl": ["next-intl@4.4.0", "", { "dependencies": { "@formatjs/intl-localematcher": "^0.5.4", "negotiator": "^1.0.0", "use-intl": "^4.4.0" }, "peerDependencies": { "next": "^12.0.0 || ^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0", "typescript": "^5.0.0" }, "optionalPeers": ["typescript"] }, "sha512-QHqnP9V9Pe7Tn0PdVQ7u1Z8k9yCkW5SJKeRy2g5gxzhSt/C01y3B9qNxuj3Fsmup/yreIHe6osxU6sFa+9WIkQ=="], + + "next-themes": ["next-themes@0.4.6", "", { "peerDependencies": { "react": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc", "react-dom": "^16.8 || ^17 || ^18 || ^19 || ^19.0.0-rc" } }, "sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA=="], + + "oniguruma-to-es": ["oniguruma-to-es@2.3.0", "", { "dependencies": { "emoji-regex-xs": "^1.0.0", "regex": "^5.1.1", "regex-recursion": "^5.1.1" } }, "sha512-bwALDxriqfKGfUufKGGepCzu9x7nJQuoRoAFp4AnwehhC2crqrDIAP/uN2qdlsAvSMpeRC3+Yzhqc7hLmle5+g=="], + + "openapi-types": ["openapi-types@12.1.3", "", {}, "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw=="], + + "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], + + "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + + "path-parse": ["path-parse@1.0.7", "", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], + + "path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="], + + "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="], + + "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=="], + + "potpack": ["potpack@1.0.2", "", {}, "sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ=="], + + "promise-worker-transferable": ["promise-worker-transferable@1.0.4", "", { "dependencies": { "is-promise": "^2.1.0", "lie": "^3.0.2" } }, "sha512-bN+0ehEnrXfxV2ZQvU2PetO0n4gqBD4ulq3MI1WOPLgr7/Mg9yRQkX5+0v1vagr74ZTsl7XtzlaYDo2EuCeYJw=="], + + "property-information": ["property-information@7.1.0", "", {}, "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ=="], + + "protobufjs": ["protobufjs@7.5.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.4", "@protobufjs/eventemitter": "^1.1.0", "@protobufjs/fetch": "^1.1.0", "@protobufjs/float": "^1.0.2", "@protobufjs/inquire": "^1.1.0", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.0", "@types/node": ">=13.7.0", "long": "^5.0.0" } }, "sha512-CvexbZtbov6jW2eXAvLukXjXUW1TzFaivC46BpWc/3BpcCysb5Vffu+B3XHMm8lVEuy2Mm4XGex8hBSg1yapPg=="], + + "radash": ["radash@12.1.1", "", {}, "sha512-h36JMxKRqrAxVD8201FrCpyeNuUY9Y5zZwujr20fFO77tpUtGa6EZzfKw/3WaiBX95fq7+MpsuMLNdSnORAwSA=="], + + "radix-ui": ["radix-ui@1.4.3", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-accessible-icon": "1.1.7", "@radix-ui/react-accordion": "1.2.12", "@radix-ui/react-alert-dialog": "1.1.15", "@radix-ui/react-arrow": "1.1.7", "@radix-ui/react-aspect-ratio": "1.1.7", "@radix-ui/react-avatar": "1.1.10", "@radix-ui/react-checkbox": "1.3.3", "@radix-ui/react-collapsible": "1.1.12", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-context-menu": "2.2.16", "@radix-ui/react-dialog": "1.1.15", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-dropdown-menu": "2.1.16", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-form": "0.1.8", "@radix-ui/react-hover-card": "1.1.15", "@radix-ui/react-label": "2.1.7", "@radix-ui/react-menu": "2.1.16", "@radix-ui/react-menubar": "1.1.16", "@radix-ui/react-navigation-menu": "1.2.14", "@radix-ui/react-one-time-password-field": "0.1.8", "@radix-ui/react-password-toggle-field": "0.1.3", "@radix-ui/react-popover": "1.1.15", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-progress": "1.1.7", "@radix-ui/react-radio-group": "1.3.8", "@radix-ui/react-roving-focus": "1.1.11", "@radix-ui/react-scroll-area": "1.2.10", "@radix-ui/react-select": "2.2.6", "@radix-ui/react-separator": "1.1.7", "@radix-ui/react-slider": "1.3.6", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-switch": "1.2.6", "@radix-ui/react-tabs": "1.1.13", "@radix-ui/react-toast": "1.2.15", "@radix-ui/react-toggle": "1.1.10", "@radix-ui/react-toggle-group": "1.1.11", "@radix-ui/react-toolbar": "1.1.11", "@radix-ui/react-tooltip": "1.2.8", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-escape-keydown": "1.1.1", "@radix-ui/react-use-is-hydrated": "0.1.0", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-size": "1.1.1", "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-aWizCQiyeAenIdUbqEpXgRA1ya65P13NKn/W8rWkcN0OPkRDxdBVLWnIEDsS2RpwCK2nobI7oMUSmexzTDyAmA=="], + + "react": ["react@19.2.0", "", {}, "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ=="], + + "react-dom": ["react-dom@19.2.0", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.0" } }, "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ=="], + + "react-icons": ["react-icons@5.5.0", "", { "peerDependencies": { "react": "*" } }, "sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw=="], + + "react-reconciler": ["react-reconciler@0.31.0", "", { "dependencies": { "scheduler": "^0.25.0" }, "peerDependencies": { "react": "^19.0.0" } }, "sha512-7Ob7Z+URmesIsIVRjnLoDGwBEG/tVitidU0nMsqX/eeJaLY89RISO/10ERe0MqmzuKUUB1rmY+h1itMbUHg9BQ=="], + + "react-remove-scroll": ["react-remove-scroll@2.7.1", "", { "dependencies": { "react-remove-scroll-bar": "^2.3.7", "react-style-singleton": "^2.2.3", "tslib": "^2.1.0", "use-callback-ref": "^1.3.3", "use-sidecar": "^1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA=="], + + "react-remove-scroll-bar": ["react-remove-scroll-bar@2.3.8", "", { "dependencies": { "react-style-singleton": "^2.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q=="], + + "react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="], + + "react-universal-interface": ["react-universal-interface@0.6.2", "", { "peerDependencies": { "react": "*", "tslib": "*" } }, "sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw=="], + + "react-use": ["react-use@17.6.0", "", { "dependencies": { "@types/js-cookie": "^2.2.6", "@xobotyi/scrollbar-width": "^1.9.5", "copy-to-clipboard": "^3.3.1", "fast-deep-equal": "^3.1.3", "fast-shallow-equal": "^1.0.0", "js-cookie": "^2.2.1", "nano-css": "^5.6.2", "react-universal-interface": "^0.6.2", "resize-observer-polyfill": "^1.5.1", "screenfull": "^5.1.0", "set-harmonic-interval": "^1.0.1", "throttle-debounce": "^3.0.1", "ts-easing": "^0.2.0", "tslib": "^2.1.0" }, "peerDependencies": { "react": "*", "react-dom": "*" } }, "sha512-OmedEScUMKFfzn1Ir8dBxiLLSOzhKe/dPZwVxcujweSj45aNM7BEGPb9BEVIgVEqEXx6f3/TsXzwIktNgUR02g=="], + + "react-use-measure": ["react-use-measure@2.1.7", "", { "peerDependencies": { "react": ">=16.13", "react-dom": ">=16.13" }, "optionalPeers": ["react-dom"] }, "sha512-KrvcAo13I/60HpwGO5jpW7E9DfusKyLPLvuHlUyP5zqnmAPhNc6qTRjUQrdTADl0lpPpDVU2/Gg51UlOGHXbdg=="], + + "reflect-metadata": ["reflect-metadata@0.2.2", "", {}, "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q=="], + + "regex": ["regex@5.1.1", "", { "dependencies": { "regex-utilities": "^2.3.0" } }, "sha512-dN5I359AVGPnwzJm2jN1k0W9LPZ+ePvoOeVMMfqIMFz53sSwXkxaJoxr50ptnsC771lK95BnTrVSZxq0b9yCGw=="], + + "regex-recursion": ["regex-recursion@5.1.1", "", { "dependencies": { "regex": "^5.1.1", "regex-utilities": "^2.3.0" } }, "sha512-ae7SBCbzVNrIjgSbh7wMznPcQel1DNlDtzensnFxpiNpXt1U2ju/bHugH422r+4LAVS1FpW1YCwilmnNsjum9w=="], + + "regex-utilities": ["regex-utilities@2.3.0", "", {}, "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng=="], + + "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="], + + "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="], + + "require-in-the-middle": ["require-in-the-middle@7.5.2", "", { "dependencies": { "debug": "^4.3.5", "module-details-from-path": "^1.0.3", "resolve": "^1.22.8" } }, "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ=="], + + "resize-observer-polyfill": ["resize-observer-polyfill@1.5.1", "", {}, "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="], + + "resolve": ["resolve@1.22.11", "", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="], + + "rou3": ["rou3@0.7.9", "", {}, "sha512-+JM7c8swGkoXkWRkIz7qpYN9Bls7Rj/vuSGaxtoKHIe8Ba1ci+mXnqzqtJFrXSbvEazNL9v83P2RiXae9NSbfQ=="], + + "rtl-css-js": ["rtl-css-js@1.16.1", "", { "dependencies": { "@babel/runtime": "^7.1.2" } }, "sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg=="], + + "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], + + "scheduler": ["scheduler@0.25.0", "", {}, "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA=="], + + "screenfull": ["screenfull@5.2.0", "", {}, "sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA=="], + + "semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], + + "set-function-length": ["set-function-length@1.2.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2" } }, "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg=="], + + "set-harmonic-interval": ["set-harmonic-interval@1.0.1", "", {}, "sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g=="], + + "sha.js": ["sha.js@2.4.12", "", { "dependencies": { "inherits": "^2.0.4", "safe-buffer": "^5.2.1", "to-buffer": "^1.2.0" }, "bin": { "sha.js": "bin.js" } }, "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w=="], + + "sharp": ["sharp@0.33.5", "", { "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.3", "semver": "^7.6.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.33.5", "@img/sharp-darwin-x64": "0.33.5", "@img/sharp-libvips-darwin-arm64": "1.0.4", "@img/sharp-libvips-darwin-x64": "1.0.4", "@img/sharp-libvips-linux-arm": "1.0.5", "@img/sharp-libvips-linux-arm64": "1.0.4", "@img/sharp-libvips-linux-s390x": "1.0.4", "@img/sharp-libvips-linux-x64": "1.0.4", "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", "@img/sharp-libvips-linuxmusl-x64": "1.0.4", "@img/sharp-linux-arm": "0.33.5", "@img/sharp-linux-arm64": "0.33.5", "@img/sharp-linux-s390x": "0.33.5", "@img/sharp-linux-x64": "0.33.5", "@img/sharp-linuxmusl-arm64": "0.33.5", "@img/sharp-linuxmusl-x64": "0.33.5", "@img/sharp-wasm32": "0.33.5", "@img/sharp-win32-ia32": "0.33.5", "@img/sharp-win32-x64": "0.33.5" } }, "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw=="], + + "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=="], + + "shiki": ["shiki@1.29.2", "", { "dependencies": { "@shikijs/core": "1.29.2", "@shikijs/engine-javascript": "1.29.2", "@shikijs/engine-oniguruma": "1.29.2", "@shikijs/langs": "1.29.2", "@shikijs/themes": "1.29.2", "@shikijs/types": "1.29.2", "@shikijs/vscode-textmate": "^10.0.1", "@types/hast": "^3.0.4" } }, "sha512-njXuliz/cP+67jU2hukkxCNuH1yUi4QfdZZY+sMr5PPrIyXSu5iTb/qYC4BiWWB0vZ+7TbdvYUCeL23zpwCfbg=="], + + "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + + "simple-swizzle": ["simple-swizzle@0.2.4", "", { "dependencies": { "is-arrayish": "^0.3.1" } }, "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw=="], + + "sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="], + + "sonner": ["sonner@1.7.4", "", { "peerDependencies": { "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-DIS8z4PfJRbIyfVFDVnK9rO3eYDtse4Omcm6bt0oEr5/jtLgysmjuBl1frJ9E/EQZrFmKx2A8m/s5s9CRXIzhw=="], + + "source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], + + "source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + + "space-separated-tokens": ["space-separated-tokens@2.0.2", "", {}, "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q=="], + + "sql-highlight": ["sql-highlight@6.1.0", "", {}, "sha512-ed7OK4e9ywpE7pgRMkMQmZDPKSVdm0oX5IEtZiKnFucSF0zu6c80GZBe38UqHuVhTWJ9xsKgSMjCG2bml86KvA=="], + + "stack-generator": ["stack-generator@2.0.10", "", { "dependencies": { "stackframe": "^1.3.4" } }, "sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ=="], + + "stackframe": ["stackframe@1.3.4", "", {}, "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw=="], + + "stacktrace-gps": ["stacktrace-gps@3.1.2", "", { "dependencies": { "source-map": "0.5.6", "stackframe": "^1.3.4" } }, "sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ=="], + + "stacktrace-js": ["stacktrace-js@2.0.2", "", { "dependencies": { "error-stack-parser": "^2.0.6", "stack-generator": "^2.0.5", "stacktrace-gps": "^3.0.4" } }, "sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg=="], + + "stats-gl": ["stats-gl@2.4.2", "", { "dependencies": { "@types/three": "*", "three": "^0.170.0" } }, "sha512-g5O9B0hm9CvnM36+v7SFl39T7hmAlv541tU81ME8YeSb3i1CIP5/QdDeSB3A0la0bKNHpxpwxOVRo2wFTYEosQ=="], + + "stats.js": ["stats.js@0.17.0", "", {}, "sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw=="], + + "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "string-width-cjs": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "stringify-entities": ["stringify-entities@4.0.4", "", { "dependencies": { "character-entities-html4": "^2.0.0", "character-entities-legacy": "^3.0.0" } }, "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg=="], + + "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "styled-jsx": ["styled-jsx@5.1.6", "", { "dependencies": { "client-only": "0.0.1" }, "peerDependencies": { "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" } }, "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA=="], + + "stylis": ["stylis@4.3.6", "", {}, "sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ=="], + + "superjson": ["superjson@2.2.3", "", { "dependencies": { "copy-anything": "^4" } }, "sha512-ay3d+LW/S6yppKoTz3Bq4mG0xrS5bFwfWEBmQfbC7lt5wmtk+Obq0TxVuA9eYRirBTQb1K3eEpBRHMQEo0WyVw=="], + + "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], + + "suspend-react": ["suspend-react@0.1.3", "", { "peerDependencies": { "react": ">=17.0" } }, "sha512-aqldKgX9aZqpoDp3e8/BZ8Dm7x1pJl+qI3ZKxDN0i/IQTWUwBx/ManmlVJ3wowqbno6c2bmiIfs+Um6LbsjJyQ=="], + + "swetrix": ["swetrix@1.3.2", "", { "dependencies": { "@types/node": "^14.18.0" } }, "sha512-vbUPo4Tc/YjUiNO96PiwIznMs1rlHGZE6RKwMGVt8TtJiZEJblNgjjnJ2/+hKQRvp6CMoPkOXILrihdig8Np3g=="], + + "tagged-tag": ["tagged-tag@1.0.0", "", {}, "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng=="], + + "tailwind-merge": ["tailwind-merge@3.3.1", "", {}, "sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g=="], + + "tailwind-variants": ["tailwind-variants@3.1.1", "", { "peerDependencies": { "tailwind-merge": ">=3.0.0", "tailwindcss": "*" }, "optionalPeers": ["tailwind-merge"] }, "sha512-ftLXe3krnqkMHsuBTEmaVUXYovXtPyTK7ckEfDRXS8PBZx0bAUas+A0jYxuKA5b8qg++wvQ3d2MQ7l/xeZxbZQ=="], + + "tailwindcss": ["tailwindcss@4.1.16", "", {}, "sha512-pONL5awpaQX4LN5eiv7moSiSPd/DLDzKVRJz8Q9PgzmAdd1R4307GQS2ZpfiN7ZmekdQrfhZZiSE5jkLR4WNaA=="], + + "tailwindcss-animate": ["tailwindcss-animate@1.0.7", "", { "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders" } }, "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA=="], + + "tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="], + + "three": ["three@0.180.0", "", {}, "sha512-o+qycAMZrh+TsE01GqWUxUIKR1AL0S8pq7zDkYOQw8GqfX8b8VoCKYUoHbhiX5j+7hr8XsuHDVU6+gkQJQKg9w=="], + + "three-mesh-bvh": ["three-mesh-bvh@0.8.3", "", { "peerDependencies": { "three": ">= 0.159.0" } }, "sha512-4G5lBaF+g2auKX3P0yqx+MJC6oVt6sB5k+CchS6Ob0qvH0YIhuUk1eYr7ktsIpY+albCqE80/FVQGV190PmiAg=="], + + "three-stdlib": ["three-stdlib@2.36.0", "", { "dependencies": { "@types/draco3d": "^1.4.0", "@types/offscreencanvas": "^2019.6.4", "@types/webxr": "^0.5.2", "draco3d": "^1.4.1", "fflate": "^0.6.9", "potpack": "^1.0.1" }, "peerDependencies": { "three": ">=0.128.0" } }, "sha512-kv0Byb++AXztEGsULgMAs8U2jgUdz6HPpAB/wDJnLiLlaWQX2APHhiTJIN7rqW+Of0eRgcp7jn05U1BsCP3xBA=="], + + "throttle-debounce": ["throttle-debounce@3.0.1", "", {}, "sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg=="], + + "to-buffer": ["to-buffer@1.2.2", "", { "dependencies": { "isarray": "^2.0.5", "safe-buffer": "^5.2.1", "typed-array-buffer": "^1.0.3" } }, "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw=="], + + "toggle-selection": ["toggle-selection@1.0.6", "", {}, "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ=="], + + "trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="], + + "troika-three-text": ["troika-three-text@0.52.4", "", { "dependencies": { "bidi-js": "^1.0.2", "troika-three-utils": "^0.52.4", "troika-worker-utils": "^0.52.0", "webgl-sdf-generator": "1.1.1" }, "peerDependencies": { "three": ">=0.125.0" } }, "sha512-V50EwcYGruV5rUZ9F4aNsrytGdKcXKALjEtQXIOBfhVoZU9VAqZNIoGQ3TMiooVqFAbR1w15T+f+8gkzoFzawg=="], + + "troika-three-utils": ["troika-three-utils@0.52.4", "", { "peerDependencies": { "three": ">=0.125.0" } }, "sha512-NORAStSVa/BDiG52Mfudk4j1FG4jC4ILutB3foPnfGbOeIs9+G5vZLa0pnmnaftZUGm4UwSoqEpWdqvC7zms3A=="], + + "troika-worker-utils": ["troika-worker-utils@0.52.0", "", {}, "sha512-W1CpvTHykaPH5brv5VHLfQo9D1OYuo0cSBEUQFFT/nBUzM8iD6Lq2/tgG/f1OelbAS1WtaTPQzE5uM49egnngw=="], + + "ts-easing": ["ts-easing@0.2.0", "", {}, "sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ=="], + + "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + + "tunnel-rat": ["tunnel-rat@0.1.2", "", { "dependencies": { "zustand": "^4.3.2" } }, "sha512-lR5VHmkPhzdhrM092lI2nACsLO4QubF0/yoOhzX7c+wIpbN1GjHNzCc91QlpxBi+cnx8vVJ+Ur6vL5cEoQPFpQ=="], + + "tw-animate-css": ["tw-animate-css@1.4.0", "", {}, "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ=="], + + "type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="], + + "typed-array-buffer": ["typed-array-buffer@1.0.3", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-typed-array": "^1.1.14" } }, "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw=="], + + "typeorm": ["typeorm@0.3.27", "", { "dependencies": { "@sqltools/formatter": "^1.2.5", "ansis": "^3.17.0", "app-root-path": "^3.1.0", "buffer": "^6.0.3", "dayjs": "^1.11.13", "debug": "^4.4.0", "dedent": "^1.6.0", "dotenv": "^16.4.7", "glob": "^10.4.5", "sha.js": "^2.4.12", "sql-highlight": "^6.0.0", "tslib": "^2.8.1", "uuid": "^11.1.0", "yargs": "^17.7.2" }, "peerDependencies": { "@google-cloud/spanner": "^5.18.0 || ^6.0.0 || ^7.0.0", "@sap/hana-client": "^2.14.22", "better-sqlite3": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0", "ioredis": "^5.0.4", "mongodb": "^5.8.0 || ^6.0.0", "mssql": "^9.1.1 || ^10.0.1 || ^11.0.1", "mysql2": "^2.2.5 || ^3.0.1", "oracledb": "^6.3.0", "pg": "^8.5.1", "pg-native": "^3.0.0", "pg-query-stream": "^4.0.0", "redis": "^3.1.1 || ^4.0.0 || ^5.0.14", "reflect-metadata": "^0.1.14 || ^0.2.0", "sql.js": "^1.4.0", "sqlite3": "^5.0.3", "ts-node": "^10.7.0", "typeorm-aurora-data-api-driver": "^2.0.0 || ^3.0.0" }, "optionalPeers": ["@google-cloud/spanner", "@sap/hana-client", "better-sqlite3", "ioredis", "mongodb", "mssql", "mysql2", "oracledb", "pg", "pg-native", "pg-query-stream", "redis", "sql.js", "sqlite3", "ts-node", "typeorm-aurora-data-api-driver"], "bin": { "typeorm": "cli.js", "typeorm-ts-node-esm": "cli-ts-node-esm.js", "typeorm-ts-node-commonjs": "cli-ts-node-commonjs.js" } }, "sha512-pNV1bn+1n8qEe8tUNsNdD8ejuPcMAg47u2lUGnbsajiNUr3p2Js1XLKQjBMH0yMRMDfdX8T+fIRejFmIwy9x4A=="], + + "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], + + "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], + + "unist-util-is": ["unist-util-is@6.0.1", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g=="], + + "unist-util-position": ["unist-util-position@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA=="], + + "unist-util-stringify-position": ["unist-util-stringify-position@4.0.0", "", { "dependencies": { "@types/unist": "^3.0.0" } }, "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ=="], + + "unist-util-visit": ["unist-util-visit@5.0.0", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg=="], + + "unist-util-visit-parents": ["unist-util-visit-parents@6.0.2", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-is": "^6.0.0" } }, "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ=="], + + "use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="], + + "use-intl": ["use-intl@4.4.0", "", { "dependencies": { "@formatjs/fast-memoize": "^2.2.0", "@schummar/icu-type-parser": "1.21.5", "intl-messageformat": "^10.5.14" }, "peerDependencies": { "react": "^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 || ^19.0.0" } }, "sha512-smFekJWtokDRBLC5/ZumlBREzdXOkw06+56Ifj2uRe9266Mk+yWQm2PcJO+EwlOE5sHIXHixOTzN6V8E0RGUbw=="], + + "use-sidecar": ["use-sidecar@1.1.3", "", { "dependencies": { "detect-node-es": "^1.1.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ=="], + + "use-sync-external-store": ["use-sync-external-store@1.6.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w=="], + + "utility-types": ["utility-types@3.11.0", "", {}, "sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw=="], + + "uuid": ["uuid@11.1.0", "", { "bin": { "uuid": "dist/esm/bin/uuid" } }, "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A=="], + + "vfile": ["vfile@6.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "vfile-message": "^4.0.0" } }, "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q=="], + + "vfile-message": ["vfile-message@4.0.3", "", { "dependencies": { "@types/unist": "^3.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw=="], + + "webgl-constants": ["webgl-constants@1.1.1", "", {}, "sha512-LkBXKjU5r9vAW7Gcu3T5u+5cvSvh5WwINdr0C+9jpzVB41cjQAP5ePArDtk/WHYdVj0GefCgM73BA7FlIiNtdg=="], + + "webgl-sdf-generator": ["webgl-sdf-generator@1.1.1", "", {}, "sha512-9Z0JcMTFxeE+b2x1LJTdnaT8rT8aEp7MVxkNwoycNmJWwPdzoXzMh0BjJSh/AEFP+KPYZUli814h8bJZFIZ2jA=="], + + "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + + "which-typed-array": ["which-typed-array@1.1.19", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw=="], + + "wildcard-match": ["wildcard-match@5.1.4", "", {}, "sha512-wldeCaczs8XXq7hj+5d/F38JE2r7EXgb6WQDM84RVwxy81T/sxB5e9+uZLK9Q9oNz1mlvjut+QtvgaOQFPVq/g=="], + + "wrap-ansi": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + + "wrap-ansi-cjs": ["wrap-ansi@7.0.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + + "ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="], + + "y18n": ["y18n@5.0.8", "", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], + + "yargs": ["yargs@17.7.2", "", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], + + "yargs-parser": ["yargs-parser@21.1.1", "", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], + + "zod": ["zod@4.1.12", "", {}, "sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ=="], + + "zustand": ["zustand@5.0.8", "", { "peerDependencies": { "@types/react": ">=18.0.0", "immer": ">=9.0.6", "react": ">=18.0.0", "use-sync-external-store": ">=1.2.0" }, "optionalPeers": ["@types/react", "immer", "react", "use-sync-external-store"] }, "sha512-gyPKpIaxY9XcO2vSMrLbiER7QMAMGOQZVRdJ6Zi782jkbzZygq5GI9nG8g+sMgitRtndwaBSl7uiqC49o1SSiw=="], + + "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="], + + "@c15t/react/@radix-ui/react-accordion": ["@radix-ui/react-accordion@1.2.4", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-collapsible": "1.1.4", "@radix-ui/react-collection": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-primitive": "2.0.3", "@radix-ui/react-use-controllable-state": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-SGCxlSBaMvEzDROzyZjsVNzu9XY5E28B3k8jOENyrz6csOv/pG1eHyYfLJai1n9tRjwG61coXDhfpgtxKxUv5g=="], + + "@c15t/react/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.0", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-ujc+V6r0HNDviYqIK3rW4ffgYiZ8g5DEHrGJVk4x7kTlLXRDILnKX9vAUYeIsLOoDpDJ0ujpqMkjH4w2ofuo6w=="], + + "@c15t/react/@radix-ui/react-switch": ["@radix-ui/react-switch@1.1.4", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.0.3", "@radix-ui/react-use-controllable-state": "1.1.1", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-zGP6W8plLeogoeGMiTHJ/uvf+TE1C2chVsEwfP8YlvpQKJHktG+iCkUtCLGPAuDV8/qDSmIRPm4NggaTxFMVBQ=="], + + "@formatjs/ecma402-abstract/@formatjs/intl-localematcher": ["@formatjs/intl-localematcher@0.6.2", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-XOMO2Hupl0wdd172Y06h6kLpBz6Dv+J4okPLl4LPtzbr8f66WbIoy4ev98EBuZ6ZK4h5ydTN6XneT4QVpD7cdA=="], + + "@isaacs/cliui/string-width": ["string-width@5.1.2", "", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], + + "@isaacs/cliui/strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], + + "@isaacs/cliui/wrap-ansi": ["wrap-ansi@8.1.0", "", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], + + "@opentelemetry/exporter-logs-otlp-grpc/@opentelemetry/core": ["@opentelemetry/core@2.0.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw=="], + + "@opentelemetry/exporter-logs-otlp-http/@opentelemetry/core": ["@opentelemetry/core@2.0.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw=="], + + "@opentelemetry/exporter-logs-otlp-proto/@opentelemetry/core": ["@opentelemetry/core@2.0.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw=="], + + "@opentelemetry/exporter-logs-otlp-proto/@opentelemetry/resources": ["@opentelemetry/resources@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw=="], + + "@opentelemetry/exporter-logs-otlp-proto/@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/resources": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ=="], + + "@opentelemetry/exporter-metrics-otlp-grpc/@opentelemetry/core": ["@opentelemetry/core@2.0.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw=="], + + "@opentelemetry/exporter-metrics-otlp-grpc/@opentelemetry/resources": ["@opentelemetry/resources@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw=="], + + "@opentelemetry/exporter-metrics-otlp-http/@opentelemetry/core": ["@opentelemetry/core@2.0.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw=="], + + "@opentelemetry/exporter-metrics-otlp-http/@opentelemetry/resources": ["@opentelemetry/resources@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw=="], + + "@opentelemetry/exporter-metrics-otlp-proto/@opentelemetry/core": ["@opentelemetry/core@2.0.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw=="], + + "@opentelemetry/exporter-metrics-otlp-proto/@opentelemetry/resources": ["@opentelemetry/resources@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw=="], + + "@opentelemetry/exporter-prometheus/@opentelemetry/core": ["@opentelemetry/core@2.0.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw=="], + + "@opentelemetry/exporter-prometheus/@opentelemetry/resources": ["@opentelemetry/resources@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw=="], + + "@opentelemetry/exporter-trace-otlp-grpc/@opentelemetry/core": ["@opentelemetry/core@2.0.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw=="], + + "@opentelemetry/exporter-trace-otlp-grpc/@opentelemetry/resources": ["@opentelemetry/resources@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw=="], + + "@opentelemetry/exporter-trace-otlp-grpc/@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/resources": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ=="], + + "@opentelemetry/exporter-trace-otlp-http/@opentelemetry/core": ["@opentelemetry/core@2.0.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw=="], + + "@opentelemetry/exporter-trace-otlp-http/@opentelemetry/resources": ["@opentelemetry/resources@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw=="], + + "@opentelemetry/exporter-trace-otlp-http/@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/resources": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ=="], + + "@opentelemetry/exporter-trace-otlp-proto/@opentelemetry/core": ["@opentelemetry/core@2.0.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw=="], + + "@opentelemetry/exporter-trace-otlp-proto/@opentelemetry/resources": ["@opentelemetry/resources@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw=="], + + "@opentelemetry/exporter-trace-otlp-proto/@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/resources": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ=="], + + "@opentelemetry/exporter-zipkin/@opentelemetry/core": ["@opentelemetry/core@2.0.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw=="], + + "@opentelemetry/exporter-zipkin/@opentelemetry/resources": ["@opentelemetry/resources@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw=="], + + "@opentelemetry/exporter-zipkin/@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/resources": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ=="], + + "@opentelemetry/otlp-exporter-base/@opentelemetry/core": ["@opentelemetry/core@2.0.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw=="], + + "@opentelemetry/otlp-grpc-exporter-base/@opentelemetry/core": ["@opentelemetry/core@2.0.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw=="], + + "@opentelemetry/otlp-transformer/@opentelemetry/core": ["@opentelemetry/core@2.0.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw=="], + + "@opentelemetry/otlp-transformer/@opentelemetry/resources": ["@opentelemetry/resources@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw=="], + + "@opentelemetry/otlp-transformer/@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/resources": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ=="], + + "@opentelemetry/propagator-b3/@opentelemetry/core": ["@opentelemetry/core@2.0.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw=="], + + "@opentelemetry/propagator-jaeger/@opentelemetry/core": ["@opentelemetry/core@2.0.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw=="], + + "@opentelemetry/sdk-logs/@opentelemetry/core": ["@opentelemetry/core@2.0.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw=="], + + "@opentelemetry/sdk-logs/@opentelemetry/resources": ["@opentelemetry/resources@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw=="], + + "@opentelemetry/sdk-metrics/@opentelemetry/core": ["@opentelemetry/core@2.0.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw=="], + + "@opentelemetry/sdk-metrics/@opentelemetry/resources": ["@opentelemetry/resources@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw=="], + + "@opentelemetry/sdk-node/@opentelemetry/core": ["@opentelemetry/core@2.0.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw=="], + + "@opentelemetry/sdk-node/@opentelemetry/resources": ["@opentelemetry/resources@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw=="], + + "@opentelemetry/sdk-node/@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/resources": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ=="], + + "@opentelemetry/sdk-trace-node/@opentelemetry/core": ["@opentelemetry/core@2.0.1", "", { "dependencies": { "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.0.0 <1.10.0" } }, "sha512-MaZk9SJIDgo1peKevlbhP6+IwIiNPNmswNL4AF0WaQJLbHXjr9SrZMgS12+iqr9ToV4ZVosCcc0f8Rg67LXjxw=="], + + "@opentelemetry/sdk-trace-node/@opentelemetry/sdk-trace-base": ["@opentelemetry/sdk-trace-base@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/resources": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-xYLlvk/xdScGx1aEqvxLwf6sXQLXCjk3/1SQT9X9AoN5rXRhkdvIFShuNNmtTEPRBqcsMbS4p/gJLNI2wXaDuQ=="], + + "@orpc/otel/@orpc/shared": ["@orpc/shared@1.10.2", "", { "dependencies": { "radash": "^12.1.1", "type-fest": "^5.1.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.9.0" }, "optionalPeers": ["@opentelemetry/api"] }, "sha512-TIH4sohjVJQ9UOSHrqJm+psCX3P6DVnzzB6ltohBMUwPXWvZgk8TTh4K3cMw2HhofvLylUtGe61uf5ReUiECLA=="], + + "@pixiv/types-vrmc-vrm-animation-1.0/@pixiv/types-vrmc-vrm-1.0": ["@pixiv/types-vrmc-vrm-1.0@2.0.3", "", {}, "sha512-RMP34Bk1qLFQv/CRB1Zqvn2qMFfWQfP2Hms5QrrfoBsW9XroZdEe0zPLNbGmUPYh4F7VtBb+B7+RCuymRtpehA=="], + + "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.6.0", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-zq/ay+9fNIJJtJiZxdTnXS20PllcYMX3OE23ESc4HK/bdYu3cOWYVhsOhVnXALfU/uqJIxn5NBPd9z4v+SfoSg=="], + + "@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.6.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-obtUmAHTMjll499P+D9A3axeJFlhdjOWdKUNs/U6QIGT7V5RjcUW1xToAzjvmgTSQhDbYn/NwfTRoJcQ2rNBxA=="], + + "@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.0.7", "", { "dependencies": { "@emnapi/core": "^1.5.0", "@emnapi/runtime": "^1.5.0", "@tybys/wasm-util": "^0.10.1" }, "bundled": true }, "sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw=="], + + "@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=="], + + "fumadb/kysely": ["kysely@0.28.8", "", {}, "sha512-QUOgl5ZrS9IRuhq5FvOKFSsD/3+IA6MLE81/bOOTRA/YQpKDza2sFdN5g6JCB9BOpqMJDGefLCQ9F12hRS13TA=="], + + "its-fine/@types/react-reconciler": ["@types/react-reconciler@0.28.9", "", { "peerDependencies": { "@types/react": "*" } }, "sha512-HHM3nxyUZ3zAylX8ZEyrDNd2XZOnQ0D5XfunJF5FLQnZbHHYq4UWvW1QfelQNXv1ICNkwYhfxjwfnqivYB6bFg=="], + + "next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="], + + "next/sharp": ["sharp@0.34.4", "", { "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.0", "semver": "^7.7.2" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.4", "@img/sharp-darwin-x64": "0.34.4", "@img/sharp-libvips-darwin-arm64": "1.2.3", "@img/sharp-libvips-darwin-x64": "1.2.3", "@img/sharp-libvips-linux-arm": "1.2.3", "@img/sharp-libvips-linux-arm64": "1.2.3", "@img/sharp-libvips-linux-ppc64": "1.2.3", "@img/sharp-libvips-linux-s390x": "1.2.3", "@img/sharp-libvips-linux-x64": "1.2.3", "@img/sharp-libvips-linuxmusl-arm64": "1.2.3", "@img/sharp-libvips-linuxmusl-x64": "1.2.3", "@img/sharp-linux-arm": "0.34.4", "@img/sharp-linux-arm64": "0.34.4", "@img/sharp-linux-ppc64": "0.34.4", "@img/sharp-linux-s390x": "0.34.4", "@img/sharp-linux-x64": "0.34.4", "@img/sharp-linuxmusl-arm64": "0.34.4", "@img/sharp-linuxmusl-x64": "0.34.4", "@img/sharp-wasm32": "0.34.4", "@img/sharp-win32-arm64": "0.34.4", "@img/sharp-win32-ia32": "0.34.4", "@img/sharp-win32-x64": "0.34.4" } }, "sha512-FUH39xp3SBPnxWvd5iib1X8XY7J0K0X7d93sie9CJg2PO8/7gmg89Nve6OjItK53/MlAushNNxteBYfM6DEuoA=="], + + "react-dom/scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="], + + "stacktrace-gps/source-map": ["source-map@0.5.6", "", {}, "sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA=="], + + "stats-gl/three": ["three@0.170.0", "", {}, "sha512-FQK+LEpYc0fBD+J8g6oSEyyNzjp+Q7Ks1C568WWaoMRLW+TkNNWmenWeGgJjV105Gd+p/2ql1ZcjYvNiPZBhuQ=="], + + "swetrix/@types/node": ["@types/node@14.18.63", "", {}, "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ=="], + + "three-stdlib/fflate": ["fflate@0.6.10", "", {}, "sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg=="], + + "tunnel-rat/zustand": ["zustand@4.5.7", "", { "dependencies": { "use-sync-external-store": "^1.2.2" }, "peerDependencies": { "@types/react": ">=16.8", "immer": ">=9.0.6", "react": ">=16.8" }, "optionalPeers": ["@types/react", "immer", "react"] }, "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw=="], + + "@c15t/react/@radix-ui/react-accordion/@radix-ui/primitive": ["@radix-ui/primitive@1.1.2", "", {}, "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA=="], + + "@c15t/react/@radix-ui/react-accordion/@radix-ui/react-collapsible": ["@radix-ui/react-collapsible@1.1.4", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.3", "@radix-ui/react-primitive": "2.0.3", "@radix-ui/react-use-controllable-state": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-u7LCw1EYInQtBNLGjm9nZ89S/4GcvX1UR5XbekEgnQae2Hkpq39ycJ1OhdeN1/JDfVNG91kWaWoest127TaEKQ=="], + + "@c15t/react/@radix-ui/react-accordion/@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.0.3", "@radix-ui/react-slot": "1.2.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-mM2pxoQw5HJ49rkzwOs7Y6J4oYH22wS8BfK2/bBxROlI4xuR0c4jEenQP63LlTlDkO6Buj2Vt+QYAYcOgqtrXA=="], + + "@c15t/react/@radix-ui/react-accordion/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.0.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Pf/t/GkndH7CQ8wE2hbkXA+WyZ83fhQQn5DDmwDiDo6AwN/fhaH8oqZ0jRjMrO2iaMhDi6P1HRx6AZwyMinY1g=="], + + "@c15t/react/@radix-ui/react-accordion/@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.1.1", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-YnEXIy8/ga01Y1PN0VfaNH//MhA91JlEGVBDxDzROqwrAtG5Yr2QGEPz8A/rJA3C7ZAHryOYGaUv8fLSW2H/mg=="], + + "@c15t/react/@radix-ui/react-switch/@radix-ui/primitive": ["@radix-ui/primitive@1.1.2", "", {}, "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA=="], + + "@c15t/react/@radix-ui/react-switch/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.0.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.0" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Pf/t/GkndH7CQ8wE2hbkXA+WyZ83fhQQn5DDmwDiDo6AwN/fhaH8oqZ0jRjMrO2iaMhDi6P1HRx6AZwyMinY1g=="], + + "@c15t/react/@radix-ui/react-switch/@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.1.1", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-YnEXIy8/ga01Y1PN0VfaNH//MhA91JlEGVBDxDzROqwrAtG5Yr2QGEPz8A/rJA3C7ZAHryOYGaUv8fLSW2H/mg=="], + + "@isaacs/cliui/string-width/emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], + + "@isaacs/cliui/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], + + "@isaacs/cliui/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], + + "@opentelemetry/sdk-trace-node/@opentelemetry/sdk-trace-base/@opentelemetry/resources": ["@opentelemetry/resources@2.0.1", "", { "dependencies": { "@opentelemetry/core": "2.0.1", "@opentelemetry/semantic-conventions": "^1.29.0" }, "peerDependencies": { "@opentelemetry/api": ">=1.3.0 <1.10.0" } }, "sha512-dZOB3R6zvBwDKnHDTB4X1xtMArB/d324VsbiPkX/Yu0Q8T2xceRthoIVFhJdvgVM2QhGVUyX9tzwiNxGtoBJUw=="], + + "@orpc/otel/@orpc/shared/type-fest": ["type-fest@5.1.0", "", { "dependencies": { "tagged-tag": "^1.0.0" } }, "sha512-wQ531tuWvB6oK+pchHIu5lHe5f5wpSCqB8Kf4dWQRbOYc9HTge7JL0G4Qd44bh6QuJCccIzL3bugb8GI0MwHrg=="], + + "next/sharp/@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.3" }, "os": "darwin", "cpu": "arm64" }, "sha512-sitdlPzDVyvmINUdJle3TNHl+AG9QcwiAMsXmccqsCOMZNIdW2/7S26w0LyU8euiLVzFBL3dXPwVCq/ODnf2vA=="], + + "next/sharp/@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.2.3" }, "os": "darwin", "cpu": "x64" }, "sha512-rZheupWIoa3+SOdF/IcUe1ah4ZDpKBGWcsPX6MT0lYniH9micvIU7HQkYTfrx5Xi8u+YqwLtxC/3vl8TQN6rMg=="], + + "next/sharp/@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.2.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-QzWAKo7kpHxbuHqUC28DZ9pIKpSi2ts2OJnoIGI26+HMgq92ZZ4vk8iJd4XsxN+tYfNJxzH6W62X5eTcsBymHw=="], + + "next/sharp/@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.2.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-Ju+g2xn1E2AKO6YBhxjj+ACcsPQRHT0bhpglxcEf+3uyPY+/gL8veniKoo96335ZaPo03bdDXMv0t+BBFAbmRA=="], + + "next/sharp/@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.2.3", "", { "os": "linux", "cpu": "arm" }, "sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA=="], + + "next/sharp/@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.2.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ=="], + + "next/sharp/@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.2.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w=="], + + "next/sharp/@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.2.3", "", { "os": "linux", "cpu": "x64" }, "sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg=="], + + "next/sharp/@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.2.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw=="], + + "next/sharp/@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.2.3", "", { "os": "linux", "cpu": "x64" }, "sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g=="], + + "next/sharp/@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.2.3" }, "os": "linux", "cpu": "arm" }, "sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA=="], + + "next/sharp/@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.2.3" }, "os": "linux", "cpu": "arm64" }, "sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ=="], + + "next/sharp/@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.2.3" }, "os": "linux", "cpu": "s390x" }, "sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw=="], + + "next/sharp/@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.2.3" }, "os": "linux", "cpu": "x64" }, "sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A=="], + + "next/sharp/@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.2.3" }, "os": "linux", "cpu": "arm64" }, "sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA=="], + + "next/sharp/@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.34.4", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.2.3" }, "os": "linux", "cpu": "x64" }, "sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg=="], + + "next/sharp/@img/sharp-wasm32": ["@img/sharp-wasm32@0.34.4", "", { "dependencies": { "@emnapi/runtime": "^1.5.0" }, "cpu": "none" }, "sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA=="], + + "next/sharp/@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.34.4", "", { "os": "win32", "cpu": "ia32" }, "sha512-3ZeLue5V82dT92CNL6rsal6I2weKw1cYu+rGKm8fOCCtJTR2gYeUfY3FqUnIJsMUPIH68oS5jmZ0NiJ508YpEw=="], + + "next/sharp/@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.4", "", { "os": "win32", "cpu": "x64" }, "sha512-xIyj4wpYs8J18sVN3mSQjwrw7fKUqRw+Z5rnHNCy5fYTxigBz81u5mOMPmFumwjcn8+ld1ppptMBCLic1nz6ig=="], + + "@c15t/react/@radix-ui/react-accordion/@radix-ui/react-collapsible/@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-IrVLIhskYhH3nLvtcBLQFZr61tBG7wx7O3kEmdzcYwRGAEBmBicGGL7ATzNgruYJ3xBTbuzEEq9OXJM3PAX3tA=="], + } +} diff --git a/bun.lockb b/bun.lockb deleted file mode 100755 index 82c326b..0000000 Binary files a/bun.lockb and /dev/null differ diff --git a/bunfig.toml b/bunfig.toml deleted file mode 100644 index d350d26..0000000 --- a/bunfig.toml +++ /dev/null @@ -1,2 +0,0 @@ -[install.scopes] -neodyland = { token = "$GH_NPM_TOKEN", url = "https://npm.pkg.github.com/" } \ No newline at end of file diff --git a/components.json b/components.json new file mode 100644 index 0000000..48e56a9 --- /dev/null +++ b/components.json @@ -0,0 +1,25 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "tailwind.config.ts", + "css": "src/app/globals.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "iconLibrary": "lucide", + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "registries": { + "@animate-ui": "https://animate-ui.com/r/{name}.json", + "@fancy": "https://fancycomponents.dev/r/{name}.json" + } +} diff --git a/imgLoader.ts b/imgLoader.ts new file mode 100644 index 0000000..c70a0f7 --- /dev/null +++ b/imgLoader.ts @@ -0,0 +1,19 @@ +const optimizerUrl = process.env.NEXT_PUBLIC_IMAGE_OPTIMIZER_URL || ""; +const hostname = process.env.CF_PAGES_URL; + +export default function ImageLoader({ + src, + width, + quality, +}: { + src: string; + width: number; + quality: number; +}) { + if (process.env.NODE_ENV === "development") { + return src; + } + const params = [`size=${width}`]; + params.push(`quality=${quality || 75}`); + return `${optimizerUrl}/${encodeURIComponent(`${hostname}${src}`)}?${params.join("&")}`; +} diff --git a/next.config.mjs b/next.config.mjs index b9a3ffd..75bc556 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -4,6 +4,13 @@ import createNextIntlPlugin from "next-intl/plugin"; const withNextIntl = createNextIntlPlugin(); -const nextConfig = {}; +const nextConfig = { + output: "export", + images: { + loader: "custom", + loaderFile: "./imgLoader.ts", + }, + reactCompiler: true, +}; export default withNextIntl(nextConfig); diff --git a/open-next.config.ts b/open-next.config.ts deleted file mode 100644 index 609ed7c..0000000 --- a/open-next.config.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { defineCloudflareConfig } from "@opennextjs/cloudflare"; -import kvIncrementalCache from "@opennextjs/cloudflare/overrides/incremental-cache/kv-incremental-cache"; -import doQueue from "@opennextjs/cloudflare/overrides/queue/do-queue"; - -export default defineCloudflareConfig({ - incrementalCache: kvIncrementalCache, - queue: doQueue, -}); diff --git a/package.json b/package.json index fd7ed51..1a6e8a3 100644 --- a/package.json +++ b/package.json @@ -1,54 +1,58 @@ { - "name": "mikn-dev", - "version": "0.1.0", - "private": true, - "scripts": { - "build": "next build", - "dev": "NODE_OPTIONS='--inspect' next dev --turbo", - "format": "biome format --write .", - "lint": "next lint", - "start": "next start", - "preview": "opennextjs-cloudflare build && opennextjs-cloudflare preview", - "deploy": "opennextjs-cloudflare build && opennextjs-cloudflare deploy", - "upload": "opennextjs-cloudflare build && opennextjs-cloudflare upload", - "cf-typegen": "wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts" - }, - "dependencies": { - "@opennextjs/cloudflare": "^1.0.4", - "@pixiv/three-vrm": "^3.3.4", - "@pixiv/three-vrm-animation": "^3.3.4", - "@react-three/fiber": "^9.1.2", - "@swetrix/nextjs": "^1.0.1", - "@tailwindcss/postcss": "^4.1.7", - "@types/three": "^0.176.0", - "caniuse-lite": "^1.0.30001664", - "clsx": "^2.1.1", - "daisyui": "^5.0.0", - "motion": "^11.15.0", - "next": "^15.3.2", - "next-intl": "^4.1.0", - "next-themes": "^0.4.4", - "postcss": "^8.5.3", - "react": "^19.1.0", - "react-cookie-consent": "^9.0.0", - "react-dom": "^19.1.0", - "react-icons": "^5.2.1", - "react-use": "^17.6.0", - "sharp": "^0.33.5", - "shiki": "^1.24.4", - "sonner": "^1.7.1", - "tailwind-merge": "^2.6.0", - "tailwind-variants": "^0.3.0", - "three": "^0.176.0" - }, - "devDependencies": { - "@biomejs/biome": "^1.5.1", - "@opennextjs/aws": "^3.6.4", - "@types/node": "^20", - "@types/react": "^18", - "@types/react-dom": "^18", - "tailwindcss": "^4.1.7", - "typescript": "^5", - "wrangler": "^4.16.1" - } + "name": "mikn-dev", + "version": "0.1.0", + "private": true, + "scripts": { + "build": "next build", + "dev": "next dev --turbo", + "format": "biome format --write .", + "lint": "next lint", + "start": "next start" + }, + "dependencies": { + "@c15t/nextjs": "^1.7.1", + "@c15t/scripts": "^1.0.0", + "@pixiv/three-vrm": "^3.3.4", + "@pixiv/three-vrm-animation": "^3.3.4", + "@radix-ui/react-slot": "^1.2.3", + "@react-three/drei": "^10.7.6", + "@react-three/fiber": "^9.4.0", + "@swetrix/nextjs": "^1.0.1", + "@tailwindcss/postcss": "^4.1.7", + "@types/three": "^0.176.0", + "babel-plugin-react-compiler": "^1.0.0", + "caniuse-lite": "^1.0.30001664", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "daisyui": "^5.0.0", + "gsap": "^3.13.0", + "lucide-react": "^0.548.0", + "maath": "^0.10.8", + "motion": "^12.23.24", + "next": "^16.0.0", + "next-intl": "^4.4.0", + "next-themes": "^0.4.4", + "postcss": "^8.5.3", + "radix-ui": "^1.4.3", + "react": "^19.2.0", + "react-dom": "^19.2.0", + "react-icons": "^5.2.1", + "react-use": "^17.6.0", + "sharp": "^0.33.5", + "shiki": "^1.24.4", + "sonner": "^1.7.1", + "tailwind-merge": "^3.3.1", + "tailwind-variants": "^3.1.1", + "tailwindcss-animate": "^1.0.7", + "three": "^0.180.0", + "tw-animate-css": "^1.4.0" + }, + "devDependencies": { + "@biomejs/biome": "^2.3.1", + "@types/node": "^20", + "@types/react": "^19.2.2", + "@types/react-dom": "^18", + "tailwindcss": "^4.1.7", + "typescript": "^5" + } } diff --git a/postcss.config.mjs b/postcss.config.mjs index 2a0059f..7059fe9 100644 --- a/postcss.config.mjs +++ b/postcss.config.mjs @@ -1,6 +1,6 @@ const config = { - plugins: { - "@tailwindcss/postcss": {}, - }, + plugins: { + "@tailwindcss/postcss": {}, + }, }; export default config; diff --git a/renovate.json b/renovate.json index ac08426..22a9943 100644 --- a/renovate.json +++ b/renovate.json @@ -1,4 +1,4 @@ { - "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": ["config:recommended"] + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": ["config:recommended"] } diff --git a/src/app/[locale]/about/page.tsx b/src/app/[locale]/about/page.tsx deleted file mode 100644 index c967216..0000000 --- a/src/app/[locale]/about/page.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { AiOutlineLoading3Quarters } from "react-icons/ai"; - -export default async function Home() { - return ( -
- -
- ); -} diff --git a/src/app/[locale]/contact/page.tsx b/src/app/[locale]/contact/page.tsx deleted file mode 100644 index 541504c..0000000 --- a/src/app/[locale]/contact/page.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import Link from "next/link"; - -import { useTranslations } from "next-intl"; - -import { IoMdMail } from "react-icons/io"; -import { - MdPhone, - MdSupportAgent, - MdMonetizationOn, - MdWarning, -} from "react-icons/md"; -import { FaDiscord } from "react-icons/fa"; - -export default function Home() { - const t = useTranslations("contact"); - return ( -
-
-

- {t("title")} -

-
-
-
- -

{t("mail")}

-
-
-
- -

hello@mikn.dev

-
-
- -

billing@mikn.dev

-
-
- -

abuse@mikn.dev

-
-
-
-
-
-
-
- -

- {t("phone")} -

-
-
-

+81 090-9276-3628

-
-
-
-
-
-
- -

- {t("discord")} -

-
-
- - - -
-
-
-

{t("phone-disclaimer")}

-
-
- ); -} diff --git a/src/app/[locale]/cost/page.tsx b/src/app/[locale]/cost/page.tsx deleted file mode 100644 index c967216..0000000 --- a/src/app/[locale]/cost/page.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { AiOutlineLoading3Quarters } from "react-icons/ai"; - -export default async function Home() { - return ( -
- -
- ); -} diff --git a/src/app/[locale]/layout.tsx b/src/app/[locale]/layout.tsx index 42f2881..1d066f7 100644 --- a/src/app/[locale]/layout.tsx +++ b/src/app/[locale]/layout.tsx @@ -1,5 +1,4 @@ import type { Metadata } from "next"; -import localFont from "next/font/local"; import { Toaster } from "sonner"; import { NextIntlClientProvider } from "next-intl"; import { getMessages, setRequestLocale } from "next-intl/server"; @@ -7,49 +6,46 @@ import { notFound } from "next/navigation"; import { routing } from "@/i18n/routing"; import { ReactNode } from "react"; import "../globals.css"; - -const hsr = localFont({ src: "../../assets/fonts/HSR.woff2" }); +import { ConsentManager } from "@/components/consent-manager"; export const metadata: Metadata = { - title: "MikanDev", - description: "We make cool stuff to make life easier 🍊", - openGraph: { - images: ["https://mikn.dev/img/og-homepage.png"], - }, + title: "MikanDev", + description: "We make cool stuff to make life easier 🍊", + openGraph: { + images: ["https://mikn.dev/img/og-homepage.png"], + }, }; interface LocaleLayoutProps { - children: ReactNode; - params: Promise<{ locale: string }>; + children: ReactNode; + params: Promise<{ locale: string }>; } export function generateStaticParams() { - return routing.locales.map((locale) => ({ locale })); + return routing.locales.map((locale) => ({ locale })); } export default async function LocaleLayout({ - children, - params, + children, + params, }: LocaleLayoutProps) { - const { locale } = await params; + const { locale } = await params; + + if (!routing.locales.includes(locale as any)) { + notFound(); + } - // Ensure that the incoming `locale` is valid - if (!routing.locales.includes(locale as any)) { - notFound(); - } + setRequestLocale(locale); - setRequestLocale(locale); - // Providing all messages to the client - // side is the easiest way to get started - const messages = await getMessages(); - return ( - - - - {children} - - - - - ); + const messages = await getMessages(); + return ( + <> + + + {children} + + + + + ); } diff --git a/src/app/[locale]/page.tsx b/src/app/[locale]/page.tsx index a931df9..a072dcd 100644 --- a/src/app/[locale]/page.tsx +++ b/src/app/[locale]/page.tsx @@ -1,9 +1,10 @@ +import { Button } from "@/components/animate-ui/components/buttons/button"; +import SpotlightCard from "@/components/SpotlightCard"; +import { setRequestLocale, getTranslations } from "next-intl/server"; import Image from "next/image"; import Link from "next/link"; -import { useTranslations } from "next-intl"; -import Typewriter from "@/components/fancy/typewriter"; -import { NumberTicker } from "@/components/fancy/NumberTicker"; -import { Marquee } from "@/components/fancy/marqee"; +import NumberTicker from "@/components/fancy/text/basic-number-ticker"; +import Marquee from "@/components/fancy/blocks/simple-marquee"; import { VRM } from "@/components/vrm"; import { TbBrandOpenSource, TbWallet, TbPigMoney } from "react-icons/tb"; @@ -15,291 +16,286 @@ import RTLogo from "@/assets/img/rt.png"; import KuronekoLogo from "@/assets/img/kuroneko.png"; import TakasumiLogo from "@/assets/img/takasumi.png"; -export default function Home() { - const t = useTranslations("home"); - return ( -
-
-
- -
- -

- Backed by my own pocket money -

-
- -
-

- {t("creating-cool")} -

- -
-

- {t("makeLifeEasier")} -

-

- {t("mainBlurb1")} -

-

- {t("mainBlurb2")} -

-
- - - - - - -
-
-
- -
-
+export default async function IndexPage(params: Promise<{ locale: string }>) { + const { locale } = await params; -
-
-

- {t("infoTitle")} -

-

- {t("infoBlurb")} -

-
+ setRequestLocale(locale); -
-
- {"Mascot - -
-

- {t("OSSonOSS")} -

-

- {t("OSSonOSSBlurb")} -

-
-

- {t("partOfPage")} -

-
- - - + const t = await getTranslations("home"); + return ( +
+
+
+ +
+ +

+ Backed by my own pocket money +

+
+ +
+

+ {t("creating-cool")} +

+
+

+ {t("makeLifeEasier")} +

+

+ {t("mainBlurb1")} +

+

{t("mainBlurb2")}

+
+ + + + + + +
+
+
+ +
+
-
- - {"Mascot -
-

- {t("SimpleNCheap")} -

-

- {t("SimpleNCheapBlurb")} -

-
-
-
-
-

~$

- -
- {t("monthlyCost")} -
-
-
-
-
-

0

-
- {t("MAUBilled")} -
-
-
-

- {t("despite")} -

-
-
-
-
- -

- {" "} - +TB -

-
- {t("monthlyBandwidth")} -
-
-
-
-
- -

+

-
- {t("mainServices")} -
-
-
-
-
- -

%

-
- {t("monthlyUptime")} -
-
-
- - - +
+
+

+ {t("infoTitle")} +

+

+ {t("infoBlurb")} +

+
-
- {"Mikan"} -
-

- {t("SelfFunded")} -

-

- {t("SelfFundedBlurb")} -

+
+
+ {"Mascot + +
+

+ {t("OSSonOSS")} +

+

+ {t("OSSonOSSBlurb")} +

+
+

{t("partOfPage")}

+
+ + + -
- {"Mascot -
-

- {t("WorkWithBest")} -

-

- {t("WorkWithBestBlurb")} -

+
+ + {"Mascot +
+

+ {t("SimpleNCheap")} +

+

+ {t("SimpleNCheapBlurb")} +

+
+ +
+
+

~$

+ +
+ {t("monthlyCost")} +
+
+ +
+
+

0

+
+ {t("MAUBilled")} +
+
+
+

+ {t("despite")} +

+
+ +
+
+ +

+TB

+
+ {t("monthlyBandwidth")} +
+
+ +
+
+ +

+

+
+ {t("mainServices")} +
+
+ +
+
+ +

%

+
+ {t("monthlyUptime")} +
+
+
+ + + - - - {"Neody"} - - - {"RT"} - - - {"Kuroneko"} - - - {"Takasumi"} - - +
+ {"Mikan"} +
+

+ {t("SelfFunded")} +

+

+ {t("SelfFundedBlurb")} +

- - - +
+ {"Mascot +
+

+ {t("WorkWithBest")} +

+

+ {t("WorkWithBestBlurb")} +

-
+ + + {"Neody"} + + + {"RT"} + + + {"Kuroneko"} + + + {"Takasumi"} + + -

- {t("NoWait")} -

-

- {t("NoWaitBlurb")} -

- - - -
-
-
- ); + + + + +
+ +

+ {t("NoWait")} +

+

+ {t("NoWaitBlurb")} +

+ + + +
+
+
+ ); } diff --git a/src/app/[locale]/solutions/page.tsx b/src/app/[locale]/solutions/page.tsx deleted file mode 100644 index 9006478..0000000 --- a/src/app/[locale]/solutions/page.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { AiOutlineLoading3Quarters } from "react-icons/ai"; - -export default async function Home() { - return ( -
- -
- ); -} diff --git a/src/app/[locale]/tech/page.tsx b/src/app/[locale]/tech/page.tsx deleted file mode 100644 index c967216..0000000 --- a/src/app/[locale]/tech/page.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { AiOutlineLoading3Quarters } from "react-icons/ai"; - -export default async function Home() { - return ( -
- -
- ); -} diff --git a/src/app/[locale]/template.tsx b/src/app/[locale]/template.tsx index 234491f..07b32d7 100644 --- a/src/app/[locale]/template.tsx +++ b/src/app/[locale]/template.tsx @@ -1,197 +1,18 @@ "use client"; -import { useTranslations } from "next-intl"; -import { Header } from "@/components/nUI/Header"; -import { Footer } from "@/components/nUI/Footer"; -import Image from "next/image"; -import mikanLogo from "@/assets/img/mikan.png"; -import MikanCat from "@/assets/img/mikan-cat.png"; -import KawaiiLogo from "@/assets/img/mikan-vtube.svg"; -import { useSwetrix } from '@swetrix/nextjs' -import { useRouter, usePathname } from "next/navigation"; -import CookieConsent from "react-cookie-consent"; +import { useSwetrix } from "@swetrix/nextjs"; import { ReactNode } from "react"; - -import { FaDiscord, FaGithub, FaTwitter } from "react-icons/fa"; -import { SiMisskey } from "react-icons/si"; +import { CursorToys } from "@/components/CursorToys"; +import SettingsController from "@/components/SettingsController"; export default function PagesLayout({ children }: { children: ReactNode }) { - const router = useRouter(); - const pathname = usePathname(); - const t = useTranslations("nav"); - useSwetrix("XxNIMaHCaVG3", { apiURL: "https://analytics.mikandev.tech/log" }) - - const changeLanguage = () => { - //@ts-ignore - const pathSegments = pathname.split("/"); - if (pathSegments[1] === "en") { - pathSegments[1] = "ja"; - } else if (pathSegments[1] === "ja") { - pathSegments[1] = "en"; - } - const newPath = pathSegments.join("/"); - router.push(newPath); - }; - - const nav = [ - { - name: t("support"), - href: "/contact", - }, - { - name: t("docs"), - href: "https://docs.mikn.dev/", - }, - { - name: t("solutions"), - href: "/solutions", - }, - { - name: t("legal"), - href: "https://docs.mikn.dev/legal/", - }, - { - name: t("payments"), - href: "https://payments.mikandev.com/", - }, - ]; - - const social = [ - { - name: "GitHub", - href: "https://github.com/mikndotdev", - color: "hover:text-github hover:bg-github", - icon: FaGithub, - }, - { - name: "Twitter", - href: "https://twitter.com/kunkunmaamo", - color: "hover:text-twitter hover:bg-twitter", - icon: FaTwitter, - }, - { - name: "Discord", - href: "https://discord.gg/FZCN6fjPuG", - color: "hover:text-discord hover:bg-discord", - icon: FaDiscord, - }, - { - name: "Misskey Server", - href: "https://ekaki.art/", - color: "hover:text-misskey hover:bg-misskey", - icon: SiMisskey, - }, - ]; - - const links = [ - { - name: t("resources"), - children: [ - { - name: t("payments"), - href: "https://payments.mikandev.com/", - }, - { - name: t("solutions"), - href: "https:/mikn.dev/solutions", - }, - { - name: t("blog"), - href: "https://blog.mikn.dev/", - }, - ], - }, - { - name: t("support"), - children: [ - { - name: t("discord"), - href: "https://discord.gg/FZCN6fjPuG", - }, - { - name: t("contact"), - href: "https://mikn.dev/contact", - }, - ], - }, - { - name: t("legal"), - children: [ - { - name: t("terms"), - href: "https://docs.mikn.dev/legal/terms", - }, - { - name: t("privacy"), - href: "https://docs.mikn.dev/legal/privacy", - }, - { - name: t("jp-payments"), - href: "https://docs.mikn.dev/legal/jp-payments", - }, - ], - }, - ]; - - const buttons = [ - { - href: "https://my.mikandev.com/init?url=https://mikn.dev", - title: t("myAccount"), - }, - { - title: "🌎", - onClick: () => { - changeLanguage(); - }, - }, - ]; - - return ( - <> -
-
- {children} - {}} - > - {t("cookieConsent")} - -
- - - ); + useSwetrix("XxNIMaHCaVG3", { apiURL: "https://analytics.mikandev.tech/log" }); + + return ( + +
+ {children} +
+ +
+ ); } diff --git a/src/app/globals.css b/src/app/globals.css index 96a77d7..04dd10c 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -1,26 +1,176 @@ -@import 'tailwindcss'; +@import "tailwindcss"; -@config '../.././tailwind.config.ts'; +@plugin "tailwindcss-animate"; +@import "tw-animate-css"; -@layer base { - *, - ::after, - ::before, - ::backdrop, - ::file-selector-button { - border-color: var(--color-gray-200, currentColor); - } +@custom-variant dark (&:is(.dark *)); + +:root { + --background: #2d1800; + --foreground: #ffffff; + --card: #663d00; + --card-foreground: #fafafa; + --popover: #262626; + --popover-foreground: #fafafa; + --primary: #ff9900; + --primary-foreground: #ffffff; + --secondary: #ff7700; + --secondary-foreground: #ffffff; + --muted: #663d00; + --muted-foreground: #ffffff; + --accent: #ff7700; + --accent-foreground: #ffffff; + --destructive: #ff6467; + --destructive-foreground: #fafafa; + --border: #ff9900; + --input: #ff9900; + --ring: #ffffff; + --chart-1: #ff7700; + --chart-2: #2d1800; + --chart-3: #995c00; + --chart-4: #ff0000; + --chart-5: #1f3fad; + --sidebar: #2d1800; + --sidebar-foreground: #fafafa; + --sidebar-primary: #1447e6; + --sidebar-primary-foreground: #fafafa; + --sidebar-accent: #ff7700; + --sidebar-accent-foreground: #fafafa; + --sidebar-border: #ff9900; + --sidebar-ring: #525252; + --radius: 0.625rem; + --shadow-x: 0; + --shadow-y: 1px; + --shadow-blur: 3px; + --shadow-spread: 0px; + --shadow-opacity: 0.1; + --shadow-color: oklch(0 0 0); + --shadow-2xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05); + --shadow-xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05); + --shadow-sm: + 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1); + --shadow: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1); + --shadow-md: + 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 2px 4px -1px hsl(0 0% 0% / 0.1); + --shadow-lg: + 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 4px 6px -1px hsl(0 0% 0% / 0.1); + --shadow-xl: + 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 8px 10px -1px hsl(0 0% 0% / 0.1); + --shadow-2xl: 0 1px 3px 0px hsl(0 0% 0% / 0.25); } -body { - color: #2d1800; - background: #2d1800 +.dark { + --background: #2d1800; + --foreground: #ffffff; + --card: #663d00; + --card-foreground: #fafafa; + --popover: #262626; + --popover-foreground: #fafafa; + --primary: #ff9900; + --primary-foreground: #ffffff; + --secondary: #ff7700; + --secondary-foreground: #ffffff; + --muted: #663d00; + --muted-foreground: #ffffff; + --accent: #ff7700; + --accent-foreground: #ffffff; + --destructive: #ff6467; + --destructive-foreground: #fafafa; + --border: #ff9900; + --input: #ff9900; + --ring: #ffffff; + --chart-1: #ff7700; + --chart-2: #2d1800; + --chart-3: #995c00; + --chart-4: #ff0000; + --chart-5: #1f3fad; + --sidebar: #2d1800; + --sidebar-foreground: #fafafa; + --sidebar-primary: #1447e6; + --sidebar-primary-foreground: #fafafa; + --sidebar-accent: #ff7700; + --sidebar-accent-foreground: #fafafa; + --sidebar-border: #ff9900; + --sidebar-ring: #525252; + --radius: 0.625rem; + --shadow-x: 0; + --shadow-y: 1px; + --shadow-blur: 3px; + --shadow-spread: 0px; + --shadow-opacity: 0.1; + --shadow-color: oklch(0 0 0); + --shadow-2xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05); + --shadow-xs: 0 1px 3px 0px hsl(0 0% 0% / 0.05); + --shadow-sm: + 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1); + --shadow: 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 1px 2px -1px hsl(0 0% 0% / 0.1); + --shadow-md: + 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 2px 4px -1px hsl(0 0% 0% / 0.1); + --shadow-lg: + 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 4px 6px -1px hsl(0 0% 0% / 0.1); + --shadow-xl: + 0 1px 3px 0px hsl(0 0% 0% / 0.1), 0 8px 10px -1px hsl(0 0% 0% / 0.1); + --shadow-2xl: 0 1px 3px 0px hsl(0 0% 0% / 0.25); +} + +@theme inline { + --color-background: var(--background); + --color-foreground: var(--foreground); + --color-card: var(--card); + --color-card-foreground: var(--card-foreground); + --color-popover: var(--popover); + --color-popover-foreground: var(--popover-foreground); + --color-primary: var(--primary); + --color-primary-foreground: var(--primary-foreground); + --color-secondary: var(--secondary); + --color-secondary-foreground: var(--secondary-foreground); + --color-muted: var(--muted); + --color-muted-foreground: var(--muted-foreground); + --color-accent: var(--accent); + --color-accent-foreground: var(--accent-foreground); + --color-destructive: var(--destructive); + --color-destructive-foreground: var(--destructive-foreground); + --color-border: var(--border); + --color-input: var(--input); + --color-ring: var(--ring); + --color-chart-1: var(--chart-1); + --color-chart-2: var(--chart-2); + --color-chart-3: var(--chart-3); + --color-chart-4: var(--chart-4); + --color-chart-5: var(--chart-5); + --color-sidebar: var(--sidebar); + --color-sidebar-foreground: var(--sidebar-foreground); + --color-sidebar-primary: var(--sidebar-primary); + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); + --color-sidebar-accent: var(--sidebar-accent); + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); + --color-sidebar-border: var(--sidebar-border); + --color-sidebar-ring: var(--sidebar-ring); + + --font-sans: var(--font-sans); + --font-mono: var(--font-mono); + --font-serif: var(--font-serif); + + --radius-sm: calc(var(--radius) - 4px); + --radius-md: calc(var(--radius) - 2px); + --radius-lg: var(--radius); + --radius-xl: calc(var(--radius) + 4px); + + --shadow-2xs: var(--shadow-2xs); + --shadow-xs: var(--shadow-xs); + --shadow-sm: var(--shadow-sm); + --shadow: var(--shadow); + --shadow-md: var(--shadow-md); + --shadow-lg: var(--shadow-lg); + --shadow-xl: var(--shadow-xl); + --shadow-2xl: var(--shadow-2xl); } -@plugin "daisyui"; -@plugin "daisyui/theme" { - name: "mikn"; - default: true; /* set as default */ - --color-primary: #ff9900; - --color-secondary: #ff7700; -} \ No newline at end of file +@layer base { + * { + @apply border-border outline-ring/50; + } + body { + @apply bg-background text-foreground; + } +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index b1c9b6a..ddadfb8 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,11 +1,18 @@ import { ReactNode } from "react"; -import type { Metadata } from "next"; +import localFont from "next/font/local"; +import { CursorToysProvider } from "@/contexts/CursorToysContext"; -export const metadata: Metadata = { - title: "MikanDev", - description: "We make cool stuff to make life easier 🍊", -}; +const hsr = localFont({ + src: "../assets/fonts/HSR.woff2", + variable: "--font-sans", +}); export default function RootLayout({ children }: { children: ReactNode }) { - return <>{children}; + return ( + + + {children} + + + ); } diff --git a/src/app/not-found.tsx b/src/app/not-found.tsx index e378cef..c7934ff 100644 --- a/src/app/not-found.tsx +++ b/src/app/not-found.tsx @@ -5,24 +5,22 @@ import "./globals.css"; const hsr = localFont({ src: ".././assets/fonts/HSR.woff2" }); export default function NotFound() { - return ( - <> - - -
-

- 404 - Page Not Found -

- - - -
- - - - ); + return ( + <> + + +
+

+ 404 - Page Not Found +

+ + + +
+ + + + ); } diff --git a/src/assets/cloudfront.png b/src/assets/cloudfront.png deleted file mode 100644 index 4cabff8..0000000 Binary files a/src/assets/cloudfront.png and /dev/null differ diff --git a/src/components/BubbleMenu.tsx b/src/components/BubbleMenu.tsx new file mode 100644 index 0000000..0bba8d8 --- /dev/null +++ b/src/components/BubbleMenu.tsx @@ -0,0 +1,430 @@ +import type { CSSProperties, ReactNode } from "react"; +import { useEffect, useRef, useState } from "react"; +import { gsap } from "gsap"; + +type MenuItem = { + label: string; + href: string; + ariaLabel?: string; + rotation?: number; + hoverStyles?: { + bgColor?: string; + textColor?: string; + }; +}; + +export type BubbleMenuProps = { + logo: ReactNode | string; + onMenuClick?: (open: boolean) => void; + className?: string; + style?: CSSProperties; + menuAriaLabel?: string; + menuBg?: string; + menuContentColor?: string; + useFixedPosition?: boolean; + items?: MenuItem[]; + animationEase?: string; + animationDuration?: number; + staggerDelay?: number; +}; + +const DEFAULT_ITEMS: MenuItem[] = [ + { + label: "home", + href: "#", + ariaLabel: "Home", + rotation: -8, + hoverStyles: { bgColor: "#3b82f6", textColor: "#ffffff" }, + }, + { + label: "about", + href: "#", + ariaLabel: "About", + rotation: 8, + hoverStyles: { bgColor: "#10b981", textColor: "#ffffff" }, + }, + { + label: "projects", + href: "#", + ariaLabel: "Documentation", + rotation: 8, + hoverStyles: { bgColor: "#f59e0b", textColor: "#ffffff" }, + }, + { + label: "blog", + href: "#", + ariaLabel: "Blog", + rotation: 8, + hoverStyles: { bgColor: "#ef4444", textColor: "#ffffff" }, + }, + { + label: "contact", + href: "#", + ariaLabel: "Contact", + rotation: -8, + hoverStyles: { bgColor: "#8b5cf6", textColor: "#ffffff" }, + }, +]; + +export default function BubbleMenu({ + logo, + onMenuClick, + className, + style, + menuAriaLabel = "Toggle menu", + menuBg = "#fff", + menuContentColor = "#111", + useFixedPosition = false, + items, + animationEase = "back.out(1.5)", + animationDuration = 0.5, + staggerDelay = 0.12, +}: BubbleMenuProps) { + const [isMenuOpen, setIsMenuOpen] = useState(false); + const [showOverlay, setShowOverlay] = useState(false); + + const overlayRef = useRef(null); + const bubblesRef = useRef([]); + const labelRefs = useRef([]); + + const menuItems = items?.length ? items : DEFAULT_ITEMS; + + const containerClassName = [ + "bubble-menu", + useFixedPosition ? "fixed" : "absolute", + "left-0 right-0 top-8", + "flex items-center justify-between", + "gap-4 px-8", + "pointer-events-none", + "z-[1001]", + className, + ] + .filter(Boolean) + .join(" "); + + const handleToggle = () => { + const nextState = !isMenuOpen; + if (nextState) setShowOverlay(true); + setIsMenuOpen(nextState); + onMenuClick?.(nextState); + }; + + useEffect(() => { + const overlay = overlayRef.current; + const bubbles = bubblesRef.current.filter(Boolean); + const labels = labelRefs.current.filter(Boolean); + if (!overlay || !bubbles.length) return; + + if (isMenuOpen) { + gsap.set(overlay, { display: "flex" }); + gsap.killTweensOf([...bubbles, ...labels]); + gsap.set(bubbles, { scale: 0, transformOrigin: "50% 50%" }); + gsap.set(labels, { y: 24, autoAlpha: 0 }); + + bubbles.forEach((bubble, i) => { + const delay = i * staggerDelay + gsap.utils.random(-0.05, 0.05); + const tl = gsap.timeline({ delay }); + tl.to(bubble, { + scale: 1, + duration: animationDuration, + ease: animationEase, + }); + if (labels[i]) { + tl.to( + labels[i], + { + y: 0, + autoAlpha: 1, + duration: animationDuration, + ease: "power3.out", + }, + "-=" + animationDuration * 0.9, + ); + } + }); + } else if (showOverlay) { + gsap.killTweensOf([...bubbles, ...labels]); + gsap.to(labels, { + y: 24, + autoAlpha: 0, + duration: 0.2, + ease: "power3.in", + }); + gsap.to(bubbles, { + scale: 0, + duration: 0.2, + ease: "power3.in", + onComplete: () => { + gsap.set(overlay, { display: "none" }); + setShowOverlay(false); + }, + }); + } + }, [isMenuOpen, showOverlay, animationEase, animationDuration, staggerDelay]); + + useEffect(() => { + const handleResize = () => { + if (isMenuOpen) { + const bubbles = bubblesRef.current.filter(Boolean); + const isDesktop = window.innerWidth >= 900; + bubbles.forEach((bubble, i) => { + const item = menuItems[i]; + if (bubble && item) { + const rotation = isDesktop ? (item.rotation ?? 0) : 0; + gsap.set(bubble, { rotation }); + } + }); + } + }; + window.addEventListener("resize", handleResize); + return () => window.removeEventListener("resize", handleResize); + }, [isMenuOpen, menuItems]); + + return ( + <> + {/* Workaround for silly Tailwind capabilities */} + + + + + {showOverlay && ( +
+ +
+ )} + + ); +} diff --git a/src/components/ClickSpark.tsx b/src/components/ClickSpark.tsx new file mode 100644 index 0000000..5282452 --- /dev/null +++ b/src/components/ClickSpark.tsx @@ -0,0 +1,173 @@ +"use client"; +import React, { useRef, useEffect, useCallback } from "react"; + +interface ClickSparkProps { + sparkColor?: string; + sparkSize?: number; + sparkRadius?: number; + sparkCount?: number; + duration?: number; + easing?: "linear" | "ease-in" | "ease-out" | "ease-in-out"; + extraScale?: number; + children?: React.ReactNode; +} + +interface Spark { + x: number; + y: number; + angle: number; + startTime: number; +} + +const ClickSpark: React.FC = ({ + sparkColor = "#fff", + sparkSize = 10, + sparkRadius = 15, + sparkCount = 8, + duration = 400, + easing = "ease-out", + extraScale = 1.0, + children, +}) => { + const canvasRef = useRef(null); + const sparksRef = useRef([]); + const startTimeRef = useRef(null); + + useEffect(() => { + const canvas = canvasRef.current; + if (!canvas) return; + + const parent = canvas.parentElement; + if (!parent) return; + + let resizeTimeout: NodeJS.Timeout; + + const resizeCanvas = () => { + const { width, height } = parent.getBoundingClientRect(); + if (canvas.width !== width || canvas.height !== height) { + canvas.width = width; + canvas.height = height; + } + }; + + const handleResize = () => { + clearTimeout(resizeTimeout); + resizeTimeout = setTimeout(resizeCanvas, 100); + }; + + const ro = new ResizeObserver(handleResize); + ro.observe(parent); + + resizeCanvas(); + + return () => { + ro.disconnect(); + clearTimeout(resizeTimeout); + }; + }, []); + + const easeFunc = useCallback( + (t: number) => { + switch (easing) { + case "linear": + return t; + case "ease-in": + return t * t; + case "ease-in-out": + return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t; + default: + return t * (2 - t); + } + }, + [easing], + ); + + useEffect(() => { + const canvas = canvasRef.current; + if (!canvas) return; + const ctx = canvas.getContext("2d"); + if (!ctx) return; + + let animationId: number; + + const draw = (timestamp: number) => { + if (!startTimeRef.current) { + startTimeRef.current = timestamp; + } + ctx?.clearRect(0, 0, canvas.width, canvas.height); + + sparksRef.current = sparksRef.current.filter((spark: Spark) => { + const elapsed = timestamp - spark.startTime; + if (elapsed >= duration) { + return false; + } + + const progress = elapsed / duration; + const eased = easeFunc(progress); + + const distance = eased * sparkRadius * extraScale; + const lineLength = sparkSize * (1 - eased); + + const x1 = spark.x + distance * Math.cos(spark.angle); + const y1 = spark.y + distance * Math.sin(spark.angle); + const x2 = spark.x + (distance + lineLength) * Math.cos(spark.angle); + const y2 = spark.y + (distance + lineLength) * Math.sin(spark.angle); + + ctx.strokeStyle = sparkColor; + ctx.lineWidth = 2; + ctx.beginPath(); + ctx.moveTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.stroke(); + + return true; + }); + + animationId = requestAnimationFrame(draw); + }; + + animationId = requestAnimationFrame(draw); + + return () => { + cancelAnimationFrame(animationId); + }; + }, [ + sparkColor, + sparkSize, + sparkRadius, + sparkCount, + duration, + easeFunc, + extraScale, + ]); + + const handleClick = (e: React.MouseEvent): void => { + const canvas = canvasRef.current; + if (!canvas) return; + const rect = canvas.getBoundingClientRect(); + const x = e.clientX - rect.left; + const y = e.clientY - rect.top; + + const now = performance.now(); + const newSparks: Spark[] = Array.from({ length: sparkCount }, (_, i) => ({ + x, + y, + angle: (2 * Math.PI * i) / sparkCount, + startTime: now, + })); + + sparksRef.current.push(...newSparks); + }; + + return ( +
+ + {children} +
+ ); +}; + +export default ClickSpark; diff --git a/src/components/CursorToys.tsx b/src/components/CursorToys.tsx new file mode 100644 index 0000000..d45ae0c --- /dev/null +++ b/src/components/CursorToys.tsx @@ -0,0 +1,26 @@ +"use client"; +import { ICursorToys } from "@/interfaces/CursorToys"; +import { FC } from "react"; +import { useCursorToys } from "@/contexts/CursorToysContext"; + +import ClickSpark from "@/components/ClickSpark"; +import SplashCursor from "@/components/SplashCursor"; +import CustomCursor from "@/components/CustomCursor"; +import TargetCursor from "@/components/TargetCursor"; + +export const CursorToys: FC = ({ children }) => { + const { selectedToy } = useCursorToys(); + + if (selectedToy === "spark") { + return {children}; + } + + return ( + <> + {selectedToy === "splash" && } + {selectedToy === "custom" && } + {selectedToy === "target" && } + {children} + + ); +}; diff --git a/src/components/CustomCursor.tsx b/src/components/CustomCursor.tsx new file mode 100644 index 0000000..c70ef6d --- /dev/null +++ b/src/components/CustomCursor.tsx @@ -0,0 +1,62 @@ +"use client"; +import { useEffect, useRef } from "react"; +import Mikan from "@/assets/img/mikan.png"; +import Image from "next/image"; + +export default function CustomCursor() { + const cursorRef = useRef(null); + + useEffect(() => { + // Add a global style to hide cursor on all elements + const styleElement = document.createElement("style"); + styleElement.id = "custom-cursor-style"; + styleElement.innerHTML = `* { cursor: none !important; }`; + document.head.appendChild(styleElement); + + const handleMouseMove = (e: MouseEvent) => { + if (cursorRef.current) { + // Use requestAnimationFrame for smooth rendering without flickering + requestAnimationFrame(() => { + if (cursorRef.current) { + // Center the cursor on the mouse position + cursorRef.current.style.left = `${e.clientX}px`; + cursorRef.current.style.top = `${e.clientY}px`; + } + }); + } + }; + + window.addEventListener("mousemove", handleMouseMove, { passive: true }); + + return () => { + window.removeEventListener("mousemove", handleMouseMove); + // Remove the global cursor style + const style = document.getElementById("custom-cursor-style"); + if (style) { + style.remove(); + } + }; + }, []); + + return ( +
+ Custom Cursor +
+ ); +} diff --git a/src/components/FluidGlass.tsx b/src/components/FluidGlass.tsx new file mode 100644 index 0000000..7a5998f --- /dev/null +++ b/src/components/FluidGlass.tsx @@ -0,0 +1,385 @@ +import * as THREE from "three"; +import { useRef, useState, useEffect, memo, ReactNode } from "react"; +import { + Canvas, + createPortal, + useFrame, + useThree, + ThreeElements, +} from "@react-three/fiber"; +import { + useFBO, + useGLTF, + useScroll, + Image, + Scroll, + Preload, + ScrollControls, + MeshTransmissionMaterial, + Text, +} from "@react-three/drei"; +import { easing } from "maath"; + +type Mode = "lens" | "bar" | "cube"; + +interface NavItem { + label: string; + link: string; +} + +type ModeProps = Record; + +interface FluidGlassProps { + mode?: Mode; + lensProps?: ModeProps; + barProps?: ModeProps; + cubeProps?: ModeProps; +} + +export default function FluidGlass({ + mode = "lens", + lensProps = {}, + barProps = {}, + cubeProps = {}, +}: FluidGlassProps) { + const Wrapper = mode === "bar" ? Bar : mode === "cube" ? Cube : Lens; + const rawOverrides = + mode === "bar" ? barProps : mode === "cube" ? cubeProps : lensProps; + + const { + navItems = [ + { label: "Home", link: "" }, + { label: "About", link: "" }, + { label: "Contact", link: "" }, + ], + ...modeProps + } = rawOverrides; + + return ( + + + {mode === "bar" && } + + + + + + + + + + + ); +} + +type MeshProps = ThreeElements["mesh"]; + +interface ModeWrapperProps extends MeshProps { + children?: ReactNode; + glb: string; + geometryKey: string; + lockToBottom?: boolean; + followPointer?: boolean; + modeProps?: ModeProps; +} + +interface ZoomMaterial extends THREE.Material { + zoom: number; +} + +interface ZoomMesh extends THREE.Mesh {} + +type ZoomGroup = THREE.Group & { children: ZoomMesh[] }; + +const ModeWrapper = memo(function ModeWrapper({ + children, + glb, + geometryKey, + lockToBottom = false, + followPointer = true, + modeProps = {}, + ...props +}: ModeWrapperProps) { + const ref = useRef(null!); + const { nodes } = useGLTF(glb); + const buffer = useFBO(); + const { viewport: vp } = useThree(); + const [scene] = useState(() => new THREE.Scene()); + const geoWidthRef = useRef(1); + + useEffect(() => { + const geo = (nodes[geometryKey] as THREE.Mesh)?.geometry; + geo.computeBoundingBox(); + geoWidthRef.current = geo.boundingBox!.max.x - geo.boundingBox!.min.x || 1; + }, [nodes, geometryKey]); + + useFrame((state, delta) => { + const { gl, viewport, pointer, camera } = state; + const v = viewport.getCurrentViewport(camera, [0, 0, 15]); + + const destX = followPointer ? (pointer.x * v.width) / 2 : 0; + const destY = lockToBottom + ? -v.height / 2 + 0.2 + : followPointer + ? (pointer.y * v.height) / 2 + : 0; + easing.damp3(ref.current.position, [destX, destY, 15], 0.15, delta); + + if ((modeProps as { scale?: number }).scale == null) { + const maxWorld = v.width * 0.9; + const desired = maxWorld / geoWidthRef.current; + ref.current.scale.setScalar(Math.min(0.15, desired)); + } + + gl.setRenderTarget(buffer); + gl.render(scene, camera); + gl.setRenderTarget(null); + gl.setClearColor(0x5227ff, 1); + }); + + const { + scale, + ior, + thickness, + anisotropy, + chromaticAberration, + ...extraMat + } = modeProps as { + scale?: number; + ior?: number; + thickness?: number; + anisotropy?: number; + chromaticAberration?: number; + [key: string]: unknown; + }; + + return ( + <> + {createPortal(children, scene)} + + + + + + + + + ); +}); + +function Lens({ modeProps, ...p }: { modeProps?: ModeProps } & MeshProps) { + return ( + + ); +} + +function Cube({ modeProps, ...p }: { modeProps?: ModeProps } & MeshProps) { + return ( + + ); +} + +function Bar({ modeProps = {}, ...p }: { modeProps?: ModeProps } & MeshProps) { + const defaultMat = { + transmission: 1, + roughness: 0, + thickness: 10, + ior: 1.15, + color: "#ffffff", + attenuationColor: "#ffffff", + attenuationDistance: 0.25, + }; + + return ( + + ); +} + +function NavItems({ items }: { items: NavItem[] }) { + const group = useRef(null!); + const { viewport, camera } = useThree(); + + const DEVICE = { + mobile: { max: 639, spacing: 0.2, fontSize: 0.035 }, + tablet: { max: 1023, spacing: 0.24, fontSize: 0.045 }, + desktop: { max: Infinity, spacing: 0.3, fontSize: 0.045 }, + }; + const getDevice = () => { + const w = window.innerWidth; + return w <= DEVICE.mobile.max + ? "mobile" + : w <= DEVICE.tablet.max + ? "tablet" + : "desktop"; + }; + + const [device, setDevice] = useState(getDevice()); + + useEffect(() => { + const onResize = () => setDevice(getDevice()); + window.addEventListener("resize", onResize); + return () => window.removeEventListener("resize", onResize); + }, []); + + const { spacing, fontSize } = DEVICE[device]; + + useFrame(() => { + if (!group.current) return; + const v = viewport.getCurrentViewport(camera, [0, 0, 15]); + group.current.position.set(0, -v.height / 2 + 0.2, 15.1); + + group.current.children.forEach((child, i) => { + child.position.x = (i - (items.length - 1) / 2) * spacing; + }); + }); + + const handleNavigate = (link: string) => { + if (!link) return; + link.startsWith("#") + ? (window.location.hash = link) + : (window.location.href = link); + }; + + return ( + + {items.map(({ label, link }) => ( + { + e.stopPropagation(); + handleNavigate(link); + }} + onPointerOver={() => (document.body.style.cursor = "pointer")} + onPointerOut={() => (document.body.style.cursor = "auto")} + > + {label} + + ))} + + ); +} + +function Images() { + const group = useRef(null!); + const data = useScroll(); + const { height } = useThree((s) => s.viewport); + + useFrame(() => { + group.current.children[0].material.zoom = 1 + data.range(0, 1 / 3) / 3; + group.current.children[1].material.zoom = 1 + data.range(0, 1 / 3) / 3; + group.current.children[2].material.zoom = + 1 + data.range(1.15 / 3, 1 / 3) / 2; + group.current.children[3].material.zoom = + 1 + data.range(1.15 / 3, 1 / 3) / 2; + group.current.children[4].material.zoom = + 1 + data.range(1.15 / 3, 1 / 3) / 2; + }); + + return ( + + + + + + + + ); +} + +function Typography() { + const DEVICE = { + mobile: { fontSize: 0.2 }, + tablet: { fontSize: 0.4 }, + desktop: { fontSize: 0.6 }, + }; + const getDevice = () => { + const w = window.innerWidth; + return w <= 639 ? "mobile" : w <= 1023 ? "tablet" : "desktop"; + }; + + const [device, setDevice] = useState(getDevice()); + + useEffect(() => { + const onResize = () => setDevice(getDevice()); + window.addEventListener("resize", onResize); + return () => window.removeEventListener("resize", onResize); + }, []); + + const { fontSize } = DEVICE[device]; + + return ( + + React Bits + + ); +} diff --git a/src/components/GlobalCursorToys.tsx b/src/components/GlobalCursorToys.tsx new file mode 100644 index 0000000..535472c --- /dev/null +++ b/src/components/GlobalCursorToys.tsx @@ -0,0 +1,13 @@ +"use client"; +import { useCursorToys } from "@/contexts/CursorToysContext"; +import TargetCursor from "@/components/TargetCursor"; + +export default function GlobalCursorToys() { + const { selectedToy } = useCursorToys(); + + if (selectedToy === "target") { + return ; + } + + return null; +} diff --git a/src/components/SettingsController.tsx b/src/components/SettingsController.tsx new file mode 100644 index 0000000..d26215b --- /dev/null +++ b/src/components/SettingsController.tsx @@ -0,0 +1,114 @@ +"use client"; +import { motion, AnimatePresence } from "motion/react"; +import { useState } from "react"; +import { Settings } from "@/components/animate-ui/icons/settings"; +import { useConsentManager } from "@c15t/react"; +import { Button } from "@/components/animate-ui/components/buttons/button"; +import { useCursorToys } from "@/contexts/CursorToysContext"; + +interface AccButtonProps { + children?: React.ReactNode; +} + +const AnimatedButton = ({ onClick }: { onClick: () => void }) => { + return ( + +
+ +
+
+ ); +}; + +export default function SettingsController({ children }: AccButtonProps) { + const [open, setOpen] = useState(false); + const { setIsPrivacyDialogOpen } = useConsentManager(); + const { selectedToy, setSelectedToy } = useCursorToys(); + + return ( +
+ setOpen(!open)} /> + + {open && ( + +
+

Site settings

+
+
+ +
+

Cursor Toys

+
+ + + + + +
+
+
+
+ )} +
+ {children} +
+ ); +} diff --git a/src/components/SplashCursor.tsx b/src/components/SplashCursor.tsx new file mode 100644 index 0000000..6d1610a --- /dev/null +++ b/src/components/SplashCursor.tsx @@ -0,0 +1,1521 @@ +"use client"; +import React, { useEffect, useRef } from "react"; + +interface ColorRGB { + r: number; + g: number; + b: number; +} + +interface SplashCursorProps { + SIM_RESOLUTION?: number; + DYE_RESOLUTION?: number; + CAPTURE_RESOLUTION?: number; + DENSITY_DISSIPATION?: number; + VELOCITY_DISSIPATION?: number; + PRESSURE?: number; + PRESSURE_ITERATIONS?: number; + CURL?: number; + SPLAT_RADIUS?: number; + SPLAT_FORCE?: number; + SHADING?: boolean; + COLOR_UPDATE_SPEED?: number; + BACK_COLOR?: ColorRGB; + TRANSPARENT?: boolean; +} + +interface Pointer { + id: number; + texcoordX: number; + texcoordY: number; + prevTexcoordX: number; + prevTexcoordY: number; + deltaX: number; + deltaY: number; + down: boolean; + moved: boolean; + color: ColorRGB; +} + +function pointerPrototype(): Pointer { + return { + id: -1, + texcoordX: 0, + texcoordY: 0, + prevTexcoordX: 0, + prevTexcoordY: 0, + deltaX: 0, + deltaY: 0, + down: false, + moved: false, + color: { r: 0, g: 0, b: 0 }, + }; +} + +export default function SplashCursor({ + SIM_RESOLUTION = 128, + DYE_RESOLUTION = 1440, + CAPTURE_RESOLUTION = 512, + DENSITY_DISSIPATION = 3.5, + VELOCITY_DISSIPATION = 2, + PRESSURE = 0.1, + PRESSURE_ITERATIONS = 20, + CURL = 3, + SPLAT_RADIUS = 0.2, + SPLAT_FORCE = 6000, + SHADING = true, + COLOR_UPDATE_SPEED = 10, + BACK_COLOR = { r: 0.5, g: 0, b: 0 }, + TRANSPARENT = true, +}: SplashCursorProps) { + const canvasRef = useRef(null); + + useEffect(() => { + const canvas = canvasRef.current; + if (!canvas) return; + + let pointers: Pointer[] = [pointerPrototype()]; + + let config = { + SIM_RESOLUTION: SIM_RESOLUTION!, + DYE_RESOLUTION: DYE_RESOLUTION!, + CAPTURE_RESOLUTION: CAPTURE_RESOLUTION!, + DENSITY_DISSIPATION: DENSITY_DISSIPATION!, + VELOCITY_DISSIPATION: VELOCITY_DISSIPATION!, + PRESSURE: PRESSURE!, + PRESSURE_ITERATIONS: PRESSURE_ITERATIONS!, + CURL: CURL!, + SPLAT_RADIUS: SPLAT_RADIUS!, + SPLAT_FORCE: SPLAT_FORCE!, + SHADING, + COLOR_UPDATE_SPEED: COLOR_UPDATE_SPEED!, + PAUSED: false, + BACK_COLOR, + TRANSPARENT, + }; + + const { gl, ext } = getWebGLContext(canvas); + if (!gl || !ext) return; + + if (!ext.supportLinearFiltering) { + config.DYE_RESOLUTION = 256; + config.SHADING = false; + } + + function getWebGLContext(canvas: HTMLCanvasElement) { + const params = { + alpha: true, + depth: false, + stencil: false, + antialias: false, + preserveDrawingBuffer: false, + }; + + let gl = canvas.getContext( + "webgl2", + params, + ) as WebGL2RenderingContext | null; + + if (!gl) { + gl = (canvas.getContext("webgl", params) || + canvas.getContext( + "experimental-webgl", + params, + )) as WebGL2RenderingContext | null; + } + + if (!gl) { + throw new Error("Unable to initialize WebGL."); + } + + const isWebGL2 = "drawBuffers" in gl; + + let supportLinearFiltering = false; + let halfFloat = null; + + if (isWebGL2) { + (gl as WebGL2RenderingContext).getExtension("EXT_color_buffer_float"); + supportLinearFiltering = !!(gl as WebGL2RenderingContext).getExtension( + "OES_texture_float_linear", + ); + } else { + halfFloat = gl.getExtension("OES_texture_half_float"); + supportLinearFiltering = !!gl.getExtension( + "OES_texture_half_float_linear", + ); + } + + gl.clearColor(0, 0, 0, 1); + + const halfFloatTexType = isWebGL2 + ? (gl as WebGL2RenderingContext).HALF_FLOAT + : (halfFloat && (halfFloat as any).HALF_FLOAT_OES) || 0; + + let formatRGBA: any; + let formatRG: any; + let formatR: any; + + if (isWebGL2) { + formatRGBA = getSupportedFormat( + gl, + (gl as WebGL2RenderingContext).RGBA16F, + gl.RGBA, + halfFloatTexType, + ); + formatRG = getSupportedFormat( + gl, + (gl as WebGL2RenderingContext).RG16F, + (gl as WebGL2RenderingContext).RG, + halfFloatTexType, + ); + formatR = getSupportedFormat( + gl, + (gl as WebGL2RenderingContext).R16F, + (gl as WebGL2RenderingContext).RED, + halfFloatTexType, + ); + } else { + formatRGBA = getSupportedFormat(gl, gl.RGBA, gl.RGBA, halfFloatTexType); + formatRG = getSupportedFormat(gl, gl.RGBA, gl.RGBA, halfFloatTexType); + formatR = getSupportedFormat(gl, gl.RGBA, gl.RGBA, halfFloatTexType); + } + + return { + gl, + ext: { + formatRGBA, + formatRG, + formatR, + halfFloatTexType, + supportLinearFiltering, + }, + }; + } + + function getSupportedFormat( + gl: WebGLRenderingContext | WebGL2RenderingContext, + internalFormat: number, + format: number, + type: number, + ): { internalFormat: number; format: number } | null { + if (!supportRenderTextureFormat(gl, internalFormat, format, type)) { + if ("drawBuffers" in gl) { + const gl2 = gl as WebGL2RenderingContext; + switch (internalFormat) { + case gl2.R16F: + return getSupportedFormat(gl2, gl2.RG16F, gl2.RG, type); + case gl2.RG16F: + return getSupportedFormat(gl2, gl2.RGBA16F, gl2.RGBA, type); + default: + return null; + } + } + return null; + } + return { internalFormat, format }; + } + + function supportRenderTextureFormat( + gl: WebGLRenderingContext | WebGL2RenderingContext, + internalFormat: number, + format: number, + type: number, + ) { + const texture = gl.createTexture(); + if (!texture) return false; + + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texImage2D( + gl.TEXTURE_2D, + 0, + internalFormat, + 4, + 4, + 0, + format, + type, + null, + ); + + const fbo = gl.createFramebuffer(); + if (!fbo) return false; + + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + gl.framebufferTexture2D( + gl.FRAMEBUFFER, + gl.COLOR_ATTACHMENT0, + gl.TEXTURE_2D, + texture, + 0, + ); + const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER); + return status === gl.FRAMEBUFFER_COMPLETE; + } + + function hashCode(s: string) { + if (!s.length) return 0; + let hash = 0; + for (let i = 0; i < s.length; i++) { + hash = (hash << 5) - hash + s.charCodeAt(i); + hash |= 0; + } + return hash; + } + + function addKeywords(source: string, keywords: string[] | null) { + if (!keywords) return source; + let keywordsString = ""; + for (const keyword of keywords) { + keywordsString += `#define ${keyword}\n`; + } + return keywordsString + source; + } + + function compileShader( + type: number, + source: string, + keywords: string[] | null = null, + ): WebGLShader | null { + const shaderSource = addKeywords(source, keywords); + const shader = gl.createShader(type); + if (!shader) return null; + gl.shaderSource(shader, shaderSource); + gl.compileShader(shader); + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + console.trace(gl.getShaderInfoLog(shader)); + } + return shader; + } + + function createProgram( + vertexShader: WebGLShader | null, + fragmentShader: WebGLShader | null, + ): WebGLProgram | null { + if (!vertexShader || !fragmentShader) return null; + const program = gl.createProgram(); + if (!program) return null; + gl.attachShader(program, vertexShader); + gl.attachShader(program, fragmentShader); + gl.linkProgram(program); + if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { + console.trace(gl.getProgramInfoLog(program)); + } + return program; + } + + function getUniforms(program: WebGLProgram) { + let uniforms: Record = {}; + const uniformCount = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS); + for (let i = 0; i < uniformCount; i++) { + const uniformInfo = gl.getActiveUniform(program, i); + if (uniformInfo) { + uniforms[uniformInfo.name] = gl.getUniformLocation( + program, + uniformInfo.name, + ); + } + } + return uniforms; + } + + class Program { + program: WebGLProgram | null; + uniforms: Record; + + constructor( + vertexShader: WebGLShader | null, + fragmentShader: WebGLShader | null, + ) { + this.program = createProgram(vertexShader, fragmentShader); + this.uniforms = this.program ? getUniforms(this.program) : {}; + } + + bind() { + if (this.program) gl.useProgram(this.program); + } + } + + class Material { + vertexShader: WebGLShader | null; + fragmentShaderSource: string; + programs: Record; + activeProgram: WebGLProgram | null; + uniforms: Record; + + constructor( + vertexShader: WebGLShader | null, + fragmentShaderSource: string, + ) { + this.vertexShader = vertexShader; + this.fragmentShaderSource = fragmentShaderSource; + this.programs = {}; + this.activeProgram = null; + this.uniforms = {}; + } + + setKeywords(keywords: string[]) { + let hash = 0; + for (const kw of keywords) { + hash += hashCode(kw); + } + let program = this.programs[hash]; + if (program == null) { + const fragmentShader = compileShader( + gl.FRAGMENT_SHADER, + this.fragmentShaderSource, + keywords, + ); + program = createProgram(this.vertexShader, fragmentShader); + this.programs[hash] = program; + } + if (program === this.activeProgram) return; + if (program) { + this.uniforms = getUniforms(program); + } + this.activeProgram = program; + } + + bind() { + if (this.activeProgram) { + gl.useProgram(this.activeProgram); + } + } + } + + const baseVertexShader = compileShader( + gl.VERTEX_SHADER, + ` + precision highp float; + attribute vec2 aPosition; + varying vec2 vUv; + varying vec2 vL; + varying vec2 vR; + varying vec2 vT; + varying vec2 vB; + uniform vec2 texelSize; + + void main () { + vUv = aPosition * 0.5 + 0.5; + vL = vUv - vec2(texelSize.x, 0.0); + vR = vUv + vec2(texelSize.x, 0.0); + vT = vUv + vec2(0.0, texelSize.y); + vB = vUv - vec2(0.0, texelSize.y); + gl_Position = vec4(aPosition, 0.0, 1.0); + } + `, + ); + + const copyShader = compileShader( + gl.FRAGMENT_SHADER, + ` + precision mediump float; + precision mediump sampler2D; + varying highp vec2 vUv; + uniform sampler2D uTexture; + + void main () { + gl_FragColor = texture2D(uTexture, vUv); + } + `, + ); + + const clearShader = compileShader( + gl.FRAGMENT_SHADER, + ` + precision mediump float; + precision mediump sampler2D; + varying highp vec2 vUv; + uniform sampler2D uTexture; + uniform float value; + + void main () { + gl_FragColor = value * texture2D(uTexture, vUv); + } + `, + ); + + const displayShaderSource = ` + precision highp float; + precision highp sampler2D; + varying vec2 vUv; + varying vec2 vL; + varying vec2 vR; + varying vec2 vT; + varying vec2 vB; + uniform sampler2D uTexture; + uniform sampler2D uDithering; + uniform vec2 ditherScale; + uniform vec2 texelSize; + + vec3 linearToGamma (vec3 color) { + color = max(color, vec3(0)); + return max(1.055 * pow(color, vec3(0.416666667)) - 0.055, vec3(0)); + } + + void main () { + vec3 c = texture2D(uTexture, vUv).rgb; + #ifdef SHADING + vec3 lc = texture2D(uTexture, vL).rgb; + vec3 rc = texture2D(uTexture, vR).rgb; + vec3 tc = texture2D(uTexture, vT).rgb; + vec3 bc = texture2D(uTexture, vB).rgb; + + float dx = length(rc) - length(lc); + float dy = length(tc) - length(bc); + + vec3 n = normalize(vec3(dx, dy, length(texelSize))); + vec3 l = vec3(0.0, 0.0, 1.0); + + float diffuse = clamp(dot(n, l) + 0.7, 0.7, 1.0); + c *= diffuse; + #endif + + float a = max(c.r, max(c.g, c.b)); + gl_FragColor = vec4(c, a); + } + `; + + const splatShader = compileShader( + gl.FRAGMENT_SHADER, + ` + precision highp float; + precision highp sampler2D; + varying vec2 vUv; + uniform sampler2D uTarget; + uniform float aspectRatio; + uniform vec3 color; + uniform vec2 point; + uniform float radius; + + void main () { + vec2 p = vUv - point.xy; + p.x *= aspectRatio; + vec3 splat = exp(-dot(p, p) / radius) * color; + vec3 base = texture2D(uTarget, vUv).xyz; + gl_FragColor = vec4(base + splat, 1.0); + } + `, + ); + + const advectionShader = compileShader( + gl.FRAGMENT_SHADER, + ` + precision highp float; + precision highp sampler2D; + varying vec2 vUv; + uniform sampler2D uVelocity; + uniform sampler2D uSource; + uniform vec2 texelSize; + uniform vec2 dyeTexelSize; + uniform float dt; + uniform float dissipation; + + vec4 bilerp (sampler2D sam, vec2 uv, vec2 tsize) { + vec2 st = uv / tsize - 0.5; + vec2 iuv = floor(st); + vec2 fuv = fract(st); + + vec4 a = texture2D(sam, (iuv + vec2(0.5, 0.5)) * tsize); + vec4 b = texture2D(sam, (iuv + vec2(1.5, 0.5)) * tsize); + vec4 c = texture2D(sam, (iuv + vec2(0.5, 1.5)) * tsize); + vec4 d = texture2D(sam, (iuv + vec2(1.5, 1.5)) * tsize); + + return mix(mix(a, b, fuv.x), mix(c, d, fuv.x), fuv.y); + } + + void main () { + #ifdef MANUAL_FILTERING + vec2 coord = vUv - dt * bilerp(uVelocity, vUv, texelSize).xy * texelSize; + vec4 result = bilerp(uSource, coord, dyeTexelSize); + #else + vec2 coord = vUv - dt * texture2D(uVelocity, vUv).xy * texelSize; + vec4 result = texture2D(uSource, coord); + #endif + float decay = 1.0 + dissipation * dt; + gl_FragColor = result / decay; + } + `, + ext.supportLinearFiltering ? null : ["MANUAL_FILTERING"], + ); + + const divergenceShader = compileShader( + gl.FRAGMENT_SHADER, + ` + precision mediump float; + precision mediump sampler2D; + varying highp vec2 vUv; + varying highp vec2 vL; + varying highp vec2 vR; + varying highp vec2 vT; + varying highp vec2 vB; + uniform sampler2D uVelocity; + + void main () { + float L = texture2D(uVelocity, vL).x; + float R = texture2D(uVelocity, vR).x; + float T = texture2D(uVelocity, vT).y; + float B = texture2D(uVelocity, vB).y; + + vec2 C = texture2D(uVelocity, vUv).xy; + if (vL.x < 0.0) { L = -C.x; } + if (vR.x > 1.0) { R = -C.x; } + if (vT.y > 1.0) { T = -C.y; } + if (vB.y < 0.0) { B = -C.y; } + + float div = 0.5 * (R - L + T - B); + gl_FragColor = vec4(div, 0.0, 0.0, 1.0); + } + `, + ); + + const curlShader = compileShader( + gl.FRAGMENT_SHADER, + ` + precision mediump float; + precision mediump sampler2D; + varying highp vec2 vUv; + varying highp vec2 vL; + varying highp vec2 vR; + varying highp vec2 vT; + varying highp vec2 vB; + uniform sampler2D uVelocity; + + void main () { + float L = texture2D(uVelocity, vL).y; + float R = texture2D(uVelocity, vR).y; + float T = texture2D(uVelocity, vT).x; + float B = texture2D(uVelocity, vB).x; + float vorticity = R - L - T + B; + gl_FragColor = vec4(0.5 * vorticity, 0.0, 0.0, 1.0); + } + `, + ); + + const vorticityShader = compileShader( + gl.FRAGMENT_SHADER, + ` + precision highp float; + precision highp sampler2D; + varying vec2 vUv; + varying vec2 vL; + varying vec2 vR; + varying vec2 vT; + varying vec2 vB; + uniform sampler2D uVelocity; + uniform sampler2D uCurl; + uniform float curl; + uniform float dt; + + void main () { + float L = texture2D(uCurl, vL).x; + float R = texture2D(uCurl, vR).x; + float T = texture2D(uCurl, vT).x; + float B = texture2D(uCurl, vB).x; + float C = texture2D(uCurl, vUv).x; + + vec2 force = 0.5 * vec2(abs(T) - abs(B), abs(R) - abs(L)); + force /= length(force) + 0.0001; + force *= curl * C; + force.y *= -1.0; + + vec2 velocity = texture2D(uVelocity, vUv).xy; + velocity += force * dt; + velocity = min(max(velocity, -1000.0), 1000.0); + gl_FragColor = vec4(velocity, 0.0, 1.0); + } + `, + ); + + const pressureShader = compileShader( + gl.FRAGMENT_SHADER, + ` + precision mediump float; + precision mediump sampler2D; + varying highp vec2 vUv; + varying highp vec2 vL; + varying highp vec2 vR; + varying highp vec2 vT; + varying highp vec2 vB; + uniform sampler2D uPressure; + uniform sampler2D uDivergence; + + void main () { + float L = texture2D(uPressure, vL).x; + float R = texture2D(uPressure, vR).x; + float T = texture2D(uPressure, vT).x; + float B = texture2D(uPressure, vB).x; + float C = texture2D(uPressure, vUv).x; + float divergence = texture2D(uDivergence, vUv).x; + float pressure = (L + R + B + T - divergence) * 0.25; + gl_FragColor = vec4(pressure, 0.0, 0.0, 1.0); + } + `, + ); + + const gradientSubtractShader = compileShader( + gl.FRAGMENT_SHADER, + ` + precision mediump float; + precision mediump sampler2D; + varying highp vec2 vUv; + varying highp vec2 vL; + varying highp vec2 vR; + varying highp vec2 vT; + varying highp vec2 vB; + uniform sampler2D uPressure; + uniform sampler2D uVelocity; + + void main () { + float L = texture2D(uPressure, vL).x; + float R = texture2D(uPressure, vR).x; + float T = texture2D(uPressure, vT).x; + float B = texture2D(uPressure, vB).x; + vec2 velocity = texture2D(uVelocity, vUv).xy; + velocity.xy -= vec2(R - L, T - B); + gl_FragColor = vec4(velocity, 0.0, 1.0); + } + `, + ); + + const blit = (() => { + const buffer = gl.createBuffer()!; + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.bufferData( + gl.ARRAY_BUFFER, + new Float32Array([-1, -1, -1, 1, 1, 1, 1, -1]), + gl.STATIC_DRAW, + ); + const elemBuffer = gl.createBuffer()!; + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, elemBuffer); + gl.bufferData( + gl.ELEMENT_ARRAY_BUFFER, + new Uint16Array([0, 1, 2, 0, 2, 3]), + gl.STATIC_DRAW, + ); + gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0); + gl.enableVertexAttribArray(0); + + return (target: FBO | null, doClear = false) => { + if (!gl) return; + if (!target) { + gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + } else { + gl.viewport(0, 0, target.width, target.height); + gl.bindFramebuffer(gl.FRAMEBUFFER, target.fbo); + } + if (doClear) { + gl.clearColor(0, 0, 0, 1); + gl.clear(gl.COLOR_BUFFER_BIT); + } + gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0); + }; + })(); + + interface FBO { + texture: WebGLTexture; + fbo: WebGLFramebuffer; + width: number; + height: number; + texelSizeX: number; + texelSizeY: number; + attach: (id: number) => number; + } + + interface DoubleFBO { + width: number; + height: number; + texelSizeX: number; + texelSizeY: number; + read: FBO; + write: FBO; + swap: () => void; + } + + let dye: DoubleFBO; + let velocity: DoubleFBO; + let divergence: FBO; + let curl: FBO; + let pressure: DoubleFBO; + + const copyProgram = new Program(baseVertexShader, copyShader); + const clearProgram = new Program(baseVertexShader, clearShader); + const splatProgram = new Program(baseVertexShader, splatShader); + const advectionProgram = new Program(baseVertexShader, advectionShader); + const divergenceProgram = new Program(baseVertexShader, divergenceShader); + const curlProgram = new Program(baseVertexShader, curlShader); + const vorticityProgram = new Program(baseVertexShader, vorticityShader); + const pressureProgram = new Program(baseVertexShader, pressureShader); + const gradienSubtractProgram = new Program( + baseVertexShader, + gradientSubtractShader, + ); + const displayMaterial = new Material(baseVertexShader, displayShaderSource); + + function createFBO( + w: number, + h: number, + internalFormat: number, + format: number, + type: number, + param: number, + ): FBO { + gl.activeTexture(gl.TEXTURE0); + const texture = gl.createTexture()!; + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, param); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, param); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.texImage2D( + gl.TEXTURE_2D, + 0, + internalFormat, + w, + h, + 0, + format, + type, + null, + ); + const fbo = gl.createFramebuffer()!; + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + gl.framebufferTexture2D( + gl.FRAMEBUFFER, + gl.COLOR_ATTACHMENT0, + gl.TEXTURE_2D, + texture, + 0, + ); + gl.viewport(0, 0, w, h); + gl.clear(gl.COLOR_BUFFER_BIT); + + const texelSizeX = 1 / w; + const texelSizeY = 1 / h; + + return { + texture, + fbo, + width: w, + height: h, + texelSizeX, + texelSizeY, + attach(id: number) { + gl.activeTexture(gl.TEXTURE0 + id); + gl.bindTexture(gl.TEXTURE_2D, texture); + return id; + }, + }; + } + + function createDoubleFBO( + w: number, + h: number, + internalFormat: number, + format: number, + type: number, + param: number, + ): DoubleFBO { + const fbo1 = createFBO(w, h, internalFormat, format, type, param); + const fbo2 = createFBO(w, h, internalFormat, format, type, param); + return { + width: w, + height: h, + texelSizeX: fbo1.texelSizeX, + texelSizeY: fbo1.texelSizeY, + read: fbo1, + write: fbo2, + swap() { + const tmp = this.read; + this.read = this.write; + this.write = tmp; + }, + }; + } + + function resizeFBO( + target: FBO, + w: number, + h: number, + internalFormat: number, + format: number, + type: number, + param: number, + ) { + const newFBO = createFBO(w, h, internalFormat, format, type, param); + copyProgram.bind(); + if (copyProgram.uniforms.uTexture) + gl.uniform1i(copyProgram.uniforms.uTexture, target.attach(0)); + blit(newFBO, false); + return newFBO; + } + + function resizeDoubleFBO( + target: DoubleFBO, + w: number, + h: number, + internalFormat: number, + format: number, + type: number, + param: number, + ) { + if (target.width === w && target.height === h) return target; + target.read = resizeFBO( + target.read, + w, + h, + internalFormat, + format, + type, + param, + ); + target.write = createFBO(w, h, internalFormat, format, type, param); + target.width = w; + target.height = h; + target.texelSizeX = 1 / w; + target.texelSizeY = 1 / h; + return target; + } + + function initFramebuffers() { + const simRes = getResolution(config.SIM_RESOLUTION!); + const dyeRes = getResolution(config.DYE_RESOLUTION!); + + const texType = ext.halfFloatTexType; + const rgba = ext.formatRGBA; + const rg = ext.formatRG; + const r = ext.formatR; + const filtering = ext.supportLinearFiltering ? gl.LINEAR : gl.NEAREST; + gl.disable(gl.BLEND); + + if (!dye) { + dye = createDoubleFBO( + dyeRes.width, + dyeRes.height, + rgba.internalFormat, + rgba.format, + texType, + filtering, + ); + } else { + dye = resizeDoubleFBO( + dye, + dyeRes.width, + dyeRes.height, + rgba.internalFormat, + rgba.format, + texType, + filtering, + ); + } + + if (!velocity) { + velocity = createDoubleFBO( + simRes.width, + simRes.height, + rg.internalFormat, + rg.format, + texType, + filtering, + ); + } else { + velocity = resizeDoubleFBO( + velocity, + simRes.width, + simRes.height, + rg.internalFormat, + rg.format, + texType, + filtering, + ); + } + + divergence = createFBO( + simRes.width, + simRes.height, + r.internalFormat, + r.format, + texType, + gl.NEAREST, + ); + curl = createFBO( + simRes.width, + simRes.height, + r.internalFormat, + r.format, + texType, + gl.NEAREST, + ); + pressure = createDoubleFBO( + simRes.width, + simRes.height, + r.internalFormat, + r.format, + texType, + gl.NEAREST, + ); + } + + function updateKeywords() { + const displayKeywords: string[] = []; + if (config.SHADING) displayKeywords.push("SHADING"); + displayMaterial.setKeywords(displayKeywords); + } + + function getResolution(resolution: number) { + const w = gl.drawingBufferWidth; + const h = gl.drawingBufferHeight; + const aspectRatio = w / h; + let aspect = aspectRatio < 1 ? 1 / aspectRatio : aspectRatio; + const min = Math.round(resolution); + const max = Math.round(resolution * aspect); + if (w > h) { + return { width: max, height: min }; + } + return { width: min, height: max }; + } + + function scaleByPixelRatio(input: number) { + const pixelRatio = window.devicePixelRatio || 1; + return Math.floor(input * pixelRatio); + } + + updateKeywords(); + initFramebuffers(); + + let lastUpdateTime = Date.now(); + let colorUpdateTimer = 0.0; + + function updateFrame() { + const dt = calcDeltaTime(); + if (resizeCanvas()) initFramebuffers(); + updateColors(dt); + applyInputs(); + step(dt); + render(null); + requestAnimationFrame(updateFrame); + } + + function calcDeltaTime() { + const now = Date.now(); + let dt = (now - lastUpdateTime) / 1000; + dt = Math.min(dt, 0.016666); + lastUpdateTime = now; + return dt; + } + + function resizeCanvas() { + const width = scaleByPixelRatio(canvas!.clientWidth); + const height = scaleByPixelRatio(canvas!.clientHeight); + if (canvas!.width !== width || canvas!.height !== height) { + canvas!.width = width; + canvas!.height = height; + return true; + } + return false; + } + + function updateColors(dt: number) { + colorUpdateTimer += dt * config.COLOR_UPDATE_SPEED; + if (colorUpdateTimer >= 1) { + colorUpdateTimer = wrap(colorUpdateTimer, 0, 1); + pointers.forEach((p) => { + p.color = generateColor(); + }); + } + } + + function applyInputs() { + for (const p of pointers) { + if (p.moved) { + p.moved = false; + splatPointer(p); + } + } + } + + function step(dt: number) { + gl.disable(gl.BLEND); + + curlProgram.bind(); + if (curlProgram.uniforms.texelSize) { + gl.uniform2f( + curlProgram.uniforms.texelSize, + velocity.texelSizeX, + velocity.texelSizeY, + ); + } + if (curlProgram.uniforms.uVelocity) { + gl.uniform1i(curlProgram.uniforms.uVelocity, velocity.read.attach(0)); + } + blit(curl); + + vorticityProgram.bind(); + if (vorticityProgram.uniforms.texelSize) { + gl.uniform2f( + vorticityProgram.uniforms.texelSize, + velocity.texelSizeX, + velocity.texelSizeY, + ); + } + if (vorticityProgram.uniforms.uVelocity) { + gl.uniform1i( + vorticityProgram.uniforms.uVelocity, + velocity.read.attach(0), + ); + } + if (vorticityProgram.uniforms.uCurl) { + gl.uniform1i(vorticityProgram.uniforms.uCurl, curl.attach(1)); + } + if (vorticityProgram.uniforms.curl) { + gl.uniform1f(vorticityProgram.uniforms.curl, config.CURL); + } + if (vorticityProgram.uniforms.dt) { + gl.uniform1f(vorticityProgram.uniforms.dt, dt); + } + blit(velocity.write); + velocity.swap(); + + divergenceProgram.bind(); + if (divergenceProgram.uniforms.texelSize) { + gl.uniform2f( + divergenceProgram.uniforms.texelSize, + velocity.texelSizeX, + velocity.texelSizeY, + ); + } + if (divergenceProgram.uniforms.uVelocity) { + gl.uniform1i( + divergenceProgram.uniforms.uVelocity, + velocity.read.attach(0), + ); + } + blit(divergence); + + clearProgram.bind(); + if (clearProgram.uniforms.uTexture) { + gl.uniform1i(clearProgram.uniforms.uTexture, pressure.read.attach(0)); + } + if (clearProgram.uniforms.value) { + gl.uniform1f(clearProgram.uniforms.value, config.PRESSURE); + } + blit(pressure.write); + pressure.swap(); + + pressureProgram.bind(); + if (pressureProgram.uniforms.texelSize) { + gl.uniform2f( + pressureProgram.uniforms.texelSize, + velocity.texelSizeX, + velocity.texelSizeY, + ); + } + if (pressureProgram.uniforms.uDivergence) { + gl.uniform1i( + pressureProgram.uniforms.uDivergence, + divergence.attach(0), + ); + } + for (let i = 0; i < config.PRESSURE_ITERATIONS; i++) { + if (pressureProgram.uniforms.uPressure) { + gl.uniform1i( + pressureProgram.uniforms.uPressure, + pressure.read.attach(1), + ); + } + blit(pressure.write); + pressure.swap(); + } + + gradienSubtractProgram.bind(); + if (gradienSubtractProgram.uniforms.texelSize) { + gl.uniform2f( + gradienSubtractProgram.uniforms.texelSize, + velocity.texelSizeX, + velocity.texelSizeY, + ); + } + if (gradienSubtractProgram.uniforms.uPressure) { + gl.uniform1i( + gradienSubtractProgram.uniforms.uPressure, + pressure.read.attach(0), + ); + } + if (gradienSubtractProgram.uniforms.uVelocity) { + gl.uniform1i( + gradienSubtractProgram.uniforms.uVelocity, + velocity.read.attach(1), + ); + } + blit(velocity.write); + velocity.swap(); + + advectionProgram.bind(); + if (advectionProgram.uniforms.texelSize) { + gl.uniform2f( + advectionProgram.uniforms.texelSize, + velocity.texelSizeX, + velocity.texelSizeY, + ); + } + if ( + !ext.supportLinearFiltering && + advectionProgram.uniforms.dyeTexelSize + ) { + gl.uniform2f( + advectionProgram.uniforms.dyeTexelSize, + velocity.texelSizeX, + velocity.texelSizeY, + ); + } + const velocityId = velocity.read.attach(0); + if (advectionProgram.uniforms.uVelocity) { + gl.uniform1i(advectionProgram.uniforms.uVelocity, velocityId); + } + if (advectionProgram.uniforms.uSource) { + gl.uniform1i(advectionProgram.uniforms.uSource, velocityId); + } + if (advectionProgram.uniforms.dt) { + gl.uniform1f(advectionProgram.uniforms.dt, dt); + } + if (advectionProgram.uniforms.dissipation) { + gl.uniform1f( + advectionProgram.uniforms.dissipation, + config.VELOCITY_DISSIPATION, + ); + } + blit(velocity.write); + velocity.swap(); + + if ( + !ext.supportLinearFiltering && + advectionProgram.uniforms.dyeTexelSize + ) { + gl.uniform2f( + advectionProgram.uniforms.dyeTexelSize, + dye.texelSizeX, + dye.texelSizeY, + ); + } + if (advectionProgram.uniforms.uVelocity) { + gl.uniform1i( + advectionProgram.uniforms.uVelocity, + velocity.read.attach(0), + ); + } + if (advectionProgram.uniforms.uSource) { + gl.uniform1i(advectionProgram.uniforms.uSource, dye.read.attach(1)); + } + if (advectionProgram.uniforms.dissipation) { + gl.uniform1f( + advectionProgram.uniforms.dissipation, + config.DENSITY_DISSIPATION, + ); + } + blit(dye.write); + dye.swap(); + } + + function render(target: FBO | null) { + gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); + gl.enable(gl.BLEND); + drawDisplay(target); + } + + function drawDisplay(target: FBO | null) { + const width = target ? target.width : gl.drawingBufferWidth; + const height = target ? target.height : gl.drawingBufferHeight; + displayMaterial.bind(); + if (config.SHADING && displayMaterial.uniforms.texelSize) { + gl.uniform2f(displayMaterial.uniforms.texelSize, 1 / width, 1 / height); + } + if (displayMaterial.uniforms.uTexture) { + gl.uniform1i(displayMaterial.uniforms.uTexture, dye.read.attach(0)); + } + blit(target, false); + } + + function splatPointer(pointer: Pointer) { + const dx = pointer.deltaX * config.SPLAT_FORCE; + const dy = pointer.deltaY * config.SPLAT_FORCE; + splat(pointer.texcoordX, pointer.texcoordY, dx, dy, pointer.color); + } + + function clickSplat(pointer: Pointer) { + const color = generateColor(); + color.r *= 10; + color.g *= 10; + color.b *= 10; + const dx = 10 * (Math.random() - 0.5); + const dy = 30 * (Math.random() - 0.5); + splat(pointer.texcoordX, pointer.texcoordY, dx, dy, color); + } + + function splat( + x: number, + y: number, + dx: number, + dy: number, + color: ColorRGB, + ) { + splatProgram.bind(); + if (splatProgram.uniforms.uTarget) { + gl.uniform1i(splatProgram.uniforms.uTarget, velocity.read.attach(0)); + } + if (splatProgram.uniforms.aspectRatio) { + gl.uniform1f( + splatProgram.uniforms.aspectRatio, + canvas!.width / canvas!.height, + ); + } + if (splatProgram.uniforms.point) { + gl.uniform2f(splatProgram.uniforms.point, x, y); + } + if (splatProgram.uniforms.color) { + gl.uniform3f(splatProgram.uniforms.color, dx, dy, 0); + } + if (splatProgram.uniforms.radius) { + gl.uniform1f( + splatProgram.uniforms.radius, + correctRadius(config.SPLAT_RADIUS / 100)!, + ); + } + blit(velocity.write); + velocity.swap(); + + if (splatProgram.uniforms.uTarget) { + gl.uniform1i(splatProgram.uniforms.uTarget, dye.read.attach(0)); + } + if (splatProgram.uniforms.color) { + gl.uniform3f(splatProgram.uniforms.color, color.r, color.g, color.b); + } + blit(dye.write); + dye.swap(); + } + + function correctRadius(radius: number) { + const aspectRatio = canvas!.width / canvas!.height; + if (aspectRatio > 1) radius *= aspectRatio; + return radius; + } + + function updatePointerDownData( + pointer: Pointer, + id: number, + posX: number, + posY: number, + ) { + pointer.id = id; + pointer.down = true; + pointer.moved = false; + pointer.texcoordX = posX / canvas!.width; + pointer.texcoordY = 1 - posY / canvas!.height; + pointer.prevTexcoordX = pointer.texcoordX; + pointer.prevTexcoordY = pointer.texcoordY; + pointer.deltaX = 0; + pointer.deltaY = 0; + pointer.color = generateColor(); + } + + function updatePointerMoveData( + pointer: Pointer, + posX: number, + posY: number, + color: ColorRGB, + ) { + pointer.prevTexcoordX = pointer.texcoordX; + pointer.prevTexcoordY = pointer.texcoordY; + pointer.texcoordX = posX / canvas!.width; + pointer.texcoordY = 1 - posY / canvas!.height; + pointer.deltaX = correctDeltaX( + pointer.texcoordX - pointer.prevTexcoordX, + )!; + pointer.deltaY = correctDeltaY( + pointer.texcoordY - pointer.prevTexcoordY, + )!; + pointer.moved = + Math.abs(pointer.deltaX) > 0 || Math.abs(pointer.deltaY) > 0; + pointer.color = color; + } + + function updatePointerUpData(pointer: Pointer) { + pointer.down = false; + } + + function correctDeltaX(delta: number) { + const aspectRatio = canvas!.width / canvas!.height; + if (aspectRatio < 1) delta *= aspectRatio; + return delta; + } + + function correctDeltaY(delta: number) { + const aspectRatio = canvas!.width / canvas!.height; + if (aspectRatio > 1) delta /= aspectRatio; + return delta; + } + + function generateColor(): ColorRGB { + const c = HSVtoRGB(Math.random(), 1.0, 1.0); + c.r *= 0.15; + c.g *= 0.15; + c.b *= 0.15; + return c; + } + + function HSVtoRGB(h: number, s: number, v: number): ColorRGB { + let r = 0, + g = 0, + b = 0; + const i = Math.floor(h * 6); + const f = h * 6 - i; + const p = v * (1 - s); + const q = v * (1 - f * s); + const t = v * (1 - (1 - f) * s); + + switch (i % 6) { + case 0: + r = v; + g = t; + b = p; + break; + case 1: + r = q; + g = v; + b = p; + break; + case 2: + r = p; + g = v; + b = t; + break; + case 3: + r = p; + g = q; + b = v; + break; + case 4: + r = t; + g = p; + b = v; + break; + case 5: + r = v; + g = p; + b = q; + break; + } + return { r, g, b }; + } + + function wrap(value: number, min: number, max: number) { + const range = max - min; + if (range === 0) return min; + return ((value - min) % range) + min; + } + + window.addEventListener("mousedown", (e) => { + const pointer = pointers[0]; + const posX = scaleByPixelRatio(e.clientX); + const posY = scaleByPixelRatio(e.clientY); + updatePointerDownData(pointer, -1, posX, posY); + clickSplat(pointer); + }); + + function handleFirstMouseMove(e: MouseEvent) { + const pointer = pointers[0]; + const posX = scaleByPixelRatio(e.clientX); + const posY = scaleByPixelRatio(e.clientY); + const color = generateColor(); + updateFrame(); + updatePointerMoveData(pointer, posX, posY, color); + document.body.removeEventListener("mousemove", handleFirstMouseMove); + } + document.body.addEventListener("mousemove", handleFirstMouseMove); + + window.addEventListener("mousemove", (e) => { + const pointer = pointers[0]; + const posX = scaleByPixelRatio(e.clientX); + const posY = scaleByPixelRatio(e.clientY); + const color = pointer.color; + updatePointerMoveData(pointer, posX, posY, color); + }); + + function handleFirstTouchStart(e: TouchEvent) { + const touches = e.targetTouches; + const pointer = pointers[0]; + for (let i = 0; i < touches.length; i++) { + const posX = scaleByPixelRatio(touches[i].clientX); + const posY = scaleByPixelRatio(touches[i].clientY); + updateFrame(); + updatePointerDownData(pointer, touches[i].identifier, posX, posY); + } + document.body.removeEventListener("touchstart", handleFirstTouchStart); + } + document.body.addEventListener("touchstart", handleFirstTouchStart); + + window.addEventListener( + "touchstart", + (e) => { + const touches = e.targetTouches; + const pointer = pointers[0]; + for (let i = 0; i < touches.length; i++) { + const posX = scaleByPixelRatio(touches[i].clientX); + const posY = scaleByPixelRatio(touches[i].clientY); + updatePointerDownData(pointer, touches[i].identifier, posX, posY); + } + }, + false, + ); + + window.addEventListener( + "touchmove", + (e) => { + const touches = e.targetTouches; + const pointer = pointers[0]; + for (let i = 0; i < touches.length; i++) { + const posX = scaleByPixelRatio(touches[i].clientX); + const posY = scaleByPixelRatio(touches[i].clientY); + updatePointerMoveData(pointer, posX, posY, pointer.color); + } + }, + false, + ); + + window.addEventListener("touchend", (e) => { + const touches = e.changedTouches; + const pointer = pointers[0]; + for (let i = 0; i < touches.length; i++) { + updatePointerUpData(pointer); + } + }); + }, [ + SIM_RESOLUTION, + DYE_RESOLUTION, + CAPTURE_RESOLUTION, + DENSITY_DISSIPATION, + VELOCITY_DISSIPATION, + PRESSURE, + PRESSURE_ITERATIONS, + CURL, + SPLAT_RADIUS, + SPLAT_FORCE, + SHADING, + COLOR_UPDATE_SPEED, + BACK_COLOR, + TRANSPARENT, + ]); + + return ( +
+ +
+ ); +} diff --git a/src/components/SpotlightCard.tsx b/src/components/SpotlightCard.tsx new file mode 100644 index 0000000..9e30e4f --- /dev/null +++ b/src/components/SpotlightCard.tsx @@ -0,0 +1,71 @@ +"use client"; +import React, { useRef, useState } from "react"; + +interface Position { + x: number; + y: number; +} + +interface SpotlightCardProps extends React.PropsWithChildren { + className?: string; + spotlightColor?: `rgba(${number}, ${number}, ${number}, ${number})`; +} + +const SpotlightCard: React.FC = ({ + children, + className = "", + spotlightColor = "rgba(255, 255, 255, 0.25)", +}) => { + const divRef = useRef(null); + const [isFocused, setIsFocused] = useState(false); + const [position, setPosition] = useState({ x: 0, y: 0 }); + const [opacity, setOpacity] = useState(0); + + const handleMouseMove: React.MouseEventHandler = (e) => { + if (!divRef.current || isFocused) return; + + const rect = divRef.current.getBoundingClientRect(); + setPosition({ x: e.clientX - rect.left, y: e.clientY - rect.top }); + }; + + const handleFocus = () => { + setIsFocused(true); + setOpacity(0.6); + }; + + const handleBlur = () => { + setIsFocused(false); + setOpacity(0); + }; + + const handleMouseEnter = () => { + setOpacity(0.6); + }; + + const handleMouseLeave = () => { + setOpacity(0); + }; + + return ( +
+
+ {children} +
+ ); +}; + +export default SpotlightCard; diff --git a/src/components/TargetCursor.tsx b/src/components/TargetCursor.tsx new file mode 100644 index 0000000..dc188ee --- /dev/null +++ b/src/components/TargetCursor.tsx @@ -0,0 +1,373 @@ +import React, { useEffect, useRef, useCallback, useMemo } from "react"; +import { gsap } from "gsap"; + +export interface TargetCursorProps { + targetSelector?: string; + spinDuration?: number; + hideDefaultCursor?: boolean; +} + +const TargetCursor: React.FC = ({ + targetSelector = ".cursor-target", + spinDuration = 2, + hideDefaultCursor = true, +}) => { + const cursorRef = useRef(null); + const cornersRef = useRef>(null); + const spinTl = useRef(null); + const dotRef = useRef(null); + const constants = useMemo( + () => ({ + borderWidth: 3, + cornerSize: 12, + parallaxStrength: 0.00005, + }), + [], + ); + + const moveCursor = useCallback((x: number, y: number) => { + if (!cursorRef.current) return; + gsap.to(cursorRef.current, { + x, + y, + duration: 0.1, + ease: "power3.out", + }); + }, []); + + useEffect(() => { + if (!cursorRef.current) return; + + const originalCursor = document.body.style.cursor; + if (hideDefaultCursor) { + document.body.style.cursor = "none"; + } + + const cursor = cursorRef.current; + cornersRef.current = cursor.querySelectorAll( + ".target-cursor-corner", + ); + + let activeTarget: Element | null = null; + let currentTargetMove: ((ev: Event) => void) | null = null; + let currentLeaveHandler: (() => void) | null = null; + let isAnimatingToTarget = false; + let resumeTimeout: ReturnType | null = null; + + const cleanupTarget = (target: Element) => { + if (currentTargetMove) { + target.removeEventListener("mousemove", currentTargetMove); + } + if (currentLeaveHandler) { + target.removeEventListener("mouseleave", currentLeaveHandler); + } + currentTargetMove = null; + currentLeaveHandler = null; + }; + + gsap.set(cursor, { + xPercent: -50, + yPercent: -50, + x: window.innerWidth / 2, + y: window.innerHeight / 2, + }); + + const createSpinTimeline = () => { + if (spinTl.current) { + spinTl.current.kill(); + } + spinTl.current = gsap.timeline({ repeat: -1 }).to(cursor, { + rotation: "+=360", + duration: spinDuration, + ease: "none", + }); + }; + + createSpinTimeline(); + + const moveHandler = (e: MouseEvent) => moveCursor(e.clientX, e.clientY); + window.addEventListener("mousemove", moveHandler); + + const scrollHandler = () => { + if (!activeTarget || !cursorRef.current) return; + + const mouseX = gsap.getProperty(cursorRef.current, "x") as number; + const mouseY = gsap.getProperty(cursorRef.current, "y") as number; + + const elementUnderMouse = document.elementFromPoint(mouseX, mouseY); + const isStillOverTarget = + elementUnderMouse && + (elementUnderMouse === activeTarget || + elementUnderMouse.closest(targetSelector) === activeTarget); + + if (!isStillOverTarget) { + if (currentLeaveHandler) { + currentLeaveHandler(); + } + } + }; + + window.addEventListener("scroll", scrollHandler, { passive: true }); + window.addEventListener("mousemove", moveHandler); + + const mouseDownHandler = (): void => { + if (!dotRef.current) return; + gsap.to(dotRef.current, { scale: 0.7, duration: 0.3 }); + gsap.to(cursorRef.current, { scale: 0.9, duration: 0.2 }); + }; + + const mouseUpHandler = (): void => { + if (!dotRef.current) return; + gsap.to(dotRef.current, { scale: 1, duration: 0.3 }); + gsap.to(cursorRef.current, { scale: 1, duration: 0.2 }); + }; + + window.addEventListener("mousedown", mouseDownHandler); + window.addEventListener("mouseup", mouseUpHandler); + + const enterHandler = (e: MouseEvent) => { + const directTarget = e.target as Element; + + const allTargets: Element[] = []; + let current = directTarget; + while (current && current !== document.body) { + if (current.matches(targetSelector)) { + allTargets.push(current); + } + current = current.parentElement!; + } + + const target = allTargets[0] || null; + if (!target || !cursorRef.current || !cornersRef.current) return; + + if (activeTarget === target) return; + + if (activeTarget) { + cleanupTarget(activeTarget); + } + + if (resumeTimeout) { + clearTimeout(resumeTimeout); + resumeTimeout = null; + } + + activeTarget = target; + const corners = Array.from(cornersRef.current); + corners.forEach((corner) => { + gsap.killTweensOf(corner); + }); + gsap.killTweensOf(cursorRef.current, "rotation"); + spinTl.current?.pause(); + + gsap.set(cursorRef.current, { rotation: 0 }); + + const updateCorners = (mouseX?: number, mouseY?: number) => { + const rect = target.getBoundingClientRect(); + const cursorRect = cursorRef.current!.getBoundingClientRect(); + + const cursorCenterX = cursorRect.left + cursorRect.width / 2; + const cursorCenterY = cursorRect.top + cursorRect.height / 2; + + const [tlc, trc, brc, blc] = Array.from(cornersRef.current!); + + const { borderWidth, cornerSize, parallaxStrength } = constants; + + let tlOffset = { + x: rect.left - cursorCenterX - borderWidth, + y: rect.top - cursorCenterY - borderWidth, + }; + let trOffset = { + x: rect.right - cursorCenterX + borderWidth - cornerSize, + y: rect.top - cursorCenterY - borderWidth, + }; + let brOffset = { + x: rect.right - cursorCenterX + borderWidth - cornerSize, + y: rect.bottom - cursorCenterY + borderWidth - cornerSize, + }; + let blOffset = { + x: rect.left - cursorCenterX - borderWidth, + y: rect.bottom - cursorCenterY + borderWidth - cornerSize, + }; + + if (mouseX !== undefined && mouseY !== undefined) { + const targetCenterX = rect.left + rect.width / 2; + const targetCenterY = rect.top + rect.height / 2; + const mouseOffsetX = (mouseX - targetCenterX) * parallaxStrength; + const mouseOffsetY = (mouseY - targetCenterY) * parallaxStrength; + + tlOffset.x += mouseOffsetX; + tlOffset.y += mouseOffsetY; + trOffset.x += mouseOffsetX; + trOffset.y += mouseOffsetY; + brOffset.x += mouseOffsetX; + brOffset.y += mouseOffsetY; + blOffset.x += mouseOffsetX; + blOffset.y += mouseOffsetY; + } + + const tl = gsap.timeline(); + const corners = [tlc, trc, brc, blc]; + const offsets = [tlOffset, trOffset, brOffset, blOffset]; + + corners.forEach((corner, index) => { + tl.to( + corner, + { + x: offsets[index].x, + y: offsets[index].y, + duration: 0.2, + ease: "power2.out", + }, + 0, + ); + }); + }; + + isAnimatingToTarget = true; + updateCorners(); + + setTimeout(() => { + isAnimatingToTarget = false; + }, 1); + + let moveThrottle: number | null = null; + const targetMove = (ev: Event) => { + if (moveThrottle || isAnimatingToTarget) return; + moveThrottle = requestAnimationFrame(() => { + const mouseEvent = ev as MouseEvent; + updateCorners(mouseEvent.clientX, mouseEvent.clientY); + moveThrottle = null; + }); + }; + + const leaveHandler = () => { + activeTarget = null; + isAnimatingToTarget = false; + + if (cornersRef.current) { + const corners = Array.from(cornersRef.current); + gsap.killTweensOf(corners); + + const { cornerSize } = constants; + const positions = [ + { x: -cornerSize * 1.5, y: -cornerSize * 1.5 }, + { x: cornerSize * 0.5, y: -cornerSize * 1.5 }, + { x: cornerSize * 0.5, y: cornerSize * 0.5 }, + { x: -cornerSize * 1.5, y: cornerSize * 0.5 }, + ]; + + const tl = gsap.timeline(); + corners.forEach((corner, index) => { + tl.to( + corner, + { + x: positions[index].x, + y: positions[index].y, + duration: 0.3, + ease: "power3.out", + }, + 0, + ); + }); + } + + resumeTimeout = setTimeout(() => { + if (!activeTarget && cursorRef.current && spinTl.current) { + const currentRotation = gsap.getProperty( + cursorRef.current, + "rotation", + ) as number; + const normalizedRotation = currentRotation % 360; + + spinTl.current.kill(); + spinTl.current = gsap + .timeline({ repeat: -1 }) + .to(cursorRef.current, { + rotation: "+=360", + duration: spinDuration, + ease: "none", + }); + + gsap.to(cursorRef.current, { + rotation: normalizedRotation + 360, + duration: spinDuration * (1 - normalizedRotation / 360), + ease: "none", + onComplete: () => { + spinTl.current?.restart(); + }, + }); + } + resumeTimeout = null; + }, 50); + + cleanupTarget(target); + }; + + currentTargetMove = targetMove; + currentLeaveHandler = leaveHandler; + + target.addEventListener("mousemove", targetMove); + target.addEventListener("mouseleave", leaveHandler); + }; + + window.addEventListener("mouseover", enterHandler, { passive: true }); + + return () => { + window.removeEventListener("mousemove", moveHandler); + window.removeEventListener("mouseover", enterHandler); + window.removeEventListener("scroll", scrollHandler); + + if (activeTarget) { + cleanupTarget(activeTarget); + } + + spinTl.current?.kill(); + document.body.style.cursor = originalCursor; + }; + }, [targetSelector, spinDuration, moveCursor, constants, hideDefaultCursor]); + + useEffect(() => { + if (!cursorRef.current || !spinTl.current) return; + + if (spinTl.current.isActive()) { + spinTl.current.kill(); + spinTl.current = gsap.timeline({ repeat: -1 }).to(cursorRef.current, { + rotation: "+=360", + duration: spinDuration, + ease: "none", + }); + } + }, [spinDuration]); + + return ( +
+
+
+
+
+
+
+ ); +}; + +export default TargetCursor; diff --git a/src/components/animate-ui/components/buttons/button.tsx b/src/components/animate-ui/components/buttons/button.tsx new file mode 100644 index 0000000..fd8d38c --- /dev/null +++ b/src/components/animate-ui/components/buttons/button.tsx @@ -0,0 +1,57 @@ +"use client"; + +import * as React from "react"; +import { cva, type VariantProps } from "class-variance-authority"; + +import { + Button as ButtonPrimitive, + type ButtonProps as ButtonPrimitiveProps, +} from "@/components/animate-ui/primitives/buttons/button"; +import { cn } from "@/lib/utils"; + +const buttonVariants = cva( + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-[box-shadow,_color,_background-color,_border-color,_outline-color,_text-decoration-color,_fill,_stroke] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", + { + variants: { + variant: { + default: + "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90", + accent: "bg-accent text-accent-foreground shadow-xs hover:bg-accent/90", + destructive: + "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", + outline: + "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50", + secondary: + "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80", + ghost: + "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-9 px-4 py-2 has-[>svg]:px-3", + sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5", + lg: "h-10 rounded-md px-6 has-[>svg]:px-4", + icon: "size-9", + "icon-sm": "size-8 rounded-md", + "icon-lg": "size-10 rounded-md", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + }, +); + +type ButtonProps = ButtonPrimitiveProps & VariantProps; + +function Button({ className, variant, size, ...props }: ButtonProps) { + return ( + + ); +} + +export { Button, buttonVariants, type ButtonProps }; diff --git a/src/components/animate-ui/icons/icon.tsx b/src/components/animate-ui/icons/icon.tsx new file mode 100644 index 0000000..5e59d2b --- /dev/null +++ b/src/components/animate-ui/icons/icon.tsx @@ -0,0 +1,658 @@ +"use client"; + +import * as React from "react"; +import { + motion, + useAnimation, + type SVGMotionProps, + type UseInViewOptions, + type LegacyAnimationControls, + type Variants, + type HTMLMotionProps, +} from "motion/react"; + +import { cn } from "@/lib/utils"; +import { useIsInView } from "@/hooks/use-is-in-view"; +import { + Slot, + type WithAsChild, +} from "@/components/animate-ui/primitives/animate/slot"; + +const staticAnimations = { + path: { + initial: { pathLength: 1 }, + animate: { + pathLength: [0.05, 1], + transition: { + duration: 0.8, + ease: "easeInOut", + }, + }, + } as Variants, + "path-loop": { + initial: { pathLength: 1 }, + animate: { + pathLength: [1, 0.05, 1], + transition: { + duration: 1.6, + ease: "easeInOut", + }, + }, + } as Variants, +} as const; + +type StaticAnimations = keyof typeof staticAnimations; +type TriggerProp = boolean | StaticAnimations | T; +type Trigger = TriggerProp; + +type AnimateIconContextValue = { + controls: LegacyAnimationControls | undefined; + animation: StaticAnimations | string; + loop: boolean; + loopDelay: number; + active: boolean; + animate?: Trigger; + initialOnAnimateEnd?: boolean; + completeOnStop?: boolean; + persistOnAnimateEnd?: boolean; + delay?: number; +}; + +type DefaultIconProps = { + animate?: TriggerProp; + animateOnHover?: TriggerProp; + animateOnTap?: TriggerProp; + animateOnView?: TriggerProp; + animateOnViewMargin?: UseInViewOptions["margin"]; + animateOnViewOnce?: boolean; + animation?: T | StaticAnimations; + loop?: boolean; + loopDelay?: number; + initialOnAnimateEnd?: boolean; + completeOnStop?: boolean; + persistOnAnimateEnd?: boolean; + delay?: number; +}; + +type AnimateIconProps = WithAsChild< + HTMLMotionProps<"span"> & + DefaultIconProps & { + children: React.ReactNode; + asChild?: boolean; + } +>; + +type IconProps = DefaultIconProps & + Omit, "animate"> & { + size?: number; + }; + +type IconWrapperProps = IconProps & { + icon: React.ComponentType>; +}; + +const AnimateIconContext = React.createContext( + null, +); + +function useAnimateIconContext() { + const context = React.useContext(AnimateIconContext); + if (!context) + return { + controls: undefined, + animation: "default", + loop: undefined, + loopDelay: undefined, + active: undefined, + animate: undefined, + initialOnAnimateEnd: undefined, + completeOnStop: undefined, + persistOnAnimateEnd: undefined, + delay: undefined, + }; + return context; +} + +function composeEventHandlers>( + theirs?: (event: E) => void, + ours?: (event: E) => void, +) { + return (event: E) => { + theirs?.(event); + ours?.(event); + }; +} + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +type AnyProps = Record; + +function AnimateIcon({ + asChild = false, + animate = false, + animateOnHover = false, + animateOnTap = false, + animateOnView = false, + animateOnViewMargin = "0px", + animateOnViewOnce = true, + animation = "default", + loop = false, + loopDelay = 0, + initialOnAnimateEnd = false, + completeOnStop = false, + persistOnAnimateEnd = false, + delay = 0, + children, + ...props +}: AnimateIconProps) { + const controls = useAnimation(); + + const [localAnimate, setLocalAnimate] = React.useState(() => { + if (animate === undefined || animate === false) return false; + return delay <= 0; + }); + const [currentAnimation, setCurrentAnimation] = React.useState< + string | StaticAnimations + >(typeof animate === "string" ? animate : animation); + const [status, setStatus] = React.useState<"initial" | "animate">("initial"); + + const delayRef = React.useRef | null>(null); + const loopDelayRef = React.useRef | null>(null); + const isAnimateInProgressRef = React.useRef(false); + const animateEndPromiseRef = React.useRef | null>(null); + const resolveAnimateEndRef = React.useRef<(() => void) | null>(null); + const activeRef = React.useRef(localAnimate); + + const runGenRef = React.useRef(0); + const cancelledRef = React.useRef(false); + + const bumpGeneration = React.useCallback(() => { + runGenRef.current++; + }, []); + + const startAnimation = React.useCallback( + (trigger: TriggerProp) => { + const next = typeof trigger === "string" ? trigger : animation; + bumpGeneration(); + if (delayRef.current) { + clearTimeout(delayRef.current); + delayRef.current = null; + } + setCurrentAnimation(next); + if (delay > 0) { + setLocalAnimate(false); + delayRef.current = setTimeout(() => { + setLocalAnimate(true); + }, delay); + } else { + setLocalAnimate(true); + } + }, + [animation, delay, bumpGeneration], + ); + + const stopAnimation = React.useCallback(() => { + bumpGeneration(); + if (delayRef.current) { + clearTimeout(delayRef.current); + delayRef.current = null; + } + if (loopDelayRef.current) { + clearTimeout(loopDelayRef.current); + loopDelayRef.current = null; + } + setLocalAnimate(false); + }, [bumpGeneration]); + + React.useEffect(() => { + activeRef.current = localAnimate; + }, [localAnimate]); + + React.useEffect(() => { + if (animate === undefined) return; + setCurrentAnimation(typeof animate === "string" ? animate : animation); + if (animate) startAnimation(animate as TriggerProp); + else stopAnimation(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [animate]); + + React.useEffect(() => { + return () => { + if (delayRef.current) clearTimeout(delayRef.current); + if (loopDelayRef.current) clearTimeout(loopDelayRef.current); + }; + }, []); + + const viewOuterRef = React.useRef(null); + const { ref: inViewRef, isInView } = useIsInView(viewOuterRef, { + inView: !!animateOnView, + inViewOnce: animateOnViewOnce, + inViewMargin: animateOnViewMargin, + }); + + const startAnim = React.useCallback( + async (anim: "initial" | "animate", method: "start" | "set" = "start") => { + try { + await controls[method](anim); + setStatus(anim); + } catch { + return; + } + }, + [controls], + ); + + React.useEffect(() => { + if (!animateOnView) return; + if (isInView) startAnimation(animateOnView); + else stopAnimation(); + }, [isInView, animateOnView, startAnimation, stopAnimation]); + + React.useEffect(() => { + const gen = ++runGenRef.current; + cancelledRef.current = false; + + async function run() { + if (cancelledRef.current || gen !== runGenRef.current) { + await startAnim("initial"); + return; + } + + if (!localAnimate) { + if ( + completeOnStop && + isAnimateInProgressRef.current && + animateEndPromiseRef.current + ) { + try { + await animateEndPromiseRef.current; + } catch { + // noop + } + } + if (!persistOnAnimateEnd) { + if (cancelledRef.current || gen !== runGenRef.current) { + await startAnim("initial"); + return; + } + await startAnim("initial"); + } + return; + } + + if (loop) { + if (cancelledRef.current || gen !== runGenRef.current) { + await startAnim("initial"); + return; + } + await startAnim("initial", "set"); + } + + isAnimateInProgressRef.current = true; + animateEndPromiseRef.current = new Promise((resolve) => { + resolveAnimateEndRef.current = resolve; + }); + + if (cancelledRef.current || gen !== runGenRef.current) { + isAnimateInProgressRef.current = false; + resolveAnimateEndRef.current?.(); + resolveAnimateEndRef.current = null; + animateEndPromiseRef.current = null; + await startAnim("initial"); + return; + } + + await startAnim("animate"); + + if (cancelledRef.current || gen !== runGenRef.current) { + isAnimateInProgressRef.current = false; + resolveAnimateEndRef.current?.(); + resolveAnimateEndRef.current = null; + animateEndPromiseRef.current = null; + await startAnim("initial"); + return; + } + + isAnimateInProgressRef.current = false; + resolveAnimateEndRef.current?.(); + resolveAnimateEndRef.current = null; + animateEndPromiseRef.current = null; + + if (initialOnAnimateEnd) { + if (cancelledRef.current || gen !== runGenRef.current) { + await startAnim("initial"); + return; + } + await startAnim("initial", "set"); + } + + if (loop) { + if (loopDelay > 0) { + await new Promise((resolve) => { + loopDelayRef.current = setTimeout(() => { + loopDelayRef.current = null; + resolve(); + }, loopDelay); + }); + + if (cancelledRef.current || gen !== runGenRef.current) { + await startAnim("initial"); + return; + } + if (!activeRef.current) { + if (status !== "initial" && !persistOnAnimateEnd) + await startAnim("initial"); + return; + } + } else { + if (!activeRef.current) { + if (status !== "initial" && !persistOnAnimateEnd) + await startAnim("initial"); + return; + } + } + if (cancelledRef.current || gen !== runGenRef.current) { + await startAnim("initial"); + return; + } + await run(); + } + } + + void run(); + + return () => { + cancelledRef.current = true; + if (delayRef.current) { + clearTimeout(delayRef.current); + delayRef.current = null; + } + if (loopDelayRef.current) { + clearTimeout(loopDelayRef.current); + loopDelayRef.current = null; + } + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [localAnimate, controls]); + + const childProps = ( + React.isValidElement(children) ? (children as React.ReactElement).props : {} + ) as AnyProps; + + const handleMouseEnter = composeEventHandlers>( + childProps.onMouseEnter, + () => { + if (animateOnHover) startAnimation(animateOnHover); + }, + ); + + const handleMouseLeave = composeEventHandlers>( + childProps.onMouseLeave, + () => { + if (animateOnHover || animateOnTap) stopAnimation(); + }, + ); + + const handlePointerDown = composeEventHandlers< + React.PointerEvent + >(childProps.onPointerDown, () => { + if (animateOnTap) startAnimation(animateOnTap); + }); + + const handlePointerUp = composeEventHandlers>( + childProps.onPointerUp, + () => { + if (animateOnTap) stopAnimation(); + }, + ); + + const content = asChild ? ( + + {children} + + ) : ( + + {children} + + ); + + return ( + + {content} + + ); +} + +const pathClassName = + "[&_[stroke-dasharray='1px_1px']]:![stroke-dasharray:1px_0px]"; + +function IconWrapper({ + size = 28, + animation: animationProp, + animate, + animateOnHover, + animateOnTap, + animateOnView, + animateOnViewMargin, + animateOnViewOnce, + icon: IconComponent, + loop, + loopDelay, + persistOnAnimateEnd, + initialOnAnimateEnd, + delay, + completeOnStop, + className, + ...props +}: IconWrapperProps) { + const context = React.useContext(AnimateIconContext); + + if (context) { + const { + controls, + animation: parentAnimation, + loop: parentLoop, + loopDelay: parentLoopDelay, + active: parentActive, + animate: parentAnimate, + persistOnAnimateEnd: parentPersistOnAnimateEnd, + initialOnAnimateEnd: parentInitialOnAnimateEnd, + delay: parentDelay, + completeOnStop: parentCompleteOnStop, + } = context; + + const hasOverrides = + animate !== undefined || + animateOnHover !== undefined || + animateOnTap !== undefined || + animateOnView !== undefined || + loop !== undefined || + loopDelay !== undefined || + initialOnAnimateEnd !== undefined || + persistOnAnimateEnd !== undefined || + delay !== undefined || + completeOnStop !== undefined; + + if (hasOverrides) { + const inheritedAnimate: Trigger = parentActive + ? (animationProp ?? parentAnimation ?? "default") + : false; + + const finalAnimate: Trigger = (animate ?? + parentAnimate ?? + inheritedAnimate) as Trigger; + + return ( + + + + ); + } + + const animationToUse = animationProp ?? parentAnimation; + const loopToUse = parentLoop; + const loopDelayToUse = parentLoopDelay; + + return ( + + + + ); + } + + if ( + animate !== undefined || + animateOnHover !== undefined || + animateOnTap !== undefined || + animateOnView !== undefined || + animationProp !== undefined + ) { + return ( + + + + ); + } + + return ( + + ); +} + +function getVariants< + V extends { default: T; [key: string]: T }, + T extends Record, +>(animations: V): T { + // eslint-disable-next-line react-hooks/rules-of-hooks + const { animation: animationType } = useAnimateIconContext(); + + let result: T; + + if (animationType in staticAnimations) { + const variant = staticAnimations[animationType as StaticAnimations]; + result = {} as T; + for (const key in animations.default) { + if ( + (animationType === "path" || animationType === "path-loop") && + key.includes("group") + ) + continue; + result[key] = variant as T[Extract]; + } + } else { + result = (animations[animationType as keyof V] as T) ?? animations.default; + } + + return result; +} + +export { + pathClassName, + staticAnimations, + AnimateIcon, + IconWrapper, + useAnimateIconContext, + getVariants, + type IconProps, + type IconWrapperProps, + type AnimateIconProps, + type AnimateIconContextValue, +}; diff --git a/src/components/animate-ui/icons/settings.tsx b/src/components/animate-ui/icons/settings.tsx new file mode 100644 index 0000000..cf2c1ae --- /dev/null +++ b/src/components/animate-ui/icons/settings.tsx @@ -0,0 +1,97 @@ +"use client"; + +import * as React from "react"; +import { motion, type Variants } from "motion/react"; + +import { + getVariants, + useAnimateIconContext, + IconWrapper, + type IconProps, +} from "@/components/animate-ui/icons/icon"; + +type SettingsProps = IconProps; + +const animations = { + default: { + group: { + initial: { + rotate: 0, + }, + animate: { + rotate: [0, 90, 180], + transition: { + duration: 1.25, + ease: "easeInOut", + }, + }, + }, + path: {}, + circle: {}, + } satisfies Record, + rotate: { + group: { + initial: { + rotate: 0, + }, + animate: { + rotate: 360, + transition: { + duration: 2, + ease: "linear", + }, + }, + }, + path: {}, + circle: {}, + } satisfies Record, +} as const; + +function IconComponent({ size, ...props }: SettingsProps) { + const { controls } = useAnimateIconContext(); + const variants = getVariants(animations); + + return ( + + + + + + + ); +} + +function Settings(props: SettingsProps) { + return ; +} + +export { + animations, + Settings, + Settings as SettingsIcon, + type SettingsProps, + type SettingsProps as SettingsIconProps, +}; diff --git a/src/components/animate-ui/primitives/animate/slot.tsx b/src/components/animate-ui/primitives/animate/slot.tsx new file mode 100644 index 0000000..4f1973c --- /dev/null +++ b/src/components/animate-ui/primitives/animate/slot.tsx @@ -0,0 +1,97 @@ +"use client"; + +import * as React from "react"; +import { motion, isMotionComponent, type HTMLMotionProps } from "motion/react"; +import { cn } from "@/lib/utils"; + +type AnyProps = Record; + +type DOMMotionProps = Omit< + HTMLMotionProps, + "ref" +> & { ref?: React.Ref }; + +type WithAsChild = + | (Base & { asChild: true; children: React.ReactElement }) + | (Base & { asChild?: false | undefined }); + +type SlotProps = { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + children?: any; +} & DOMMotionProps; + +function mergeRefs( + ...refs: (React.Ref | undefined)[] +): React.RefCallback { + return (node) => { + refs.forEach((ref) => { + if (!ref) return; + if (typeof ref === "function") { + ref(node); + } else { + (ref as React.RefObject).current = node; + } + }); + }; +} + +function mergeProps( + childProps: AnyProps, + slotProps: DOMMotionProps, +): AnyProps { + const merged: AnyProps = { ...childProps, ...slotProps }; + + if (childProps.className || slotProps.className) { + merged.className = cn( + childProps.className as string, + slotProps.className as string, + ); + } + + if (childProps.style || slotProps.style) { + merged.style = { + ...(childProps.style as React.CSSProperties), + ...(slotProps.style as React.CSSProperties), + }; + } + + return merged; +} + +function Slot({ + children, + ref, + ...props +}: SlotProps) { + const isAlreadyMotion = + typeof children.type === "object" && + children.type !== null && + isMotionComponent(children.type); + + const Base = React.useMemo( + () => + isAlreadyMotion + ? (children.type as React.ElementType) + : motion.create(children.type as React.ElementType), + [isAlreadyMotion, children.type], + ); + + if (!React.isValidElement(children)) return null; + + const { ref: childRef, ...childProps } = children.props as AnyProps; + + const mergedProps = mergeProps(childProps, props); + + return ( + //@ts-ignore + , ref)} /> + ); +} + +export { + Slot, + type SlotProps, + type WithAsChild, + type DOMMotionProps, + type AnyProps, +}; diff --git a/src/components/animate-ui/primitives/buttons/button.tsx b/src/components/animate-ui/primitives/buttons/button.tsx new file mode 100644 index 0000000..da70bac --- /dev/null +++ b/src/components/animate-ui/primitives/buttons/button.tsx @@ -0,0 +1,35 @@ +"use client"; + +import * as React from "react"; +import { motion, type HTMLMotionProps } from "motion/react"; + +import { + Slot, + type WithAsChild, +} from "@/components/animate-ui/primitives/animate/slot"; + +type ButtonProps = WithAsChild< + HTMLMotionProps<"button"> & { + hoverScale?: number; + tapScale?: number; + } +>; + +function Button({ + hoverScale = 1.05, + tapScale = 0.95, + asChild = false, + ...props +}: ButtonProps) { + const Component = asChild ? Slot : motion.button; + + return ( + + ); +} + +export { Button, type ButtonProps }; diff --git a/src/components/animate-ui/primitives/radix/radio-group.tsx b/src/components/animate-ui/primitives/radix/radio-group.tsx new file mode 100644 index 0000000..db44838 --- /dev/null +++ b/src/components/animate-ui/primitives/radix/radio-group.tsx @@ -0,0 +1,130 @@ +"use client"; + +import * as React from "react"; +import { RadioGroup as RadioGroupPrimitive } from "radix-ui"; +import { AnimatePresence, motion, type HTMLMotionProps } from "motion/react"; + +import { getStrictContext } from "@/lib/get-strict-context"; +import { useControlledState } from "@/hooks/use-controlled-state"; + +type RadioGroupContextType = { + value: string; + setValue: (value: string) => void; +}; + +type RadioGroupItemContextType = { + isChecked: boolean; + setIsChecked: (isChecked: boolean) => void; +}; + +const [RadioGroupProvider, useRadioGroup] = + getStrictContext("RadioGroupContext"); + +const [RadioGroupItemProvider, useRadioGroupItem] = + getStrictContext("RadioGroupItemContext"); + +type RadioGroupProps = React.ComponentProps; + +function RadioGroup(props: RadioGroupProps) { + const [value, setValue] = useControlledState({ + value: props.value ?? undefined, + defaultValue: props.defaultValue, + onChange: props.onValueChange, + }); + + return ( + + + + ); +} + +type RadioGroupIndicatorProps = Omit< + React.ComponentProps, + "asChild" | "forceMount" +> & + HTMLMotionProps<"div">; + +function RadioGroupIndicator({ + transition = { type: "spring", stiffness: 200, damping: 16 }, + ...props +}: RadioGroupIndicatorProps) { + const { isChecked } = useRadioGroupItem(); + + return ( + + {isChecked && ( + + + + )} + + ); +} + +type RadioGroupItemProps = Omit< + React.ComponentProps, + "asChild" +> & + HTMLMotionProps<"button">; + +function RadioGroupItem({ + value: valueProps, + disabled, + required, + ...props +}: RadioGroupItemProps) { + const { value } = useRadioGroup(); + const [isChecked, setIsChecked] = React.useState(value === valueProps); + + React.useEffect(() => { + setIsChecked(value === valueProps); + }, [value, valueProps]); + + return ( + + + + + + ); +} + +export { + RadioGroup, + RadioGroupItem, + RadioGroupIndicator, + useRadioGroup, + useRadioGroupItem, + type RadioGroupProps, + type RadioGroupItemProps, + type RadioGroupIndicatorProps, + type RadioGroupContextType, + type RadioGroupItemContextType, +}; diff --git a/src/components/cn.ts b/src/components/cn.ts index 3200be2..a5ef193 100644 --- a/src/components/cn.ts +++ b/src/components/cn.ts @@ -2,5 +2,5 @@ import { clsx, type ClassValue } from "clsx"; import { twMerge } from "tailwind-merge"; export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)); + return twMerge(clsx(inputs)); } diff --git a/src/components/codecomp-v3v4.tsx b/src/components/codecomp-v3v4.tsx deleted file mode 100644 index 3abcfb3..0000000 --- a/src/components/codecomp-v3v4.tsx +++ /dev/null @@ -1,67 +0,0 @@ -export const beforeCode = ` -
- MikanDev -
- - {t("below-main-heading")} - -
- - -
-
`; - -export const afterCode = `
-
- -

- Backed by my own pocket money -

-
-
-

- {t("creating-cool")} -

- -`; diff --git a/src/components/consent-manager.tsx b/src/components/consent-manager.tsx new file mode 100644 index 0000000..e7fa8f1 --- /dev/null +++ b/src/components/consent-manager.tsx @@ -0,0 +1,20 @@ +import type { ReactNode } from "react"; +import { + ConsentManagerDialog, + ConsentManagerProvider, + CookieBanner, +} from "@c15t/nextjs/client"; + +export function ConsentManager({ children }: { children: ReactNode }) { + return ( + + + + {children} + + ); +} diff --git a/src/components/fancy/NumberTicker.tsx b/src/components/fancy/NumberTicker.tsx deleted file mode 100644 index feacd0b..0000000 --- a/src/components/fancy/NumberTicker.tsx +++ /dev/null @@ -1,58 +0,0 @@ -"use client"; - -import { useEffect, useRef } from "react"; -import { useInView, useMotionValue, useSpring } from "motion/react"; - -import { cn } from "../cn"; - -export function NumberTicker({ - value, - direction = "up", - delay = 0, - className, - decimalPlaces = 0, -}: { - value: number; - direction?: "up" | "down"; - className?: string; - delay?: number; // delay in s - decimalPlaces?: number; -}) { - const ref = useRef(null); - const motionValue = useMotionValue(direction === "down" ? value : 0); - const springValue = useSpring(motionValue, { - damping: 60, - stiffness: 100, - }); - const isInView = useInView(ref, { once: true, margin: "0px" }); - - useEffect(() => { - isInView && - setTimeout(() => { - motionValue.set(direction === "down" ? 0 : value); - }, delay * 1000); - }, [motionValue, isInView, delay, value, direction]); - - useEffect( - () => - springValue.on("change", (latest) => { - if (ref.current) { - ref.current.textContent = Intl.NumberFormat("en-US", { - minimumFractionDigits: decimalPlaces, - maximumFractionDigits: decimalPlaces, - }).format(Number(latest.toFixed(decimalPlaces))); - } - }), - [springValue, decimalPlaces], - ); - - return ( - - ); -} diff --git a/src/components/fancy/blocks/marquee-along-svg-path.tsx b/src/components/fancy/blocks/marquee-along-svg-path.tsx new file mode 100644 index 0000000..bca00c5 --- /dev/null +++ b/src/components/fancy/blocks/marquee-along-svg-path.tsx @@ -0,0 +1,409 @@ +import React, { RefObject, useCallback, useEffect, useRef } from "react"; +import { + motion, + SpringOptions, + useAnimationFrame, + useMotionValue, + useScroll, + useSpring, + useTransform, + useVelocity, +} from "motion/react"; + +import { cn } from "@/lib/utils"; + +// Custom wrap function +const wrap = (min: number, max: number, value: number): number => { + const range = max - min; + return ((((value - min) % range) + range) % range) + min; +}; + +type PreserveAspectRatioAlign = + | "none" + | "xMinYMin" + | "xMidYMin" + | "xMaxYMin" + | "xMinYMid" + | "xMidYMid" + | "xMaxYMid" + | "xMinYMax" + | "xMidYMax" + | "xMaxYMax"; + +interface CSSVariableInterpolation { + property: string; + from: number | string; + to: number | string; +} + +type PreserveAspectRatioMeetOrSlice = "meet" | "slice"; + +type PreserveAspectRatio = + | PreserveAspectRatioAlign + | `${Exclude} ${PreserveAspectRatioMeetOrSlice}`; + +interface MarqueeAlongSvgPathProps { + children: React.ReactNode; + className?: string; + + // Path properties + path: string; + pathId?: string; + preserveAspectRatio?: PreserveAspectRatio; + showPath?: boolean; + + // SVG properties + width?: string | number; + height?: string | number; + viewBox?: string; + + // Marquee properties + baseVelocity?: number; + direction?: "normal" | "reverse"; + easing?: (value: number) => number; + slowdownOnHover?: boolean; + slowDownFactor?: number; + slowDownSpringConfig?: SpringOptions; + + // Scroll properties + useScrollVelocity?: boolean; + scrollAwareDirection?: boolean; + scrollSpringConfig?: SpringOptions; + scrollContainer?: RefObject | HTMLElement | null; + + // Item repetition + repeat?: number; + + // Drag properties + draggable?: boolean; + dragSensitivity?: number; + dragVelocityDecay?: number; + dragAwareDirection?: boolean; + grabCursor?: boolean; + + // Z-index properties + enableRollingZIndex?: boolean; + zIndexBase?: number; + zIndexRange?: number; + + cssVariableInterpolation?: CSSVariableInterpolation[]; +} + +const MarqueeAlongSvgPath = ({ + children, + className, + + // Path defaults + path, + pathId, + preserveAspectRatio = "xMidYMid meet", + showPath = false, + + // SVG defaults + width = "100%", + height = "100%", + viewBox = "0 0 100 100", + + // Marquee defaults + baseVelocity = 5, + direction = "normal", + easing, + slowdownOnHover = false, + slowDownFactor = 0.3, + slowDownSpringConfig = { damping: 50, stiffness: 400 }, + + // Scroll defaults + useScrollVelocity = false, + scrollAwareDirection = false, + scrollSpringConfig = { damping: 50, stiffness: 400 }, + scrollContainer, + + // Items repetition + repeat = 3, + + // Drag defaults + draggable = false, + dragSensitivity = 0.2, + dragVelocityDecay = 0.96, + dragAwareDirection = false, + grabCursor = false, + + // Z-index defaults + enableRollingZIndex = true, + zIndexBase = 1, // Base z-index value + zIndexRange = 10, // Range of z-index values to use + + cssVariableInterpolation = [], +}: MarqueeAlongSvgPathProps) => { + const container = useRef(null); + const baseOffset = useMotionValue(0); + + const pathRef = useRef(null); + + const itemRefs = useRef>(new Map()); + + // Create an array of items outside of the render function + const items = React.useMemo(() => { + const childrenArray = React.Children.toArray(children); + + return childrenArray.flatMap((child, childIndex) => + Array.from({ length: repeat }, (_, repeatIndex) => { + const itemIndex = repeatIndex * childrenArray.length + childIndex; + const key = `${childIndex}-${repeatIndex}`; + return { + child, + childIndex, + repeatIndex, + itemIndex, + key, + }; + }), + ); + }, [children, repeat]); + + // Function to calculate z-index based on offset distance + const calculateZIndex = useCallback( + (offsetDistance: number) => { + if (!enableRollingZIndex) { + return undefined; + } + + // Simple progress-based z-index + const normalizedDistance = offsetDistance / 100; + return Math.floor(zIndexBase + normalizedDistance * zIndexRange); + }, + [enableRollingZIndex, zIndexBase, zIndexRange], + ); + + // Generate a random ID for the path if not provided + const id = + pathId || `marquee-path-${Math.random().toString(36).substring(7)}`; + + // Scroll tracking + const { scrollY } = useScroll({ + container: + (scrollContainer as RefObject) || container, + }); + + const scrollVelocity = useVelocity(scrollY); + const smoothVelocity = useSpring(scrollVelocity, scrollSpringConfig); + + // Hover and drag state tracking + const isHovered = useRef(false); + const isDragging = useRef(false); + const dragVelocity = useRef(0); + + // Direction factor for changing direction based on scroll or drag + const directionFactor = useRef(direction === "normal" ? 1 : -1); + + // Motion values for animation + const hoverFactorValue = useMotionValue(1); + const defaultVelocity = useMotionValue(1); + const smoothHoverFactor = useSpring(hoverFactorValue, slowDownSpringConfig); + + // Transform scroll velocity into a factor that affects marquee speed + const velocityFactor = useTransform( + useScrollVelocity ? smoothVelocity : defaultVelocity, + [0, 1000], + [0, 5], + { clamp: false }, + ); + + // Animation frame handler + useAnimationFrame((_, delta) => { + if (isDragging.current && draggable) { + baseOffset.set(baseOffset.get() + dragVelocity.current); + + // Add decay to dragVelocity + dragVelocity.current *= 0.9; + + // Stop completely if velocity is very small + if (Math.abs(dragVelocity.current) < 0.01) { + dragVelocity.current = 0; + } + + return; + } + + // Update hover factor + if (isHovered.current) { + hoverFactorValue.set(slowdownOnHover ? slowDownFactor : 1); + } else { + hoverFactorValue.set(1); + } + + // Calculate regular movement + let moveBy = + directionFactor.current * + baseVelocity * + (delta / 1000) * + smoothHoverFactor.get(); + + // Adjust movement based on scroll velocity if scrollAwareDirection is enabled + if (scrollAwareDirection && !isDragging.current) { + if (velocityFactor.get() < 0) { + directionFactor.current = -1; + } else if (velocityFactor.get() > 0) { + directionFactor.current = 1; + } + } + + moveBy += directionFactor.current * moveBy * velocityFactor.get(); + + if (draggable) { + moveBy += dragVelocity.current; + + // Update direction based on drag direction if dragAwareDirection is true + if (dragAwareDirection && Math.abs(dragVelocity.current) > 0.1) { + directionFactor.current = Math.sign(dragVelocity.current); + } + + // Gradually decay drag velocity back to zero + if (!isDragging.current && Math.abs(dragVelocity.current) > 0.01) { + dragVelocity.current *= dragVelocityDecay; + } else if (!isDragging.current) { + dragVelocity.current = 0; + } + } + + baseOffset.set(baseOffset.get() + moveBy); + }); + + // Pointer event handlers for dragging + const lastPointerPosition = useRef({ x: 0, y: 0 }); + + const handlePointerDown = (e: React.PointerEvent) => { + if (!draggable) return; + (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId); + + if (grabCursor) { + (e.currentTarget as HTMLElement).style.cursor = "grabbing"; + } + + isDragging.current = true; + lastPointerPosition.current = { x: e.clientX, y: e.clientY }; + + // Pause automatic animation by setting velocity to 0 + dragVelocity.current = 0; + }; + + const handlePointerMove = (e: React.PointerEvent) => { + if (!draggable || !isDragging.current) return; + + const currentPosition = { x: e.clientX, y: e.clientY }; + + // Calculate movement delta - simplified for path movement + const deltaX = currentPosition.x - lastPointerPosition.current.x; + const deltaY = currentPosition.y - lastPointerPosition.current.y; + + // For path following, we use a simple magnitude of movement + const delta = Math.sqrt(deltaX * deltaX + deltaY * deltaY); + const projectedDelta = deltaX > 0 ? delta : -delta; + + // Update drag velocity based on the projected movement + dragVelocity.current = projectedDelta * dragSensitivity; + + // Update last position + lastPointerPosition.current = currentPosition; + }; + + const handlePointerUp = (e: React.PointerEvent) => { + if (!draggable) return; + (e.currentTarget as HTMLElement).releasePointerCapture(e.pointerId); + isDragging.current = false; + + if (grabCursor) { + (e.currentTarget as HTMLElement).style.cursor = "grab"; + } + }; + + return ( +
+ + + + + {items.map(({ child, repeatIndex, itemIndex, key }) => { + // Create a unique offset transform for each item + const itemOffset = useTransform(baseOffset, (v) => { + const position = (itemIndex * 100) / items.length; + const wrappedValue = wrap(0, 100, v + position); + return `${easing ? easing(wrappedValue / 100) * 100 : wrappedValue}%`; + }); + + // Create a motion value for the current offset distance + const currentOffsetDistance = useMotionValue(0); + + // Update z-index when offset distance changes + const zIndex = useTransform(currentOffsetDistance, (value) => + calculateZIndex(value), + ); + + // Update current offset distance value when animation runs + useEffect(() => { + const unsubscribe = itemOffset.on("change", (value: string) => { + // Parse percentage string to get numerical value + const match = value.match(/^([\d.]+)%$/); + if (match && match[1]) { + currentOffsetDistance.set(parseFloat(match[1])); + } + }); + return unsubscribe; + }, [itemOffset, currentOffsetDistance]); + + const cssVariables = Object.fromEntries( + (cssVariableInterpolation || []).map(({ property, from, to }) => [ + property, + useTransform(currentOffsetDistance, [0, 100], [from, to]), + ]), + ); + + return ( + { + if (el) itemRefs.current.set(key, el); + }} + className={cn( + "absolute top-0 left-0", + draggable && grabCursor && "cursor-grab", + )} + style={{ + offsetPath: `path('${path}')`, + offsetDistance: itemOffset, + zIndex: enableRollingZIndex ? zIndex : undefined, + ...cssVariables, + }} + aria-hidden={repeatIndex > 0} + onMouseEnter={() => (isHovered.current = true)} + onMouseLeave={() => (isHovered.current = false)} + > + {child} + + ); + })} +
+ ); +}; + +export default MarqueeAlongSvgPath; diff --git a/src/components/fancy/blocks/simple-marquee.tsx b/src/components/fancy/blocks/simple-marquee.tsx new file mode 100644 index 0000000..a074bed --- /dev/null +++ b/src/components/fancy/blocks/simple-marquee.tsx @@ -0,0 +1,273 @@ +"use client"; +import { RefObject, useRef } from "react"; +import { + motion, + SpringOptions, + useAnimationFrame, + useMotionValue, + useScroll, + useSpring, + useTransform, + useVelocity, +} from "motion/react"; + +import { cn } from "@/lib/utils"; + +// Custom wrap function +const wrap = (min: number, max: number, value: number): number => { + const range = max - min; + return ((((value - min) % range) + range) % range) + min; +}; + +interface SimpleMarqueeProps { + children: React.ReactNode; // The elements to be scrolled + className?: string; // Additional CSS classes for the container + direction?: "left" | "right" | "up" | "down"; // The direction of the marquee + baseVelocity?: number; // The base velocity of the marquee in pixels per second + easing?: (value: number) => number; // The easing function for the animation + slowdownOnHover?: boolean; // Whether to slow down the animation on hover + slowDownFactor?: number; // The factor to slow down the animation on hover + slowDownSpringConfig?: SpringOptions; // The spring config for the slow down animation + useScrollVelocity?: boolean; // Whether to use the scroll velocity to control the marquee speed + scrollAwareDirection?: boolean; // Whether to adjust the direction based on the scroll direction + scrollSpringConfig?: SpringOptions; // The spring config for the scroll velocity-based direction adjustment + scrollContainer?: RefObject | HTMLElement | null; // The container to use for the scroll velocity + repeat?: number; // The number of times to repeat the children. + draggable?: boolean; // Whether to allow dragging of the marquee + dragSensitivity?: number; // The sensitivity of the drag movement + dragVelocityDecay?: number; // The decay of the drag velocity. This means how fast the velocity will gradually reduce to baseVelocity when we release the drag + dragAwareDirection?: boolean; // Whether to adjust the direction based on the drag velocity + dragAngle?: number; // The angle of the drag movement in degrees. This is useful if you eg. rotating your marquee by 45 degrees + grabCursor?: boolean; // Whether to change the cursor to grabbing when dragging +} + +const SimpleMarquee = ({ + children, + className, + direction = "right", + baseVelocity = 5, + slowdownOnHover = false, + slowDownFactor = 0.3, + slowDownSpringConfig = { damping: 50, stiffness: 400 }, + useScrollVelocity = false, + scrollAwareDirection = false, + scrollSpringConfig = { damping: 50, stiffness: 400 }, + scrollContainer, + repeat = 3, + draggable = false, + dragSensitivity = 0.2, + dragVelocityDecay = 0.96, + dragAwareDirection = false, + dragAngle = 0, + grabCursor = false, + easing, +}: SimpleMarqueeProps) => { + const baseX = useMotionValue(0); + const baseY = useMotionValue(0); + + const { scrollY } = useScroll({ + ...(scrollContainer && { + container: scrollContainer as RefObject, + }), + }); + + const scrollVelocity = useVelocity(scrollY); + const smoothVelocity = useSpring(scrollVelocity, scrollSpringConfig); + + const hoverFactorValue = useMotionValue(1); + const defaultVelocity = useMotionValue(1); + + // Track if user is currently dragging + const isDragging = useRef(false); + + // Store drag velocity + const dragVelocity = useRef(0); + + const smoothHoverFactor = useSpring(hoverFactorValue, slowDownSpringConfig); + + // Transform scroll velocity into a factor that affects marquee speed + const velocityFactor = useTransform( + useScrollVelocity ? smoothVelocity : defaultVelocity, + [0, 1000], + [0, 5], + { + clamp: false, + }, + ); + + // Determine if movement is horizontal or vertical. + const isHorizontal = direction === "left" || direction === "right"; + + // Convert baseVelocity to the correct direction + const actualBaseVelocity = + direction === "left" || direction === "up" ? -baseVelocity : baseVelocity; + + // Reference to track if mouse is hovering + const isHovered = useRef(false); + + // Direction factor for changing direction based on scroll or drag + const directionFactor = useRef(1); + + // Transform baseX/baseY into a percentage for the transform + // The wrap function ensures the value stays between 0 and -100 + const x = useTransform(baseX, (v) => { + // Apply easing if provided, otherwise use linear (v directly) + const wrappedValue = wrap(0, -100, v); + return `${easing ? easing(wrappedValue / -100) * -100 : wrappedValue}%`; + }); + const y = useTransform(baseY, (v) => { + // Apply easing if provided, otherwise use linear (v directly) + const wrappedValue = wrap(0, -100, v); + return `${easing ? easing(wrappedValue / -100) * -100 : wrappedValue}%`; + }); + + useAnimationFrame((t, delta) => { + if (isDragging.current && draggable) { + if (isHorizontal) { + baseX.set(baseX.get() + dragVelocity.current); + } else { + baseY.set(baseY.get() + dragVelocity.current); + } + + // Add decay to dragVelocity when not moving + // This will gradually reduce the velocity to zero when the pointer isn't moving + dragVelocity.current *= 0.9; + + // Stop completely if velocity is very small + if (Math.abs(dragVelocity.current) < 0.01) { + dragVelocity.current = 0; + } + + return; + } + + // Update hover factor + if (isHovered.current) { + hoverFactorValue.set(slowdownOnHover ? slowDownFactor : 1); + } else { + hoverFactorValue.set(1); + } + + // Calculate regular movement + let moveBy = + directionFactor.current * + actualBaseVelocity * + (delta / 1000) * + smoothHoverFactor.get(); + + // Adjust movement based on scroll velocity if scrollAwareDirection is enabled + if (scrollAwareDirection && !isDragging.current) { + if (velocityFactor.get() < 0) { + directionFactor.current = -1; + } else if (velocityFactor.get() > 0) { + directionFactor.current = 1; + } + } + + moveBy += directionFactor.current * moveBy * velocityFactor.get(); + + if (draggable) { + moveBy += dragVelocity.current; + + // Update direction based on drag direction if dragAwareDirection is true + if (dragAwareDirection && Math.abs(dragVelocity.current) > 0.1) { + // If dragging in negative direction, set directionFactor to -1 + // If dragging in positive direction, set directionFactor to 1 + directionFactor.current = Math.sign(dragVelocity.current); + } + + // Gradually decay drag velocity back to zero + if (!isDragging.current && Math.abs(dragVelocity.current) > 0.01) { + dragVelocity.current *= dragVelocityDecay; + } else if (!isDragging.current) { + dragVelocity.current = 0; + } + } + + if (isHorizontal) { + baseX.set(baseX.get() + moveBy); + } else { + baseY.set(baseY.get() + moveBy); + } + }); + + const lastPointerPosition = useRef({ x: 0, y: 0 }); + + const handlePointerDown = (e: React.PointerEvent) => { + if (!draggable) return; // Capture the pointer to receive events even when pointer moves outside + (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId); + + if (grabCursor) { + (e.currentTarget as HTMLElement).style.cursor = "grabbing"; + } + + isDragging.current = true; + lastPointerPosition.current = { x: e.clientX, y: e.clientY }; + + // Pause automatic animation by setting velocity to 0 + dragVelocity.current = 0; + }; + + const handlePointerMove = (e: React.PointerEvent) => { + if (!draggable || !isDragging.current) return; + + const currentPosition = { x: e.clientX, y: e.clientY }; + + // Calculate delta from last position + const deltaX = currentPosition.x - lastPointerPosition.current.x; + const deltaY = currentPosition.y - lastPointerPosition.current.y; + + // Convert dragAngle from degrees to radians + const angleInRadians = (dragAngle * Math.PI) / 180; + + // Calculate the projection of the movement along the angle direction + // Using the dot product of the movement vector and the direction vector + const directionX = Math.cos(angleInRadians); + const directionY = Math.sin(angleInRadians); + + // Project the movement onto the angle direction + const projectedDelta = deltaX * directionX + deltaY * directionY; + + // Update drag velocity based on the projected movement + dragVelocity.current = projectedDelta * dragSensitivity; + + // Update last position + lastPointerPosition.current = currentPosition; + }; + + const handlePointerUp = (e: React.PointerEvent) => { + if (!draggable) return; // Release pointer capture + (e.currentTarget as HTMLElement).releasePointerCapture(e.pointerId); + + isDragging.current = false; + }; + + return ( + (isHovered.current = true)} + onHoverEnd={() => (isHovered.current = false)} + onPointerDown={handlePointerDown} + onPointerMove={handlePointerMove} + onPointerUp={handlePointerUp} + onPointerCancel={handlePointerUp} + > + {Array.from({ length: repeat }, (_, i) => i).map((i) => ( + 0} + > + {children} + + ))} + + ); +}; + +export default SimpleMarquee; diff --git a/src/components/fancy/code-comp.tsx b/src/components/fancy/code-comp.tsx deleted file mode 100644 index b18db7e..0000000 --- a/src/components/fancy/code-comp.tsx +++ /dev/null @@ -1,105 +0,0 @@ -"use client"; - -import { LuFile } from "react-icons/lu"; -import { useTheme } from "next-themes"; -import { useEffect, useState } from "react"; -import { codeToHtml } from "shiki"; - -interface CodeComparisonProps { - beforeCode: string; - afterCode: string; - language: string; - filename: string; - lightTheme: string; - darkTheme: string; - beforeTitle: string; - afterTitle: string; -} - -export function CodeComparison({ - beforeCode, - afterCode, - language, - filename, - lightTheme, - darkTheme, - beforeTitle, - afterTitle, -}: CodeComparisonProps) { - const { theme, systemTheme } = useTheme(); - const [highlightedBefore, setHighlightedBefore] = useState(""); - const [highlightedAfter, setHighlightedAfter] = useState(""); - - useEffect(() => { - const currentTheme = theme === "system" ? systemTheme : theme; - const selectedTheme = currentTheme === "dark" ? darkTheme : lightTheme; - - async function highlightCode() { - const before = await codeToHtml(beforeCode, { - lang: language, - theme: selectedTheme, - }); - const after = await codeToHtml(afterCode, { - lang: language, - theme: selectedTheme, - }); - setHighlightedBefore(before); - setHighlightedAfter(after); - } - - highlightCode(); - }, [ - theme, - systemTheme, - beforeCode, - afterCode, - language, - lightTheme, - darkTheme, - ]); - - const renderCode = (code: string, highlighted: string) => { - if (highlighted) { - return ( -
- ); - } else { - return ( -
-					{code}
-				
- ); - } - }; - return ( -
-
-
-
-
- - {filename} - - {beforeTitle} - -
- {renderCode(beforeCode, highlightedBefore)} -
-
-
- - {filename} - - {afterTitle} - -
- {renderCode(afterCode, highlightedAfter)} -
-
-
-
- ); -} diff --git a/src/components/fancy/icon-cloud.tsx b/src/components/fancy/icon-cloud.tsx deleted file mode 100644 index 6e19714..0000000 --- a/src/components/fancy/icon-cloud.tsx +++ /dev/null @@ -1,350 +0,0 @@ -"use client"; - -import React, { useEffect, useRef, useState } from "react"; -import { renderToString } from "react-dom/server"; - -interface Icon { - x: number; - y: number; - z: number; - scale: number; - opacity: number; - id: number; -} - -interface IconCloudProps { - icons?: React.ReactNode[]; - images?: string[]; -} - -function easeOutCubic(t: number): number { - return 1 - Math.pow(1 - t, 3); -} - -export function IconCloud({ icons, images }: IconCloudProps) { - const canvasRef = useRef(null); - const [iconPositions, setIconPositions] = useState([]); - const [rotation, setRotation] = useState({ x: 0, y: 0 }); - const [isDragging, setIsDragging] = useState(false); - const [lastMousePos, setLastMousePos] = useState({ x: 0, y: 0 }); - const [mousePos, setMousePos] = useState({ x: 0, y: 0 }); - const [targetRotation, setTargetRotation] = useState<{ - x: number; - y: number; - startX: number; - startY: number; - distance: number; - startTime: number; - duration: number; - } | null>(null); - const animationFrameRef = useRef(); - const rotationRef = useRef(rotation); - const iconCanvasesRef = useRef([]); - const imagesLoadedRef = useRef([]); - - // Create icon canvases once when icons/images change - useEffect(() => { - if (!icons && !images) return; - - const items = icons || images || []; - imagesLoadedRef.current = new Array(items.length).fill(false); - - const newIconCanvases = items.map((item, index) => { - const offscreen = document.createElement("canvas"); - offscreen.width = 40; - offscreen.height = 40; - const offCtx = offscreen.getContext("2d"); - - if (offCtx) { - if (images) { - // Handle image URLs directly - const img = new Image(); - img.crossOrigin = "anonymous"; - img.src = items[index] as string; - img.onload = () => { - offCtx.clearRect( - 0, - 0, - offscreen.width, - offscreen.height, - ); - - // Create circular clipping path - offCtx.beginPath(); - offCtx.arc(20, 20, 20, 0, Math.PI * 2); - offCtx.closePath(); - offCtx.clip(); - - // Draw the image - offCtx.drawImage(img, 0, 0, 40, 40); - - imagesLoadedRef.current[index] = true; - }; - } else { - // Handle SVG icons - offCtx.scale(0.4, 0.4); - const svgString = renderToString( - item as React.ReactElement, - ); - const img = new Image(); - img.src = "data:image/svg+xml;base64," + btoa(svgString); - img.onload = () => { - offCtx.clearRect( - 0, - 0, - offscreen.width, - offscreen.height, - ); - offCtx.drawImage(img, 0, 0); - imagesLoadedRef.current[index] = true; - }; - } - } - return offscreen; - }); - - iconCanvasesRef.current = newIconCanvases; - }, [icons, images]); - - // Generate initial icon positions on a sphere - useEffect(() => { - const items = icons || images || []; - const newIcons: Icon[] = []; - const numIcons = items.length || 20; - - // Fibonacci sphere parameters - const offset = 2 / numIcons; - const increment = Math.PI * (3 - Math.sqrt(5)); - - for (let i = 0; i < numIcons; i++) { - const y = i * offset - 1 + offset / 2; - const r = Math.sqrt(1 - y * y); - const phi = i * increment; - - const x = Math.cos(phi) * r; - const z = Math.sin(phi) * r; - - newIcons.push({ - x: x * 100, - y: y * 100, - z: z * 100, - scale: 1, - opacity: 1, - id: i, - }); - } - setIconPositions(newIcons); - }, [icons, images]); - - // Handle mouse events - const handleMouseDown = (e: React.MouseEvent) => { - const rect = canvasRef.current?.getBoundingClientRect(); - if (!rect || !canvasRef.current) return; - - const x = e.clientX - rect.left; - const y = e.clientY - rect.top; - - const ctx = canvasRef.current.getContext("2d"); - if (!ctx) return; - - iconPositions.forEach((icon) => { - const cosX = Math.cos(rotationRef.current.x); - const sinX = Math.sin(rotationRef.current.x); - const cosY = Math.cos(rotationRef.current.y); - const sinY = Math.sin(rotationRef.current.y); - - const rotatedX = icon.x * cosY - icon.z * sinY; - const rotatedZ = icon.x * sinY + icon.z * cosY; - const rotatedY = icon.y * cosX + rotatedZ * sinX; - - const screenX = canvasRef.current!.width / 2 + rotatedX; - const screenY = canvasRef.current!.height / 2 + rotatedY; - - const scale = (rotatedZ + 200) / 300; - const radius = 20 * scale; - const dx = x - screenX; - const dy = y - screenY; - - if (dx * dx + dy * dy < radius * radius) { - const targetX = -Math.atan2( - icon.y, - Math.sqrt(icon.x * icon.x + icon.z * icon.z), - ); - const targetY = Math.atan2(icon.x, icon.z); - - const currentX = rotationRef.current.x; - const currentY = rotationRef.current.y; - const distance = Math.sqrt( - Math.pow(targetX - currentX, 2) + - Math.pow(targetY - currentY, 2), - ); - - const duration = Math.min(2000, Math.max(800, distance * 1000)); - - setTargetRotation({ - x: targetX, - y: targetY, - startX: currentX, - startY: currentY, - distance, - startTime: performance.now(), - duration, - }); - return; - } - }); - - setIsDragging(true); - setLastMousePos({ x: e.clientX, y: e.clientY }); - }; - - const handleMouseMove = (e: React.MouseEvent) => { - const rect = canvasRef.current?.getBoundingClientRect(); - if (rect) { - const x = e.clientX - rect.left; - const y = e.clientY - rect.top; - setMousePos({ x, y }); - } - - if (isDragging) { - const deltaX = e.clientX - lastMousePos.x; - const deltaY = e.clientY - lastMousePos.y; - - rotationRef.current = { - x: rotationRef.current.x + deltaY * 0.002, - y: rotationRef.current.y + deltaX * 0.002, - }; - - setLastMousePos({ x: e.clientX, y: e.clientY }); - } - }; - - const handleMouseUp = () => { - setIsDragging(false); - }; - - // Animation and rendering - useEffect(() => { - const canvas = canvasRef.current; - const ctx = canvas?.getContext("2d"); - if (!canvas || !ctx) return; - - const animate = () => { - ctx.clearRect(0, 0, canvas.width, canvas.height); - - const centerX = canvas.width / 2; - const centerY = canvas.height / 2; - const maxDistance = Math.sqrt( - centerX * centerX + centerY * centerY, - ); - const dx = mousePos.x - centerX; - const dy = mousePos.y - centerY; - const distance = Math.sqrt(dx * dx + dy * dy); - const speed = 0.003 + (distance / maxDistance) * 0.01; - - if (targetRotation) { - const elapsed = performance.now() - targetRotation.startTime; - const progress = Math.min(1, elapsed / targetRotation.duration); - const easedProgress = easeOutCubic(progress); - - rotationRef.current = { - x: - targetRotation.startX + - (targetRotation.x - targetRotation.startX) * - easedProgress, - y: - targetRotation.startY + - (targetRotation.y - targetRotation.startY) * - easedProgress, - }; - - if (progress >= 1) { - setTargetRotation(null); - } - } else if (!isDragging) { - rotationRef.current = { - x: rotationRef.current.x + (dy / canvas.height) * speed, - y: rotationRef.current.y + (dx / canvas.width) * speed, - }; - } - - iconPositions.forEach((icon, index) => { - const cosX = Math.cos(rotationRef.current.x); - const sinX = Math.sin(rotationRef.current.x); - const cosY = Math.cos(rotationRef.current.y); - const sinY = Math.sin(rotationRef.current.y); - - const rotatedX = icon.x * cosY - icon.z * sinY; - const rotatedZ = icon.x * sinY + icon.z * cosY; - const rotatedY = icon.y * cosX + rotatedZ * sinX; - - const scale = (rotatedZ + 200) / 300; - const opacity = Math.max( - 0.2, - Math.min(1, (rotatedZ + 150) / 200), - ); - - ctx.save(); - ctx.translate( - canvas.width / 2 + rotatedX, - canvas.height / 2 + rotatedY, - ); - ctx.scale(scale, scale); - ctx.globalAlpha = opacity; - - if (icons || images) { - // Only try to render icons/images if they exist - if ( - iconCanvasesRef.current[index] && - imagesLoadedRef.current[index] - ) { - ctx.drawImage( - iconCanvasesRef.current[index], - -20, - -20, - 40, - 40, - ); - } - } else { - // Show numbered circles if no icons/images are provided - ctx.beginPath(); - ctx.arc(0, 0, 20, 0, Math.PI * 2); - ctx.fillStyle = "#4444ff"; - ctx.fill(); - ctx.fillStyle = "white"; - ctx.textAlign = "center"; - ctx.textBaseline = "middle"; - ctx.font = "16px Arial"; - ctx.fillText(`${icon.id + 1}`, 0, 0); - } - - ctx.restore(); - }); - animationFrameRef.current = requestAnimationFrame(animate); - }; - - animate(); - - return () => { - if (animationFrameRef.current) { - cancelAnimationFrame(animationFrameRef.current); - } - }; - }, [icons, images, iconPositions, isDragging, mousePos, targetRotation]); - - return ( - - ); -} diff --git a/src/components/fancy/marqee.tsx b/src/components/fancy/marqee.tsx deleted file mode 100644 index fcbeeac..0000000 --- a/src/components/fancy/marqee.tsx +++ /dev/null @@ -1,77 +0,0 @@ -import { cn } from "../cn"; -import { ComponentPropsWithoutRef } from "react"; - -interface MarqueeProps extends ComponentPropsWithoutRef<"div"> { - /** - * Optional CSS class name to apply custom styles - */ - className?: string; - /** - * Whether to reverse the animation direction - * @default false - */ - reverse?: boolean; - /** - * Whether to pause the animation on hover - * @default false - */ - pauseOnHover?: boolean; - /** - * Content to be displayed in the marquee - */ - children: React.ReactNode; - /** - * Whether to animate vertically instead of horizontally - * @default false - */ - vertical?: boolean; - /** - * Number of times to repeat the content - * @default 4 - */ - repeat?: number; -} - -export function Marquee({ - className, - reverse = false, - pauseOnHover = false, - children, - vertical = false, - repeat = 4, - ...props -}: MarqueeProps) { - return ( -
- {Array(repeat) - .fill(0) - .map((_, i) => ( -
- {children} -
- ))} -
- ); -} diff --git a/src/components/fancy/text/basic-number-ticker.tsx b/src/components/fancy/text/basic-number-ticker.tsx new file mode 100644 index 0000000..e3779c4 --- /dev/null +++ b/src/components/fancy/text/basic-number-ticker.tsx @@ -0,0 +1,107 @@ +"use client"; + +import { + forwardRef, + useCallback, + useEffect, + useImperativeHandle, + useState, +} from "react"; +import { + animate, + AnimationPlaybackControls, + motion, + useMotionValue, + useTransform, + ValueAnimationTransition, +} from "motion/react"; + +import { cn } from "@/lib/utils"; + +interface NumberTickerProps { + from: number; // Starting value of the animation + target: number; // End value of the animation + transition?: ValueAnimationTransition; // Animation configuration, refer to motion docs for more details + className?: string; // additionl CSS classes for styling + onStart?: () => void; // Callback function when animation starts + onComplete?: () => void; // Callback function when animation completes + autoStart?: boolean; // Whether to start the animation automatically +} + +// Ref interface to allow external control of the animation +export interface NumberTickerRef { + startAnimation: () => void; +} + +const NumberTicker = forwardRef( + ( + { + from = 0, + target = 100, + transition = { + duration: 3, + type: "tween", + ease: "easeInOut", + }, + className, + onStart, + onComplete, + autoStart = true, + ...props + }, + ref, + ) => { + const count = useMotionValue(from); + const rounded = useTransform(count, (latest) => Math.round(latest)); + const [controls, setControls] = useState( + null, + ); + + // Function to start the animation + const startAnimation = useCallback(() => { + if (controls) controls.stop(); + onStart?.(); + + count.set(from); + + const newControls = animate(count, target, { + ...transition, + onComplete: () => { + onComplete?.(); + }, + }); + setControls(newControls); + }, []); + + // Expose the startAnimation function via ref + useImperativeHandle(ref, () => ({ + startAnimation, + })); + + useEffect(() => { + if (autoStart) { + startAnimation(); + } + return () => controls?.stop(); + }, [autoStart]); + + return ( + + {rounded} + + ); + }, +); + +NumberTicker.displayName = "NumberTicker"; + +export default NumberTicker; + +// Usage example: +// To start the animation from outside the component: +// 1. Create a ref: +// const tickerRef = useRef(null); +// 2. Pass the ref to the NumberTicker component: +// +// 3. Call the startAnimation function: +// tickerRef.current?.startAnimation(); diff --git a/src/components/fancy/typewriter.tsx b/src/components/fancy/typewriter.tsx deleted file mode 100644 index c7524aa..0000000 --- a/src/components/fancy/typewriter.tsx +++ /dev/null @@ -1,138 +0,0 @@ -"use client"; -import { cn } from "../cn"; -import { motion, Variants } from "motion/react"; -import { useEffect, useState } from "react"; - -interface TypewriterProps { - text: string | string[]; - speed?: number; - initialDelay?: number; - waitTime?: number; - deleteSpeed?: number; - loop?: boolean; - className?: string; - showCursor?: boolean; - hideCursorOnType?: boolean; - cursorChar?: string | React.ReactNode; - cursorAnimationVariants?: { - initial: Variants["initial"]; - animate: Variants["animate"]; - }; - cursorClassName?: string; -} - -const Typewriter = ({ - text, - speed = 50, - initialDelay = 0, - waitTime = 2000, - deleteSpeed = 30, - loop = true, - className, - showCursor = true, - hideCursorOnType = false, - cursorChar = "|", - cursorClassName = "ml-1", - cursorAnimationVariants = { - initial: { opacity: 0 }, - animate: { - opacity: 1, - transition: { - duration: 0.01, - repeat: Infinity, - repeatDelay: 0.4, - repeatType: "reverse", - }, - }, - }, -}: TypewriterProps) => { - const [displayText, setDisplayText] = useState(""); - const [currentIndex, setCurrentIndex] = useState(0); - const [isDeleting, setIsDeleting] = useState(false); - const [currentTextIndex, setCurrentTextIndex] = useState(0); - - const texts = Array.isArray(text) ? text : [text]; - - useEffect(() => { - let timeout: NodeJS.Timeout; - - const currentText = texts[currentTextIndex]; - - const startTyping = () => { - if (isDeleting) { - if (displayText === "") { - setIsDeleting(false); - if (currentTextIndex === texts.length - 1 && !loop) { - return; - } - setCurrentTextIndex((prev) => (prev + 1) % texts.length); - setCurrentIndex(0); - timeout = setTimeout(() => {}, waitTime); - } else { - timeout = setTimeout(() => { - setDisplayText((prev) => prev.slice(0, -1)); - }, deleteSpeed); - } - } else { - if (currentIndex < currentText.length) { - timeout = setTimeout(() => { - setDisplayText( - (prev) => prev + currentText[currentIndex], - ); - setCurrentIndex((prev) => prev + 1); - }, speed); - } else if (texts.length > 1) { - timeout = setTimeout(() => { - setIsDeleting(true); - }, waitTime); - } - } - }; - - // Apply initial delay only at the start - if (currentIndex === 0 && !isDeleting && displayText === "") { - timeout = setTimeout(startTyping, initialDelay); - } else { - startTyping(); - } - - return () => clearTimeout(timeout); - }, [ - currentIndex, - displayText, - isDeleting, - speed, - deleteSpeed, - waitTime, - texts, - currentTextIndex, - loop, - ]); - - return ( -
- {displayText} - {showCursor && ( - - {cursorChar} - - )} -
- ); -}; - -export default Typewriter; diff --git a/src/components/nUI/Footer.tsx b/src/components/nUI/Footer.tsx deleted file mode 100644 index e743842..0000000 --- a/src/components/nUI/Footer.tsx +++ /dev/null @@ -1,95 +0,0 @@ -import React from "react"; - -import { IconType } from "react-icons"; -import { tv } from "tailwind-variants"; - -export const footerVariants = tv({ - base: "w-full bg-primary", -}); - -export interface FooterProps { - social: { - name: string; - href: string; - icon: IconType; - }[]; - links: { - name: string; - children: { - name: string; - href: string; - }[]; - }[]; - copylight?: string; - className?: string; - children?: React.ReactNode; -} - -export const Footer: React.FC = ({ - social, - links, - children, - className, - copylight = " 2021- Neody. All rights reserved.", -}) => { - const maxWidth = links.length < 4 ? "max-w-4xl" : "max-w-5xl"; - - return ( -
-
-
- {links.map((item) => ( -
-

- {item.name} -

- -
- ))} - {children} -
-
-
-
-

- © {copylight} -

-
- {social.map((item) => ( - - - - ))} -
-
-
-
-
-
- ); -}; -Footer.displayName = "Footer"; diff --git a/src/components/nUI/Header.tsx b/src/components/nUI/Header.tsx deleted file mode 100644 index 69c9f4c..0000000 --- a/src/components/nUI/Header.tsx +++ /dev/null @@ -1,361 +0,0 @@ -import type React from "react"; -import { type ComponentPropsWithoutRef, forwardRef, useState } from "react"; -import { tv } from "tailwind-variants"; -import { motion, useMotionValueEvent, useScroll } from "motion/react"; -import { useLockBodyScroll, useToggle } from "react-use"; -import { MenuToggle } from "./MenuToggle"; -import { useIsWide } from "./hooks"; -import Link from "next/link"; - -const headerVariants = tv({ - base: "fixed inset-x-0 top-0 z-50 py-2 transition-[padding-top,padding-bottom,box-shadow] ease-in-out lg:py-0 text-white", - variants: { - isScrolled: { - true: "border-b border-outline bg-primary border-primary backdrop-blur-sm lg:bg-opacity-70", - false: "bg-transparent lg:py-4", - }, - }, -}); - -const barVariants = { - rest: { opacity: 0, y: 5 }, - hover: { - opacity: 1, - y: 0, - transition: { - delay: 0.1, - type: "spring", - }, - }, -}; - -const mobileMenuContainerVariants = { - open: { - display: "block", - }, - closed: { - display: "none", - transition: { delay: 0.8 }, - }, -}; - -const mobileMenuItemContainerVariants = { - open: { - opacity: 1, - transition: { - ease: "easeOut", - staggerChildren: 0.07, - delayChildren: 0.2, - }, - }, - closed: { - opacity: 0, - transition: { delay: 0.6, staggerChildren: 0.05, staggerDirection: -1 }, - }, -}; - -const mobileMenuItemVariants = { - open: { - y: 0, - opacity: 1, - transition: { - ease: "easeOut", - y: { stiffness: 1000, velocity: -100 }, - }, - }, - closed: { - y: 50, - opacity: 0, - transition: { - ease: "easeIn", - y: { stiffness: 1000 }, - }, - }, -}; - -const mobileMenuButtonsVariants = { - open: { - opacity: 1, - transition: { delay: 0.4, duration: 0.4 }, - }, - closed: { - opacity: 0, - transition: { delay: 0 }, - }, -}; - -const headerAnimationVariants = { - show: { - top: 0, - transition: { ease: "easeOut", stiffness: 100 }, - }, - hide: { - top: -88, - }, -}; - -interface MobileMenuItemProps { - name: string; - href: string; - index: number; - isCurrent: boolean; - color: string; -} - -const MobileMenuItem: React.FC = ({ - name, - href, - color, - isCurrent, -}) => { - return ( - - - {name} - {isCurrent && ( - - Current page - - - )} - - - ); -}; - -export interface HeaderButtonProps { - href?: string; - target?: "_blank" | "_self" | "_parent" | "_top"; - title: string; - onClick?: () => void; - disabled?: boolean; - className?: string; -} - -export interface HeaderProps extends ComponentPropsWithoutRef<"div"> { - brand?: { - name: string; - href: string; - logo: string; - showTitle?: boolean; - rounded?: boolean; - }; - navigation: { name: string; href: string }[]; - buttons?: HeaderButtonProps[]; - color?: string; - current?: string | number; -} - -export const Header = forwardRef( - ( - { - navigation, - brand = { - logo: "/", - href: "/", - name: "/", - }, - current, - color, - buttons, - }: HeaderProps, - ref, - ) => { - const [isScrolled, setIsScrolled] = useState(false); - const [lastYPosition, setLastYPosition] = useState(0); - const [isHeaderShown, setIsHeaderShown] = useState(true); - const isWide = useIsWide(); - - const { scrollY } = useScroll(); - const [isMobileMenuOpen, toggleMobileMenuOpen] = useToggle(false); - - const headerHeight = 88; - - useLockBodyScroll(isMobileMenuOpen); - - useMotionValueEvent(scrollY, "change", (latest) => { - setIsScrolled(latest > 10); - if (!isMobileMenuOpen) { - setIsHeaderShown( - latest < headerHeight || latest < lastYPosition, - ); - setLastYPosition(latest); - } - }); - - return ( - - - toggleMobileMenuOpen()} /> - - - {brand.name} - {brand.showTitle && ( - - {brand.name} - - )} - - - - - {navigation.map((item, index) => { - const _color = color || ""; - const isCurrent = - (typeof current === "string" && - item.href === current) || - (typeof current === "number" && - index === current); - return ( - - ); - })} - {buttons?.length && ( - - {buttons?.map((buttonProps) => { - return buttonProps.href ? ( - - - - ) : ( - - ); - })} - - )} - - - -
- {navigation.map((item, index) => { - const _color = color; - const isCurrent = - (typeof current === "string" && - item.href === current) || - (typeof current === "number" && - index === current); - return ( - - {item.name} - {isCurrent ? ( - - - - ) : ( - - - - )} - - ); - })} -
- -
- {buttons?.map((buttonProps) => { - return buttonProps.href ? ( - - - - ) : ( - - ); - })} -
- -
- - - ); - }, -); -Header.displayName = "Header"; diff --git a/src/components/nUI/MenuToggle.tsx b/src/components/nUI/MenuToggle.tsx deleted file mode 100644 index 9705685..0000000 --- a/src/components/nUI/MenuToggle.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import * as React from "react"; -import { SVGMotionProps, motion } from "motion/react"; - -const Path: React.FC> = (props) => ( - -); - -export interface MenuToggleProps { - toggle: () => void; -} - -export const MenuToggle: React.FC = ({ toggle }) => ( - -); diff --git a/src/components/nUI/hooks.tsx b/src/components/nUI/hooks.tsx deleted file mode 100644 index 79ed2eb..0000000 --- a/src/components/nUI/hooks.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import { useEffect, useState } from "react"; -import { useMedia } from "react-use"; - -export const useIsWide = () => { - const [isWide, setIsWide] = useState(false); - - const _isWide = useMedia("(min-width: 780px)", false); - - useEffect(() => { - setIsWide(_isWide); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [_isWide]); - - return isWide; -}; diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx new file mode 100644 index 0000000..d09a695 --- /dev/null +++ b/src/components/ui/button.tsx @@ -0,0 +1,57 @@ +import * as React from "react"; +import { Slot } from "@radix-ui/react-slot"; +import { cva, type VariantProps } from "class-variance-authority"; + +import { cn } from "@/lib/utils"; + +const buttonVariants = cva( + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", + { + 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 border-input bg-background 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", + }, + }, +); + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean; +} + +const Button = React.forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button"; + return ( + + ); + }, +); +Button.displayName = "Button"; + +export { Button, buttonVariants }; diff --git a/src/components/ui/src/components/ui/button.tsx b/src/components/ui/src/components/ui/button.tsx new file mode 100644 index 0000000..2adaf00 --- /dev/null +++ b/src/components/ui/src/components/ui/button.tsx @@ -0,0 +1,59 @@ +import * as React from "react"; +import { Slot } from "@radix-ui/react-slot"; +import { cva, type VariantProps } from "class-variance-authority"; + +import { cn } from "@/lib/utils"; + +const buttonVariants = cva( + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", + { + variants: { + variant: { + default: + "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90", + destructive: + "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", + outline: + "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50", + secondary: + "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80", + ghost: + "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-9 px-4 py-2 has-[>svg]:px-3", + sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5", + lg: "h-10 rounded-md px-6 has-[>svg]:px-4", + icon: "size-9", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + }, +); + +function Button({ + className, + variant, + size, + asChild = false, + ...props +}: React.ComponentProps<"button"> & + VariantProps & { + asChild?: boolean; + }) { + const Comp = asChild ? Slot : "button"; + + return ( + + ); +} + +export { Button, buttonVariants }; diff --git a/src/components/vrm.tsx b/src/components/vrm.tsx index 168fe9c..3d525a5 100644 --- a/src/components/vrm.tsx +++ b/src/components/vrm.tsx @@ -6,213 +6,276 @@ import { GLTF, GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader"; import { AnimationAction } from "three"; import { VRMLoaderPlugin } from "@pixiv/three-vrm"; import { - VRMAnimationLoaderPlugin, - createVRMAnimationClip, + VRMAnimationLoaderPlugin, + createVRMAnimationClip, } from "@pixiv/three-vrm-animation"; import { AnimationMixer, LoopOnce, LoopRepeat } from "three"; import { PiPlayPause, PiRepeat } from "react-icons/pi"; const animations = [ - { - url: "https://cdn.mikn.dev/vroid/shikanoko.vrma", - loop: true, - percentage: 10, - }, - { url: "https://cdn.mikn.dev/vroid/hi.vrma", loop: false, percentage: 50 }, - { - url: "https://cdn.mikn.dev/vroid/uishig.vrma", - loop: false, - percentage: 10, - }, - { - url: "https://cdn.mikn.dev/vroid/tetoris.vrma", - loop: false, - percentage: 10, - }, - { - url: "https://cdn.mikn.dev/vroid/telepathy.vrma", - loop: false, - percentage: 10, - }, - { - url: "https://cdn.mikn.dev/vroid/soware.vrma", - loop: false, - percentage: 10, - }, + { + url: "https://cdn.mikn.dev/vroid/shikanoko.vrma", + loop: true, + percentage: 10, + }, + { url: "https://cdn.mikn.dev/vroid/hi.vrma", loop: false, percentage: 50 }, + { + url: "https://cdn.mikn.dev/vroid/uishig.vrma", + loop: false, + percentage: 10, + }, + { + url: "https://cdn.mikn.dev/vroid/tetoris.vrma", + loop: false, + percentage: 10, + }, + { + url: "https://cdn.mikn.dev/vroid/telepathy.vrma", + loop: false, + percentage: 10, + }, + { + url: "https://cdn.mikn.dev/vroid/soware.vrma", + loop: false, + percentage: 10, + }, ]; export const VRMModel: FC<{ - vrm: import("@pixiv/three-vrm").VRM | null; - mixer: AnimationMixer | null; -}> = ({ vrm, mixer }) => { - useFrame(({ clock }, delta) => { - if (vrm) { - vrm.scene.position.set(0, -4.2, 0); - vrm.scene.scale.set(6.5, 5, 5); - vrm.scene.rotation.y = Math.PI; - vrm.expressionManager?.setValue("neutral", 1); - - vrm.update(delta); - } - if (mixer) { - mixer.update(delta); - } - }); - - return vrm ? : null; + vrm: import("@pixiv/three-vrm").VRM | null; + mixer: AnimationMixer | null; + enableLookAt: boolean; + mousePosition: { x: number; y: number }; +}> = ({ vrm, mixer, enableLookAt, mousePosition }) => { + useFrame(({ clock }, delta) => { + if (vrm) { + vrm.scene.position.set(0, -4.2, 0); + vrm.scene.scale.set(6.5, 5, 5); + vrm.scene.rotation.y = Math.PI; + vrm.expressionManager?.setValue("neutral", 1); + + // Enable eye tracking if animation is done + if (enableLookAt && vrm.lookAt) { + // Convert mouse position to 3D world coordinates + const target = { + x: mousePosition.x * 2, + y: mousePosition.y * 2 + 0.5, + z: 2, + }; + // Use the lookAt method to set the target position + try { + //@ts-ignore + vrm.lookAt.lookAt(target); + } catch (error) { + // Silently handle if lookAt is not available + } + + // Also rotate the head slightly to match + const headBone = vrm.humanoid.getNormalizedBoneNode("head"); + if (headBone) { + // Apply subtle head rotation based on mouse position + const headRotationX = mousePosition.y * 0.3; // Up/down + const headRotationY = mousePosition.x * 0.3; // Left/right + + // Smoothly interpolate to the target rotation + headBone.rotation.x += (headRotationX - headBone.rotation.x) * 0.1; + headBone.rotation.y += (headRotationY - headBone.rotation.y) * 0.1; + } + } + + vrm.update(delta); + } + if (mixer) { + mixer.update(delta); + } + }); + + return vrm ? : null; }; export function VRM() { - const [vrm, setVrm] = useState(null); - const [mixer, setMixer] = useState(null); - const [isLoaded, setIsLoaded] = useState(false); - const actionRef = useRef(null); - - useEffect(() => { - const loader = new GLTFLoader(); - loader.register((parser: any) => new VRMLoaderPlugin(parser)); - loader.register((parser: any) => new VRMAnimationLoaderPlugin(parser)); - - const loadModel = () => { - return new Promise( - (resolve, reject) => { - loader.load( - "https://cdn.mikn.dev/vroid/mikan.dev(kyonyu).vrm", - (gltf: GLTF) => { - const loadedVrm = gltf.userData.vrm; - setVrm(loadedVrm); - resolve(loadedVrm); - }, - undefined, - (error: Error) => { - console.error( - "An error occurred while loading the model:", - error, - ); - reject(error); - }, - ); - }, - ); - }; - - function pickAnimation() { - const total = animations.reduce( - (sum, anim) => sum + anim.percentage, - 0, - ); - const rand = Math.random() * total; - let acc = 0; - for (const anim of animations) { - acc += anim.percentage; - if (rand < acc) return anim; - } - return animations[0]; // fallback - } - - const loadAnimation = (loadedVrm: import("@pixiv/three-vrm").VRM) => { - const { url, loop } = pickAnimation(); - - loader.load( - url, - (gltf: GLTF) => { - const vrmAnimations = gltf.userData.vrmAnimations; - if (vrmAnimations && vrmAnimations.length > 0) { - if (loadedVrm && loadedVrm.humanoid) { - const animationClip = createVRMAnimationClip( - vrmAnimations[0], - loadedVrm, - ); - const animationMixer = new AnimationMixer( - loadedVrm.scene, - ); - const action = - animationMixer.clipAction(animationClip); - - if (loop) { - action.setLoop(LoopRepeat, Infinity); - } else { - action.setLoop(LoopOnce, 1); - action.clampWhenFinished = true; - } - - action.play(); - setMixer(animationMixer); - actionRef.current = action; - } else { - console.error( - "VRM model or humanoid is not loaded correctly.", - ); - } - } - }, - undefined, - (error: Error) => { - console.error( - "An error occurred while loading the animation:", - error, - ); - }, - ); - }; - - loadModel() - .then((loadedVrm) => { - setIsLoaded(true); - loadAnimation(loadedVrm); - }) - .catch((error) => { - console.error("An error occurred:", error); - }); - }, []); - - return ( -
-
- {!isLoaded ? ( -
- -
- ) : ( - - - - - - - )} -
-
- { - if (!actionRef.current) return; - if (actionRef.current?.paused) { - actionRef.current.paused = false; - } else { - actionRef.current.paused = true; - } - }} - > - Pause - - { - if (actionRef.current) { - actionRef.current.reset(); - actionRef.current.paused = false; - actionRef.current.play(); - } - }} - > - Restart - -
-
- ); + const [vrm, setVrm] = useState(null); + const [mixer, setMixer] = useState(null); + const [isLoaded, setIsLoaded] = useState(false); + const [enableLookAt, setEnableLookAt] = useState(false); + const [mousePosition, setMousePosition] = useState({ x: 0, y: 0 }); + const actionRef = useRef(null); + const isLoopingRef = useRef(false); + const containerRef = useRef(null); + + // Global mouse tracking + useEffect(() => { + const handleGlobalMouseMove = (e: MouseEvent) => { + if (!containerRef.current) return; + + const rect = containerRef.current.getBoundingClientRect(); + const centerX = rect.left + rect.width / 2; + const centerY = rect.top + rect.height / 2; + + // Calculate normalized position relative to the container center + const x = (e.clientX - centerX) / rect.width; + const y = -(e.clientY - centerY) / rect.height; + + setMousePosition({ x, y }); + }; + + window.addEventListener("mousemove", handleGlobalMouseMove); + + return () => { + window.removeEventListener("mousemove", handleGlobalMouseMove); + }; + }, []); + + useEffect(() => { + const loader = new GLTFLoader(); + loader.register((parser: any) => new VRMLoaderPlugin(parser)); + loader.register((parser: any) => new VRMAnimationLoaderPlugin(parser)); + + const loadModel = () => { + return new Promise((resolve, reject) => { + loader.load( + "https://cdn.mikn.dev/vroid/mikan.dev(kyonyu).vrm", + (gltf: GLTF) => { + const loadedVrm = gltf.userData.vrm; + setVrm(loadedVrm); + resolve(loadedVrm); + }, + undefined, + (error: Error) => { + console.error("An error occurred while loading the model:", error); + reject(error); + }, + ); + }); + }; + + function pickAnimation() { + const total = animations.reduce((sum, anim) => sum + anim.percentage, 0); + const rand = Math.random() * total; + let acc = 0; + for (const anim of animations) { + acc += anim.percentage; + if (rand < acc) return anim; + } + return animations[0]; // fallback + } + + const loadAnimation = (loadedVrm: import("@pixiv/three-vrm").VRM) => { + const { url, loop } = pickAnimation(); + isLoopingRef.current = loop; + + loader.load( + url, + (gltf: GLTF) => { + const vrmAnimations = gltf.userData.vrmAnimations; + if (vrmAnimations && vrmAnimations.length > 0) { + if (loadedVrm && loadedVrm.humanoid) { + const animationClip = createVRMAnimationClip( + vrmAnimations[0], + loadedVrm, + ); + const animationMixer = new AnimationMixer(loadedVrm.scene); + const action = animationMixer.clipAction(animationClip); + + if (loop) { + action.setLoop(LoopRepeat, Infinity); + } else { + action.setLoop(LoopOnce, 1); + action.clampWhenFinished = true; + + // Enable eye tracking when animation finishes + animationMixer.addEventListener("finished", () => { + setEnableLookAt(true); + }); + } + + action.play(); + setMixer(animationMixer); + actionRef.current = action; + } else { + console.error("VRM model or humanoid is not loaded correctly."); + } + } + }, + undefined, + (error: Error) => { + console.error( + "An error occurred while loading the animation:", + error, + ); + }, + ); + }; + + loadModel() + .then((loadedVrm) => { + setIsLoaded(true); + loadAnimation(loadedVrm); + }) + .catch((error) => { + console.error("An error occurred:", error); + }); + }, []); + + return ( +
+
+ {!isLoaded ? ( +
+ +
+ ) : ( + + + + + + + )} +
+
+ { + if (!actionRef.current) return; + if (actionRef.current?.paused) { + actionRef.current.paused = false; + } else { + actionRef.current.paused = true; + } + }} + > + Pause + + { + if (actionRef.current) { + actionRef.current.reset(); + actionRef.current.paused = false; + actionRef.current.play(); + // Disable look-at when restarting animation + if (!isLoopingRef.current) { + setEnableLookAt(false); + } + } + }} + > + Restart + +
+
+ ); } diff --git a/src/contexts/CursorToysContext.tsx b/src/contexts/CursorToysContext.tsx new file mode 100644 index 0000000..ef05a8e --- /dev/null +++ b/src/contexts/CursorToysContext.tsx @@ -0,0 +1,44 @@ +"use client"; +import { createContext, useContext, useState, ReactNode } from "react"; + +type SelectedToy = "none" | "spark" | "splash" | "custom" | "target"; + +interface CursorToysContextType { + selectedToy: SelectedToy; + setSelectedToy: (value: SelectedToy) => void; +} + +const CursorToysContext = createContext( + undefined, +); + +export const CursorToysProvider = ({ children }: { children: ReactNode }) => { + const [selectedToy, setSelectedToyState] = useState(() => { + if (typeof window !== "undefined") { + const stored = localStorage.getItem("cursorToy") as SelectedToy; + return stored && + ["none", "spark", "splash", "custom", "target"].includes(stored) + ? stored + : "none"; + } + return "none"; + }); + + const setSelectedToy = (value: SelectedToy) => { + setSelectedToyState(value); + localStorage.setItem("cursorToy", value); + }; + + return ( + + {children} + + ); +}; + +export const useCursorToys = () => { + const context = useContext(CursorToysContext); + if (!context) + throw new Error("useCursorToys must be used within CursorToysProvider"); + return context; +}; diff --git a/src/hooks/use-controlled-state.tsx b/src/hooks/use-controlled-state.tsx new file mode 100644 index 0000000..1417946 --- /dev/null +++ b/src/hooks/use-controlled-state.tsx @@ -0,0 +1,33 @@ +import * as React from "react"; + +interface CommonControlledStateProps { + value?: T; + defaultValue?: T; +} + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export function useControlledState( + props: CommonControlledStateProps & { + onChange?: (value: T, ...args: Rest) => void; + }, +): readonly [T, (next: T, ...args: Rest) => void] { + const { value, defaultValue, onChange } = props; + + const [state, setInternalState] = React.useState( + value !== undefined ? value : (defaultValue as T), + ); + + React.useEffect(() => { + if (value !== undefined) setInternalState(value); + }, [value]); + + const setState = React.useCallback( + (next: T, ...args: Rest) => { + setInternalState(next); + onChange?.(next, ...args); + }, + [onChange], + ); + + return [state, setState] as const; +} diff --git a/src/hooks/use-is-in-view.tsx b/src/hooks/use-is-in-view.tsx new file mode 100644 index 0000000..b15a16a --- /dev/null +++ b/src/hooks/use-is-in-view.tsx @@ -0,0 +1,25 @@ +import * as React from "react"; +import { useInView, type UseInViewOptions } from "motion/react"; + +interface UseIsInViewOptions { + inView?: boolean; + inViewOnce?: boolean; + inViewMargin?: UseInViewOptions["margin"]; +} + +function useIsInView( + ref: React.Ref, + options: UseIsInViewOptions = {}, +) { + const { inView, inViewOnce = false, inViewMargin = "0px" } = options; + const localRef = React.useRef(null); + React.useImperativeHandle(ref, () => localRef.current as T); + const inViewResult = useInView(localRef, { + once: inViewOnce, + margin: inViewMargin, + }); + const isInView = !inView || inViewResult; + return { ref: localRef, isInView }; +} + +export { useIsInView, type UseIsInViewOptions }; diff --git a/src/i18n/request.ts b/src/i18n/request.ts index 1d083d9..cd53451 100644 --- a/src/i18n/request.ts +++ b/src/i18n/request.ts @@ -1,35 +1,10 @@ import { getRequestConfig } from "next-intl/server"; -import { routing } from "./routing"; -export default getRequestConfig(async ({ requestLocale }) => { - let locale = await requestLocale; +export default getRequestConfig(async () => { + const locale = "en"; - if (!locale || !routing.locales.includes(locale as any)) { - locale = routing.defaultLocale; - } - - if (process.env.NODE_ENV === "development") { - const res = await fetch( - `${process.env.TOLGEE_API_URL}/v2/projects/${process.env.TOLGEE_PROJECT_ID}/translations/${locale}`, - { - headers: { - "x-api-key": `${process.env.TOLGEE_API_KEY}`, - }, - }, - ); - const data = await res.json(); - const messages = data[locale]; - - return { - locale, - messages, - }; - } - - const res = await fetch(`${process.env.I18N_PUBLIC_URL}/${locale}.json`); - - return { - locale, - messages: await res.json(), - }; + return { + locale, + messages: (await import(`../messages/${locale}.json`)).default, + }; }); diff --git a/src/i18n/routing.ts b/src/i18n/routing.ts index 63c0b5a..502a7ed 100644 --- a/src/i18n/routing.ts +++ b/src/i18n/routing.ts @@ -2,14 +2,14 @@ import { defineRouting } from "next-intl/routing"; import { createNavigation } from "next-intl/navigation"; export const routing = defineRouting({ - // A list of all locales that are supported - locales: ["en", "ja"], + // A list of all locales that are supported + locales: ["en", "ja"], - // Used when no locale matches - defaultLocale: "en", + // Used when no locale matches + defaultLocale: "en", }); // Lightweight wrappers around Next.js' navigation APIs // that will consider the routing configuration export const { Link, redirect, usePathname, useRouter, getPathname } = - createNavigation(routing); + createNavigation(routing); diff --git a/src/imgLoader.ts b/src/imgLoader.ts deleted file mode 100644 index e17bf20..0000000 --- a/src/imgLoader.ts +++ /dev/null @@ -1,19 +0,0 @@ -const normalizeSrc = (src: string) => { - return src.startsWith("/") ? src.slice(1) : src; -}; - -export default function cloudflareLoader({ - src, - width, - quality, -}: { src: string; width: number; quality?: number }) { - if (process.env.NODE_ENV === "development") { - return src; - } - const params = [`width=${width}`]; - if (quality) { - params.push(`quality=${quality}`); - } - const paramsString = params.join(","); - return `/cdn-cgi/image/${paramsString}/${normalizeSrc(src)}`; -} diff --git a/src/interfaces/CursorToys.ts b/src/interfaces/CursorToys.ts new file mode 100644 index 0000000..117b6df --- /dev/null +++ b/src/interfaces/CursorToys.ts @@ -0,0 +1,6 @@ +import { ReactNode } from "react"; + +export interface ICursorToys { + children?: ReactNode; + selectedToy?: "none" | "spark" | "splash" | "custom" | "target"; +} diff --git a/src/lib/get-strict-context.tsx b/src/lib/get-strict-context.tsx new file mode 100644 index 0000000..7bbe8d1 --- /dev/null +++ b/src/lib/get-strict-context.tsx @@ -0,0 +1,36 @@ +import * as React from "react"; + +function getStrictContext( + name?: string, +): readonly [ + ({ + value, + children, + }: { + value: T; + children?: React.ReactNode; + }) => React.JSX.Element, + () => T, +] { + const Context = React.createContext(undefined); + + const Provider = ({ + value, + children, + }: { + value: T; + children?: React.ReactNode; + }) => {children}; + + const useSafeContext = () => { + const ctx = React.useContext(Context); + if (ctx === undefined) { + throw new Error(`useContext must be used within ${name ?? "a Provider"}`); + } + return ctx; + }; + + return [Provider, useSafeContext] as const; +} + +export { getStrictContext }; diff --git a/src/lib/src/lib/utils.ts b/src/lib/src/lib/utils.ts new file mode 100644 index 0000000..a5ef193 --- /dev/null +++ b/src/lib/src/lib/utils.ts @@ -0,0 +1,6 @@ +import { clsx, type ClassValue } from "clsx"; +import { twMerge } from "tailwind-merge"; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} diff --git a/src/lib/utils.ts b/src/lib/utils.ts new file mode 100644 index 0000000..a5ef193 --- /dev/null +++ b/src/lib/utils.ts @@ -0,0 +1,6 @@ +import { clsx, type ClassValue } from "clsx"; +import { twMerge } from "tailwind-merge"; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} diff --git a/src/messages/en.json b/src/messages/en.json index c6034c3..cdb8f8a 100644 --- a/src/messages/en.json +++ b/src/messages/en.json @@ -1,65 +1,65 @@ { - "home": { - "creating-cool": "Creating cool", - "makeLifeEasier": "to make life easier.", - "stuff": "stuff", - "apps": "Apps", - "tools": "Tools", - "bots": "Bots", - "mainBlurb1": "We create open-source solutions for those itches in life that need scratching.", - "mainBlurb2": "Enrich your life without breaking the bank.", - "takeLook": "Take a look", - "learnMore": "Learn More", - "infoTitle": "what makes us special", - "infoBlurb": "The MikanDev Difference", - "OSSonOSS": "Open Source with Open Source", - "OSSonOSSBlurb": "We believe in the power of open source. All of our projects are free to self-host, modify and contribute to. Any third-party services we use are also open source.", - "partOfPage": "the very page you're reading is open source!", - "viewOnGH": "View on GitHub", - "SimpleNCheap": "Designed with simplicity for ultimate cost-effectiveness", - "SimpleNCheapBlurb": "We don't believe in overcomplicating things. Our projects are designed to be simple to use, and aren't held up by expensive third-party services. The savings are passed on to you!", - "monthlyCost": "Avg. Monthly running cost", - "MAUBilled": "MAU billed services used", - "despite": "Despite...", - "monthlyBandwidth": "Avg. Monthly bandwidth usage", - "mainServices": "Main services", - "monthlyUptime": "Avg. Monthly uptime", - "HowSoCheap": "How so cheap?", - "SelfFunded": "100% Self-funded", - "SelfFundedBlurb": "We don't have any investors or VC to answer to, so we can decide when we make a profit. We're here to make cool stuff, not money.", - "WorkWithBest": "Working with the best", - "WorkWithBestBlurb": "We partner with other cool organizations and help get their cool stuff out there. We're all about the community :3", - "workWithMe": "Work with us!", - "NoWait": "What's more to say?", - "NoWaitBlurb": "Check out our projects and see if there's something you like!" - }, - "nav": { - "support": "Support", - "docs": "Docs", - "solutions": "Solutions", - "legal": "Legal", - "payments": "Payment Center", - "blog": "Blog", - "discord": "Discord", - "contact": "Contact Us", - "terms": "Terms of Service", - "privacy": "Privacy Policy", - "jp-payments": "特定商取引法に基づく表記", - "gdpr": "GDPR Compliance", - "myAccount": "My Account", - "resources": "Resources", - "cookieConsent": "We use cookies for analytics and making stuff work. By clicking 'mmmmmmm cookies 🍪', you agree to our use of cookies.", - "accept": "mmmmmmm cookies 🍪" - }, - "contact": { - "title": "Contact Us", - "mail": "Email", - "phone": "Phone (JP Only)*", - "discord": "Discord", - "join": "Join our Discord", - "general-support": "General Support", - "billing-support": "Billing Support", - "abuse-reports": "Abuse Reports", - "phone-disclaimer": "*Calling this number from outside of Japan may result in high charges. Please use the email or Discord for support." - } + "home": { + "creating-cool": "Creating cool", + "makeLifeEasier": "to make life easier.", + "stuff": "stuff", + "apps": "Apps", + "tools": "Tools", + "bots": "Bots", + "mainBlurb1": "We create open-source solutions for those itches in life that need scratching.", + "mainBlurb2": "Enrich your life without breaking the bank.", + "takeLook": "Take a look", + "learnMore": "Learn More", + "infoTitle": "what makes us special", + "infoBlurb": "The MikanDev Difference", + "OSSonOSS": "Open Source with Open Source", + "OSSonOSSBlurb": "We believe in the power of open source. All of our projects are free to self-host, modify and contribute to. Any third-party services we use are also open source.", + "partOfPage": "the very page you're reading is open source!", + "viewOnGH": "View on GitHub", + "SimpleNCheap": "Designed with simplicity for ultimate cost-effectiveness", + "SimpleNCheapBlurb": "We don't believe in overcomplicating things. Our projects are designed to be simple to use, and aren't held up by expensive third-party services. The savings are passed on to you!", + "monthlyCost": "Avg. Monthly running cost", + "MAUBilled": "MAU billed services used", + "despite": "Despite...", + "monthlyBandwidth": "Avg. Monthly bandwidth usage", + "mainServices": "Main services", + "monthlyUptime": "Avg. Monthly uptime", + "HowSoCheap": "How so cheap?", + "SelfFunded": "100% Self-funded", + "SelfFundedBlurb": "We don't have any investors or VC to answer to, so we can decide when we make a profit. We're here to make cool stuff, not money.", + "WorkWithBest": "Working with the best", + "WorkWithBestBlurb": "We partner with other cool organizations and help get their cool stuff out there. We're all about the community :3", + "workWithMe": "Work with us!", + "NoWait": "What's more to say?", + "NoWaitBlurb": "Check out our projects and see if there's something you like!" + }, + "nav": { + "support": "Support", + "docs": "Docs", + "solutions": "Solutions", + "legal": "Legal", + "payments": "Payment Center", + "blog": "Blog", + "discord": "Discord", + "contact": "Contact Us", + "terms": "Terms of Service", + "privacy": "Privacy Policy", + "jp-payments": "特定商取引法に基づく表記", + "gdpr": "GDPR Compliance", + "myAccount": "My Account", + "resources": "Resources", + "cookieConsent": "We use cookies for analytics and making stuff work. By clicking 'mmmmmmm cookies 🍪', you agree to our use of cookies.", + "accept": "mmmmmmm cookies 🍪" + }, + "contact": { + "title": "Contact Us", + "mail": "Email", + "phone": "Phone (JP Only)*", + "discord": "Discord", + "join": "Join our Discord", + "general-support": "General Support", + "billing-support": "Billing Support", + "abuse-reports": "Abuse Reports", + "phone-disclaimer": "*Calling this number from outside of Japan may result in high charges. Please use the email or Discord for support." + } } diff --git a/src/messages/ja.json b/src/messages/ja.json index 54bb18f..abbc9d4 100644 --- a/src/messages/ja.json +++ b/src/messages/ja.json @@ -1,65 +1,65 @@ { - "home": { - "creating-cool": "生活を豊かにする", - "makeLifeEasier": "を作っています。", - "stuff": "ヤツ", - "apps": "アプリ", - "tools": "ツール", - "bots": "Bot", - "mainBlurb1": "日常生活で出会う問題に対するオープンソースの解決策を作ります。", - "mainBlurb2": "大金持ちでなくても人生を豊かに。", - "takeLook": "見てみよう", - "learnMore": "もっと知る", - "infoTitle": "私達の秘訣", - "infoBlurb": "「The MikanDev Difference」", - "OSSonOSS": "オープンソース上のオープンソース", - "OSSonOSSBlurb": "私達はオープンソースの力を信じています。私達のプロジェクトは全て自己ホスト、修正、貢献が可能です。使用するサードパーティサービスもオープンソースです。", - "partOfPage": "このページもなんとオープンソースです!", - "viewOnGH": "GitHubで見てみる", - "SimpleNCheap": "シンプルさを追求し生まれた究極ののコストパフォマンス", - "SimpleNCheapBlurb": "私達は複雑なことを好みません。私達のプロジェクトは使いやすさを重視し、高額なサードパーティサービスに依存しません。その節約分はあなたに還元されます!", - "monthlyCost": "平均月額運用費用", - "MAUBilled": "従量課金サービス使用", - "despite": "にもかかわらず...", - "monthlyBandwidth": "平均月間帯域幅使用量", - "mainServices": "主要サービス", - "monthlyUptime": "平均月間稼働率", - "HowSoCheap": "なぜこんなに安いの?", - "SelfFunded": "100%自己資金", - "SelfFundedBlurb": "私達は投資家やVCに責任を負う必要がないため、利益を上げるタイミングを自分たちで決めることができます。私達はお金を稼ぐためではなく、面白いものを作るためにここにいます。", - "WorkWithBest": "最高の人たちと一緒に", - "WorkWithBestBlurb": "私達は他の素敵な組織と提携し、彼らの素晴らしいものを世に出すお手伝いをします。私達はコミュニティに全力を注いでいます!", - "workWithMe": "私たちと一緒にやろう!", - "NoWait": "これ以上言うことはありません。", - "NoWaitBlurb": "私たちのプロジェクトをチェックして、気に入るものがあるかどうかを見てください!" - }, - "nav": { - "support": "サポート", - "docs": "ドキュメント", - "solutions": "ソリューション", - "legal": "法的条約", - "payments": "支払いセンター", - "blog": "ブログ", - "discord": "Discord", - "contact": "お問い合わせ", - "terms": "利用規約", - "privacy": "プライバシーポリシー", - "jp-payments": "特定商取引法に基づく表記", - "gdpr": "GDPRコンプライアンス", - "myAccount": "マイアカウント", - "resources": "リソース", - "cookieConsent": "そこの君!このサイトはCookieを使ってるぞ!!いいよね?", - "accept": "いいね!" - }, - "contact": { - "title": "お問い合わせ", - "mail": "メール", - "phone": "電話 (日本のみ)*", - "discord": "Discord", - "join": "Discordに参加", - "general-support": "一般サポート", - "billing-support": "請求に関する問い合わせ", - "abuse-reports": "不正行為の報告", - "phone-disclaimer": "※日本国内の電話番号のみ対応しています。" - } + "home": { + "creating-cool": "生活を豊かにする", + "makeLifeEasier": "を作っています。", + "stuff": "ヤツ", + "apps": "アプリ", + "tools": "ツール", + "bots": "Bot", + "mainBlurb1": "日常生活で出会う問題に対するオープンソースの解決策を作ります。", + "mainBlurb2": "大金持ちでなくても人生を豊かに。", + "takeLook": "見てみよう", + "learnMore": "もっと知る", + "infoTitle": "私達の秘訣", + "infoBlurb": "「The MikanDev Difference」", + "OSSonOSS": "オープンソース上のオープンソース", + "OSSonOSSBlurb": "私達はオープンソースの力を信じています。私達のプロジェクトは全て自己ホスト、修正、貢献が可能です。使用するサードパーティサービスもオープンソースです。", + "partOfPage": "このページもなんとオープンソースです!", + "viewOnGH": "GitHubで見てみる", + "SimpleNCheap": "シンプルさを追求し生まれた究極ののコストパフォマンス", + "SimpleNCheapBlurb": "私達は複雑なことを好みません。私達のプロジェクトは使いやすさを重視し、高額なサードパーティサービスに依存しません。その節約分はあなたに還元されます!", + "monthlyCost": "平均月額運用費用", + "MAUBilled": "従量課金サービス使用", + "despite": "にもかかわらず...", + "monthlyBandwidth": "平均月間帯域幅使用量", + "mainServices": "主要サービス", + "monthlyUptime": "平均月間稼働率", + "HowSoCheap": "なぜこんなに安いの?", + "SelfFunded": "100%自己資金", + "SelfFundedBlurb": "私達は投資家やVCに責任を負う必要がないため、利益を上げるタイミングを自分たちで決めることができます。私達はお金を稼ぐためではなく、面白いものを作るためにここにいます。", + "WorkWithBest": "最高の人たちと一緒に", + "WorkWithBestBlurb": "私達は他の素敵な組織と提携し、彼らの素晴らしいものを世に出すお手伝いをします。私達はコミュニティに全力を注いでいます!", + "workWithMe": "私たちと一緒にやろう!", + "NoWait": "これ以上言うことはありません。", + "NoWaitBlurb": "私たちのプロジェクトをチェックして、気に入るものがあるかどうかを見てください!" + }, + "nav": { + "support": "サポート", + "docs": "ドキュメント", + "solutions": "ソリューション", + "legal": "法的条約", + "payments": "支払いセンター", + "blog": "ブログ", + "discord": "Discord", + "contact": "お問い合わせ", + "terms": "利用規約", + "privacy": "プライバシーポリシー", + "jp-payments": "特定商取引法に基づく表記", + "gdpr": "GDPRコンプライアンス", + "myAccount": "マイアカウント", + "resources": "リソース", + "cookieConsent": "そこの君!このサイトはCookieを使ってるぞ!!いいよね?", + "accept": "いいね!" + }, + "contact": { + "title": "お問い合わせ", + "mail": "メール", + "phone": "電話 (日本のみ)*", + "discord": "Discord", + "join": "Discordに参加", + "general-support": "一般サポート", + "billing-support": "請求に関する問い合わせ", + "abuse-reports": "不正行為の報告", + "phone-disclaimer": "※日本国内の電話番号のみ対応しています。" + } } diff --git a/src/middleware.ts b/src/middleware.ts deleted file mode 100644 index 38a46be..0000000 --- a/src/middleware.ts +++ /dev/null @@ -1,10 +0,0 @@ -import createMiddleware from "next-intl/middleware"; -import { routing } from "@/i18n/routing"; - -export default createMiddleware(routing); - -export const config = { - matcher: [ - "/((?!api|_next/static|_next/image|img|favicon.ico|sw.js|sitemap.xml|vroid*|98gas9mkeb.txt|robots.txt|opengraph-image.png).*)", - ], -}; diff --git a/src/public/_redirects b/src/public/_redirects new file mode 100644 index 0000000..e6a59c6 --- /dev/null +++ b/src/public/_redirects @@ -0,0 +1,23 @@ +# Redirect root to English +/ /en 302 + +# Don't redirect existing locale paths +/en /en 200 +/ja /ja 200 +/en.txt /en.txt 200 +/ja.txt /ja.txt 200 +/en/* /en/:splat 200 +/ja/* /ja/:splat 200 + +# Static assets and special paths that should not be redirected +/_next/* /_next/:splat 200 +/.well-known/* /.well-known/:splat 200 +/img/* /img/:splat 200 +/robots.txt /robots.txt 200 +/ads.txt /ads.txt 200 +/sitemap.xml /sitemap.xml 200 +/sitemap-0.xml /sitemap-0.xml 200 +/favicon.ico /favicon.ico 200 + +# Redirect all other paths to English version +/* /en/:splat 302 \ No newline at end of file diff --git a/tailwind.config.ts b/tailwind.config.ts index 2b2e786..8657b5a 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -1,37 +1,36 @@ import type { Config } from "tailwindcss"; const config: Config = { - content: [ - "./index.html", - "./pages/**/*.{js,ts,jsx,tsx,mdx}", - "./components/**/*.{js,ts,jsx,tsx,mdx}", - "./app/**/*.{js,ts,jsx,tsx,mdx}", - ], - theme: { - extend: { - colors: { - primary: "#ff9900", - "on-primary": "#ffffff", - secondary: "#ff7700", - "on-secondary": "#ffffff", - }, - animation: { - marquee: "marquee var(--duration) linear infinite", - "marquee-vertical": - "marquee-vertical var(--duration) linear infinite", - }, - keyframes: { - marquee: { - from: { transform: "translateX(0)" }, - to: { transform: "translateX(calc(-100% - var(--gap)))" }, - }, - "marquee-vertical": { - from: { transform: "translateY(0)" }, - to: { transform: "translateY(calc(-100% - var(--gap)))" }, - }, - }, - }, - }, - plugins: [], + content: [ + "./index.html", + "./pages/**/*.{js,ts,jsx,tsx,mdx}", + "./components/**/*.{js,ts,jsx,tsx,mdx}", + "./app/**/*.{js,ts,jsx,tsx,mdx}", + ], + theme: { + extend: { + colors: { + primary: "#ff9900", + "on-primary": "#ffffff", + secondary: "#ff7700", + "on-secondary": "#ffffff", + }, + animation: { + marquee: "marquee var(--duration) linear infinite", + "marquee-vertical": "marquee-vertical var(--duration) linear infinite", + }, + keyframes: { + marquee: { + from: { transform: "translateX(0)" }, + to: { transform: "translateX(calc(-100% - var(--gap)))" }, + }, + "marquee-vertical": { + from: { transform: "translateY(0)" }, + to: { transform: "translateY(calc(-100% - var(--gap)))" }, + }, + }, + }, + }, + plugins: [], }; export default config; diff --git a/tsconfig.json b/tsconfig.json index 59829b3..0ba7d3f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,36 +1,36 @@ { - "compilerOptions": { - "target": "es2017", - "lib": ["dom", "dom.iterable", "esnext"], - "allowJs": true, - "skipLibCheck": true, - "strict": true, - "noEmit": true, - "esModuleInterop": true, - "module": "esnext", - "moduleResolution": "bundler", - "resolveJsonModule": true, - "isolatedModules": true, - "jsx": "preserve", - "incremental": true, - "plugins": [ - { - "name": "next" - } - ], - "paths": { - "@/*": ["./src/*"] - } - }, - "include": [ - "next-env.d.ts", - "**/*.ts", - "**/*.tsx", - ".next/types/**/*.ts", - "nextra.config.jsx", - "theme.config.jsx", - "app/libraries/logto.js", - "app/ui/cobe.jsx" - ], - "exclude": ["node_modules", "sst.config.ts"] + "compilerOptions": { + "target": "ES2017", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": false, + "noEmit": true, + "incremental": true, + "module": "esnext", + "esModuleInterop": true, + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "react-jsx", + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./src/*"] + } + }, + "include": [ + "next-env.d.ts", + ".next/types/**/*.ts", + ".next/dev/types/**/*.ts", + "**/*.mts", + "**/*.ts", + "**/*.tsx", + ".next\\dev/types/**/*.ts", + ".next\\dev/types/**/*.ts" + ], + "exclude": ["node_modules"] } diff --git a/wrangler.jsonc b/wrangler.jsonc deleted file mode 100644 index 1ca1072..0000000 --- a/wrangler.jsonc +++ /dev/null @@ -1,45 +0,0 @@ -{ - "$schema": "node_modules/wrangler/config-schema.json", - "main": ".open-next/worker.js", - "name": "mikn-dev", - "compatibility_date": "2025-05-03", - "compatibility_flags": [ - // Enable Node.js API - // see https://developers.cloudflare.com/workers/configuration/compatibility-flags/#nodejs-compatibility-flag - "nodejs_compat", - // Allow to fetch URLs in your app - // see https://developers.cloudflare.com/workers/configuration/compatibility-flags/#global-fetch-strictly-public - "global_fetch_strictly_public" - ], - "assets": { - "directory": ".open-next/assets", - "binding": "ASSETS" - }, - "kv_namespaces": [ - { - "binding": "NEXT_INC_CACHE_KV", - "id": "914f30b5215d4d3c9dbae19952e042c5" - } - ], - "durable_objects": { - "bindings": [ - { - "name": "NEXT_CACHE_DO_QUEUE", - "class_name": "DOQueueHandler" - } - ] - }, - "migrations": [ - { - "tag": "v1", - "new_sqlite_classes": ["DOQueueHandler", "DOShardedTagCache"] - } - ], - "services": [ - { - "binding": "WORKER_SELF_REFERENCE", - // The service should match the "name" of your worker - "service": "mikn-dev" - } - ] -}