From 01edd57296c77d961f99936efdece11e130e3985 Mon Sep 17 00:00:00 2001 From: Severian Date: Sun, 19 Jan 2025 21:47:26 +0800 Subject: [PATCH] chore: initial transfer commit --- .gitignore | 2 + components.json | 21 + next-env.d.ts | 5 + package-lock.json | 2609 +++++++++++++++++++++++++++++ package.json | 40 + postcss.config.js | 6 + public/android-chrome-192x192.png | Bin 0 -> 7460 bytes public/android-chrome-512x512.png | Bin 0 -> 24185 bytes public/apple-touch-icon.png | Bin 0 -> 6651 bytes public/favicon-16x16.png | Bin 0 -> 410 bytes public/favicon-32x32.png | Bin 0 -> 848 bytes public/favicon.ico | Bin 0 -> 15406 bytes public/site.webmanifest | 1 + src/app/api/proxy/image/route.ts | 25 + src/app/api/proxy/route.ts | 190 +++ src/app/globals.css | 76 + src/app/layout.tsx | 36 + src/app/page.tsx | 413 +++++ src/components/ui/accordion.tsx | 55 + src/components/ui/button.tsx | 57 + src/components/ui/card.tsx | 76 + src/components/ui/collapsible.tsx | 9 + src/components/ui/dialog.tsx | 120 ++ src/components/ui/input.tsx | 22 + src/components/ui/separator.tsx | 29 + src/lib/png.ts | 240 +++ src/lib/utils.ts | 6 + sucker.config.js | 12 + sucker.js | 21 + tailwind.config.js | 76 + tsconfig.json | 29 + 31 files changed, 4176 insertions(+) create mode 100644 .gitignore create mode 100644 components.json create mode 100644 next-env.d.ts create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 postcss.config.js create mode 100644 public/android-chrome-192x192.png create mode 100644 public/android-chrome-512x512.png create mode 100644 public/apple-touch-icon.png create mode 100644 public/favicon-16x16.png create mode 100644 public/favicon-32x32.png create mode 100644 public/favicon.ico create mode 100644 public/site.webmanifest create mode 100644 src/app/api/proxy/image/route.ts create mode 100644 src/app/api/proxy/route.ts create mode 100644 src/app/globals.css create mode 100644 src/app/layout.tsx create mode 100644 src/app/page.tsx create mode 100644 src/components/ui/accordion.tsx create mode 100644 src/components/ui/button.tsx create mode 100644 src/components/ui/card.tsx create mode 100644 src/components/ui/collapsible.tsx create mode 100644 src/components/ui/dialog.tsx create mode 100644 src/components/ui/input.tsx create mode 100644 src/components/ui/separator.tsx create mode 100644 src/lib/png.ts create mode 100644 src/lib/utils.ts create mode 100644 sucker.config.js create mode 100644 sucker.js create mode 100644 tailwind.config.js create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1380c2e --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules +.next \ No newline at end of file diff --git a/components.json b/components.json new file mode 100644 index 0000000..275d416 --- /dev/null +++ b/components.json @@ -0,0 +1,21 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": false, + "tsx": true, + "tailwind": { + "config": "tailwind.config.js", + "css": "src/index.css", + "baseColor": "zinc", + "cssVariables": true, + "prefix": "" + }, + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "iconLibrary": "lucide" +} diff --git a/next-env.d.ts b/next-env.d.ts new file mode 100644 index 0000000..40c3d68 --- /dev/null +++ b/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information. diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..2376481 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2609 @@ +{ + "name": "request-interceptor", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "request-interceptor", + "version": "0.1.0", + "dependencies": { + "@radix-ui/react-accordion": "^1.2.2", + "@radix-ui/react-collapsible": "^1.1.2", + "@radix-ui/react-dialog": "^1.1.4", + "@radix-ui/react-separator": "^1.1.1", + "@radix-ui/react-slot": "^1.1.1", + "@types/react": "^18.2.39", + "@types/react-dom": "^18.2.17", + "axios": "^1.6.2", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "cors": "^2.8.5", + "crc-32": "^1.2.2", + "html2canvas": "^1.4.1", + "lucide-react": "^0.471.0", + "next": "^14.0.3", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "tailwind-merge": "^2.6.0", + "tailwindcss-animate": "^1.0.7", + "typescript": "^5.3.2" + }, + "devDependencies": { + "@types/cors": "^2.8.17", + "@types/node": "^22.10.5", + "autoprefixer": "^10.4.16", + "postcss": "^8.4.31", + "tailwindcss": "^3.3.5" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "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" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@next/env": { + "version": "14.2.23", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.23.tgz", + "integrity": "sha512-CysUC9IO+2Bh0omJ3qrb47S8DtsTKbFidGm6ow4gXIG6reZybqxbkH2nhdEm1tC8SmgzDdpq3BIML0PWsmyUYA==" + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "14.2.23", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.23.tgz", + "integrity": "sha512-WhtEntt6NcbABA8ypEoFd3uzq5iAnrl9AnZt9dXdO+PZLACE32z3a3qA5OoV20JrbJfSJ6Sd6EqGZTrlRnGxQQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "14.2.23", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.23.tgz", + "integrity": "sha512-vwLw0HN2gVclT/ikO6EcE+LcIN+0mddJ53yG4eZd0rXkuEr/RnOaMH8wg/sYl5iz5AYYRo/l6XX7FIo6kwbw1Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "14.2.23", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.23.tgz", + "integrity": "sha512-uuAYwD3At2fu5CH1wD7FpP87mnjAv4+DNvLaR9kiIi8DLStWSW304kF09p1EQfhcbUI1Py2vZlBO2VaVqMRtpg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "14.2.23", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.23.tgz", + "integrity": "sha512-Mm5KHd7nGgeJ4EETvVgFuqKOyDh+UMXHXxye6wRRFDr4FdVRI6YTxajoV2aHE8jqC14xeAMVZvLqYqS7isHL+g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "14.2.23", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.23.tgz", + "integrity": "sha512-Ybfqlyzm4sMSEQO6lDksggAIxnvWSG2cDWnG2jgd+MLbHYn2pvFA8DQ4pT2Vjk3Cwrv+HIg7vXJ8lCiLz79qoQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "14.2.23", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.23.tgz", + "integrity": "sha512-OSQX94sxd1gOUz3jhhdocnKsy4/peG8zV1HVaW6DLEbEmRRtUCUQZcKxUD9atLYa3RZA+YJx+WZdOnTkDuNDNA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "14.2.23", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.23.tgz", + "integrity": "sha512-ezmbgZy++XpIMTcTNd0L4k7+cNI4ET5vMv/oqNfTuSXkZtSA9BURElPFyarjjGtRgZ9/zuKDHoMdZwDZIY3ehQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "14.2.23", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.23.tgz", + "integrity": "sha512-zfHZOGguFCqAJ7zldTKg4tJHPJyJCOFhpoJcVxKL9BSUHScVDnMdDuOU1zPPGdOzr/GWxbhYTjyiEgLEpAoFPA==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "14.2.23", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.23.tgz", + "integrity": "sha512-xCtq5BD553SzOgSZ7UH5LH+OATQihydObTrCTvVzOro8QiWYKdBVwcB2Mn2MLMo6DGW9yH1LSPw7jS7HhgJgjw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@radix-ui/primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz", + "integrity": "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==" + }, + "node_modules/@radix-ui/react-accordion": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.2.2.tgz", + "integrity": "sha512-b1oh54x4DMCdGsB4/7ahiSrViXxaBwRPotiZNnYXjLha9vfuURSAZErki6qjDoSIV0eXx5v57XnTGVtGwnfp2g==", + "dependencies": { + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-collapsible": "1.1.2", + "@radix-ui/react-collection": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-direction": "1.1.0", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-use-controllable-state": "1.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" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collapsible": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.2.tgz", + "integrity": "sha512-PliMB63vxz7vggcyq0IxNYk8vGDrLXVWw4+W4B8YnwI1s18x7YZYqlG9PLX7XxAJUi0g2DxP4XKJMFHh/iVh9A==", + "dependencies": { + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-presence": "1.1.2", + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-use-controllable-state": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.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" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.1.tgz", + "integrity": "sha512-LwT3pSho9Dljg+wY2KN2mrrh6y3qELfftINERIzBUO9e0N+t0oMTyn3k9iv+ZqgrwGkRnLpNJrsMv9BZlt2yuA==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-slot": "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" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz", + "integrity": "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.1.tgz", + "integrity": "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.4.tgz", + "integrity": "sha512-Ur7EV1IwQGCyaAuyDRiOLA5JIUZxELJljF+MbM/2NC0BYwfuRrbpS30BiQBJrVruscgUkieKkqXYDOoByaxIoA==", + "dependencies": { + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-context": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.3", + "@radix-ui/react-focus-guards": "1.1.1", + "@radix-ui/react-focus-scope": "1.1.1", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-portal": "1.1.3", + "@radix-ui/react-presence": "1.1.2", + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-slot": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.1.0", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "^2.6.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" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-direction": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.0.tgz", + "integrity": "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.3.tgz", + "integrity": "sha512-onrWn/72lQoEucDmJnr8uczSNTujT0vJnA/X5+3AkChVPowr8n1yvIKIabhWyMQeMvvmdpsvcyDqx3X1LEXCPg==", + "dependencies": { + "@radix-ui/primitive": "1.1.1", + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-escape-keydown": "1.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" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-guards": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz", + "integrity": "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.1.tgz", + "integrity": "sha512-01omzJAYRxXdG2/he/+xy+c8a8gCydoQ1yOxnWNcRhrrBW5W+RQJ22EK1SaO8tb3WoUsuEw7mJjBozPzihDFjA==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-use-callback-ref": "1.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" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-id": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz", + "integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.3.tgz", + "integrity": "sha512-NciRqhXnGojhT93RPyDaMPfLH3ZSl4jjIFbZQ1b/vxvZEdHsBZ49wP9w8L3HzUQwep01LcWtkUvm0OVB5JAHTw==", + "dependencies": { + "@radix-ui/react-primitive": "2.0.1", + "@radix-ui/react-use-layout-effect": "1.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" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.2.tgz", + "integrity": "sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.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" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz", + "integrity": "sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==", + "dependencies": { + "@radix-ui/react-slot": "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" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-separator": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.1.tgz", + "integrity": "sha512-RRiNRSrD8iUiXriq/Y5n4/3iE8HzqgLHsusUSg5jVpU2+3tqcUFPJXHDymwEypunc2sWxDUS3UC+rkZRlHedsw==", + "dependencies": { + "@radix-ui/react-primitive": "2.0.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" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.1.tgz", + "integrity": "sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", + "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", + "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz", + "integrity": "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", + "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==" + }, + "node_modules/@swc/helpers": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", + "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", + "dependencies": { + "@swc/counter": "^0.1.3", + "tslib": "^2.4.0" + } + }, + "node_modules/@types/cors": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/node": { + "version": "22.10.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.5.tgz", + "integrity": "sha512-F8Q+SeGimwOo86fiovQh8qiXfFEh2/ocYv7tU5pJ3EXMSSxk1Joj5wefpFK2fHTf/N6HKGSxIDBT9f3gCxXPkQ==", + "dev": true, + "dependencies": { + "undici-types": "~6.20.0" + } + }, + "node_modules/@types/prop-types": { + "version": "15.7.14", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", + "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==" + }, + "node_modules/@types/react": { + "version": "18.3.18", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz", + "integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.5", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.5.tgz", + "integrity": "sha512-P4t6saawp+b/dFrUr2cvkVsfvPguwsxtH6dNIYRllMsefqFzkZk5UIjzyDOv5g1dXIPdG4Sp1yCR4Z6RCUsG/Q==", + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, + "node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + }, + "node_modules/aria-hidden": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz", + "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/autoprefixer": { + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", + "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "browserslist": "^4.23.3", + "caniuse-lite": "^1.0.30001646", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/axios": { + "version": "1.7.9", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", + "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001692", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001692.tgz", + "integrity": "sha512-A95VKan0kdtrsnMubMKxEKUKImOPSuCpYgxSQBo036P5YYgVIcOYJEgt/txJWqObiRQeISNCfef9nvlQ0vbV7A==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/class-variance-authority": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", + "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", + "dependencies": { + "clsx": "^2.1.1" + }, + "funding": { + "url": "https://polar.sh/cva" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/css-line-break": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-line-break/-/css-line-break-2.1.0.tgz", + "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", + "dependencies": { + "utrie": "^1.0.2" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==" + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.80", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.80.tgz", + "integrity": "sha512-LTrKpW0AqIuHwmlVNV+cjFYTnXtM9K37OGhpe0ZI10ScPSxqVSryZHIY3WnCS5NSYbBODRTZyhRMS2h5FAEqAw==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fastq": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz", + "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "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" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/html2canvas": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/html2canvas/-/html2canvas-1.4.1.tgz", + "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", + "dependencies": { + "css-line-break": "^2.1.0", + "text-segmentation": "^1.0.3" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + }, + "node_modules/lucide-react": { + "version": "0.471.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.471.0.tgz", + "integrity": "sha512-3L0OOJClsKDETJGK7nABqW8ftaVmUjWzluzPpw/6dGdI1bOmzsLsCjZpAEpg24Xs/U7xdYveQU+CBkHxWy7MrA==", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/next": { + "version": "14.2.23", + "resolved": "https://registry.npmjs.org/next/-/next-14.2.23.tgz", + "integrity": "sha512-mjN3fE6u/tynneLiEg56XnthzuYw+kD7mCujgVqioxyPqbmiotUCGJpIZGS/VaPg3ZDT1tvWxiVyRzeqJFm/kw==", + "dependencies": { + "@next/env": "14.2.23", + "@swc/helpers": "0.5.5", + "busboy": "1.6.0", + "caniuse-lite": "^1.0.30001579", + "graceful-fs": "^4.2.11", + "postcss": "8.4.31", + "styled-jsx": "5.1.1" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=18.17.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "14.2.23", + "@next/swc-darwin-x64": "14.2.23", + "@next/swc-linux-arm64-gnu": "14.2.23", + "@next/swc-linux-arm64-musl": "14.2.23", + "@next/swc-linux-x64-gnu": "14.2.23", + "@next/swc-linux-x64-musl": "14.2.23", + "@next/swc-win32-arm64-msvc": "14.2.23", + "@next/swc-win32-ia32-msvc": "14.2.23", + "@next/swc-win32-x64-msvc": "14.2.23" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.41.2", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/postcss": { + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-remove-scroll": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.2.tgz", + "integrity": "sha512-KmONPx5fnlXYJQqC62Q+lwIeAk64ws/cUw6omIumRzMRPqgnYqhSSti99nbj0Ry13bv7dF+BKn7NB+OqkdZGTw==", + "dependencies": { + "react-remove-scroll-bar": "^2.3.7", + "react-style-singleton": "^2.2.1", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.3", + "use-sidecar": "^1.1.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-remove-scroll-bar": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", + "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", + "dependencies": { + "react-style-singleton": "^2.2.2", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-style-singleton": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", + "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", + "dependencies": { + "get-nonce": "^1.0.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", + "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwind-merge": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.6.0.tgz", + "integrity": "sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.17", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", + "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.6", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss-animate": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz", + "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==", + "peerDependencies": { + "tailwindcss": ">=3.0.0 || insiders" + } + }, + "node_modules/text-segmentation": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", + "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", + "dependencies": { + "utrie": "^1.0.2" + } + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "node_modules/typescript": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", + "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", + "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "dev": true + }, + "node_modules/update-browserslist-db": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz", + "integrity": "sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/use-callback-ref": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", + "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sidecar": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", + "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", + "dependencies": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/utrie": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/utrie/-/utrie-1.0.2.tgz", + "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", + "dependencies": { + "base64-arraybuffer": "^1.0.2" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yaml": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", + "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..8c28f74 --- /dev/null +++ b/package.json @@ -0,0 +1,40 @@ +{ + "name": "sucker", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "@radix-ui/react-accordion": "^1.2.2", + "@radix-ui/react-collapsible": "^1.1.2", + "@radix-ui/react-dialog": "^1.1.4", + "@radix-ui/react-separator": "^1.1.1", + "@radix-ui/react-slot": "^1.1.1", + "@types/react": "^18.2.39", + "@types/react-dom": "^18.2.17", + "axios": "^1.6.2", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "cors": "^2.8.5", + "crc-32": "^1.2.2", + "html2canvas": "^1.4.1", + "lucide-react": "^0.471.0", + "next": "^14.0.3", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "tailwind-merge": "^2.6.0", + "tailwindcss-animate": "^1.0.7", + "typescript": "^5.3.2" + }, + "devDependencies": { + "@types/cors": "^2.8.17", + "@types/node": "^22.10.5", + "autoprefixer": "^10.4.16", + "postcss": "^8.4.31", + "tailwindcss": "^3.3.5" + } +} diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..0cc9a9d --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} \ No newline at end of file diff --git a/public/android-chrome-192x192.png b/public/android-chrome-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..26ebefc761f03d1d6089f6bf78eb028dcca18659 GIT binary patch literal 7460 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 JrRnXs{{ds*+B*OM literal 0 HcmV?d00001 diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..2c91d4b6be6e19a528a4ea011fbf0e31ae5ce4da GIT binary patch literal 6651 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 literal 0 HcmV?d00001 diff --git a/public/favicon-16x16.png b/public/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..2c29f4bb90d5dd7abd6714c5afdcfd748a4bff75 GIT binary patch literal 410 zcmV;L0cHM)P)Px$R7pfZR5(v#WS|f*QmCI{5F4PU=f=&-`kfEt#oxank?z!o8qlZZ6Kp zDG;Npr{^vvE^f%r&o9Eo%>~x;?dw;Dj~_q1dG+$;`OB9s?fmrp!;&i}Prd}nfeo;7 zbT9Mt_HM9uaOC9V;9z+D<_*KUH*Xleeg6(NfRmGxK}1A^K}1xP;rsXR3Q_(0E+-|{^NqV1^@s607*qoM6N<$ Ef?5T@g#Z8m literal 0 HcmV?d00001 diff --git a/public/favicon-32x32.png b/public/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..e2c03c89d363ce893fcef6679b3498b8b56f05df GIT binary patch literal 848 zcmV-W1F!svP)Px&3Q0skR9HvtRNYIHQ5=4L?}wsW`$$Dsrh;F!t&exh8L7Fb8;QD$pzyA4L#dno zgeW5FvaW)PpqmKvMrf&pA8oVPR%(G}*}`d4w}IRH?$j2GW;J=;g#`Ou9L~jap65Bw zIlmuai;K2c9|Z%21PTfKe+ih)POYF#R&Y$#Gl4Hk%@LB7c#?!=Il?Uj0 zN$RM8$c}@f!;C=^c&^D{FqZ2LM$%|XA&O~zBoc8%qfsn}!z>&Qhh#;WB!U+VFFBbX zaJyZhf0_EjfYa#|mSgg15S=#|jYlk2tI*WcjM}<7R900%5QLl;lw}!TgF(#B%wTG2 z5`Ldg4ljLs4#Hi13IEvTa>>6FWEt4k(tc7Dg&QpnM?k0YL6qM&VT|GZ^faEk zp5fKl=#;Fm-igt{zKn?sJ4ufA>)R_Tde59aM>a{yx@96B$Nc;}g269X3@u`HWd*TV z3<)`r#)*Q6lF}0Bbb6GPmBF;b1k;Y45JfSI$K&zf(ZdI9DYS6aJ34$N{eM!6)Y^W@ zR9$o3=4ge*ya$c-_4qhD3$Mq6fZvzir=nF;si&%`t%ccQg=Dj(_tPIfz#n)E&)6uw z%*|c&jt$)=v)NpvHC6_Xoj7Uacphuf2qyi0eEKw}MsGuGb@eVZTP!HnXpvMD4D>x+ z7#}V-k=@>5+E#9uZ?^7*&+A1js;Y}N6kZP~)o5XrBux5zSXvELrk;Sa9qRnZSaPRo zwmc3H(Pz)dU`^%^bOUrR4?eX=8B0?4#Q5O-Up;o9wXKK1T?3H2(bY=*iBBNOE_=s^ zZ~f|m3`TOa9RzVV0kq|>^EU=Iq!9JI85#1dp95KFo1?RXk#Yf`QvmdNnPCY3==3Ly z!<~tdp%?49a*jE>-7YFr>L8vv0Ja~D?FOh0U^)C)QtTQ**YVtE+fhFrrh6_~H~NA6M2^tF$Zc`}^0_rnM;pYDIG43kC`a6cX6- a1ik}hvJ^swQ|a{p0000Bkw8+O0i6TM1 zf>0vzVGVTc$!Ch5Y(F3ztcc3zxt} z=*-^Cd;9MD{yv`fdEecA_xD>xNmH&lPW zHUC1$ybnD|QcgxRb%AYX+)O*Ve&;tJ|A!^~r%sUkoN%{#?4t~2sgq;)OF0I#KiW`RbLQ7a_RG7!IV^|vZI`x|X4$%_ z(J5^$o6xpH{`lL&LYY-{HKz*(nN`${{Wz9dC-#qb}`{4sVWVzGIf=`zMa);-Aas+tiONO+AX|{fjuC zm964UzGXiyz<0YkrR!{3wrVM_5u;S>J* zaUWEaZ_C^nlLdRPl=?`-8-37MF?@!@p08(QWPCBl)IO?zVvej_Hcu8mRwd=5ic*e) zHffta=qo1@{IEp93lx5s{~6_@3ei_B?QNUoPwyO&Jv&;tx0Lbaqa?=+_8Jd$s7o8P zMVquuAM}N5a@vLY=OGREi@K3Rb30mIXmn&LA1l8*en@t2|A{m=t(KL`7fDU^OqugY zg;Z5eatiB)6pxECl%)=JX#-rp0(+xrJAun?oA_LDuo%8omaZNI{trhK=5_o4^I9?SKIff> z?>($@uGwcp2C@e%!`I;W3WrP!$DQGLSBu9b+)nZGEBNEE(0zD zE(0zDSAhY>Nf4q{#-q4#5|H5jTn1bQTn1bQTn1bQTn74vfwYp6lIsfk_rC!#fg2H{ zy@`eO62zm}2e%jHbNdF$rL7Vp-|bD^8!?04(ul5BAjUiwx#y*bF|5M*k0XX}E#eew zS!bKm2N}vDr(D9=uVJX^jI~|bTWWg2ms z(M#ZGsA>AXb-8l`F1=AreH@sN0dr4yy)xVv&l7zfL0J?H1TuR%C+2_wxA1!h=$%CQ zJmUVz#{H?K`~MORdaIMg(IQz{-vj1tJzU4h{HD79EY?FS?-_~aBBFWkz%_IL_&ZQi z?K@TWI&kgpL#+7wUB|#{9_#!U*D&t5@%wk_djHP*6mXBW4F9SBBmAe3C%Tt&z&s|d zkLAM#XLm4vfjD>ESg)P6L~Lbu7YecB{<@rT|4=COCERZt*Eq1|;wQJaAvBlc#K`eH=D6$g$V=bYhKRjvbjNB$mp_W3iTlALHKtG$>EF2Y2=k z$l3CFJ+8Fa$@Lw7V{f;%V?JU>=0@LobDzWCYkRlL!QE|6VV#^FM_;1+X-q%)cuJJ@{L=5Z@5s{Q_gzhHLx%L6P8@iT96|XICym&bmboA8ePm z55Ma0NuRwP2X#0Xv_V_1{Jh1nO&^0I+8Ovg88y^aQ}-Ky>)dC006URLKklV*%}>E| zq6zbI6!*1%bFDu(>3&%-XS%Fd_9JO}re3z-`&E9s+TONR_U`JRfc5$7T4CK~7iu4~F=z-7Q?z-7Q? Uz-7Q?z-7Q?z-7Q?p!W>?7mbQ9Z2$lO literal 0 HcmV?d00001 diff --git a/public/site.webmanifest b/public/site.webmanifest new file mode 100644 index 0000000..45dc8a2 --- /dev/null +++ b/public/site.webmanifest @@ -0,0 +1 @@ +{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"} \ No newline at end of file diff --git a/src/app/api/proxy/image/route.ts b/src/app/api/proxy/image/route.ts new file mode 100644 index 0000000..6f3314a --- /dev/null +++ b/src/app/api/proxy/image/route.ts @@ -0,0 +1,25 @@ +import { NextResponse } from 'next/server'; +import type { NextRequest } from 'next/server'; + +export async function GET(request: NextRequest) { + const url = request.nextUrl.searchParams.get('url'); + + if (!url) { + return NextResponse.json({ error: 'URL parameter is required' }, { status: 400 }); + } + + try { + const response = await fetch(url); + const arrayBuffer = await response.arrayBuffer(); + + return new NextResponse(arrayBuffer, { + headers: { + 'Content-Type': response.headers.get('Content-Type') || 'image/webp', + 'Access-Control-Allow-Origin': '*', + }, + }); + } catch (error) { + console.error('Error proxying image:', error); + return NextResponse.json({ error: 'Failed to fetch image' }, { status: 500 }); + } +} \ No newline at end of file diff --git a/src/app/api/proxy/route.ts b/src/app/api/proxy/route.ts new file mode 100644 index 0000000..8b5c841 --- /dev/null +++ b/src/app/api/proxy/route.ts @@ -0,0 +1,190 @@ +import { NextResponse } from 'next/server'; +import type { NextRequest } from 'next/server'; + +interface StoredCard extends CardData { + timestamp: number; + id: string; +} + +let extractedCards: StoredCard[] = []; +const EXPIRY_TIME = 10 * 60 * 1000; + +function generateId(): string { + return Date.now().toString(36) + Math.random().toString(36).substring(2); +} + +function cleanupExpiredCards() { + const now = Date.now(); + extractedCards = extractedCards.filter(card => (now - card.timestamp) < EXPIRY_TIME); +} + +interface Message { + content: string; +} + +interface CardData { + name: string; + first_mes: string; + description: string; + personality: string; + mes_example: string; + scenario: string; +} + +function extractPersonaName(content: string, personaIndex: number = 0): string { + const personaMatches = Array.from(content.matchAll(/'s Persona:/g)); + if (personaMatches.length <= personaIndex) return ""; + + const personaIdx = personaMatches[personaIndex].index!; + const lineStartIdx = content.lastIndexOf('\n', personaIdx); + const lineEndIdx = personaIdx; + + return content.slice(lineStartIdx === -1 ? 0 : lineStartIdx + 1, lineEndIdx).trim(); +} + +function safeReplace(text: string, old: string, newStr: string): string { + return old ? text.replace(new RegExp(old, 'g'), newStr) : text; +} + +function extractCardData(messages: Message[]): CardData { + const content0 = messages[0].content; + const content1 = messages[1].content; + + const userName = extractPersonaName(content0, 0); + const charName = extractPersonaName(content0, 1); + + const personaMatches = Array.from(content0.matchAll(/'s Persona:/g)); + let cardData: CardData = { + name: charName, + description: "", + scenario: "", + mes_example: "", + personality: "", + first_mes: content1 + }; + + if (personaMatches.length >= 2) { + const secondPersonaIdx = personaMatches[1].index!; + const startDesc = secondPersonaIdx + "'s Persona:".length; + const remaining = content0.slice(startDesc); + + const scenarioMarker = remaining.match(/Scenario of the roleplay:/); + const exampleMarker = remaining.match(/Example conversations between/); + + let endIdx = remaining.length; + if (scenarioMarker) endIdx = Math.min(endIdx, scenarioMarker.index!); + if (exampleMarker) endIdx = Math.min(endIdx, exampleMarker.index!); + + cardData.description = remaining.slice(0, endIdx).trim(); + + if (scenarioMarker) { + const scenarioStart = scenarioMarker.index! + scenarioMarker[0].length; + const scenarioRemaining = remaining.slice(scenarioStart); + const exampleInScenarioMarker = scenarioRemaining.match(/Example conversations between/); + const scenarioEnd = exampleInScenarioMarker ? exampleInScenarioMarker.index! : scenarioRemaining.length; + cardData.scenario = scenarioRemaining.slice(0, scenarioEnd).trim(); + } + + if (exampleMarker) { + const exampleStart = exampleMarker.index!; + const rawExampleStr = remaining.slice(exampleStart).trim(); + const colonIdx = rawExampleStr.indexOf(':'); + cardData.mes_example = colonIdx !== -1 ? + rawExampleStr.slice(colonIdx + 1).trim() : + rawExampleStr.trim(); + } + } + + for (const field in cardData) { + if (field !== 'name') { + const val = cardData[field as keyof CardData]; + if (typeof val === 'string') { + let newVal = safeReplace(val, userName, '{{user}}'); + newVal = safeReplace(newVal, charName, '{{char}}'); + cardData[field as keyof CardData] = newVal; + } + } + } + + return cardData; +} + +export async function POST(request: NextRequest) { + if (request.method === 'OPTIONS') { + return new NextResponse(null, { + status: 204, + headers: { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'POST, OPTIONS, GET', + 'Access-Control-Allow-Headers': 'Content-Type, Authorization', + }, + }); + } + + try { + const body = await request.json(); + + if (!body.messages || body.messages.length < 2) { + return NextResponse.json( + { error: "Missing messages or insufficient message count" }, + { + status: 400, + headers: { + 'Access-Control-Allow-Origin': '*', + }, + } + ); + } + + const cardData = extractCardData(body.messages); + extractedCards.push({ + ...cardData, + timestamp: Date.now(), + id: generateId() + }); + + cleanupExpiredCards(); + + return NextResponse.json({ status: "Card stored successfully" }, { + headers: { + 'Access-Control-Allow-Origin': '*', + }, + }); + + } catch (error) { + console.error('Error processing request:', error); + return NextResponse.json( + { error: "Internal server error" }, + { + status: 500, + headers: { + 'Access-Control-Allow-Origin': '*', + }, + } + ); + } +} + +export async function GET() { + cleanupExpiredCards(); + + return NextResponse.json({ + status: "online", + cards: extractedCards.map(({ timestamp, ...card }) => card) // Keep ID but remove timestamp + }, { + headers: { + 'Access-Control-Allow-Origin': '*', + }, + }); +} + +export async function OPTIONS() { + return new NextResponse(null, { + status: 204, + headers: { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'POST, OPTIONS, GET', + 'Access-Control-Allow-Headers': 'Content-Type, Authorization', + }, + }); +} \ No newline at end of file diff --git a/src/app/globals.css b/src/app/globals.css new file mode 100644 index 0000000..8abdb15 --- /dev/null +++ b/src/app/globals.css @@ -0,0 +1,76 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + :root { + --background: 0 0% 100%; + --foreground: 222.2 84% 4.9%; + + --card: 0 0% 100%; + --card-foreground: 222.2 84% 4.9%; + + --popover: 0 0% 100%; + --popover-foreground: 222.2 84% 4.9%; + + --primary: 222.2 47.4% 11.2%; + --primary-foreground: 210 40% 98%; + + --secondary: 210 40% 96.1%; + --secondary-foreground: 222.2 47.4% 11.2%; + + --muted: 210 40% 96.1%; + --muted-foreground: 215.4 16.3% 46.9%; + + --accent: 210 40% 96.1%; + --accent-foreground: 222.2 47.4% 11.2%; + + --destructive: 0 84.2% 60.2%; + --destructive-foreground: 210 40% 98%; + + --border: 214.3 31.8% 91.4%; + --input: 214.3 31.8% 91.4%; + --ring: 222.2 84% 4.9%; + + --radius: 0.5rem; + } + + .dark { + --background: 222.2 84% 4.9%; + --foreground: 210 40% 98%; + + --card: 222.2 84% 4.9%; + --card-foreground: 210 40% 98%; + + --popover: 222.2 84% 4.9%; + --popover-foreground: 210 40% 98%; + + --primary: 210 40% 98%; + --primary-foreground: 222.2 47.4% 11.2%; + + --secondary: 217.2 32.6% 17.5%; + --secondary-foreground: 210 40% 98%; + + --muted: 217.2 32.6% 17.5%; + --muted-foreground: 215 20.2% 65.1%; + + --accent: 217.2 32.6% 17.5%; + --accent-foreground: 210 40% 98%; + + --destructive: 0 62.8% 30.6%; + --destructive-foreground: 210 40% 98%; + + --border: 217.2 32.6% 17.5%; + --input: 217.2 32.6% 17.5%; + --ring: 212.7 26.8% 83.9%; + } +} + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + } +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx new file mode 100644 index 0000000..5ed14f1 --- /dev/null +++ b/src/app/layout.tsx @@ -0,0 +1,36 @@ +import type { Metadata } from "next"; +import { Inter } from "next/font/google"; +import "./globals.css"; + +const inter = Inter({ subsets: ["latin"] }); + +export const metadata: Metadata = { + title: "Sucker?", + description: "Walk away if you don't know what this is for, bud.", + icons: { + icon: [ + { url: '/favicon.ico' }, + { url: '/favicon-16x16.png', sizes: '16x16', type: 'image/png' }, + { url: '/favicon-32x32.png', sizes: '32x32', type: 'image/png' }, + ], + apple: [ + { url: '/apple-touch-icon.png' } + ], + other: [ + { url: '/android-chrome-192x192.png', sizes: '192x192', type: 'image/png' }, + { url: '/android-chrome-512x512.png', sizes: '512x512', type: 'image/png' }, + ], + }, +}; + +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + {children} + + ); +} diff --git a/src/app/page.tsx b/src/app/page.tsx new file mode 100644 index 0000000..f0cc78b --- /dev/null +++ b/src/app/page.tsx @@ -0,0 +1,413 @@ +"use client"; + +import { useState, useEffect } from "react"; +import { Separator } from "@/components/ui/separator"; +import { Button } from "@/components/ui/button"; +import { Card, CardContent } from "@/components/ui/card"; +import { + Accordion, + AccordionContent, + AccordionItem, + AccordionTrigger, +} from "@/components/ui/accordion"; +import { + Dialog, + DialogContent, + DialogHeader, + DialogTitle, + DialogDescription, +} from "@/components/ui/dialog"; +import { Input } from "@/components/ui/input"; +import { Png } from "@/lib/png"; +import { ChevronUp, ChevronDown } from "lucide-react"; +import { + CollapsibleContent, + Collapsible, + CollapsibleTrigger, +} from "@/components/ui/collapsible"; + +interface Card { + id: string; + name: string; + first_mes: string; + description: string; + personality: string; + mes_example: string; + scenario: string; + avatarUrl?: string; +} + +export default function Home() { + const [isInstructionsOpen, setIsInstructionsOpen] = useState(false); + const [cards, setCards] = useState([]); + const [dialogOpen, setDialogOpen] = useState(false); + const [selectedCardIndex, setSelectedCardIndex] = useState( + null + ); + const [characterUrl, setCharacterUrl] = useState(""); + const [avatarPath, setAvatarPath] = useState(""); + const [isMetadataOpen, setIsMetadataOpen] = useState(false); + const [isRefreshing, setIsRefreshing] = useState(false); + + const fetchCards = async () => { + try { + setIsRefreshing(true); + const response = await fetch("/api/proxy"); + const data = await response.json(); + if (data.cards) { + setCards((prevCards) => { + return data.cards.map((newCard: Card) => ({ + ...newCard, + avatarUrl: + prevCards.find((c) => c.id === newCard.id)?.avatarUrl || + newCard.avatarUrl, + })); + }); + } + } catch (error) { + console.error("Error fetching cards:", error); + } finally { + setIsRefreshing(false); + } + }; + + useEffect(() => { + fetchCards(); + }, []); + + const downloadJson = (card: Card) => { + const element = document.createElement("a"); + const file = new Blob([JSON.stringify(card, null, 2)], { + type: "application/json", + }); + element.href = URL.createObjectURL(file); + element.download = `${card.name.replace(/\s+/g, "_")}.json`; + document.body.appendChild(element); + element.click(); + document.body.removeChild(element); + }; + + const downloadPng = async (card: Card, cardId: string) => { + if (!card.avatarUrl) return; + + try { + // Use proxy directly instead of attempting CORS + const img = new Image(); + img.src = `/api/proxy/image?url=${encodeURIComponent(card.avatarUrl)}`; + + await new Promise((resolve, reject) => { + img.onload = resolve; + img.onerror = reject; + }); + + // Create a canvas to convert WebP to PNG + const canvas = document.createElement("canvas"); + canvas.width = img.width; + canvas.height = img.height; + const ctx = canvas.getContext("2d"); + if (!ctx) throw new Error("Could not get canvas context"); + + // Draw the image and convert to PNG + ctx.drawImage(img, 0, 0); + const pngBlob = await new Promise((resolve) => { + canvas.toBlob((blob) => { + if (blob) resolve(blob); + else throw new Error("Could not convert to PNG"); + }, "image/png"); + }); + + // Convert blob to array buffer for PNG embedding + const arrayBuffer = await pngBlob.arrayBuffer(); + + // Prepare card data for embedding + const cardData = JSON.stringify({ + name: card.name, + first_mes: card.first_mes, + description: card.description, + personality: card.personality, + mes_example: card.mes_example, + scenario: card.scenario, + }); + + // Generate PNG with embedded card data + const newImageData = Png.Generate(arrayBuffer, cardData); + const newFileName = `${ + card.name.replace(/\s+/g, "_") || "character" + }.png`; + const newFile = new File([newImageData], newFileName, { + type: "image/png", + }); + + // Download the file + const link = URL.createObjectURL(newFile); + const a = document.createElement("a"); + a.download = newFileName; + a.href = link; + a.click(); + + // Cleanup + URL.revokeObjectURL(link); + } catch (error) { + console.error("Error generating PNG:", error); + alert("Couldn't export this character card, sorry."); + } + }; + + const handleOpenDialog = (index: number) => { + setSelectedCardIndex(index); + setDialogOpen(true); + setCharacterUrl(""); + setAvatarPath(""); + setIsMetadataOpen(false); + }; + + const handleOpenMetadata = () => { + const match = characterUrl.match(/characters\/([\w-]+)/); + if (match && match[1]) { + const characterId = match[1].split("_")[0]; + window.open( + `https://janitorai.com/hampter/characters/${characterId}`, + "_blank" + ); + setIsMetadataOpen(true); + } + }; + + const handleFetchAvatar = async () => { + if (selectedCardIndex === null) return; + + try { + const avatarUrl = `https://ella.janitorai.com/bot-avatars/${avatarPath}`; + const updatedCards = [...cards]; + updatedCards[selectedCardIndex] = { + ...updatedCards[selectedCardIndex], + avatarUrl, + }; + setCards(updatedCards); + setDialogOpen(false); + } catch (error) { + console.error("Error fetching avatar:", error); + } + }; + + return ( +
+
+
+

Sucker

+ +
+ + + + +
+

How to Use

+ + + +
+ +
+

+ Follow every instruction here to the letter because it's all you + need to know and I have no intent of helping you further. +

+
    +
  1. + Put https://sucker.severian.dev/api/proxy in your + API settings, any value for model and key. +
  2. +
  3. + Remove your custom prompt - otherwise, it'll get inserted into + cards, on the example message section. +
  4. +
  5. + Save settings and refresh the page. Not this page. That{" "} + page. +
  6. +
  7. + Start a new chat with a character or multiple. Send any + message. +
  8. +
  9. + Hit the Refresh button here, and the cards should appear here. +
  10. +
  11. + Download the JSON files or go through a little more effort to + get PNGs instead. +
  12. +
+

+ Extractions will only last for 10 minutes, after which they're + discarded. Reloading the page will remove any attached avatars. + I'm not storing shit. +

+
+
+
+ +
+ {cards.length === 0 ? ( + + +

No extractions yet.

+
+
+ ) : ( + cards.map((card, index) => ( + + + + + + {card.name || "Unnamed Card"} + + +
+ {card.description && ( + + + Description + + {card.description} + + + + )} + {card.first_mes && ( + + + + First Message + + + {card.first_mes} + + + + )} + {card.scenario && ( + + + Scenario + + {card.scenario} + + + + )} + {card.mes_example && ( + + + + Example Messages + + + {card.mes_example} + + + + )} +
+
+
+
+
+ + {!card.avatarUrl ? ( + + ) : ( + + )} +
+
+
+ )) + )} +
+
+ + + + + + {isMetadataOpen ? "Enter Avatar Path" : "Enter Character URL"} + + + {isMetadataOpen + ? "Look for the avatar field in the opened tab and paste the value here." + : "Enter the Janitor character URL (https://janitorai.com/characters/...)."} + + + + {isMetadataOpen ? ( +
+ ) => + setAvatarPath(e.target.value) + } + /> + +
+ ) : ( +
+ ) => + setCharacterUrl(e.target.value) + } + /> +

+ Upon clicking this button, a new tab will open with the + character's metadata. Look for the avatar field and copy the + value before returning to this page. +

+ +
+ )} +
+
+
+ ); +} diff --git a/src/components/ui/accordion.tsx b/src/components/ui/accordion.tsx new file mode 100644 index 0000000..e1797c9 --- /dev/null +++ b/src/components/ui/accordion.tsx @@ -0,0 +1,55 @@ +import * as React from "react" +import * as AccordionPrimitive from "@radix-ui/react-accordion" +import { ChevronDown } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Accordion = AccordionPrimitive.Root + +const AccordionItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AccordionItem.displayName = "AccordionItem" + +const AccordionTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + svg]:rotate-180", + className + )} + {...props} + > + {children} + + + +)) +AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName + +const AccordionContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + +
{children}
+
+)) +AccordionContent.displayName = AccordionPrimitive.Content.displayName + +export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx new file mode 100644 index 0000000..65d4fcd --- /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/card.tsx b/src/components/ui/card.tsx new file mode 100644 index 0000000..cabfbfc --- /dev/null +++ b/src/components/ui/card.tsx @@ -0,0 +1,76 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +const Card = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +Card.displayName = "Card" + +const CardHeader = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +CardHeader.displayName = "CardHeader" + +const CardTitle = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +CardTitle.displayName = "CardTitle" + +const CardDescription = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +CardDescription.displayName = "CardDescription" + +const CardContent = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +CardContent.displayName = "CardContent" + +const CardFooter = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)) +CardFooter.displayName = "CardFooter" + +export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } diff --git a/src/components/ui/collapsible.tsx b/src/components/ui/collapsible.tsx new file mode 100644 index 0000000..a23e7a2 --- /dev/null +++ b/src/components/ui/collapsible.tsx @@ -0,0 +1,9 @@ +import * as CollapsiblePrimitive from "@radix-ui/react-collapsible" + +const Collapsible = CollapsiblePrimitive.Root + +const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger + +const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent + +export { Collapsible, CollapsibleTrigger, CollapsibleContent } diff --git a/src/components/ui/dialog.tsx b/src/components/ui/dialog.tsx new file mode 100644 index 0000000..9dbeaa0 --- /dev/null +++ b/src/components/ui/dialog.tsx @@ -0,0 +1,120 @@ +import * as React from "react" +import * as DialogPrimitive from "@radix-ui/react-dialog" +import { X } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Dialog = DialogPrimitive.Root + +const DialogTrigger = DialogPrimitive.Trigger + +const DialogPortal = DialogPrimitive.Portal + +const DialogClose = DialogPrimitive.Close + +const DialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName + +const DialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + {children} + + + Close + + + +)) +DialogContent.displayName = DialogPrimitive.Content.displayName + +const DialogHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DialogHeader.displayName = "DialogHeader" + +const DialogFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DialogFooter.displayName = "DialogFooter" + +const DialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogTitle.displayName = DialogPrimitive.Title.displayName + +const DialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogDescription.displayName = DialogPrimitive.Description.displayName + +export { + Dialog, + DialogPortal, + DialogOverlay, + DialogTrigger, + DialogClose, + DialogContent, + DialogHeader, + DialogFooter, + DialogTitle, + DialogDescription, +} diff --git a/src/components/ui/input.tsx b/src/components/ui/input.tsx new file mode 100644 index 0000000..69b64fb --- /dev/null +++ b/src/components/ui/input.tsx @@ -0,0 +1,22 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +const Input = React.forwardRef>( + ({ className, type, ...props }, ref) => { + return ( + + ) + } +) +Input.displayName = "Input" + +export { Input } diff --git a/src/components/ui/separator.tsx b/src/components/ui/separator.tsx new file mode 100644 index 0000000..6d7f122 --- /dev/null +++ b/src/components/ui/separator.tsx @@ -0,0 +1,29 @@ +import * as React from "react" +import * as SeparatorPrimitive from "@radix-ui/react-separator" + +import { cn } from "@/lib/utils" + +const Separator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>( + ( + { className, orientation = "horizontal", decorative = true, ...props }, + ref + ) => ( + + ) +) +Separator.displayName = SeparatorPrimitive.Root.displayName + +export { Separator } diff --git a/src/lib/png.ts b/src/lib/png.ts new file mode 100644 index 0000000..c1fe4f3 --- /dev/null +++ b/src/lib/png.ts @@ -0,0 +1,240 @@ +import * as CRC32 from "crc-32"; + +// I don't know who Zoltan is, but thank you. + +interface PngChunk { + type: string; + data: Uint8Array; + crc: number; +} + +interface TextChunk { + keyword: string; + text: string; +} + +export class Png { + static uint8 = new Uint8Array(4); + static int32 = new Int32Array(this.uint8.buffer); + static uint32 = new Uint32Array(this.uint8.buffer); + + static decodeText(data: Uint8Array): TextChunk { + let naming = true; + let keyword = ""; + let text = ""; + + for (let index = 0; index < data.length; index++) { + const code = data[index]; + + if (naming) { + if (code) { + keyword += String.fromCharCode(code); + } else { + naming = false; + } + } else { + if (code) { + text += String.fromCharCode(code); + } else { + throw new Error("Invalid NULL character found in PNG tEXt chunk"); + } + } + } + + return { + keyword, + text, + }; + } + + static encodeText(keyword: string, text: string): Uint8Array { + keyword = String(keyword); + text = String(text); + + if (!/^[\x00-\xFF]+$/.test(keyword) || !/^[\x00-\xFF]+$/.test(text)) + throw new Error("Invalid character in PNG tEXt chunk"); + if (keyword.length > 79) + throw new Error( + 'Keyword "' + keyword + '" is longer than the 79 character limit' + ); + + const data = new Uint8Array(keyword.length + text.length + 1); + let idx = 0; + let code; + + for (let i = 0; i < keyword.length; i++) { + if (!(code = keyword.charCodeAt(i))) + throw new Error("0x00 character is not permitted in tEXt keywords"); + data[idx++] = code; + } + + data[idx++] = 0; + + for (let i = 0; i < text.length; i++) { + if (!(code = text.charCodeAt(i))) + throw new Error("0x00 character is not permitted in tEXt text"); + data[idx++] = code; + } + + return data; + } + + static readChunk(data: Uint8Array, idx: number): PngChunk { + this.uint8[3] = data[idx++]; + this.uint8[2] = data[idx++]; + this.uint8[1] = data[idx++]; + this.uint8[0] = data[idx++]; + const length = this.uint32[0]; + + const chunkType = + String.fromCharCode(data[idx++]) + + String.fromCharCode(data[idx++]) + + String.fromCharCode(data[idx++]) + + String.fromCharCode(data[idx++]); + + const chunkData = data.slice(idx, idx + length); + idx += length; + + this.uint8[3] = data[idx++]; + this.uint8[2] = data[idx++]; + this.uint8[1] = data[idx++]; + this.uint8[0] = data[idx++]; + const crc = this.int32[0]; + + if (crc !== CRC32.buf(chunkData, CRC32.str(chunkType))) + throw new Error( + 'CRC for "' + + chunkType + + '" header is invalid, file is likely corrupted' + ); + + return { + type: chunkType, + data: chunkData, + crc, + }; + } + + static readChunks(data: Uint8Array): PngChunk[] { + if ( + data[0] !== 0x89 || + data[1] !== 0x50 || + data[2] !== 0x4e || + data[3] !== 0x47 || + data[4] !== 0x0d || + data[5] !== 0x0a || + data[6] !== 0x1a || + data[7] !== 0x0a + ) + throw new Error("Invalid PNG header"); + + const chunks: PngChunk[] = []; + + let idx = 8; + while (idx < data.length) { + const chunk = Png.readChunk(data, idx); + + if (!chunks.length && chunk.type !== "IHDR") + throw new Error("PNG missing IHDR header"); + + chunks.push(chunk); + idx += 4 + 4 + chunk.data.length + 4; + } + + if (chunks.length === 0) + throw new Error("PNG ended prematurely, no chunks"); + if (chunks[chunks.length - 1].type !== "IEND") + throw new Error("PNG ended prematurely, missing IEND header"); + + return chunks; + } + + static encodeChunks(chunks: PngChunk[]): Uint8Array { + const output = new Uint8Array( + chunks.reduce( + (a: number, c: PngChunk) => a + 4 + 4 + c.data.length + 4, + 8 + ) + ); + + output[0] = 0x89; + output[1] = 0x50; + output[2] = 0x4e; + output[3] = 0x47; + output[4] = 0x0d; + output[5] = 0x0a; + output[6] = 0x1a; + output[7] = 0x0a; + + let idx = 8; + + chunks.forEach((c: PngChunk) => { + this.uint32[0] = c.data.length; + output[idx++] = this.uint8[3]; + output[idx++] = this.uint8[2]; + output[idx++] = this.uint8[1]; + output[idx++] = this.uint8[0]; + + output[idx++] = c.type.charCodeAt(0); + output[idx++] = c.type.charCodeAt(1); + output[idx++] = c.type.charCodeAt(2); + output[idx++] = c.type.charCodeAt(3); + + for (let i = 0; i < c.data.length; ) { + output[idx++] = c.data[i++]; + } + + this.int32[0] = c.crc || CRC32.buf(c.data, CRC32.str(c.type)); + output[idx++] = this.uint8[3]; + output[idx++] = this.uint8[2]; + output[idx++] = this.uint8[1]; + output[idx++] = this.uint8[0]; + }); + + return output; + } + + static Parse(arrayBuffer: ArrayBuffer): string { + const chunks = Png.readChunks(new Uint8Array(arrayBuffer)); + + const text = chunks + .filter((c) => c.type === "tEXt") + .map((c) => Png.decodeText(c.data)); + if (text.length < 1) throw new Error("No PNG text fields found in file"); + + const chara = text.find((t) => t.keyword === "chara"); + if (chara === undefined) + throw new Error('No PNG text field named "chara" found in file'); + + try { + return new TextDecoder().decode( + Uint8Array.from(atob(chara.text), (c) => c.charCodeAt(0)) + ); + } catch (e) { + throw new Error('Unable to parse "chara" field as base64'); + } + } + + static Generate(arrayBuffer: ArrayBuffer, text: string): Uint8Array { + const chunks = Png.readChunks(new Uint8Array(arrayBuffer)).filter( + (c) => c.type !== "tEXt" + ); + + const textData = Png.encodeText( + "chara", + btoa( + new TextEncoder() + .encode(text) + .reduce((a, c) => a + String.fromCharCode(c), "") + ) + ); + + chunks.splice(-1, 0, { + type: "tEXt", + data: textData, + crc: CRC32.buf(textData, CRC32.str("tEXt")), + }); + + return Png.encodeChunks(chunks); + } +} diff --git a/src/lib/utils.ts b/src/lib/utils.ts new file mode 100644 index 0000000..bd0c391 --- /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/sucker.config.js b/sucker.config.js new file mode 100644 index 0000000..0013322 --- /dev/null +++ b/sucker.config.js @@ -0,0 +1,12 @@ +/** + * Get compatible PM2 app config object with automatic support for .nvmrc, + * port allocation, and debug mode. + */ +module.exports = { + apps: (function () { + let nodeapp = require("/usr/local/hestia/plugins/nodeapp/nodeapp.js")( + __filename + ); + return [nodeapp]; + })(), +}; diff --git a/sucker.js b/sucker.js new file mode 100644 index 0000000..0d02bee --- /dev/null +++ b/sucker.js @@ -0,0 +1,21 @@ +#!/usr/bin/env node +const { execSync } = require("child_process"); + +// 1. Grab the port from the '-p' argument +const portIndex = process.argv.indexOf("-p"); +let port = "3000"; +if (portIndex !== -1 && portIndex + 1 < process.argv.length) { + port = process.argv[portIndex + 1]; +} + +// 2. Start Next.js using that port +try { + // Either pass it directly to next, e.g.: + // execSync(`npx next start -p ${port}`, { stdio: "inherit" }); + // + // Or set the PORT env var and run your npm script: + execSync(`PORT=${port} npm run start`, { stdio: "inherit" }); +} catch (err) { + console.error("Failed to start Next.js:", err); + process.exit(1); +} diff --git a/tailwind.config.js b/tailwind.config.js new file mode 100644 index 0000000..99f9b0e --- /dev/null +++ b/tailwind.config.js @@ -0,0 +1,76 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + darkMode: ["class"], + content: [ + "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", + "./src/components/**/*.{js,ts,jsx,tsx,mdx}", + "./src/app/**/*.{js,ts,jsx,tsx,mdx}", + ], + theme: { + extend: { + colors: { + border: 'hsl(var(--border))', + input: 'hsl(var(--input))', + ring: 'hsl(var(--ring))', + background: 'hsl(var(--background))', + foreground: 'hsl(var(--foreground))', + primary: { + DEFAULT: 'hsl(var(--primary))', + foreground: 'hsl(var(--primary-foreground))' + }, + secondary: { + DEFAULT: 'hsl(var(--secondary))', + foreground: 'hsl(var(--secondary-foreground))' + }, + destructive: { + DEFAULT: 'hsl(var(--destructive))', + foreground: 'hsl(var(--destructive-foreground))' + }, + muted: { + DEFAULT: 'hsl(var(--muted))', + foreground: 'hsl(var(--muted-foreground))' + }, + accent: { + DEFAULT: 'hsl(var(--accent))', + foreground: 'hsl(var(--accent-foreground))' + }, + popover: { + DEFAULT: 'hsl(var(--popover))', + foreground: 'hsl(var(--popover-foreground))' + }, + card: { + DEFAULT: 'hsl(var(--card))', + foreground: 'hsl(var(--card-foreground))' + } + }, + borderRadius: { + lg: '`var(--radius)`', + md: '`calc(var(--radius) - 2px)`', + sm: 'calc(var(--radius) - 4px)' + }, + keyframes: { + 'accordion-down': { + from: { + height: '0' + }, + to: { + height: 'var(--radix-accordion-content-height)' + } + }, + 'accordion-up': { + from: { + height: 'var(--radix-accordion-content-height)' + }, + to: { + height: '0' + } + } + }, + animation: { + 'accordion-down': 'accordion-down 0.2s ease-out', + 'accordion-up': 'accordion-up 0.2s ease-out' + } + } + }, + plugins: [require("tailwindcss-animate")], +}; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..f99ef87 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "baseUrl": ".", + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "types": ["node"], + "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"], + "exclude": ["node_modules"] +} \ No newline at end of file