From 3d97d39bd377d8966b1bba6d8cab540b78239329 Mon Sep 17 00:00:00 2001 From: Fares Kerkeni <93195495+Fares-Kerkeni@users.noreply.github.com> Date: Mon, 15 Dec 2025 17:30:42 +0100 Subject: [PATCH] Initial commit --- .gitignore | 41 + README.md | 36 + eslint.config.mjs | 18 + next.config.ts | 7 + package-lock.json | 6400 +++++++++++++++++++ package.json | 30 + public/file.svg | 1 + public/globe.svg | 1 + public/next.svg | 1 + public/preview.webp | Bin 0 -> 6000 bytes public/screenshot.png | Bin 0 -> 53049 bytes public/signature-fares-kerkeni (1) (1).html | 87 + public/vercel.svg | 1 + public/window.svg | 1 + src/app/(auth)/login/page.tsx | 98 + src/app/(auth)/register/page.tsx | 154 + src/app/api/auth/callback/route.ts | 18 + src/app/dashboard/page.tsx | 283 + src/app/favicon.ico | Bin 0 -> 25931 bytes src/app/layout.tsx | 19 + src/app/page.tsx | 70 + src/components/BannerGenerator.tsx | 345 + src/components/BannerUpload.tsx | 75 + src/components/ImageUpload.tsx | 105 + src/components/SignatureEditor.tsx | 220 + src/components/SignaturePreview.module.scss | 274 + src/components/SignaturePreview.tsx | 167 + src/components/StyleSelector.tsx | 160 + src/hooks/useBanners.ts | 100 + src/hooks/useSignature.ts | 182 + src/hooks/useSignatures.ts | 282 + src/lib/export.ts | 244 + src/lib/supabase/client.ts | 8 + src/lib/supabase/middleware.ts | 55 + src/lib/supabase/server.ts | 28 + src/lib/types.ts | 93 + src/lib/upload.ts | 70 + src/middleware.ts | 12 + src/styles/admin.scss | 323 + src/styles/auth.scss | 92 + src/styles/dashboard.scss | 861 +++ src/styles/globals.scss | 135 + src/styles/home.scss | 135 + src/styles/variables.scss | 65 + supabase/migrations/001_banners.sql | 171 + supabase/migrations/002_storage.sql | 35 + supabase/migrations/003_signatures.sql | 74 + tsconfig.json | 34 + 48 files changed, 11611 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 eslint.config.mjs create mode 100644 next.config.ts create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 public/file.svg create mode 100644 public/globe.svg create mode 100644 public/next.svg create mode 100644 public/preview.webp create mode 100644 public/screenshot.png create mode 100644 public/signature-fares-kerkeni (1) (1).html create mode 100644 public/vercel.svg create mode 100644 public/window.svg create mode 100644 src/app/(auth)/login/page.tsx create mode 100644 src/app/(auth)/register/page.tsx create mode 100644 src/app/api/auth/callback/route.ts create mode 100644 src/app/dashboard/page.tsx create mode 100644 src/app/favicon.ico create mode 100644 src/app/layout.tsx create mode 100644 src/app/page.tsx create mode 100644 src/components/BannerGenerator.tsx create mode 100644 src/components/BannerUpload.tsx create mode 100644 src/components/ImageUpload.tsx create mode 100644 src/components/SignatureEditor.tsx create mode 100644 src/components/SignaturePreview.module.scss create mode 100644 src/components/SignaturePreview.tsx create mode 100644 src/components/StyleSelector.tsx create mode 100644 src/hooks/useBanners.ts create mode 100644 src/hooks/useSignature.ts create mode 100644 src/hooks/useSignatures.ts create mode 100644 src/lib/export.ts create mode 100644 src/lib/supabase/client.ts create mode 100644 src/lib/supabase/middleware.ts create mode 100644 src/lib/supabase/server.ts create mode 100644 src/lib/types.ts create mode 100644 src/lib/upload.ts create mode 100644 src/middleware.ts create mode 100644 src/styles/admin.scss create mode 100644 src/styles/auth.scss create mode 100644 src/styles/dashboard.scss create mode 100644 src/styles/globals.scss create mode 100644 src/styles/home.scss create mode 100644 src/styles/variables.scss create mode 100644 supabase/migrations/001_banners.sql create mode 100644 supabase/migrations/002_storage.sql create mode 100644 supabase/migrations/003_signatures.sql create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5ef6a52 --- /dev/null +++ b/.gitignore @@ -0,0 +1,41 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/versions + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# env files (can opt-in for committing if needed) +.env* + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/README.md b/README.md new file mode 100644 index 0000000..e215bc4 --- /dev/null +++ b/README.md @@ -0,0 +1,36 @@ +This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..05e726d --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,18 @@ +import { defineConfig, globalIgnores } from "eslint/config"; +import nextVitals from "eslint-config-next/core-web-vitals"; +import nextTs from "eslint-config-next/typescript"; + +const eslintConfig = defineConfig([ + ...nextVitals, + ...nextTs, + // Override default ignores of eslint-config-next. + globalIgnores([ + // Default ignores of eslint-config-next: + ".next/**", + "out/**", + "build/**", + "next-env.d.ts", + ]), +]); + +export default eslintConfig; diff --git a/next.config.ts b/next.config.ts new file mode 100644 index 0000000..e9ffa30 --- /dev/null +++ b/next.config.ts @@ -0,0 +1,7 @@ +import type { NextConfig } from "next"; + +const nextConfig: NextConfig = { + /* config options here */ +}; + +export default nextConfig; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..6c12868 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6400 @@ +{ + "name": "signature-generator", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "signature-generator", + "version": "0.1.0", + "dependencies": { + "@supabase/ssr": "^0.8.0", + "@supabase/supabase-js": "^2.86.0", + "canvas": "^3.2.0", + "gifenc": "^1.0.3", + "html-to-image": "^1.11.13", + "next": "16.0.7", + "react": "19.2.0", + "react-dom": "19.2.0", + "sass": "^1.94.2" + }, + "devDependencies": { + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "eslint": "^9", + "eslint-config-next": "16.0.7", + "typescript": "^5" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", + "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", + "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", + "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "dev": true, + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.28.5" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", + "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.5", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@emnapi/core": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.1.tgz", + "integrity": "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==", + "dev": true, + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.1.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz", + "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", + "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", + "dev": true, + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "dev": true, + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", + "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.1", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz", + "integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "dev": true, + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@img/colour": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz", + "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==", + "optional": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "cpu": [ + "s390x" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "cpu": [ + "wasm32" + ], + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.7.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "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==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "dev": true, + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" + } + }, + "node_modules/@next/env": { + "version": "16.0.7", + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.0.7.tgz", + "integrity": "sha512-gpaNgUh5nftFKRkRQGnVi5dpcYSKGcZZkQffZ172OrG/XkrnS7UBTQ648YY+8ME92cC4IojpI2LqTC8sTDhAaw==" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "16.0.7", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-16.0.7.tgz", + "integrity": "sha512-hFrTNZcMEG+k7qxVxZJq3F32Kms130FAhG8lvw2zkKBgAcNOJIxlljNiCjGygvBshvaGBdf88q2CqWtnqezDHA==", + "dev": true, + "dependencies": { + "fast-glob": "3.3.1" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "16.0.7", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.0.7.tgz", + "integrity": "sha512-LlDtCYOEj/rfSnEn/Idi+j1QKHxY9BJFmxx7108A6D8K0SB+bNgfYQATPk/4LqOl4C0Wo3LACg2ie6s7xqMpJg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "16.0.7", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.0.7.tgz", + "integrity": "sha512-rtZ7BhnVvO1ICf3QzfW9H3aPz7GhBrnSIMZyr4Qy6boXF0b5E3QLs+cvJmg3PsTCG2M1PBoC+DANUi4wCOKXpA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "16.0.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.0.7.tgz", + "integrity": "sha512-mloD5WcPIeIeeZqAIP5c2kdaTa6StwP4/2EGy1mUw8HiexSHGK/jcM7lFuS3u3i2zn+xH9+wXJs6njO7VrAqww==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "16.0.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.0.7.tgz", + "integrity": "sha512-+ksWNrZrthisXuo9gd1XnjHRowCbMtl/YgMpbRvFeDEqEBd523YHPWpBuDjomod88U8Xliw5DHhekBC3EOOd9g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "16.0.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.0.7.tgz", + "integrity": "sha512-4WtJU5cRDxpEE44Ana2Xro1284hnyVpBb62lIpU5k85D8xXxatT+rXxBgPkc7C1XwkZMWpK5rXLXTh9PFipWsA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "16.0.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.0.7.tgz", + "integrity": "sha512-HYlhqIP6kBPXalW2dbMTSuB4+8fe+j9juyxwfMwCe9kQPPeiyFn7NMjNfoFOfJ2eXkeQsoUGXg+O2SE3m4Qg2w==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "16.0.7", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.0.7.tgz", + "integrity": "sha512-EviG+43iOoBRZg9deGauXExjRphhuYmIOJ12b9sAPy0eQ6iwcPxfED2asb/s2/yiLYOdm37kPaiZu8uXSYPs0Q==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "16.0.7", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.0.7.tgz", + "integrity": "sha512-gniPjy55zp5Eg0896qSrf3yB1dw4F/3s8VK1ephdsZZ129j2n6e1WqCbE2YgcKhW9hPB9TVZENugquWJD5x0ug==", + "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==", + "dev": true, + "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==", + "dev": true, + "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==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true, + "engines": { + "node": ">=12.4.0" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", + "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "detect-libc": "^1.0.3", + "is-glob": "^4.0.3", + "micromatch": "^4.0.5", + "node-addon-api": "^7.0.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.1", + "@parcel/watcher-darwin-arm64": "2.5.1", + "@parcel/watcher-darwin-x64": "2.5.1", + "@parcel/watcher-freebsd-x64": "2.5.1", + "@parcel/watcher-linux-arm-glibc": "2.5.1", + "@parcel/watcher-linux-arm-musl": "2.5.1", + "@parcel/watcher-linux-arm64-glibc": "2.5.1", + "@parcel/watcher-linux-arm64-musl": "2.5.1", + "@parcel/watcher-linux-x64-glibc": "2.5.1", + "@parcel/watcher-linux-x64-musl": "2.5.1", + "@parcel/watcher-win32-arm64": "2.5.1", + "@parcel/watcher-win32-ia32": "2.5.1", + "@parcel/watcher-win32-x64": "2.5.1" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz", + "integrity": "sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz", + "integrity": "sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz", + "integrity": "sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz", + "integrity": "sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz", + "integrity": "sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz", + "integrity": "sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz", + "integrity": "sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz", + "integrity": "sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz", + "integrity": "sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz", + "integrity": "sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz", + "integrity": "sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz", + "integrity": "sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz", + "integrity": "sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher/node_modules/detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "optional": true, + "bin": { + "detect-libc": "bin/detect-libc.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true + }, + "node_modules/@supabase/auth-js": { + "version": "2.86.0", + "resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.86.0.tgz", + "integrity": "sha512-3xPqMvBWC6Haqpr6hEWmSUqDq+6SA1BAEdbiaHdAZM9QjZ5uiQJ+6iD9pZOzOa6MVXZh4GmwjhC9ObIG0K1NcA==", + "dependencies": { + "tslib": "2.8.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@supabase/functions-js": { + "version": "2.86.0", + "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.86.0.tgz", + "integrity": "sha512-AlOoVfeaq9XGlBFIyXTmb+y+CZzxNO4wWbfgRM6iPpNU5WCXKawtQYSnhivi3UVxS7GA0rWovY4d6cIAxZAojA==", + "dependencies": { + "tslib": "2.8.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@supabase/postgrest-js": { + "version": "2.86.0", + "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-2.86.0.tgz", + "integrity": "sha512-QVf+wIXILcZJ7IhWhWn+ozdf8B+oO0Ulizh2AAPxD/6nQL+x3r9lJ47a+fpc/jvAOGXMbkeW534Kw6jz7e8iIA==", + "dependencies": { + "tslib": "2.8.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@supabase/realtime-js": { + "version": "2.86.0", + "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.86.0.tgz", + "integrity": "sha512-dyS8bFoP29R/sj5zLi0AP3JfgG8ar1nuImcz5jxSx7UIW7fbFsXhUCVrSY2Ofo0+Ev6wiATiSdBOzBfWaiFyPA==", + "dependencies": { + "@types/phoenix": "^1.6.6", + "@types/ws": "^8.18.1", + "tslib": "2.8.1", + "ws": "^8.18.2" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@supabase/ssr": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@supabase/ssr/-/ssr-0.8.0.tgz", + "integrity": "sha512-/PKk8kNFSs8QvvJ2vOww1mF5/c5W8y42duYtXvkOSe+yZKRgTTZywYG2l41pjhNomqESZCpZtXuWmYjFRMV+dw==", + "dependencies": { + "cookie": "^1.0.2" + }, + "peerDependencies": { + "@supabase/supabase-js": "^2.76.1" + } + }, + "node_modules/@supabase/storage-js": { + "version": "2.86.0", + "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.86.0.tgz", + "integrity": "sha512-PM47jX/Mfobdtx7NNpoj9EvlrkapAVTQBZgGGslEXD6NS70EcGjhgRPBItwHdxZPM5GwqQ0cGMN06uhjeY2mHQ==", + "dependencies": { + "iceberg-js": "^0.8.0", + "tslib": "2.8.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@supabase/supabase-js": { + "version": "2.86.0", + "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.86.0.tgz", + "integrity": "sha512-BaC9sv5+HGNy1ulZwY8/Ev7EjfYYmWD4fOMw9bDBqTawEj6JHAiOHeTwXLRzVaeSay4p17xYLN2NSCoGgXMQnw==", + "dependencies": { + "@supabase/auth-js": "2.86.0", + "@supabase/functions-js": "2.86.0", + "@supabase/postgrest-js": "2.86.0", + "@supabase/realtime-js": "2.86.0", + "@supabase/storage-js": "2.86.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@swc/helpers": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", + "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "dev": true, + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.19.25", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.25.tgz", + "integrity": "sha512-ZsJzA5thDQMSQO788d7IocwwQbI8B5OPzmqNvpf3NY/+MHDAS759Wo0gd2WQeXYt5AAAQjzcrTVC6SKCuYgoCQ==", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/phoenix": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.6.tgz", + "integrity": "sha512-PIzZZlEppgrpoT2QgbnDU+MMzuR6BbCjllj0bM70lWoejMeNJAxCchxnv7J3XFkI8MpygtRpzXrIlmWUBclP5A==" + }, + "node_modules/@types/react": { + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz", + "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", + "dev": true, + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "dev": true, + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.48.1.tgz", + "integrity": "sha512-X63hI1bxl5ohelzr0LY5coufyl0LJNthld+abwxpCoo6Gq+hSqhKwci7MUWkXo67mzgUK6YFByhmaHmUcuBJmA==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.48.1", + "@typescript-eslint/type-utils": "8.48.1", + "@typescript-eslint/utils": "8.48.1", + "@typescript-eslint/visitor-keys": "8.48.1", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.48.1", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.48.1.tgz", + "integrity": "sha512-PC0PDZfJg8sP7cmKe6L3QIL8GZwU5aRvUFedqSIpw3B+QjRSUZeeITC2M5XKeMXEzL6wccN196iy3JLwKNvDVA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "8.48.1", + "@typescript-eslint/types": "8.48.1", + "@typescript-eslint/typescript-estree": "8.48.1", + "@typescript-eslint/visitor-keys": "8.48.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.48.1.tgz", + "integrity": "sha512-HQWSicah4s9z2/HifRPQ6b6R7G+SBx64JlFQpgSSHWPKdvCZX57XCbszg/bapbRsOEv42q5tayTYcEFpACcX1w==", + "dev": true, + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.48.1", + "@typescript-eslint/types": "^8.48.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.48.1.tgz", + "integrity": "sha512-rj4vWQsytQbLxC5Bf4XwZ0/CKd362DkWMUkviT7DCS057SK64D5lH74sSGzhI6PDD2HCEq02xAP9cX68dYyg1w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.48.1", + "@typescript-eslint/visitor-keys": "8.48.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.48.1.tgz", + "integrity": "sha512-k0Jhs4CpEffIBm6wPaCXBAD7jxBtrHjrSgtfCjUvPp9AZ78lXKdTR8fxyZO5y4vWNlOvYXRtngSZNSn+H53Jkw==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.48.1.tgz", + "integrity": "sha512-1jEop81a3LrJQLTf/1VfPQdhIY4PlGDBc/i67EVWObrtvcziysbLN3oReexHOM6N3jyXgCrkBsZpqwH0hiDOQg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.48.1", + "@typescript-eslint/typescript-estree": "8.48.1", + "@typescript-eslint/utils": "8.48.1", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.48.1.tgz", + "integrity": "sha512-+fZ3LZNeiELGmimrujsDCT4CRIbq5oXdHe7chLiW8qzqyPMnn1puNstCrMNVAqwcl2FdIxkuJ4tOs/RFDBVc/Q==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.48.1.tgz", + "integrity": "sha512-/9wQ4PqaefTK6POVTjJaYS0bynCgzh6ClJHGSBj06XEHjkfylzB+A3qvyaXnErEZSaxhIo4YdyBgq6j4RysxDg==", + "dev": true, + "dependencies": { + "@typescript-eslint/project-service": "8.48.1", + "@typescript-eslint/tsconfig-utils": "8.48.1", + "@typescript-eslint/types": "8.48.1", + "@typescript-eslint/visitor-keys": "8.48.1", + "debug": "^4.3.4", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.48.1.tgz", + "integrity": "sha512-fAnhLrDjiVfey5wwFRwrweyRlCmdz5ZxXz2G/4cLn0YDLjTapmN4gcCsTBR1N2rWnZSDeWpYtgLDsJt+FpmcwA==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.48.1", + "@typescript-eslint/types": "8.48.1", + "@typescript-eslint/typescript-estree": "8.48.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.48.1.tgz", + "integrity": "sha512-BmxxndzEWhE4TIEEMBs8lP3MBWN3jFPs/p6gPm/wkv02o41hI6cq9AuSmGAaTTHPtA1FTi2jBre4A9rm5ZmX+Q==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.48.1", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", + "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", + "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", + "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", + "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", + "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", + "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", + "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", + "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", + "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", + "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", + "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", + "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", + "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", + "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", + "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", + "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", + "cpu": [ + "wasm32" + ], + "dev": true, + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.11" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", + "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", + "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", + "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "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==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.11.0.tgz", + "integrity": "sha512-ilYanEU8vxxBexpJd8cWM4ElSQq4QctCLKih0TSfjIfCQTeyH/6zVrmIJfLPrKTKJRbiG+cfnZbQIjAlJmF1jQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "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==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "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/baseline-browser-mapping": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.0.tgz", + "integrity": "sha512-Mh++g+2LPfzZToywfE1BUzvZbfOY52Nil0rn9H1CPC5DJ7fX+Vir7nToBeoiSbB1zTNeGYbELEvJESujgGrzXw==", + "dev": true, + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "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==", + "devOptional": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "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": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "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": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001759", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001759.tgz", + "integrity": "sha512-Pzfx9fOKoKvevQf8oCXoyNRQ5QyxJj+3O0Rqx2V5oxT61KGx8+n6hV/IUyJeifUci2clnmmKVpvtiqRzgiWjSw==", + "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/canvas": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-3.2.0.tgz", + "integrity": "sha512-jk0GxrLtUEmW/TmFsk2WghvgHe8B0pxGilqCL21y8lHkPUGa6FTsnCNtHPOzT8O3y+N+m3espawV80bbBlgfTA==", + "hasInstallScript": true, + "dependencies": { + "node-addon-api": "^7.0.0", + "prebuild-install": "^7.1.3" + }, + "engines": { + "node": "^18.12.0 || >= 20.9.0" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "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/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==", + "dev": true, + "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==", + "dev": true + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.264", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.264.tgz", + "integrity": "sha512-1tEf0nLgltC3iy9wtlYDlQDc5Rg9lEKVjEmIHJ21rI9OcqkvD45K1oyNIRA4rR1z3LgJ7KeGzEBojVcV6m4qjA==", + "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==", + "dev": true + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/es-abstract": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", + "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz", + "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.6", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.4", + "safe-array-concat": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "dev": true, + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz", + "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.39.1", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-next": { + "version": "16.0.7", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-16.0.7.tgz", + "integrity": "sha512-WubFGLFHfk2KivkdRGfx6cGSFhaQqhERRfyO8BRx+qiGPGp7WLKcPvYC4mdx1z3VhVRcrfFzczjjTrbJZOpnEQ==", + "dev": true, + "dependencies": { + "@next/eslint-plugin-next": "16.0.7", + "eslint-import-resolver-node": "^0.3.6", + "eslint-import-resolver-typescript": "^3.5.2", + "eslint-plugin-import": "^2.32.0", + "eslint-plugin-jsx-a11y": "^6.10.0", + "eslint-plugin-react": "^7.37.0", + "eslint-plugin-react-hooks": "^7.0.0", + "globals": "16.4.0", + "typescript-eslint": "^8.46.0" + }, + "peerDependencies": { + "eslint": ">=9.0.0", + "typescript": ">=3.3.1" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-config-next/node_modules/globals": { + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz", + "integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz", + "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==", + "dev": true, + "dependencies": { + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.4.0", + "get-tsconfig": "^4.10.0", + "is-bun-module": "^2.0.0", + "stable-hash": "^0.0.5", + "tinyglobby": "^0.2.13", + "unrs-resolver": "^1.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-import-resolver-typescript" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", + "dev": true, + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", + "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", + "dev": true, + "dependencies": { + "aria-query": "^5.3.2", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.10.0", + "axobject-query": "^4.1.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.1" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz", + "integrity": "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "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.4" + }, + "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==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "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==", + "devOptional": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "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==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", + "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/gifenc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/gifenc/-/gifenc-1.0.3.tgz", + "integrity": "sha512-xdr6AdrfGBcfzncONUOlXMBuc5wJDtOueE3c5rdG0oNgtINLD+f2iFZltrBRZYzACRbKr+mSVU/x98zv2u3jmw==" + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==" + }, + "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==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true + }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "dependencies": { + "hermes-estree": "0.25.1" + } + }, + "node_modules/html-to-image": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/html-to-image/-/html-to-image-1.11.13.tgz", + "integrity": "sha512-cuOPoI7WApyhBElTTb9oqsawRvZ0rHhaHwghRLlTuffoD1B2aDemlCruLeZrUIIdvG7gs9xeELEPm6PhuASqrg==" + }, + "node_modules/iceberg-js": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/iceberg-js/-/iceberg-js-0.8.0.tgz", + "integrity": "sha512-kmgmea2nguZEvRqW79gDqNXyxA3OS5WIgMVffrHpqXV4F/J4UmNIw2vstixioLTNSkd5rFB8G0s3Lwzogm6OFw==", + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "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/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/immutable": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.4.tgz", + "integrity": "sha512-p6u1bG3YSnINT5RQmx/yRZBpenIl30kVxkTLDyHLIMk0gict704Q9n+thfDI7lTRm9vXdDYutVzXhzcThxTnXA==" + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bun-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", + "dev": true, + "dependencies": { + "semver": "^7.7.1" + } + }, + "node_modules/is-bun-module/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.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==", + "devOptional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "devOptional": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "devOptional": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "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==", + "dev": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "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==", + "devOptional": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "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/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==" + }, + "node_modules/napi-postinstall": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", + "dev": true, + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/next": { + "version": "16.0.7", + "resolved": "https://registry.npmjs.org/next/-/next-16.0.7.tgz", + "integrity": "sha512-3mBRJyPxT4LOxAJI6IsXeFtKfiJUbjCLgvXO02fV8Wy/lIhPvP94Fe7dGhUgHXcQy4sSuYwQNcOLhIfOm0rL0A==", + "dependencies": { + "@next/env": "16.0.7", + "@swc/helpers": "0.5.15", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.4.31", + "styled-jsx": "5.1.6" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=20.9.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "16.0.7", + "@next/swc-darwin-x64": "16.0.7", + "@next/swc-linux-arm64-gnu": "16.0.7", + "@next/swc-linux-arm64-musl": "16.0.7", + "@next/swc-linux-x64-gnu": "16.0.7", + "@next/swc-linux-x64-musl": "16.0.7", + "@next/swc-win32-arm64-msvc": "16.0.7", + "@next/swc-win32-x64-msvc": "16.0.7", + "sharp": "^0.34.4" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.51.1", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/node-abi": { + "version": "3.85.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.85.0.tgz", + "integrity": "sha512-zsFhmbkAzwhTft6nd3VxcG0cvJsT70rL+BIGHWVq5fi6MwGrHwzqKaxXE+Hl2GmnGItnDKPPkO5/LQqjVkIdFg==", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-abi/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==" + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true + }, + "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==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "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==", + "dev": true, + "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==", + "dev": true + }, + "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==", + "devOptional": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "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/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/pump": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz", + "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "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==", + "dev": true, + "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/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", + "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", + "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.0" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "dev": true, + "dependencies": { + "is-core-module": "^2.16.1", + "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/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "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==", + "dev": true, + "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/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "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/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sass": { + "version": "1.94.2", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.94.2.tgz", + "integrity": "sha512-N+7WK20/wOr7CzA2snJcUSSNTCzeCGUTFY3OgeQP3mZ1aj9NMQ0mSTXwlrnd89j33zzQJGqIN52GIOmYrfq46A==", + "dependencies": { + "chokidar": "^4.0.0", + "immutable": "^5.0.2", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==" + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/sharp": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "hasInstallScript": true, + "optional": true, + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" + } + }, + "node_modules/sharp/node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "optional": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "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==", + "dev": true, + "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==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "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/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "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": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "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/stable-hash": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", + "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==", + "dev": true + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string.prototype.includes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", + "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tar-fs": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", + "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "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==", + "devOptional": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "dev": true, + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "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/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.48.1.tgz", + "integrity": "sha512-FbOKN1fqNoXp1hIl5KYpObVrp0mCn+CLgn479nmu2IsRMrx2vyv74MmsBLVlhg8qVwNFGbXSp8fh1zp8pEoC2A==", + "dev": true, + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.48.1", + "@typescript-eslint/parser": "8.48.1", + "@typescript-eslint/typescript-estree": "8.48.1", + "@typescript-eslint/utils": "8.48.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==" + }, + "node_modules/unrs-resolver": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "napi-postinstall": "^0.3.0" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.1.tgz", + "integrity": "sha512-R9NcHbbZ45RoWfTdhn1J9SS7zxNvlddv4YRrHTUaFdtjbmfncfedB45EC9IaqJQ97iAR1GZgOfyRQO+ExIF6EQ==", + "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/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "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/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.13.tgz", + "integrity": "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-validation-error": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", + "dev": true, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..82bbb5f --- /dev/null +++ b/package.json @@ -0,0 +1,30 @@ +{ + "name": "signature-generator", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "eslint" + }, + "dependencies": { + "@supabase/ssr": "^0.8.0", + "@supabase/supabase-js": "^2.86.0", + "canvas": "^3.2.0", + "gifenc": "^1.0.3", + "html-to-image": "^1.11.13", + "next": "16.0.7", + "react": "19.2.0", + "react-dom": "19.2.0", + "sass": "^1.94.2" + }, + "devDependencies": { + "@types/node": "^20", + "@types/react": "^19", + "@types/react-dom": "^19", + "eslint": "^9", + "eslint-config-next": "16.0.7", + "typescript": "^5" + } +} diff --git a/public/file.svg b/public/file.svg new file mode 100644 index 0000000..004145c --- /dev/null +++ b/public/file.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/globe.svg b/public/globe.svg new file mode 100644 index 0000000..567f17b --- /dev/null +++ b/public/globe.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/next.svg b/public/next.svg new file mode 100644 index 0000000..5174b28 --- /dev/null +++ b/public/next.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/preview.webp b/public/preview.webp new file mode 100644 index 0000000000000000000000000000000000000000..e0a401b54daeaf6995ee36319be73df8de0a8609 GIT binary patch literal 6000 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 literal 0 HcmV?d00001 diff --git a/public/screenshot.png b/public/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..e1811b02a152a51213a05153ba0c57ba17dd14ee GIT binary patch literal 53049 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 + + + + Ma Signature Email + + + + + + + + + + + + + + + +
+
+ fares kerkeni +
+
+
fares kerkeni
+
commercial
+ + + + + + + + + + + + + +
+ + 📞 + + +33605050530 +
+ + ✉️ + + kerkenif11@gmail.com + + + 🌐 + + www.navier-instruments.com +
+ + 📍 + + 1 Square de la Paix +
+
+ Navier Instruments + +
+ + +

+ + Promotion + +
+ + \ No newline at end of file diff --git a/public/vercel.svg b/public/vercel.svg new file mode 100644 index 0000000..7705396 --- /dev/null +++ b/public/vercel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/window.svg b/public/window.svg new file mode 100644 index 0000000..b2b2a44 --- /dev/null +++ b/public/window.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/app/(auth)/login/page.tsx b/src/app/(auth)/login/page.tsx new file mode 100644 index 0000000..a511a59 --- /dev/null +++ b/src/app/(auth)/login/page.tsx @@ -0,0 +1,98 @@ +'use client' + +import { useState } from 'react' +import { useRouter } from 'next/navigation' +import Link from 'next/link' +import { createClient } from '@/lib/supabase/client' +import '@/styles/auth.scss' + +export default function LoginPage() { + const router = useRouter() + const [email, setEmail] = useState('') + const [password, setPassword] = useState('') + const [error, setError] = useState(null) + const [loading, setLoading] = useState(false) + + const handleLogin = async (e: React.FormEvent) => { + e.preventDefault() + setLoading(true) + setError(null) + + const supabase = createClient() + const { error } = await supabase.auth.signInWithPassword({ + email, + password, + }) + + if (error) { + setError(error.message) + setLoading(false) + } else { + router.push('/dashboard') + router.refresh() + } + } + + return ( +
+
+
+
+
SignGen
+

Connexion

+

+ Connectez-vous pour créer vos signatures email +

+
+ +
+ {error &&
{error}
} + +
+ + setEmail(e.target.value)} + required + /> +
+ +
+ + setPassword(e.target.value)} + required + /> +
+ + +
+ +
+ Pas encore de compte ?{' '} + Créer un compte +
+
+
+
+ ) +} diff --git a/src/app/(auth)/register/page.tsx b/src/app/(auth)/register/page.tsx new file mode 100644 index 0000000..b25940e --- /dev/null +++ b/src/app/(auth)/register/page.tsx @@ -0,0 +1,154 @@ +'use client' + +import { useState } from 'react' +import { useRouter } from 'next/navigation' +import Link from 'next/link' +import { createClient } from '@/lib/supabase/client' +import '@/styles/auth.scss' + +export default function RegisterPage() { + const router = useRouter() + const [email, setEmail] = useState('') + const [password, setPassword] = useState('') + const [confirmPassword, setConfirmPassword] = useState('') + const [error, setError] = useState(null) + const [success, setSuccess] = useState(false) + const [loading, setLoading] = useState(false) + + const handleRegister = async (e: React.FormEvent) => { + e.preventDefault() + setLoading(true) + setError(null) + + if (password !== confirmPassword) { + setError('Les mots de passe ne correspondent pas') + setLoading(false) + return + } + + if (password.length < 6) { + setError('Le mot de passe doit contenir au moins 6 caractères') + setLoading(false) + return + } + + const supabase = createClient() + const { error } = await supabase.auth.signUp({ + email, + password, + options: { + emailRedirectTo: `${window.location.origin}/api/auth/callback`, + }, + }) + + if (error) { + setError(error.message) + setLoading(false) + } else { + setSuccess(true) + setLoading(false) + } + } + + if (success) { + return ( +
+
+
+
+
SignGen
+

Vérifiez votre email

+

+ Un email de confirmation a été envoyé à {email}. + Cliquez sur le lien pour activer votre compte. +

+
+
+ Retour à la connexion +
+
+
+
+ ) + } + + return ( +
+
+
+
+
SignGen
+

Créer un compte

+

+ Inscrivez-vous pour créer vos signatures email +

+
+ +
+ {error &&
{error}
} + +
+ + setEmail(e.target.value)} + required + /> +
+ +
+ + setPassword(e.target.value)} + required + minLength={6} + /> +
+ +
+ + setConfirmPassword(e.target.value)} + required + minLength={6} + /> +
+ + +
+ +
+ Déjà un compte ?{' '} + Se connecter +
+
+
+
+ ) +} diff --git a/src/app/api/auth/callback/route.ts b/src/app/api/auth/callback/route.ts new file mode 100644 index 0000000..6569d06 --- /dev/null +++ b/src/app/api/auth/callback/route.ts @@ -0,0 +1,18 @@ +import { createClient } from '@/lib/supabase/server' +import { NextResponse } from 'next/server' + +export async function GET(request: Request) { + const { searchParams, origin } = new URL(request.url) + const code = searchParams.get('code') + const next = searchParams.get('next') ?? '/dashboard' + + if (code) { + const supabase = await createClient() + const { error } = await supabase.auth.exchangeCodeForSession(code) + if (!error) { + return NextResponse.redirect(`${origin}${next}`) + } + } + + return NextResponse.redirect(`${origin}/login?error=auth_callback_error`) +} diff --git a/src/app/dashboard/page.tsx b/src/app/dashboard/page.tsx new file mode 100644 index 0000000..746c380 --- /dev/null +++ b/src/app/dashboard/page.tsx @@ -0,0 +1,283 @@ +'use client' + +import { useRef, useState, useEffect } from 'react' +import { useRouter } from 'next/navigation' +import { createClient } from '@/lib/supabase/client' +import SignatureEditor from '@/components/SignatureEditor' +import SignaturePreview from '@/components/SignaturePreview' +import StyleSelector from '@/components/StyleSelector' +import BannerGenerator from '@/components/BannerGenerator' +import { useSignatures, SavedSignature } from '@/hooks/useSignatures' +import { colorThemes, SignatureStyle } from '@/lib/types' +import { generateSignatureHTML, exportAsImage, copyHTMLToClipboard, downloadHTML } from '@/lib/export' +import '@/styles/dashboard.scss' + +export default function DashboardPage() { + const router = useRouter() + const [user, setUser] = useState<{ email: string } | null>(null) + const [copySuccess, setCopySuccess] = useState(false) + const [exportLoading, setExportLoading] = useState(false) + const [activeTab, setActiveTab] = useState<'editor' | 'style' | 'banner'>('editor') + const signatureRef = useRef(null) + + const { + signatures, + currentSignature, + currentId, + loading, + saving, + updateSignature, + createNewSignature, + selectSignature, + deleteSignature, + } = useSignatures() + + useEffect(() => { + const supabase = createClient() + supabase.auth.getUser().then(({ data }) => { + if (data.user) { + setUser({ email: data.user.email || '' }) + } else { + router.push('/login') + } + }) + }, [router]) + + const handleLogout = async () => { + const supabase = createClient() + await supabase.auth.signOut() + router.push('/login') + router.refresh() + } + + const handleNewSignature = async () => { + await createNewSignature() + setActiveTab('editor') + } + + const handleStyleChange = (style: SignatureStyle) => { + updateSignature({ ...currentSignature, styleTemplate: style }) + } + + const handleThemeChange = (themeIndex: number) => { + const theme = colorThemes[themeIndex] + updateSignature({ + ...currentSignature, + primaryColor: theme.primary, + secondaryColor: theme.secondary, + accentColor: theme.accent, + }) + } + + const handleBannerChange = (url: string) => { + updateSignature({ ...currentSignature, bannerUrl: url }) + } + + const handleBannerLinkChange = (link: string) => { + updateSignature({ ...currentSignature, bannerLink: link }) + } + + const handleCopyHTML = async () => { + const html = generateSignatureHTML(currentSignature) + try { + await copyHTMLToClipboard(html) + setCopySuccess(true) + setTimeout(() => setCopySuccess(false), 2000) + } catch (error) { + console.error('Error copying HTML:', error) + } + } + + const handleDownloadHTML = () => { + const html = generateSignatureHTML(currentSignature) + const filename = `signature-${currentSignature.firstName || 'email'}-${currentSignature.lastName || ''}.html` + downloadHTML(html, filename) + } + + const handleExportImage = async () => { + if (!signatureRef.current) return + setExportLoading(true) + try { + await exportAsImage(signatureRef.current) + } catch (error) { + console.error('Error exporting image:', error) + } finally { + setExportLoading(false) + } + } + + const handleDeleteSignature = async (sig: SavedSignature, e: React.MouseEvent) => { + e.stopPropagation() + if (confirm(`Supprimer la signature de ${sig.firstName} ${sig.lastName} ?`)) { + await deleteSignature(sig.id) + } + } + + if (loading) { + return ( +
+
+
+

Chargement...

+
+
+ ) + } + + return ( +
+ {/* Header */} +
+
+
Navier Signatures
+
+ {saving && Sauvegarde...} + {user && {user.email}} + +
+
+
+ +
+ {/* Sidebar */} + + + {/* Main content */} +
+ {/* Tabs */} + + +
+ {/* Editor Panel */} +
+ {activeTab === 'editor' && ( + + )} + + {activeTab === 'style' && ( + t.primary === currentSignature.primaryColor)} + onStyleChange={handleStyleChange} + onThemeChange={handleThemeChange} + photoShape={currentSignature.photoShape} + onPhotoShapeChange={(shape) => updateSignature({ ...currentSignature, photoShape: shape })} + /> + )} + + {activeTab === 'banner' && ( + + )} +
+ + {/* Preview Panel */} +
+

Aperçu

+ +
+ +
+ +
+ + + +
+ +

+ Collez le HTML dans les paramètres de signature de votre client email. +

+
+
+
+
+
+ ) +} diff --git a/src/app/favicon.ico b/src/app/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..718d6fea4835ec2d246af9800eddb7ffb276240c GIT binary patch literal 25931 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 LrJugUA?W`A8`#=m literal 0 HcmV?d00001 diff --git a/src/app/layout.tsx b/src/app/layout.tsx new file mode 100644 index 0000000..614c94e --- /dev/null +++ b/src/app/layout.tsx @@ -0,0 +1,19 @@ +import type { Metadata } from "next"; +import "@/styles/globals.scss"; + +export const metadata: Metadata = { + title: "SignGen - Générateur de Signatures Email", + description: "Créez des signatures email professionnelles avec bannière en quelques clics", +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + {children} + + ); +} diff --git a/src/app/page.tsx b/src/app/page.tsx new file mode 100644 index 0000000..7c1c47d --- /dev/null +++ b/src/app/page.tsx @@ -0,0 +1,70 @@ +import Link from 'next/link' +import '@/styles/home.scss' + +export default function HomePage() { + return ( +
+
+
+
SignGen
+ +
+
+ +
+
+

+ Créez des signatures email + professionnelles +

+

+ Générez facilement des signatures email avec bannières promotionnelles. + Exportez en HTML ou PNG en un clic. +

+
+ + Commencer gratuitement + +
+
+ +
+
+
✏️
+

Éditeur simple

+

+ Remplissez vos informations et personnalisez les couleurs en temps réel +

+
+ +
+
🖼️
+

Bannières promo

+

+ Ajoutez une bannière promotionnelle cliquable à votre signature +

+
+ +
+
📤
+

Export facile

+

+ Téléchargez en HTML ou PNG, compatible Gmail et Outlook +

+
+
+
+ +
+

© 2024 SignGen. Tous droits réservés.

+
+
+ ) +} diff --git a/src/components/BannerGenerator.tsx b/src/components/BannerGenerator.tsx new file mode 100644 index 0000000..f11c2f9 --- /dev/null +++ b/src/components/BannerGenerator.tsx @@ -0,0 +1,345 @@ +'use client' + +import { useState, useRef, useEffect } from 'react' + +interface BannerGeneratorProps { + bannerUrl: string + bannerLink: string + onBannerChange: (url: string) => void + onLinkChange: (link: string) => void +} + +interface BannerTemplate { + id: string + name: string + colors: { bg1: string; bg2: string; accent: string; text: string } +} + +const bannerTemplates: BannerTemplate[] = [ + { id: 'navier', name: 'Navier Gold', colors: { bg1: '#1a1a2e', bg2: '#16213e', accent: '#F5A623', text: '#ffffff' } }, + { id: 'ocean', name: 'Ocean', colors: { bg1: '#0077B6', bg2: '#023E8A', accent: '#90E0EF', text: '#ffffff' } }, + { id: 'forest', name: 'Forest', colors: { bg1: '#2D6A4F', bg2: '#1B4332', accent: '#95D5B2', text: '#ffffff' } }, + { id: 'sunset', name: 'Sunset', colors: { bg1: '#E85D04', bg2: '#9D0208', accent: '#FFBA08', text: '#ffffff' } }, + { id: 'royal', name: 'Royal', colors: { bg1: '#7209B7', bg2: '#3A0CA3', accent: '#4CC9F0', text: '#ffffff' } }, + { id: 'charcoal', name: 'Charcoal', colors: { bg1: '#495057', bg2: '#212529', accent: '#ADB5BD', text: '#ffffff' } }, + { id: 'coral', name: 'Coral', colors: { bg1: '#FF6B6B', bg2: '#C92A2A', accent: '#FFE066', text: '#ffffff' } }, + { id: 'mint', name: 'Mint', colors: { bg1: '#12B886', bg2: '#087F5B', accent: '#C3FAE8', text: '#ffffff' } }, + { id: 'tech', name: 'Tech Dark', colors: { bg1: '#0f172a', bg2: '#1e293b', accent: '#38bdf8', text: '#ffffff' } }, + { id: 'minimal', name: 'Minimal', colors: { bg1: '#ffffff', bg2: '#f8fafc', accent: '#3b82f6', text: '#1e293b' } }, +] + +export default function BannerGenerator({ + bannerUrl, + bannerLink, + onBannerChange, + onLinkChange, +}: BannerGeneratorProps) { + const canvasRef = useRef(null) + const [selectedTemplate, setSelectedTemplate] = useState(bannerTemplates[0]) + const [bannerTitle, setBannerTitle] = useState('Découvrez nos nouvelles solutions') + const [bannerSubtitle, setBannerSubtitle] = useState('Offre spéciale -20% jusqu\'au 31 décembre') + const [ctaText, setCtaText] = useState('En savoir plus') + const [generating, setGenerating] = useState(false) + const animationRef = useRef(undefined) + const frameRef = useRef(0) + + // Animation de preview + useEffect(() => { + const animate = () => { + frameRef.current = (frameRef.current + 1) % 120 + drawBanner(frameRef.current) + animationRef.current = requestAnimationFrame(animate) + } + animate() + + return () => { + if (animationRef.current) { + cancelAnimationFrame(animationRef.current) + } + } + }, [selectedTemplate, bannerTitle, bannerSubtitle, ctaText]) + + const drawBanner = (frame: number) => { + const canvas = canvasRef.current + if (!canvas) return + + const ctx = canvas.getContext('2d') + if (!ctx) return + + const width = 600 + const height = 150 + const colors = selectedTemplate.colors + + // Clear + ctx.clearRect(0, 0, width, height) + + // Background gradient + const gradient = ctx.createLinearGradient(0, 0, width, height) + gradient.addColorStop(0, colors.bg1) + gradient.addColorStop(1, colors.bg2) + ctx.fillStyle = gradient + ctx.fillRect(0, 0, width, height) + + // Decorative elements based on template + drawDecorations(ctx, width, height, frame, colors) + + // Content + drawContent(ctx, width, height, frame, colors) + } + + const drawDecorations = ( + ctx: CanvasRenderingContext2D, + width: number, + height: number, + frame: number, + colors: BannerTemplate['colors'] + ) => { + const accentRgb = hexToRgb(colors.accent) + + // Animated circles + ctx.fillStyle = `rgba(${accentRgb.r}, ${accentRgb.g}, ${accentRgb.b}, 0.15)` + ctx.beginPath() + ctx.arc( + width - 80 + Math.sin(frame * 0.03) * 10, + 30 + Math.cos(frame * 0.02) * 5, + 60, + 0, + Math.PI * 2 + ) + ctx.fill() + + ctx.fillStyle = `rgba(${accentRgb.r}, ${accentRgb.g}, ${accentRgb.b}, 0.1)` + ctx.beginPath() + ctx.arc( + width - 120, + height - 20 + Math.sin(frame * 0.04) * 8, + 40, + 0, + Math.PI * 2 + ) + ctx.fill() + + // Animated wave at bottom + ctx.fillStyle = `rgba(${accentRgb.r}, ${accentRgb.g}, ${accentRgb.b}, 0.1)` + ctx.beginPath() + ctx.moveTo(0, height) + for (let x = 0; x <= width; x += 10) { + const y = height - 15 + Math.sin((x + frame * 2) * 0.02) * 8 + ctx.lineTo(x, y) + } + ctx.lineTo(width, height) + ctx.closePath() + ctx.fill() + + // Grid pattern for tech style + if (selectedTemplate.id === 'tech') { + ctx.strokeStyle = `rgba(${accentRgb.r}, ${accentRgb.g}, ${accentRgb.b}, 0.1)` + ctx.lineWidth = 1 + for (let x = 0; x < width; x += 30) { + ctx.beginPath() + ctx.moveTo(x, 0) + ctx.lineTo(x, height) + ctx.stroke() + } + for (let y = 0; y < height; y += 30) { + ctx.beginPath() + ctx.moveTo(0, y) + ctx.lineTo(width, y) + ctx.stroke() + } + } + + // Left accent bar for minimal + if (selectedTemplate.id === 'minimal') { + ctx.fillStyle = colors.accent + ctx.fillRect(0, 0, 6, height) + } + } + + const drawContent = ( + ctx: CanvasRenderingContext2D, + width: number, + height: number, + frame: number, + colors: BannerTemplate['colors'] + ) => { + const textX = selectedTemplate.id === 'minimal' ? 30 : 25 + + // Title + ctx.textAlign = 'left' + ctx.textBaseline = 'middle' + ctx.font = 'bold 22px Arial, sans-serif' + ctx.fillStyle = colors.text + + const titleY = height / 2 - 25 + Math.sin(frame * 0.05) * 1 + ctx.fillText(bannerTitle, textX, titleY) + + // Subtitle + ctx.font = '14px Arial, sans-serif' + ctx.fillStyle = colors.accent + ctx.fillText(bannerSubtitle, textX, height / 2 + 5) + + // CTA Button + if (ctaText) { + const btnX = textX + const btnY = height / 2 + 35 + const btnPadding = 16 + const btnHeight = 28 + + ctx.font = '13px Arial, sans-serif' + const btnWidth = ctx.measureText(ctaText).width + btnPadding * 2 + + // Button background + ctx.fillStyle = colors.accent + ctx.beginPath() + ctx.roundRect(btnX, btnY - btnHeight / 2, btnWidth, btnHeight, 14) + ctx.fill() + + // Button text + ctx.fillStyle = selectedTemplate.id === 'minimal' || selectedTemplate.id === 'charcoal' + ? colors.bg1 + : '#1a1a2e' + ctx.textAlign = 'center' + ctx.fillText(ctaText, btnX + btnWidth / 2, btnY) + + // Arrow + ctx.fillStyle = selectedTemplate.id === 'minimal' ? colors.bg1 : '#1a1a2e' + const arrowX = btnX + btnWidth - 20 + ctx.beginPath() + ctx.moveTo(arrowX, btnY - 3) + ctx.lineTo(arrowX + 5, btnY) + ctx.lineTo(arrowX, btnY + 3) + ctx.fill() + } + } + + const hexToRgb = (hex: string) => { + const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex) + return result ? { + r: parseInt(result[1], 16), + g: parseInt(result[2], 16), + b: parseInt(result[3], 16) + } : { r: 245, g: 166, b: 35 } + } + + const generateBanner = async () => { + setGenerating(true) + + // Draw final static frame + drawBanner(0) + + const dataUrl = canvasRef.current?.toDataURL('image/png') + if (dataUrl) { + onBannerChange(dataUrl) + } + + setGenerating(false) + } + + return ( +
+ {/* Preview animé */} +
+ +
+ + {/* Sélecteur de template */} +
+ +
+ {bannerTemplates.map((template) => ( + + ))} +
+
+ + {/* Champs de texte */} +
+ + setBannerTitle(e.target.value)} + placeholder="Découvrez nos nouvelles solutions" + /> +
+ +
+ + setBannerSubtitle(e.target.value)} + placeholder="Offre spéciale -20%..." + /> +
+ +
+
+ + setCtaText(e.target.value)} + placeholder="En savoir plus" + /> +
+
+ + onLinkChange(e.target.value)} + placeholder="https://..." + /> +
+
+ + {/* Actions */} +
+ + {bannerUrl && ( + + )} +
+ +

+ La bannière apparaîtra en bas de votre signature email. +

+
+ ) +} diff --git a/src/components/BannerUpload.tsx b/src/components/BannerUpload.tsx new file mode 100644 index 0000000..d9c4ca5 --- /dev/null +++ b/src/components/BannerUpload.tsx @@ -0,0 +1,75 @@ +'use client' + +import { useRef } from 'react' + +interface BannerUploadProps { + value: string + onChange: (url: string) => void + label: string + hint?: string +} + +export default function BannerUpload({ value, onChange, label, hint }: BannerUploadProps) { + const inputRef = useRef(null) + + const handleClick = () => { + inputRef.current?.click() + } + + const handleChange = (e: React.ChangeEvent) => { + const file = e.target.files?.[0] + if (file) { + // Convert to base64 for preview + const reader = new FileReader() + reader.onloadend = () => { + onChange(reader.result as string) + } + reader.readAsDataURL(file) + } + } + + const handleRemove = (e: React.MouseEvent) => { + e.stopPropagation() + onChange('') + if (inputRef.current) { + inputRef.current.value = '' + } + } + + return ( +
+ + + {value ? ( +
+ {label} + +
+ ) : ( +
+ 📷 + + Cliquez pour ajouter une {label.toLowerCase()} + + {hint && {hint}} +
+ )} +
+ ) +} diff --git a/src/components/ImageUpload.tsx b/src/components/ImageUpload.tsx new file mode 100644 index 0000000..b16bda8 --- /dev/null +++ b/src/components/ImageUpload.tsx @@ -0,0 +1,105 @@ +'use client' + +import { useRef, useState } from 'react' +import { uploadImage } from '@/lib/upload' + +interface ImageUploadProps { + value: string + onChange: (url: string) => void + folder?: string + label?: string + hint?: string + aspectRatio?: string +} + +export default function ImageUpload({ + value, + onChange, + folder = 'images', + label = 'image', + hint, + aspectRatio = '4 / 1' +}: ImageUploadProps) { + const inputRef = useRef(null) + const [uploading, setUploading] = useState(false) + const [error, setError] = useState(null) + + const handleClick = () => { + if (!uploading) { + inputRef.current?.click() + } + } + + const handleChange = async (e: React.ChangeEvent) => { + const file = e.target.files?.[0] + if (!file) return + + setUploading(true) + setError(null) + + const result = await uploadImage(file, folder) + + if (result.success && result.url) { + onChange(result.url) + } else { + setError(result.error || 'Erreur upload') + } + + setUploading(false) + + // Reset input + if (inputRef.current) { + inputRef.current.value = '' + } + } + + const handleRemove = (e: React.MouseEvent) => { + e.stopPropagation() + onChange('') + } + + return ( +
+ + + {uploading ? ( +
+ + Upload en cours... +
+ ) : value ? ( +
+ {label} + +
+ ) : ( +
+ 📷 + + Cliquez pour uploader une {label.toLowerCase()} + + {hint && {hint}} + {error && {error}} +
+ )} +
+ ) +} diff --git a/src/components/SignatureEditor.tsx b/src/components/SignatureEditor.tsx new file mode 100644 index 0000000..1984350 --- /dev/null +++ b/src/components/SignatureEditor.tsx @@ -0,0 +1,220 @@ +'use client' + +import { SignatureData } from '@/lib/types' +import BannerUpload from './BannerUpload' + +interface SignatureEditorProps { + data: SignatureData + onChange: (data: SignatureData) => void +} + +export default function SignatureEditor({ data, onChange }: SignatureEditorProps) { + const updateField = (field: keyof SignatureData, value: string) => { + onChange({ ...data, [field]: value }) + } + + return ( +
+ {/* Personal Information */} +

Informations personnelles

+ +
+
+ + updateField('firstName', e.target.value)} + /> +
+
+ + updateField('lastName', e.target.value)} + /> +
+
+ +
+
+ + updateField('jobTitle', e.target.value)} + /> +
+
+ + updateField('company', e.target.value)} + /> +
+
+ +
+ + {/* Contact Information */} +

Contact

+ +
+ + updateField('email', e.target.value)} + /> +
+ +
+
+ + updateField('phone', e.target.value)} + /> +
+
+ + updateField('mobile', e.target.value)} + /> +
+
+ +
+ + updateField('website', e.target.value)} + /> +
+ +
+ + updateField('address', e.target.value)} + /> +
+ +
+ + {/* Logo & Photo */} +

Logo & Photo

+ +
+
+ + updateField('logoUrl', url)} + label="Logo" + hint="Format carré (100x100px)" + /> +
+
+ + updateField('photoUrl', url)} + label="Photo" + hint="Image carrée (200x200px)" + /> +
+
+ +
+ + {/* Social Links */} +

Réseaux sociaux

+ +
+
+ + updateField('linkedin', e.target.value)} + /> +
+
+ + updateField('twitter', e.target.value)} + /> +
+
+ +
+
+ + updateField('facebook', e.target.value)} + /> +
+
+ + updateField('instagram', e.target.value)} + /> +
+
+ +
+ ) +} diff --git a/src/components/SignaturePreview.module.scss b/src/components/SignaturePreview.module.scss new file mode 100644 index 0000000..f7468bd --- /dev/null +++ b/src/components/SignaturePreview.module.scss @@ -0,0 +1,274 @@ +// ======================================= +// SIGNATURE PREVIEW - TEMPLATE STYLE +// ======================================= + +// Variables (couleurs du logo Navier) +$accent: #3498db; // Bleu Navier +$dark: #3a3a3a; // Gris foncé +$text: #333333; +$textLight: #666666; + +// Container principal +.signature { + display: flex; + align-items: stretch; + background: #ffffff; + border-top: 3px solid $accent; + border-bottom: 3px solid $accent; + max-width: 600px; + font-family: Arial, sans-serif; +} + +// ======================================= +// PARTIE GAUCHE - Formes + Photo +// ======================================= +.leftSection { + position: relative; + width: 160px; + min-height: 140px; + flex-shrink: 0; +} + +// Trapèze jaune (derrière) - forme de chevron gauche +.trapezoidYellow { + position: absolute; + top: 50%; + left: 10px; + width: 70px; + height: 120px; + background: $accent; + clip-path: polygon(100% 0, 0 50%, 100% 100%); + transform: translateY(-50%); +} + +// Trapèze bleu foncé (devant) - forme de chevron droit +.trapezoidDark { + position: absolute; + top: 50%; + left: 35px; + width: 70px; + height: 120px; + background: $dark; + clip-path: polygon(0 0, 100% 50%, 0 100%); + transform: translateY(-50%); +} + +// Container photo hexagonale +.photoContainer { + position: absolute; + left: 30px; + top: 50%; + transform: translateY(-50%); + width: 100px; + height: 100px; + z-index: 10; +} + +// Hexagone (bordure) +.hexagonBorder { + width: 100%; + height: 100%; + background: $dark; + clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%); + display: flex; + align-items: center; + justify-content: center; +} + +// Hexagone intérieur (photo) +.hexagonInner { + width: 92px; + height: 92px; + background: #ffffff; + clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%); + overflow: hidden; + display: flex; + align-items: center; + justify-content: center; +} + +.photo { + width: 100%; + height: 100%; + object-fit: cover; +} + +// ======================================= +// PARTIE CENTRALE - Infos +// ======================================= +.centerSection { + flex: 1; + padding: 15px 20px; + display: flex; + flex-direction: column; + justify-content: center; +} + +// Triangle décoratif en haut +.triangleTop { + align-self: flex-end; + width: 0; + height: 0; + border-left: 8px solid transparent; + border-right: 8px solid transparent; + border-bottom: 12px solid $accent; + margin-bottom: 8px; +} + +.name { + font-size: 18px; + font-weight: 700; + color: $dark; + margin: 0 0 2px 0; +} + +.jobTitle { + font-size: 13px; + color: $textLight; + margin: 0; +} + +// Barre de séparation horizontale +.separator { + width: 100%; + height: 3px; + background: $accent; + margin: 10px 0; +} + +// Contacts en 2 colonnes +.contactGrid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 6px 20px; +} + +.contactItem { + display: flex; + align-items: center; + gap: 8px; + font-size: 11px; + color: $text; +} + +// Icône ronde +.contactIcon { + width: 18px; + height: 18px; + background: $dark; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + + svg { + width: 10px; + height: 10px; + fill: #ffffff; + } +} + +.contactLink { + color: $text; + text-decoration: none; + + &:hover { + text-decoration: underline; + } +} + +// Adresse (pleine largeur) +.address { + grid-column: 1 / -1; +} + +// ======================================= +// PARTIE DROITE - Logo + Social +// ======================================= +.rightSection { + width: 110px; + padding: 15px 10px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + position: relative; +} + +// Triangle décoratif en haut à droite +.triangleTopRight { + position: absolute; + top: 0; + right: 0; + width: 0; + height: 0; + border-top: 30px solid $accent; + border-left: 25px solid transparent; +} + +// Triangle outline en bas à droite +.triangleBottomRight { + position: absolute; + bottom: 10px; + right: 10px; + width: 0; + height: 0; + border-left: 8px solid transparent; + border-right: 8px solid transparent; + border-bottom: 12px solid transparent; + border-bottom-color: $accent; + // Pour faire un outline, on peut utiliser un pseudo-element +} + +.logo { + display: block; + width: 80px; + height: auto; + max-height: 50px; + object-fit: contain; + margin-bottom: 10px; +} + +// Icônes réseaux sociaux +.socialIcons { + display: flex; + gap: 6px; + flex-wrap: wrap; + justify-content: center; +} + +.socialIcon { + width: 24px; + height: 24px; + background: $dark; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + text-decoration: none; + + svg { + width: 12px; + height: 12px; + fill: #ffffff; + } + + &:hover { + opacity: 0.8; + } +} + +// ======================================= +// BANNIÈRE PROMO +// ======================================= +.banner { + margin-top: 12px; + + img { + max-width: 100%; + height: auto; + display: block; + border-radius: 4px; + } +} diff --git a/src/components/SignaturePreview.tsx b/src/components/SignaturePreview.tsx new file mode 100644 index 0000000..9977cb5 --- /dev/null +++ b/src/components/SignaturePreview.tsx @@ -0,0 +1,167 @@ +"use client"; + +import { SignatureData } from "@/lib/types"; +import { forwardRef } from "react"; +import Styles from "./SignaturePreview.module.scss"; + +interface SignaturePreviewProps { + data: SignatureData; + bannerUrl?: string; + bannerLink?: string; +} + +const SignaturePreview = forwardRef( + ({ data, bannerUrl, bannerLink }, ref) => { + const fullName = `${data.firstName} ${data.lastName}`.trim(); + + return ( +
+ {/* ========== SIGNATURE CONTAINER ========== */} +
+ + {/* ===== PARTIE GAUCHE - Formes + Photo ===== */} +
+ {/* Trapèze jaune */} +
+ {/* Trapèze bleu foncé */} +
+ {/* Photo hexagonale */} +
+
+
+ {data.photoUrl && ( + {fullName} + )} +
+
+
+
+ + {/* ===== PARTIE CENTRALE - Infos ===== */} +
+ {/* Triangle décoratif */} +
+ + {/* Nom */} + {fullName &&
{fullName}
} + + {/* Poste */} + {data.jobTitle &&
{data.jobTitle}
} + + {/* Barre de séparation verticale */} +
+ + {/* Contacts en grille 2 colonnes */} +
+ {/* Téléphone */} + {data.phone && ( +
+ + + + {data.phone} +
+ )} + + {/* Mobile */} + {data.mobile && ( +
+ + + + {data.mobile} +
+ )} + + {/* Email */} + {data.email && ( +
+ + + + {data.email} +
+ )} + + {/* Site web */} + {data.website && ( +
+ + + + {data.website} +
+ )} + + {/* Adresse */} + {data.address && ( +
+ + + + {data.address} +
+ )} +
+
+ + {/* ===== PARTIE DROITE - Logo + Social ===== */} +
+ {/* Triangle décoratif haut */} +
+ + {/* Logo */} + {data.logoUrl && ( + {data.company + )} + + {/* Réseaux sociaux */} +
+ {data.facebook && ( + + + + )} + {data.instagram && ( + + + + )} + {data.twitter && ( + + + + )} + {data.linkedin && ( + + + + )} +
+ + {/* Triangle décoratif bas */} +
+
+ +
+ + {/* ========== BANNIÈRE PROMO ========== */} + {bannerUrl && ( +
+ {bannerLink ? ( + + Promotion + + ) : ( + Promotion + )} +
+ )} +
+ ); + } +); + +SignaturePreview.displayName = "SignaturePreview"; + +export default SignaturePreview; diff --git a/src/components/StyleSelector.tsx b/src/components/StyleSelector.tsx new file mode 100644 index 0000000..eeca67e --- /dev/null +++ b/src/components/StyleSelector.tsx @@ -0,0 +1,160 @@ +'use client' + +import { SignatureStyle, colorThemes } from '@/lib/types' + +interface StyleSelectorProps { + currentStyle: SignatureStyle + currentThemeIndex: number + onStyleChange: (style: SignatureStyle) => void + onThemeChange: (themeIndex: number) => void + photoShape: 'circle' | 'hexagon' + onPhotoShapeChange: (shape: 'circle' | 'hexagon') => void +} + +const styles: { id: SignatureStyle; name: string; description: string }[] = [ + { id: 'geometric', name: 'Géométrique', description: 'Formes triangulaires modernes' }, + { id: 'minimal', name: 'Minimal', description: 'Design épuré et simple' }, + { id: 'corporate', name: 'Corporate', description: 'Style professionnel classique' }, + { id: 'creative', name: 'Créatif', description: 'Design audacieux et coloré' }, +] + +export default function StyleSelector({ + currentStyle, + currentThemeIndex, + onStyleChange, + onThemeChange, + photoShape, + onPhotoShapeChange, +}: StyleSelectorProps) { + return ( +
+ {/* Style Templates */} +
+

Style de signature

+
+ {styles.map((style) => ( + + ))} +
+
+ + {/* Color Themes */} +
+

Thème de couleurs

+
+ {colorThemes.map((theme, index) => ( + + ))} +
+
+ + {/* Photo Shape */} +
+

Forme de la photo

+
+ + +
+
+
+ ) +} + +// Mini preview icons for each style +function StylePreviewIcon({ style }: { style: SignatureStyle }) { + switch (style) { + case 'geometric': + return ( + + + + + + ) + case 'minimal': + return ( + + + + + + + ) + case 'corporate': + return ( + + + + + + + + + ) + case 'creative': + return ( + + + + + + + + + ) + } +} diff --git a/src/hooks/useBanners.ts b/src/hooks/useBanners.ts new file mode 100644 index 0000000..1b70f11 --- /dev/null +++ b/src/hooks/useBanners.ts @@ -0,0 +1,100 @@ +'use client' + +import { useState, useEffect } from 'react' +import { createClient } from '@/lib/supabase/client' +import { Banner } from '@/lib/types' + +export function useBanners() { + const [banners, setBanners] = useState([]) + const [loading, setLoading] = useState(true) + const [error, setError] = useState(null) + + useEffect(() => { + const supabase = createClient() + + // Charger les bannières initiales + const fetchBanners = async () => { + try { + const { data, error } = await supabase + .from('banners') + .select('*') + .eq('is_active', true) + .order('order', { ascending: true }) + + if (error) throw error + setBanners(data || []) + } catch (err) { + setError(err instanceof Error ? err.message : 'Erreur lors du chargement des bannières') + } finally { + setLoading(false) + } + } + + fetchBanners() + + // Écouter les changements en temps réel + const channel = supabase + .channel('banners-changes') + .on( + 'postgres_changes', + { + event: '*', + schema: 'public', + table: 'banners', + }, + () => { + // Recharger les bannières quand il y a un changement + fetchBanners() + } + ) + .subscribe() + + return () => { + supabase.removeChannel(channel) + } + }, []) + + return { banners, loading, error } +} + +// Hook pour vérifier si l'utilisateur est admin +export function useIsAdmin() { + const [isAdmin, setIsAdmin] = useState(false) + const [loading, setLoading] = useState(true) + + useEffect(() => { + const supabase = createClient() + + const checkAdmin = async () => { + try { + const { data: { user } } = await supabase.auth.getUser() + + if (!user) { + setIsAdmin(false) + return + } + + const { data, error } = await supabase + .from('admins') + .select('id') + .eq('user_id', user.id) + .single() + + if (error && error.code !== 'PGRST116') { + console.error('Erreur vérification admin:', error) + } + + setIsAdmin(!!data) + } catch (err) { + console.error('Erreur:', err) + setIsAdmin(false) + } finally { + setLoading(false) + } + } + + checkAdmin() + }, []) + + return { isAdmin, loading } +} diff --git a/src/hooks/useSignature.ts b/src/hooks/useSignature.ts new file mode 100644 index 0000000..e845eec --- /dev/null +++ b/src/hooks/useSignature.ts @@ -0,0 +1,182 @@ +'use client' + +import { useState, useEffect, useCallback } from 'react' +import { createClient } from '@/lib/supabase/client' +import { SignatureData, defaultSignatureData } from '@/lib/types' + +// Convertir les données DB vers le format de l'app +function dbToSignature(data: Record): SignatureData { + return { + firstName: (data.first_name as string) || '', + lastName: (data.last_name as string) || '', + jobTitle: (data.job_title as string) || '', + company: (data.company as string) || '', + email: (data.email as string) || '', + phone: (data.phone as string) || '', + mobile: (data.mobile as string) || '', + website: (data.website as string) || '', + address: (data.address as string) || '', + photoUrl: (data.photo_url as string) || '', + logoUrl: (data.logo_url as string) || '', + linkedin: (data.linkedin as string) || '', + twitter: (data.twitter as string) || '', + facebook: (data.facebook as string) || '', + instagram: (data.instagram as string) || '', + primaryColor: (data.primary_color as string) || '#F5A623', + secondaryColor: (data.secondary_color as string) || '#1a1a2e', + accentColor: (data.accent_color as string) || '#F5A623', + photoShape: (data.photo_shape as 'circle' | 'hexagon') || 'hexagon', + styleTemplate: (data.style_template as 'geometric' | 'minimal' | 'corporate' | 'creative') || 'geometric', + } +} + +// Convertir les données de l'app vers le format DB +function signatureToDb(data: SignatureData, userId: string) { + return { + user_id: userId, + first_name: data.firstName, + last_name: data.lastName, + job_title: data.jobTitle, + company: data.company, + email: data.email, + phone: data.phone, + mobile: data.mobile, + website: data.website, + address: data.address, + photo_url: data.photoUrl, + logo_url: data.logoUrl, + linkedin: data.linkedin, + twitter: data.twitter, + facebook: data.facebook, + instagram: data.instagram, + primary_color: data.primaryColor, + secondary_color: data.secondaryColor, + accent_color: data.accentColor, + photo_shape: data.photoShape, + style_template: data.styleTemplate, + } +} + +export function useSignature() { + const [signature, setSignature] = useState(defaultSignatureData) + const [loading, setLoading] = useState(true) + const [saving, setSaving] = useState(false) + const [userId, setUserId] = useState(null) + + // Charger la signature au démarrage + useEffect(() => { + const loadSignature = async () => { + const supabase = createClient() + const { data: { user } } = await supabase.auth.getUser() + + if (!user) { + setLoading(false) + return + } + + setUserId(user.id) + + const { data, error } = await supabase + .from('user_signatures') + .select('*') + .eq('user_id', user.id) + .single() + + if (data && !error) { + setSignature(dbToSignature(data)) + } + + setLoading(false) + } + + loadSignature() + }, []) + + // Sauvegarder la signature + const saveSignature = useCallback(async (data: SignatureData) => { + if (!userId) return { success: false, error: 'Non connecté' } + + setSaving(true) + const supabase = createClient() + + const dbData = signatureToDb(data, userId) + + // Upsert (insert ou update si existe) + const { error } = await supabase + .from('user_signatures') + .upsert(dbData, { onConflict: 'user_id' }) + + setSaving(false) + + if (error) { + return { success: false, error: error.message } + } + + setSignature(data) + return { success: true, error: null } + }, [userId]) + + return { + signature, + setSignature, + saveSignature, + loading, + saving, + userId, + } +} + +// Hook pour l'admin - charger toutes les signatures +export function useAllSignatures() { + const [signatures, setSignatures] = useState>([]) + const [loading, setLoading] = useState(true) + + useEffect(() => { + const loadSignatures = async () => { + const supabase = createClient() + + const { data, error } = await supabase + .from('user_signatures') + .select('*') + .order('created_at', { ascending: false }) + + if (error) { + console.error('Erreur chargement signatures:', error) + } + + if (data) { + setSignatures(data.map(d => ({ + ...dbToSignature(d), + id: d.id, + user_id: d.user_id, + }))) + } + + setLoading(false) + } + + loadSignatures() + }, []) + + // Modifier une signature (admin) + const updateSignature = async (userId: string, data: SignatureData) => { + const supabase = createClient() + + const dbData = signatureToDb(data, userId) + + const { error } = await supabase + .from('user_signatures') + .update(dbData) + .eq('user_id', userId) + + if (!error) { + setSignatures(prev => + prev.map(s => s.user_id === userId ? { ...data, id: s.id, user_id: userId } : s) + ) + } + + return { success: !error, error: error?.message } + } + + return { signatures, loading, updateSignature } +} diff --git a/src/hooks/useSignatures.ts b/src/hooks/useSignatures.ts new file mode 100644 index 0000000..a7993d6 --- /dev/null +++ b/src/hooks/useSignatures.ts @@ -0,0 +1,282 @@ +'use client' + +import { useState, useEffect, useCallback, useRef } from 'react' +import { createClient } from '@/lib/supabase/client' +import { SignatureData, defaultSignatureData } from '@/lib/types' + +export interface SavedSignature extends SignatureData { + id: string + createdAt: string + updatedAt: string +} + +// Convertir DB -> App +function dbToSignature(data: Record): SavedSignature { + return { + id: data.id as string, + firstName: (data.first_name as string) || '', + lastName: (data.last_name as string) || '', + jobTitle: (data.job_title as string) || '', + company: (data.company as string) || '', + email: (data.email as string) || '', + phone: (data.phone as string) || '', + mobile: (data.mobile as string) || '', + website: (data.website as string) || '', + address: (data.address as string) || '', + photoUrl: (data.photo_url as string) || '', + logoUrl: (data.logo_url as string) || '', + linkedin: (data.linkedin as string) || '', + twitter: (data.twitter as string) || '', + facebook: (data.facebook as string) || '', + instagram: (data.instagram as string) || '', + primaryColor: (data.primary_color as string) || '#F5A623', + secondaryColor: (data.secondary_color as string) || '#1a1a2e', + accentColor: (data.accent_color as string) || '#F5A623', + photoShape: (data.photo_shape as 'circle' | 'hexagon') || 'hexagon', + styleTemplate: (data.style_template as 'geometric' | 'minimal' | 'corporate' | 'creative') || 'geometric', + bannerUrl: (data.banner_url as string) || '', + bannerLink: (data.banner_link as string) || '', + createdAt: data.created_at as string, + updatedAt: data.updated_at as string, + } +} + +// Convertir App -> DB +function signatureToDb(data: SignatureData, userId: string) { + return { + created_by: userId, + first_name: data.firstName, + last_name: data.lastName, + job_title: data.jobTitle, + company: data.company, + email: data.email, + phone: data.phone, + mobile: data.mobile, + website: data.website, + address: data.address, + photo_url: data.photoUrl, + logo_url: data.logoUrl, + linkedin: data.linkedin, + twitter: data.twitter, + facebook: data.facebook, + instagram: data.instagram, + primary_color: data.primaryColor, + secondary_color: data.secondaryColor, + accent_color: data.accentColor, + photo_shape: data.photoShape, + style_template: data.styleTemplate, + banner_url: data.bannerUrl || '', + banner_link: data.bannerLink || '', + } +} + +export function useSignatures() { + const [signatures, setSignatures] = useState([]) + const [currentSignature, setCurrentSignature] = useState(defaultSignatureData) + const [currentId, setCurrentId] = useState(null) + const [loading, setLoading] = useState(true) + const [saving, setSaving] = useState(false) + const [userId, setUserId] = useState(null) + + // Pour le debounce + const saveTimeoutRef = useRef(null) + const pendingChangesRef = useRef(null) + const lastSavedRef = useRef('') + + // Charger les signatures + useEffect(() => { + const load = async () => { + const supabase = createClient() + const { data: { user } } = await supabase.auth.getUser() + + if (!user) { + setLoading(false) + return + } + + setUserId(user.id) + + const { data, error } = await supabase + .from('signatures') + .select('*') + .eq('created_by', user.id) + .order('updated_at', { ascending: false }) + + if (!error && data && data.length > 0) { + const loaded = data.map(dbToSignature) + setSignatures(loaded) + setCurrentSignature(loaded[0]) + setCurrentId(loaded[0].id) + lastSavedRef.current = JSON.stringify(loaded[0]) + } + + setLoading(false) + } + + load() + + return () => { + if (saveTimeoutRef.current) { + clearTimeout(saveTimeoutRef.current) + } + } + }, []) + + // Sauvegarder en DB + const saveToDb = useCallback(async (data: SignatureData, id: string | null) => { + if (!userId) return false + + const supabase = createClient() + const dbData = signatureToDb(data, userId) + + if (id) { + const { error } = await supabase + .from('signatures') + .update(dbData) + .eq('id', id) + return !error + } else { + const { data: result, error } = await supabase + .from('signatures') + .insert(dbData) + .select() + .single() + if (!error && result) { + setCurrentId(result.id) + return true + } + return false + } + }, [userId]) + + // Mettre à jour avec debounce (1.5s) + const updateSignature = useCallback((data: SignatureData) => { + setCurrentSignature(data) + pendingChangesRef.current = data + + // Annuler le précédent timeout + if (saveTimeoutRef.current) { + clearTimeout(saveTimeoutRef.current) + } + + // Nouveau timeout + saveTimeoutRef.current = setTimeout(async () => { + const dataToSave = pendingChangesRef.current + if (!dataToSave) return + + const currentDataStr = JSON.stringify(dataToSave) + if (currentDataStr === lastSavedRef.current) return + + setSaving(true) + const success = await saveToDb(dataToSave, currentId) + setSaving(false) + + if (success) { + lastSavedRef.current = currentDataStr + pendingChangesRef.current = null + + // Rafraîchir la liste + if (userId) { + const supabase = createClient() + const { data: refreshed } = await supabase + .from('signatures') + .select('*') + .eq('created_by', userId) + .order('updated_at', { ascending: false }) + + if (refreshed) { + setSignatures(refreshed.map(dbToSignature)) + } + } + } + }, 1500) + }, [currentId, saveToDb, userId]) + + // Créer nouvelle signature + const createNewSignature = useCallback(async () => { + if (!userId) return null + + const newData: SignatureData = { + ...defaultSignatureData, + firstName: 'Nouveau', + lastName: 'Contact', + } + + setSaving(true) + const supabase = createClient() + const dbData = signatureToDb(newData, userId) + + const { data, error } = await supabase + .from('signatures') + .insert(dbData) + .select() + .single() + + setSaving(false) + + if (!error && data) { + const created = dbToSignature(data) + setSignatures(prev => [created, ...prev]) + setCurrentSignature(created) + setCurrentId(created.id) + lastSavedRef.current = JSON.stringify(created) + return created + } + + return null + }, [userId]) + + // Sélectionner une signature + const selectSignature = useCallback((sig: SavedSignature) => { + // Annuler les sauvegardes en attente + if (saveTimeoutRef.current) { + clearTimeout(saveTimeoutRef.current) + } + pendingChangesRef.current = null + + setCurrentSignature(sig) + setCurrentId(sig.id) + lastSavedRef.current = JSON.stringify(sig) + }, []) + + // Supprimer une signature + const deleteSignature = useCallback(async (id: string) => { + if (!userId) return false + + const supabase = createClient() + const { error } = await supabase + .from('signatures') + .delete() + .eq('id', id) + + if (error) return false + + const remaining = signatures.filter(s => s.id !== id) + setSignatures(remaining) + + if (currentId === id) { + if (remaining.length > 0) { + selectSignature(remaining[0]) + } else { + setCurrentSignature(defaultSignatureData) + setCurrentId(null) + lastSavedRef.current = '' + } + } + + return true + }, [userId, currentId, signatures, selectSignature]) + + return { + signatures, + currentSignature, + currentId, + loading, + saving, + userId, + updateSignature, + createNewSignature, + selectSignature, + deleteSignature, + } +} diff --git a/src/lib/export.ts b/src/lib/export.ts new file mode 100644 index 0000000..be5148a --- /dev/null +++ b/src/lib/export.ts @@ -0,0 +1,244 @@ +import { toPng } from 'html-to-image' +import { SignatureData } from './types' + +// Logo Navier en base64 pour remplacer les chemins relatifs +const NAVIER_LOGO_BASE64 = 'data:image/webp;base64,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' + +interface SignatureExportData extends SignatureData { + bannerUrl?: string + bannerLink?: string +} + +// Vérifie si une URL est un chemin relatif ou une URL valide (pas base64) +function isRelativeOrInvalidUrl(url: string): boolean { + if (!url) return false + // Si c'est déjà en base64, c'est valide + if (url.startsWith('data:')) return false + // Si c'est un chemin relatif (commence par /) + if (url.startsWith('/')) return true + // Si c'est une URL http(s), c'est valide + if (url.startsWith('http://') || url.startsWith('https://')) return false + return true +} + +export function generateSignatureHTML(data: SignatureExportData): string { + // Remplacer le logo si c'est un chemin relatif + let logoUrl = data.logoUrl + if (isRelativeOrInvalidUrl(logoUrl) || logoUrl === '/preview.webp') { + logoUrl = NAVIER_LOGO_BASE64 + } + const fullName = `${data.firstName} ${data.lastName}`.trim() + const accentColor = data.primaryColor || '#3498db' + const darkColor = data.secondaryColor || '#3a3a3a' + + // Design identique au preview avec clip-path + let html = ` +
+ + +
+ +
+ +
+ +
+
+
` + + if (data.photoUrl) { + html += ` + ${fullName}` + } + + html += ` +
+
+
+
+ + +
+ +
` + + if (fullName) { + html += ` +
${fullName}
` + } + + if (data.jobTitle) { + html += ` +
${data.jobTitle}
` + } + + // Barre de séparation horizontale + html += ` +
` + + html += ` + +
` + + if (data.phone) { + html += ` +
+ + + + ${data.phone} +
` + } + + if (data.mobile) { + html += ` +
+ + + + ${data.mobile} +
` + } + + if (data.email) { + html += ` +
+ + + + ${data.email} +
` + } + + if (data.website) { + const websiteUrl = data.website.startsWith('http') ? data.website : `https://${data.website}` + html += ` +
+ + + + ${data.website} +
` + } + + if (data.address) { + html += ` +
+ + + + ${data.address} +
` + } + + html += ` +
+
+ + +
+ +
` + + if (logoUrl) { + html += ` + ${data.company || 'Logo'}` + } + + const hasSocials = data.linkedin || data.twitter || data.facebook || data.instagram + if (hasSocials) { + html += ` +
` + + if (data.facebook) { + html += ` + + + ` + } + if (data.instagram) { + html += ` + + + ` + } + if (data.twitter) { + html += ` + + + ` + } + if (data.linkedin) { + html += ` + + + ` + } + + html += ` +
` + } + + html += ` + +
+
+
` + + // Bannière + if (data.bannerUrl) { + html += ` + + +
+ ${data.bannerLink ? `` : ''} + Promotion + ${data.bannerLink ? '' : ''} +
` + } + + return html.trim() +} + +export async function exportAsImage(element: HTMLElement): Promise { + try { + const dataUrl = await toPng(element, { + quality: 1, + backgroundColor: '#ffffff', + pixelRatio: 2, + }) + + const link = document.createElement('a') + link.download = 'signature.png' + link.href = dataUrl + link.click() + } catch (error) { + console.error('Error exporting image:', error) + throw error + } +} + +export function copyHTMLToClipboard(html: string): Promise { + return navigator.clipboard.writeText(html) +} + +export function downloadHTML(html: string, filename: string = 'signature.html'): void { + const fullHtml = ` + + + + Ma Signature Email + + +${html} + +` + + const blob = new Blob([fullHtml], { type: 'text/html' }) + const url = URL.createObjectURL(blob) + const link = document.createElement('a') + link.download = filename + link.href = url + link.click() + URL.revokeObjectURL(url) +} diff --git a/src/lib/supabase/client.ts b/src/lib/supabase/client.ts new file mode 100644 index 0000000..792b457 --- /dev/null +++ b/src/lib/supabase/client.ts @@ -0,0 +1,8 @@ +import { createBrowserClient } from '@supabase/ssr' + +export function createClient() { + return createBrowserClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY! + ) +} diff --git a/src/lib/supabase/middleware.ts b/src/lib/supabase/middleware.ts new file mode 100644 index 0000000..05573a5 --- /dev/null +++ b/src/lib/supabase/middleware.ts @@ -0,0 +1,55 @@ +import { createServerClient } from '@supabase/ssr' +import { NextResponse, type NextRequest } from 'next/server' + +export async function updateSession(request: NextRequest) { + let supabaseResponse = NextResponse.next({ + request, + }) + + const supabase = createServerClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, + { + cookies: { + getAll() { + return request.cookies.getAll() + }, + setAll(cookiesToSet) { + cookiesToSet.forEach(({ name, value }) => request.cookies.set(name, value)) + supabaseResponse = NextResponse.next({ + request, + }) + cookiesToSet.forEach(({ name, value, options }) => + supabaseResponse.cookies.set(name, value, options) + ) + }, + }, + } + ) + + const { + data: { user }, + } = await supabase.auth.getUser() + + // Redirect to login if not authenticated and trying to access dashboard + if ( + !user && + request.nextUrl.pathname.startsWith('/dashboard') + ) { + const url = request.nextUrl.clone() + url.pathname = '/login' + return NextResponse.redirect(url) + } + + // Redirect to dashboard if authenticated and trying to access login/register + if ( + user && + (request.nextUrl.pathname === '/login' || request.nextUrl.pathname === '/register') + ) { + const url = request.nextUrl.clone() + url.pathname = '/dashboard' + return NextResponse.redirect(url) + } + + return supabaseResponse +} diff --git a/src/lib/supabase/server.ts b/src/lib/supabase/server.ts new file mode 100644 index 0000000..d0066b1 --- /dev/null +++ b/src/lib/supabase/server.ts @@ -0,0 +1,28 @@ +import { createServerClient, type CookieOptions } from '@supabase/ssr' +import { cookies } from 'next/headers' + +export async function createClient() { + const cookieStore = await cookies() + + return createServerClient( + process.env.NEXT_PUBLIC_SUPABASE_URL!, + process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!, + { + cookies: { + getAll() { + return cookieStore.getAll() + }, + setAll(cookiesToSet) { + try { + cookiesToSet.forEach(({ name, value, options }) => + cookieStore.set(name, value, options) + ) + } catch { + // The `setAll` method was called from a Server Component. + // This can be ignored if you have middleware refreshing user sessions. + } + }, + }, + } + ) +} diff --git a/src/lib/types.ts b/src/lib/types.ts new file mode 100644 index 0000000..93b7e89 --- /dev/null +++ b/src/lib/types.ts @@ -0,0 +1,93 @@ +export interface SignatureData { + // Personal Info + firstName: string + lastName: string + jobTitle: string + company: string + + // Contact Info + email: string + phone: string + mobile: string + website: string + address: string + + // Photo & Logo + photoUrl: string + logoUrl: string + + // Social Links + linkedin: string + twitter: string + facebook: string + instagram: string + + // Styling + primaryColor: string + secondaryColor: string + accentColor: string + + // Photo Shape + photoShape: 'circle' | 'hexagon' + + // Style template + styleTemplate: SignatureStyle + + // Banner + bannerUrl?: string + bannerLink?: string +} + +// Styles de signature disponibles +export type SignatureStyle = 'geometric' | 'minimal' | 'corporate' | 'creative' + +// Thèmes de couleurs prédéfinis +export interface ColorTheme { + name: string + primary: string + secondary: string + accent: string +} + +// Thème unique basé sur les couleurs du logo Navier (bleu #3498db + gris foncé #3a3a3a) +export const colorThemes: ColorTheme[] = [ + { name: 'Navier', primary: '#3498db', secondary: '#3a3a3a', accent: '#3498db' }, +] + +// Logo Navier en base64 pour l'export HTML +const NAVIER_LOGO_BASE64 = 'data:image/webp;base64,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' + +export const defaultSignatureData: SignatureData = { + firstName: '', + lastName: '', + jobTitle: '', + company: 'Navier Instruments', + email: '', + phone: '', + mobile: '', + website: 'www.navier-instruments.com', + address: '', + photoUrl: '', + logoUrl: NAVIER_LOGO_BASE64, + linkedin: '', + twitter: '', + facebook: '', + instagram: '', + primaryColor: '#3498db', + secondaryColor: '#3a3a3a', + accentColor: '#3498db', + photoShape: 'hexagon', + styleTemplate: 'geometric', +} + +// Types pour les bannières gérées par l'admin +export interface Banner { + id: string + image_url: string + link_url: string | null + title: string | null + order: number + is_active: boolean + created_at: string + updated_at: string +} diff --git a/src/lib/upload.ts b/src/lib/upload.ts new file mode 100644 index 0000000..24489d5 --- /dev/null +++ b/src/lib/upload.ts @@ -0,0 +1,70 @@ +import { createClient } from '@/lib/supabase/client' + +export interface UploadResult { + success: boolean + url?: string + error?: string +} + +/** + * Upload une image vers Supabase Storage + * @param file - Le fichier à uploader + * @param folder - Le dossier de destination (ex: 'banners', 'photos', 'logos') + * @returns L'URL publique de l'image + */ +export async function uploadImage(file: File, folder: string = 'banners'): Promise { + try { + const supabase = createClient() + + // Générer un nom unique pour le fichier + const fileExt = file.name.split('.').pop() + const fileName = `${folder}/${Date.now()}-${Math.random().toString(36).substring(7)}.${fileExt}` + + // Upload vers Supabase Storage + const { data, error } = await supabase.storage + .from('images') + .upload(fileName, file, { + cacheControl: '3600', + upsert: false + }) + + if (error) { + console.error('Upload error:', error) + return { success: false, error: error.message } + } + + // Obtenir l'URL publique + const { data: urlData } = supabase.storage + .from('images') + .getPublicUrl(data.path) + + return { success: true, url: urlData.publicUrl } + } catch (err) { + console.error('Upload exception:', err) + return { success: false, error: 'Erreur lors de l\'upload' } + } +} + +/** + * Supprime une image de Supabase Storage + * @param url - L'URL publique de l'image à supprimer + */ +export async function deleteImage(url: string): Promise { + try { + const supabase = createClient() + + // Extraire le chemin du fichier depuis l'URL + const urlObj = new URL(url) + const path = urlObj.pathname.split('/images/')[1] + + if (!path) return false + + const { error } = await supabase.storage + .from('images') + .remove([path]) + + return !error + } catch { + return false + } +} diff --git a/src/middleware.ts b/src/middleware.ts new file mode 100644 index 0000000..3867a2a --- /dev/null +++ b/src/middleware.ts @@ -0,0 +1,12 @@ +import { type NextRequest } from 'next/server' +import { updateSession } from '@/lib/supabase/middleware' + +export async function middleware(request: NextRequest) { + return await updateSession(request) +} + +export const config = { + matcher: [ + '/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)', + ], +} diff --git a/src/styles/admin.scss b/src/styles/admin.scss new file mode 100644 index 0000000..8ae59ad --- /dev/null +++ b/src/styles/admin.scss @@ -0,0 +1,323 @@ +@use 'variables' as *; + +.admin { + min-height: 100vh; + background-color: $gray-50; + + &__loading { + display: flex; + align-items: center; + justify-content: center; + height: 100vh; + font-size: $font-size-lg; + color: $gray-500; + } + + &__header { + background-color: $white; + border-bottom: 1px solid $gray-200; + padding: $spacing-4 $spacing-6; + display: flex; + align-items: center; + justify-content: space-between; + + h1 { + font-size: $font-size-xl; + font-weight: 600; + color: $gray-900; + margin: 0; + } + } + + &__main { + max-width: 1000px; + margin: 0 auto; + padding: $spacing-6; + } + + &__section { + background-color: $white; + border-radius: $radius-xl; + box-shadow: $shadow-md; + padding: $spacing-6; + margin-bottom: $spacing-6; + + h2 { + font-size: $font-size-lg; + font-weight: 600; + color: $gray-900; + margin: 0 0 $spacing-4 0; + padding-bottom: $spacing-3; + border-bottom: 1px solid $gray-200; + } + + h3 { + font-size: $font-size-base; + font-weight: 600; + color: $gray-700; + margin: 0 0 $spacing-2 0; + } + + &--info { + background-color: #eff6ff; + border: 1px solid #bfdbfe; + + p { + margin: 0; + color: #1e40af; + font-size: $font-size-sm; + line-height: 1.6; + } + } + } + + &__form { + display: flex; + flex-direction: column; + gap: $spacing-4; + } + + &__form-row { + display: grid; + grid-template-columns: 1fr 1fr; + gap: $spacing-4; + + @media (max-width: $breakpoint-md) { + grid-template-columns: 1fr; + } + } + + &__field { + display: flex; + flex-direction: column; + gap: $spacing-2; + + label { + font-size: $font-size-sm; + font-weight: 500; + color: $gray-700; + } + + &--btn { + justify-content: flex-end; + } + } + + &__preview { + margin-top: $spacing-2; + padding: $spacing-4; + background-color: $gray-100; + border-radius: $radius-lg; + + p { + margin: 0 0 $spacing-2 0; + font-size: $font-size-sm; + color: $gray-600; + } + + img { + max-width: 100%; + height: auto; + border-radius: $radius-md; + } + } + + &__empty { + text-align: center; + color: $gray-500; + padding: $spacing-8; + } + + &__banners { + display: flex; + flex-direction: column; + gap: $spacing-4; + } + + &__banner { + display: grid; + grid-template-columns: 200px 1fr auto; + gap: $spacing-4; + padding: $spacing-4; + background-color: $gray-50; + border-radius: $radius-lg; + border: 1px solid $gray-200; + + &--inactive { + opacity: 0.6; + background-color: $gray-100; + } + + @media (max-width: $breakpoint-md) { + grid-template-columns: 1fr; + } + } + + &__banner-image { + position: relative; + + img { + width: 100%; + height: auto; + border-radius: $radius-md; + } + } + + &__badge { + position: absolute; + top: $spacing-2; + left: $spacing-2; + background-color: $error; + color: $white; + font-size: $font-size-xs; + padding: 2px 8px; + border-radius: $radius-sm; + } + + &__banner-details { + display: flex; + flex-direction: column; + gap: $spacing-3; + } + + &__banner-field { + display: flex; + flex-direction: column; + gap: $spacing-1; + + label { + font-size: $font-size-xs; + font-weight: 500; + color: $gray-500; + text-transform: uppercase; + } + + .input { + font-size: $font-size-sm; + padding: $spacing-2; + } + } + + &__banner-actions { + display: flex; + flex-direction: column; + gap: $spacing-2; + justify-content: center; + + .btn { + white-space: nowrap; + } + } +} + +// Bouton danger +.btn--danger { + background-color: $error; + color: $white; + border: none; + + &:hover { + background-color: darken($error, 10%); + } +} + +// Bouton small +.btn--sm { + padding: $spacing-2 $spacing-3; + font-size: $font-size-sm; +} + +// Tabs +.admin__tabs { + display: flex; + gap: $spacing-2; + max-width: 1000px; + margin: 0 auto; + padding: 0 $spacing-6; +} + +.admin__tab { + padding: $spacing-3 $spacing-6; + background-color: $white; + border: 1px solid $gray-200; + border-bottom: none; + border-radius: $radius-lg $radius-lg 0 0; + font-size: $font-size-sm; + font-weight: 500; + color: $gray-600; + cursor: pointer; + transition: all $transition-fast; + + &:hover { + background-color: $gray-50; + color: $gray-900; + } + + &--active { + background-color: $white; + color: $primary; + border-color: $gray-200; + position: relative; + + &::after { + content: ''; + position: absolute; + bottom: -1px; + left: 0; + right: 0; + height: 2px; + background-color: $white; + } + } +} + +// Users list +.admin__users { + display: flex; + flex-direction: column; + gap: $spacing-3; +} + +.admin__user { + padding: $spacing-4; + background-color: $gray-50; + border-radius: $radius-lg; + border: 1px solid $gray-200; +} + +.admin__user-header { + display: flex; + align-items: center; + justify-content: space-between; +} + +.admin__user-info { + display: flex; + align-items: center; + gap: $spacing-3; + + h3 { + margin: 0; + font-size: $font-size-base; + font-weight: 600; + color: $gray-900; + } + + p { + margin: 0; + font-size: $font-size-sm; + color: $gray-600; + } +} + +.admin__user-photo { + width: 48px; + height: 48px; + border-radius: 50%; + object-fit: cover; +} + +.admin__user-job { + font-size: $font-size-xs !important; + color: $gray-500 !important; +} diff --git a/src/styles/auth.scss b/src/styles/auth.scss new file mode 100644 index 0000000..7817a2c --- /dev/null +++ b/src/styles/auth.scss @@ -0,0 +1,92 @@ +@use 'variables' as *; + +.auth { + min-height: 100vh; + display: flex; + align-items: center; + justify-content: center; + padding: $spacing-4; + + &__container { + width: 100%; + max-width: 420px; + } + + &__card { + background-color: $white; + border-radius: $radius-2xl; + box-shadow: $shadow-xl; + padding: $spacing-8; + } + + &__header { + text-align: center; + margin-bottom: $spacing-8; + } + + &__logo { + font-size: $font-size-2xl; + font-weight: 700; + color: $primary; + margin-bottom: $spacing-2; + } + + &__title { + font-size: $font-size-xl; + font-weight: 600; + color: $gray-900; + margin-bottom: $spacing-2; + } + + &__subtitle { + font-size: $font-size-sm; + color: $gray-500; + } + + &__form { + display: flex; + flex-direction: column; + gap: $spacing-4; + } + + &__field { + display: flex; + flex-direction: column; + } + + &__submit { + margin-top: $spacing-4; + width: 100%; + } + + &__footer { + text-align: center; + margin-top: $spacing-6; + padding-top: $spacing-6; + border-top: 1px solid $gray-200; + font-size: $font-size-sm; + color: $gray-600; + + a { + font-weight: 500; + } + } + + &__error { + background-color: rgba($error, 0.1); + border: 1px solid rgba($error, 0.2); + border-radius: $radius-lg; + padding: $spacing-3 $spacing-4; + color: $error; + font-size: $font-size-sm; + } + + &__success { + background-color: rgba($success, 0.1); + border: 1px solid rgba($success, 0.2); + border-radius: $radius-lg; + padding: $spacing-3 $spacing-4; + color: #1a9a4a; + font-size: $font-size-sm; + } +} diff --git a/src/styles/dashboard.scss b/src/styles/dashboard.scss new file mode 100644 index 0000000..340970d --- /dev/null +++ b/src/styles/dashboard.scss @@ -0,0 +1,861 @@ +@use 'variables' as *; +@use 'sass:color'; + +// ============================================ +// BASE LAYOUT +// ============================================ + +.dashboard { + min-height: 100vh; + background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%); +} + +// Loading Screen +.loading-screen { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + height: 100vh; + gap: 1rem; + color: $gray-500; + + &__spinner { + width: 32px; + height: 32px; + border: 3px solid $gray-200; + border-top-color: $primary; + border-radius: 50%; + animation: spin 0.8s linear infinite; + } +} + +@keyframes spin { + to { transform: rotate(360deg); } +} + +// ============================================ +// HEADER +// ============================================ + +.header { + background: $white; + border-bottom: 1px solid $gray-200; + position: sticky; + top: 0; + z-index: 100; + + &__inner { + max-width: 1600px; + margin: 0 auto; + padding: 0.75rem 1.5rem; + display: flex; + align-items: center; + justify-content: space-between; + } + + &__brand { + font-size: 1.125rem; + font-weight: 700; + color: $gray-900; + letter-spacing: -0.02em; + } + + &__actions { + display: flex; + align-items: center; + gap: 1rem; + } + + &__email { + font-size: 0.875rem; + color: $gray-500; + } +} + +.auto-save { + font-size: 0.75rem; + color: $primary; + background: rgba($primary, 0.1); + padding: 0.25rem 0.75rem; + border-radius: 999px; + animation: pulse 1.5s ease-in-out infinite; +} + +@keyframes pulse { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.6; } +} + +// ============================================ +// APP LAYOUT +// ============================================ + +.app-layout { + display: grid; + grid-template-columns: 260px 1fr; + max-width: 1600px; + margin: 0 auto; + gap: 1.5rem; + padding: 1.5rem; + min-height: calc(100vh - 60px); + + @media (max-width: 1024px) { + grid-template-columns: 1fr; + } +} + +// ============================================ +// SIDEBAR +// ============================================ + +.sidebar { + background: $white; + border-radius: 12px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08); + padding: 1rem; + height: fit-content; + position: sticky; + top: 80px; + + &__top { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 1rem; + padding-bottom: 0.75rem; + border-bottom: 1px solid $gray-100; + + h2 { + font-size: 0.875rem; + font-weight: 600; + color: $gray-900; + margin: 0; + } + } +} + +.signature-list { + display: flex; + flex-direction: column; + gap: 0.5rem; + max-height: 60vh; + overflow-y: auto; + + &__empty { + text-align: center; + padding: 2rem 1rem; + color: $gray-500; + + p { + font-size: 0.875rem; + margin-bottom: 1rem; + } + } +} + +.signature-card { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.75rem; + border-radius: 8px; + cursor: pointer; + transition: all 0.15s ease; + border: 1px solid transparent; + position: relative; + + &:hover { + background: $gray-50; + + .signature-card__delete { + opacity: 1; + } + } + + &--active { + background: rgba($primary, 0.08); + border-color: rgba($primary, 0.2); + + .signature-card__avatar { + background: $primary; + color: $white; + } + + .signature-card__name { + color: $primary; + } + } + + &__avatar { + width: 36px; + height: 36px; + border-radius: 8px; + background: $gray-100; + color: $gray-600; + display: flex; + align-items: center; + justify-content: center; + font-size: 0.75rem; + font-weight: 600; + flex-shrink: 0; + text-transform: uppercase; + } + + &__info { + flex: 1; + min-width: 0; + display: flex; + flex-direction: column; + gap: 2px; + } + + &__name { + font-size: 0.8125rem; + font-weight: 600; + color: $gray-900; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + &__role { + font-size: 0.6875rem; + color: $gray-500; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } + + &__delete { + width: 28px; + height: 28px; + border-radius: 6px; + background: transparent; + border: none; + color: $gray-400; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + opacity: 0; + transition: all 0.15s ease; + flex-shrink: 0; + + &:hover { + background: #fee2e2; + color: #dc2626; + } + } +} + +// ============================================ +// MAIN CONTENT +// ============================================ + +.main-content { + display: flex; + flex-direction: column; + gap: 1rem; +} + +// ============================================ +// TABS +// ============================================ + +.tabs { + display: flex; + gap: 0.25rem; + background: $white; + padding: 0.25rem; + border-radius: 10px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08); + width: fit-content; + + &__item { + padding: 0.5rem 1rem; + font-size: 0.8125rem; + font-weight: 500; + color: $gray-600; + background: transparent; + border: none; + border-radius: 8px; + cursor: pointer; + transition: all 0.15s ease; + + &:hover { + color: $gray-900; + background: $gray-50; + } + + &--active { + background: $primary; + color: $white; + + &:hover { + background: $primary; + color: $white; + } + } + } +} + +// ============================================ +// CONTENT GRID +// ============================================ + +.content-grid { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 1.5rem; + + @media (max-width: 1200px) { + grid-template-columns: 1fr; + } +} + +// ============================================ +// PANEL +// ============================================ + +.panel { + background: $white; + border-radius: 12px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08); + padding: 1.5rem; + + &__title { + font-size: 0.875rem; + font-weight: 600; + color: $gray-900; + margin: 0 0 1rem 0; + padding-bottom: 0.75rem; + border-bottom: 1px solid $gray-100; + } + + &--preview { + background: linear-gradient(180deg, $white 0%, #fafafa 100%); + } +} + +// ============================================ +// PREVIEW BOX +// ============================================ + +.preview-box { + background: $white; + border: 1px solid $gray-200; + border-radius: 8px; + padding: 1.5rem; + margin-bottom: 1rem; +} + +.export-actions { + display: flex; + gap: 0.5rem; + flex-wrap: wrap; +} + +.preview-hint { + margin-top: 1rem; + font-size: 0.75rem; + color: $gray-500; + text-align: center; +} + +// ============================================ +// EDITOR +// ============================================ + +.editor { + display: flex; + flex-direction: column; + gap: 1rem; + + &__group { + display: flex; + flex-direction: column; + gap: 0.375rem; + } + + &__row { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 1rem; + + @media (max-width: 640px) { + grid-template-columns: 1fr; + } + } + + &__divider { + height: 1px; + background: $gray-100; + margin: 0.5rem 0; + } + + &__subtitle { + font-size: 0.6875rem; + font-weight: 600; + color: $gray-500; + text-transform: uppercase; + letter-spacing: 0.05em; + margin-bottom: 0.25rem; + } +} + +// ============================================ +// BUTTONS +// ============================================ + +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 0.5rem; + padding: 0.5rem 1rem; + font-size: 0.8125rem; + font-weight: 500; + border-radius: 8px; + border: none; + cursor: pointer; + transition: all 0.15s ease; + white-space: nowrap; + + &:disabled { + opacity: 0.5; + cursor: not-allowed; + } + + &--primary { + background: $primary; + color: $white; + + &:hover:not(:disabled) { + background: color.adjust($primary, $lightness: -8%); + } + } + + &--secondary { + background: $gray-100; + color: $gray-700; + + &:hover:not(:disabled) { + background: $gray-200; + } + } + + &--ghost { + background: transparent; + color: $gray-600; + + &:hover:not(:disabled) { + background: $gray-100; + color: $gray-900; + } + } + + &--success { + background: #10b981; + color: $white; + } + + &--icon { + width: 32px; + height: 32px; + padding: 0; + font-size: 1.125rem; + } +} + +// ============================================ +// FORMS +// ============================================ + +.label { + font-size: 0.75rem; + font-weight: 500; + color: $gray-700; +} + +.input { + width: 100%; + padding: 0.5rem 0.75rem; + font-size: 0.875rem; + color: $gray-900; + background: $white; + border: 1px solid $gray-200; + border-radius: 8px; + transition: all 0.15s ease; + + &:hover { + border-color: $gray-300; + } + + &:focus { + outline: none; + border-color: $primary; + box-shadow: 0 0 0 3px rgba($primary, 0.1); + } + + &::placeholder { + color: $gray-400; + } +} + +// ============================================ +// BANNER UPLOAD +// ============================================ + +.banner-upload { + border: 2px dashed $gray-200; + border-radius: 8px; + padding: 1.5rem; + text-align: center; + cursor: pointer; + transition: all 0.15s ease; + + &:hover { + border-color: $primary; + background: rgba($primary, 0.02); + } + + &--has-image { + border-style: solid; + padding: 0.75rem; + } + + &__input { + display: none; + } + + &__placeholder { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.5rem; + color: $gray-500; + } + + &__icon { + font-size: 1.5rem; + } + + &__text { + font-size: 0.8125rem; + } + + &__hint { + font-size: 0.6875rem; + color: $gray-400; + } + + &__preview { + position: relative; + + img { + max-width: 100%; + max-height: 100px; + border-radius: 6px; + } + } + + &__remove { + position: absolute; + top: -8px; + right: -8px; + width: 20px; + height: 20px; + border-radius: 50%; + background: #dc2626; + color: $white; + border: none; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + font-size: 12px; + + &:hover { + background: #b91c1c; + } + } +} + +// ============================================ +// STYLE SELECTOR +// ============================================ + +.style-selector { + display: flex; + flex-direction: column; + gap: 1.5rem; + + &__section { + display: flex; + flex-direction: column; + gap: 0.75rem; + } + + &__label { + font-size: 0.6875rem; + font-weight: 600; + color: $gray-500; + text-transform: uppercase; + letter-spacing: 0.05em; + } + + &__grid { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 0.75rem; + } + + &__colors { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + } + + &__shapes { + display: flex; + gap: 0.75rem; + } +} + +.style-card { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.75rem; + border: 1px solid $gray-200; + border-radius: 8px; + background: $white; + cursor: pointer; + transition: all 0.15s ease; + + &:hover { + border-color: $gray-300; + } + + &--active { + border-color: $primary; + background: rgba($primary, 0.04); + } + + &__preview { + width: 48px; + height: 32px; + border-radius: 6px; + background: $gray-100; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + } + + &__info { + display: flex; + flex-direction: column; + gap: 2px; + } + + &__name { + font-size: 0.8125rem; + font-weight: 600; + color: $gray-900; + } + + &__desc { + font-size: 0.6875rem; + color: $gray-500; + } +} + +.color-theme { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.375rem; + padding: 0.375rem; + border: 2px solid transparent; + border-radius: 8px; + background: transparent; + cursor: pointer; + transition: all 0.15s ease; + + &:hover { + border-color: $gray-200; + } + + &--active { + border-color: $primary; + } + + &__preview { + display: flex; + width: 40px; + height: 24px; + border-radius: 4px; + overflow: hidden; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); + + span { + flex: 1; + } + } + + &__name { + font-size: 0.625rem; + color: $gray-600; + white-space: nowrap; + } +} + +.shape-btn { + display: flex; + flex-direction: column; + align-items: center; + gap: 0.5rem; + padding: 0.75rem; + border: 1px solid $gray-200; + border-radius: 8px; + background: $white; + cursor: pointer; + transition: all 0.15s ease; + color: $gray-500; + + &:hover { + border-color: $gray-300; + color: $gray-700; + } + + &--active { + border-color: $primary; + background: rgba($primary, 0.04); + color: $primary; + } + + span { + font-size: 0.6875rem; + font-weight: 500; + } +} + +// ============================================ +// BANNER GENERATOR +// ============================================ + +.banner-generator { + &__preview { + margin-bottom: 1rem; + border-radius: 8px; + overflow: hidden; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + } + + &__section { + margin-bottom: 1rem; + } + + &__label { + display: block; + font-size: 0.6875rem; + font-weight: 600; + color: $gray-500; + text-transform: uppercase; + letter-spacing: 0.05em; + margin-bottom: 0.5rem; + } + + &__templates { + display: flex; + flex-wrap: wrap; + gap: 0.375rem; + } + + &__row { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 1rem; + + @media (max-width: 640px) { + grid-template-columns: 1fr; + } + } + + &__actions { + display: flex; + gap: 0.5rem; + margin-top: 1rem; + } + + &__hint { + margin-top: 0.75rem; + font-size: 0.6875rem; + color: $gray-500; + text-align: center; + } +} + +.banner-template { + width: 44px; + height: 28px; + border: 2px solid transparent; + border-radius: 6px; + cursor: pointer; + padding: 0; + overflow: hidden; + transition: all 0.15s ease; + + &:hover { + transform: scale(1.05); + } + + &--active { + border-color: $gray-900; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); + } + + &__preview { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: flex-end; + padding-right: 4px; + + span { + width: 6px; + height: 6px; + border-radius: 50%; + } + } +} + +// ============================================ +// SIGNATURE PREVIEW STYLES +// ============================================ + +.preview { + &__container { + background: $gray-50; + border-radius: 8px; + padding: 1.5rem; + margin-bottom: 1rem; + } + + &__actions { + display: flex; + gap: 0.5rem; + flex-wrap: wrap; + } + + &__info { + margin-top: 1rem; + font-size: 0.6875rem; + color: $gray-500; + text-align: center; + font-style: italic; + } +} diff --git a/src/styles/globals.scss b/src/styles/globals.scss new file mode 100644 index 0000000..5a689db --- /dev/null +++ b/src/styles/globals.scss @@ -0,0 +1,135 @@ +@use 'variables' as *; + +* { + box-sizing: border-box; + padding: 0; + margin: 0; +} + +html, +body { + max-width: 100vw; + overflow-x: hidden; + font-family: $font-family; + background-color: $gray-50; + color: $gray-900; +} + +a { + color: $primary; + text-decoration: none; + + &:hover { + text-decoration: underline; + } +} + +// Utility classes +.container { + max-width: 1200px; + margin: 0 auto; + padding: 0 $spacing-4; +} + +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: $spacing-2; + padding: $spacing-3 $spacing-6; + font-size: $font-size-base; + font-weight: 500; + border-radius: $radius-lg; + border: none; + cursor: pointer; + transition: all $transition-fast; + + &:disabled { + opacity: 0.6; + cursor: not-allowed; + } + + &--primary { + background-color: $primary; + color: $white; + + &:hover:not(:disabled) { + background-color: $primary-dark; + } + } + + &--secondary { + background-color: $gray-200; + color: $gray-700; + + &:hover:not(:disabled) { + background-color: $gray-300; + } + } + + &--outline { + background-color: transparent; + border: 1px solid $gray-300; + color: $gray-700; + + &:hover:not(:disabled) { + background-color: $gray-100; + } + } + + &--success { + background-color: $success; + color: $white; + + &:hover:not(:disabled) { + background-color: #1a9a4a; + } + } +} + +.input { + width: 100%; + padding: $spacing-3 $spacing-4; + font-size: $font-size-base; + border: 1px solid $gray-300; + border-radius: $radius-lg; + background-color: $white; + transition: border-color $transition-fast, box-shadow $transition-fast; + + &:focus { + outline: none; + border-color: $primary; + box-shadow: 0 0 0 3px rgba($primary, 0.1); + } + + &::placeholder { + color: $gray-400; + } +} + +.label { + display: block; + margin-bottom: $spacing-2; + font-size: $font-size-sm; + font-weight: 500; + color: $gray-700; +} + +.card { + background-color: $white; + border-radius: $radius-xl; + box-shadow: $shadow-md; + padding: $spacing-6; +} + +.error-message { + color: $error; + font-size: $font-size-sm; + margin-top: $spacing-2; +} + +.success-message { + color: $success; + font-size: $font-size-sm; + margin-top: $spacing-2; +} diff --git a/src/styles/home.scss b/src/styles/home.scss new file mode 100644 index 0000000..3c956e5 --- /dev/null +++ b/src/styles/home.scss @@ -0,0 +1,135 @@ +@use 'variables' as *; + +.home { + min-height: 100vh; + display: flex; + flex-direction: column; + + &__header { + background-color: $white; + border-bottom: 1px solid $gray-200; + padding: $spacing-4 0; + } + + &__header-content { + display: flex; + align-items: center; + justify-content: space-between; + max-width: 1200px; + margin: 0 auto; + padding: 0 $spacing-6; + } + + &__logo { + font-size: $font-size-xl; + font-weight: 700; + color: $primary; + } + + &__nav { + display: flex; + gap: $spacing-3; + } + + &__main { + flex: 1; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: $spacing-12 $spacing-6; + } + + &__hero { + text-align: center; + max-width: 700px; + margin-bottom: $spacing-12; + } + + &__title { + font-size: 3rem; + font-weight: 700; + color: $gray-900; + line-height: 1.2; + margin-bottom: $spacing-6; + + @media (max-width: $breakpoint-md) { + font-size: 2rem; + } + } + + &__title-accent { + color: $primary; + } + + &__subtitle { + font-size: $font-size-lg; + color: $gray-600; + margin-bottom: $spacing-8; + line-height: 1.6; + } + + &__cta { + display: flex; + justify-content: center; + } + + &__features { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: $spacing-8; + max-width: 1000px; + width: 100%; + + @media (max-width: $breakpoint-md) { + grid-template-columns: 1fr; + gap: $spacing-6; + } + } + + &__feature { + background-color: $white; + border-radius: $radius-xl; + padding: $spacing-8; + text-align: center; + box-shadow: $shadow-md; + transition: transform $transition-base, box-shadow $transition-base; + + &:hover { + transform: translateY(-4px); + box-shadow: $shadow-lg; + } + } + + &__feature-icon { + font-size: 2.5rem; + margin-bottom: $spacing-4; + } + + &__feature-title { + font-size: $font-size-lg; + font-weight: 600; + color: $gray-900; + margin-bottom: $spacing-3; + } + + &__feature-text { + font-size: $font-size-sm; + color: $gray-600; + line-height: 1.6; + } + + &__footer { + background-color: $white; + border-top: 1px solid $gray-200; + padding: $spacing-6; + text-align: center; + color: $gray-500; + font-size: $font-size-sm; + } +} + +.btn--large { + padding: $spacing-4 $spacing-8; + font-size: $font-size-lg; +} diff --git a/src/styles/variables.scss b/src/styles/variables.scss new file mode 100644 index 0000000..04183ca --- /dev/null +++ b/src/styles/variables.scss @@ -0,0 +1,65 @@ +// Colors +$primary: #2563eb; +$primary-dark: #1d4ed8; +$secondary: #64748b; +$success: #22c55e; +$error: #ef4444; +$warning: #f59e0b; + +$white: #ffffff; +$gray-50: #f8fafc; +$gray-100: #f1f5f9; +$gray-200: #e2e8f0; +$gray-300: #cbd5e1; +$gray-400: #94a3b8; +$gray-500: #64748b; +$gray-600: #475569; +$gray-700: #334155; +$gray-800: #1e293b; +$gray-900: #0f172a; + +// Typography +$font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif; +$font-size-xs: 0.75rem; +$font-size-sm: 0.875rem; +$font-size-base: 1rem; +$font-size-lg: 1.125rem; +$font-size-xl: 1.25rem; +$font-size-2xl: 1.5rem; +$font-size-3xl: 1.875rem; + +// Spacing +$spacing-1: 0.25rem; +$spacing-2: 0.5rem; +$spacing-3: 0.75rem; +$spacing-4: 1rem; +$spacing-5: 1.25rem; +$spacing-6: 1.5rem; +$spacing-8: 2rem; +$spacing-10: 2.5rem; +$spacing-12: 3rem; + +// Border Radius +$radius-sm: 0.25rem; +$radius-md: 0.375rem; +$radius-lg: 0.5rem; +$radius-xl: 0.75rem; +$radius-2xl: 1rem; +$radius-full: 9999px; + +// Shadows +$shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05); +$shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); +$shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); +$shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); + +// Transitions +$transition-fast: 150ms ease; +$transition-base: 200ms ease; +$transition-slow: 300ms ease; + +// Breakpoints +$breakpoint-sm: 640px; +$breakpoint-md: 768px; +$breakpoint-lg: 1024px; +$breakpoint-xl: 1280px; diff --git a/supabase/migrations/001_banners.sql b/supabase/migrations/001_banners.sql new file mode 100644 index 0000000..71c00a9 --- /dev/null +++ b/supabase/migrations/001_banners.sql @@ -0,0 +1,171 @@ +-- Table pour les bannières du carousel (gérée par super admin) +CREATE TABLE IF NOT EXISTS banners ( + id UUID DEFAULT gen_random_uuid() PRIMARY KEY, + image_url TEXT NOT NULL, + link_url TEXT, + title TEXT, + "order" INTEGER DEFAULT 0, + is_active BOOLEAN DEFAULT true, + created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), + updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() +); + +-- Table pour les super admins +CREATE TABLE IF NOT EXISTS admins ( + id UUID DEFAULT gen_random_uuid() PRIMARY KEY, + user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE, + email TEXT NOT NULL UNIQUE, + created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() +); + +-- Table pour les signatures des utilisateurs +CREATE TABLE IF NOT EXISTS user_signatures ( + id UUID DEFAULT gen_random_uuid() PRIMARY KEY, + user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE UNIQUE, + email TEXT, + first_name TEXT, + last_name TEXT, + job_title TEXT, + company TEXT, + phone TEXT, + mobile TEXT, + website TEXT, + address TEXT, + photo_url TEXT, + logo_url TEXT, + linkedin TEXT, + twitter TEXT, + facebook TEXT, + instagram TEXT, + primary_color TEXT DEFAULT '#3498db', + secondary_color TEXT DEFAULT '#2c3e50', + accent_color TEXT DEFAULT '#5dade2', + photo_shape TEXT DEFAULT 'hexagon', + created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), + updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() +); + +-- Index pour optimiser les requêtes +CREATE INDEX IF NOT EXISTS idx_banners_active ON banners(is_active, "order"); +CREATE INDEX IF NOT EXISTS idx_admins_user_id ON admins(user_id); +CREATE INDEX IF NOT EXISTS idx_user_signatures_user_id ON user_signatures(user_id); + +-- Fonction pour mettre à jour updated_at automatiquement +CREATE OR REPLACE FUNCTION update_updated_at() +RETURNS TRIGGER AS $$ +BEGIN + NEW.updated_at = NOW(); + RETURN NEW; +END; +$$ LANGUAGE plpgsql; + +-- Trigger pour mettre à jour updated_at sur banners +DROP TRIGGER IF EXISTS banners_updated_at ON banners; +CREATE TRIGGER banners_updated_at + BEFORE UPDATE ON banners + FOR EACH ROW + EXECUTE FUNCTION update_updated_at(); + +-- Trigger pour mettre à jour updated_at sur user_signatures +DROP TRIGGER IF EXISTS user_signatures_updated_at ON user_signatures; +CREATE TRIGGER user_signatures_updated_at + BEFORE UPDATE ON user_signatures + FOR EACH ROW + EXECUTE FUNCTION update_updated_at(); + +-- RLS (Row Level Security) +ALTER TABLE banners ENABLE ROW LEVEL SECURITY; +ALTER TABLE admins ENABLE ROW LEVEL SECURITY; +ALTER TABLE user_signatures ENABLE ROW LEVEL SECURITY; + +-- Politique: Tout le monde peut lire les bannières actives +CREATE POLICY "Bannières actives visibles par tous" ON banners + FOR SELECT USING (is_active = true); + +-- Politique: Les admins peuvent TOUT lire (même inactives) +CREATE POLICY "Admins peuvent tout lire" ON banners + FOR SELECT USING ( + EXISTS ( + SELECT 1 FROM admins WHERE user_id = auth.uid() + ) + ); + +-- Politique: Les admins peuvent insérer +CREATE POLICY "Admins peuvent inserer" ON banners + FOR INSERT WITH CHECK ( + EXISTS ( + SELECT 1 FROM admins WHERE user_id = auth.uid() + ) + ); + +-- Politique: Les admins peuvent modifier +CREATE POLICY "Admins peuvent modifier" ON banners + FOR UPDATE USING ( + EXISTS ( + SELECT 1 FROM admins WHERE user_id = auth.uid() + ) + ); + +-- Politique: Les admins peuvent supprimer +CREATE POLICY "Admins peuvent supprimer" ON banners + FOR DELETE USING ( + EXISTS ( + SELECT 1 FROM admins WHERE user_id = auth.uid() + ) + ); + +-- Politique: Un utilisateur peut vérifier s'il est admin (lecture de sa propre entrée) +CREATE POLICY "Users peuvent verifier leur statut admin" ON admins + FOR SELECT USING (user_id = auth.uid()); + +-- ========================================== +-- POLITIQUES POUR user_signatures +-- ========================================== + +-- Utilisateurs peuvent lire leur propre signature +CREATE POLICY "Users peuvent lire leur signature" ON user_signatures + FOR SELECT USING (user_id = auth.uid()); + +-- Utilisateurs peuvent créer leur propre signature +CREATE POLICY "Users peuvent creer leur signature" ON user_signatures + FOR INSERT WITH CHECK (user_id = auth.uid()); + +-- Utilisateurs peuvent modifier leur propre signature +CREATE POLICY "Users peuvent modifier leur signature" ON user_signatures + FOR UPDATE USING (user_id = auth.uid()); + +-- Admins peuvent lire TOUTES les signatures +CREATE POLICY "Admins peuvent lire toutes signatures" ON user_signatures + FOR SELECT USING ( + EXISTS (SELECT 1 FROM admins WHERE user_id = auth.uid()) + ); + +-- Admins peuvent modifier TOUTES les signatures +CREATE POLICY "Admins peuvent modifier toutes signatures" ON user_signatures + FOR UPDATE USING ( + EXISTS (SELECT 1 FROM admins WHERE user_id = auth.uid()) + ); + +-- Admins peuvent créer des signatures pour n'importe qui +CREATE POLICY "Admins peuvent creer signatures" ON user_signatures + FOR INSERT WITH CHECK ( + EXISTS (SELECT 1 FROM admins WHERE user_id = auth.uid()) + ); + +-- Admins peuvent supprimer des signatures +CREATE POLICY "Admins peuvent supprimer signatures" ON user_signatures + FOR DELETE USING ( + EXISTS (SELECT 1 FROM admins WHERE user_id = auth.uid()) + ); + +-- Insérer l'admin principal +INSERT INTO admins (user_id, email) VALUES + ('27f80c55-f045-4e6c-9751-56f5c86b71a2', 'admin@navier.net') +ON CONFLICT (email) DO NOTHING; + +-- Insérer quelques bannières par défaut (à personnaliser) +INSERT INTO banners (image_url, link_url, title, "order", is_active) VALUES + ('https://via.placeholder.com/600x150/3498db/ffffff?text=Promotion+1', 'https://example.com/promo1', 'Promotion 1', 1, true), + ('https://via.placeholder.com/600x150/e74c3c/ffffff?text=Promotion+2', 'https://example.com/promo2', 'Promotion 2', 2, true), + ('https://via.placeholder.com/600x150/2ecc71/ffffff?text=Promotion+3', 'https://example.com/promo3', 'Promotion 3', 3, true) +ON CONFLICT DO NOTHING; diff --git a/supabase/migrations/002_storage.sql b/supabase/migrations/002_storage.sql new file mode 100644 index 0000000..d1bbafb --- /dev/null +++ b/supabase/migrations/002_storage.sql @@ -0,0 +1,35 @@ +-- Créer le bucket pour les images +INSERT INTO storage.buckets (id, name, public, file_size_limit, allowed_mime_types) +VALUES ( + 'images', + 'images', + true, + 5242880, -- 5MB max + ARRAY['image/jpeg', 'image/png', 'image/gif', 'image/webp'] +) +ON CONFLICT (id) DO NOTHING; + +-- Politique: Tout le monde peut voir les images publiques +CREATE POLICY "Images publiques accessibles" ON storage.objects + FOR SELECT USING (bucket_id = 'images'); + +-- Politique: Utilisateurs authentifiés peuvent uploader +CREATE POLICY "Users authentifies peuvent uploader" ON storage.objects + FOR INSERT WITH CHECK ( + bucket_id = 'images' + AND auth.role() = 'authenticated' + ); + +-- Politique: Admins peuvent tout faire sur les images +CREATE POLICY "Admins gestion complete images" ON storage.objects + FOR ALL USING ( + bucket_id = 'images' + AND EXISTS (SELECT 1 FROM admins WHERE user_id = auth.uid()) + ); + +-- Politique: Users peuvent supprimer leurs propres uploads +CREATE POLICY "Users peuvent supprimer leurs images" ON storage.objects + FOR DELETE USING ( + bucket_id = 'images' + AND auth.uid()::text = (storage.foldername(name))[1] + ); diff --git a/supabase/migrations/003_signatures.sql b/supabase/migrations/003_signatures.sql new file mode 100644 index 0000000..a08f108 --- /dev/null +++ b/supabase/migrations/003_signatures.sql @@ -0,0 +1,74 @@ +-- Table pour stocker les signatures créées par l'admin +-- (différent de user_signatures qui est 1 signature par utilisateur) +CREATE TABLE IF NOT EXISTS signatures ( + id UUID DEFAULT gen_random_uuid() PRIMARY KEY, + created_by UUID REFERENCES auth.users(id) ON DELETE CASCADE, + + -- Infos personnelles + first_name TEXT NOT NULL, + last_name TEXT, + job_title TEXT, + company TEXT DEFAULT 'Navier Instruments', + + -- Contact + email TEXT, + phone TEXT, + mobile TEXT, + website TEXT DEFAULT 'www.navier-instruments.com', + address TEXT, + + -- Images + photo_url TEXT, + logo_url TEXT DEFAULT '/preview.webp', + + -- Réseaux sociaux + linkedin TEXT, + twitter TEXT, + facebook TEXT, + instagram TEXT, + + -- Style + primary_color TEXT DEFAULT '#F5A623', + secondary_color TEXT DEFAULT '#1a1a2e', + accent_color TEXT DEFAULT '#F5A623', + photo_shape TEXT DEFAULT 'hexagon', + style_template TEXT DEFAULT 'geometric', + + -- Bannière + banner_url TEXT, + banner_link TEXT, + + -- Métadonnées + created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), + updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() +); + +-- Index +CREATE INDEX IF NOT EXISTS idx_signatures_created_by ON signatures(created_by); +CREATE INDEX IF NOT EXISTS idx_signatures_name ON signatures(first_name, last_name); + +-- Trigger pour updated_at +DROP TRIGGER IF EXISTS signatures_updated_at ON signatures; +CREATE TRIGGER signatures_updated_at + BEFORE UPDATE ON signatures + FOR EACH ROW + EXECUTE FUNCTION update_updated_at(); + +-- RLS +ALTER TABLE signatures ENABLE ROW LEVEL SECURITY; + +-- Tout utilisateur authentifié peut créer des signatures +CREATE POLICY "Users peuvent creer signatures" ON signatures + FOR INSERT WITH CHECK (auth.uid() = created_by); + +-- Users peuvent voir leurs propres signatures +CREATE POLICY "Users peuvent voir leurs signatures" ON signatures + FOR SELECT USING (auth.uid() = created_by); + +-- Users peuvent modifier leurs propres signatures +CREATE POLICY "Users peuvent modifier leurs signatures" ON signatures + FOR UPDATE USING (auth.uid() = created_by); + +-- Users peuvent supprimer leurs propres signatures +CREATE POLICY "Users peuvent supprimer leurs signatures" ON signatures + FOR DELETE USING (auth.uid() = created_by); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..cf9c65d --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,34 @@ +{ + "compilerOptions": { + "target": "ES2017", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "react-jsx", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./src/*"] + } + }, + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts", + ".next/dev/types/**/*.ts", + "**/*.mts" + ], + "exclude": ["node_modules"] +}