commit 3d97d39bd377d8966b1bba6d8cab540b78239329 Author: Fares Kerkeni <93195495+Fares-Kerkeni@users.noreply.github.com> Date: Mon Dec 15 17:30:42 2025 +0100 Initial commit 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 0000000..e0a401b Binary files /dev/null and b/public/preview.webp differ diff --git a/public/screenshot.png b/public/screenshot.png new file mode 100644 index 0000000..e1811b0 Binary files /dev/null and b/public/screenshot.png differ diff --git a/public/signature-fares-kerkeni (1) (1).html b/public/signature-fares-kerkeni (1) (1).html new file mode 100644 index 0000000..822d2bc --- /dev/null +++ b/public/signature-fares-kerkeni (1) (1).html @@ -0,0 +1,87 @@ + + + + + Ma Signature Email + + + + + + + + + + + + + + + +
+
+ fares kerkeni +
+
+
fares kerkeni
+
commercial
+ + + + + + + + + + + + + +
+ + 📞 + + +33605050530 +
+ + ✉️ + + kerkenif11@gmail.com + + + 🌐 + + www.navier-instruments.com +
+ + 📍 + + 1 Square de la Paix +
+
+ Navier Instruments +
+ + f + + + 📷 + + + 𝕏 + + + in + +
+
+ + +
+ + 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 0000000..718d6fe Binary files /dev/null and b/src/app/favicon.ico differ 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,UklGRmgXAABXRUJQVlA4IFwXAABwtACdASo6AnYCPm02l0ikIyIhI9SZQIANiWdu3N06AEU4oJkdsnmGSYjLub/q+i4nqhgbm7lbzXDrgH7xhzH9Z/Ir+4cZF4e+UvQe4i8b/K/z57z/Qx5gH8N/h/6ff1jsLfyz0Afz700fQb/iPUA/wPUJ/+jfJv3Q/dH//+9z6gH/69QD//9c+2frJDoXcO7H5UoTZkofe+inhpsE7D7dJJFRfjIqL8ZFRfjIqL8YHiVOD/kFtUPAq9l16VHILaoeBV7Lr0qOQW1Q8Cr2XXJYTFj2lVeHtKq788tF2G4NVw9x+egJxoTxvW3Rti8eJbIQVuE8/1tJlaZvE33YaXhnotEQUVx6AxZfpUrarFVSHBy89gyfFFsbp9TAL4meHwcP2ta2uvDvxxCu2h4AVwAVLZaQAb+rLqYM2uy6X41M4iGexRCuAlKRbl9TjsC5AYei0uJtk4o4FhO39qCioXrup2Yt9hnISwKtvCQ1IE27XLLa28z40q4NUDNclqexH6AkJNmuRB2eUMWNpTetSA62II9RT8B+p2G+AxB37Kvn/HJnhnZyuZ8mILE8HPDjkLBlvhmep4s9sgkkUK4JcohoMBQpCvVnhXUTHgfBkSV8wmpCoKPrAuQgQd+yr5/xyZ4aoY1gPGlZPSyV8h+RDd0mlUCQ2jxv9jELLpl3U9peQPejIvHzwMqoxQyxUIWxR6nHGNDOFJeHYFo5HxFLYKQdOdXvI5Mrmbz0FO70EQCetUnrRlyECDzX5zoCQk2a6QnrY3ahMgtyQ5PJwM+l/8opDCm/GFffF3n/HJnhqiACBF+rZSYge5lTiGjo5Lxzk4YDCIchUG3gBuhFZV8/48ptemhKRfjIbmVUWONyz4i2jPFl9eHDnpQSce3ItMu+LvP+OTPDVEAECL8Y3SDCcQ8+cMRbqWbcnESdcoi1eu6ntLyB8AVk8sciTVCYTEWUsJCk9EvlQixgY3RqXHZmjSUQu4syHDUSFPLXwG/JZPP23SP4YsT/B/lSIx0T3NduSd/Tp9TBltIqiACBo8d12dtK7igC5xHtyzjGFTIOUFV6iMM6xFvi0y74u8/45M8NUQAQZW5R755o0l3Tvj1yAGOT7GZfOrNU+DSx09GMQsumXdT2l5A+AK1V5Wain5NyOBPa0h+Mkw68Mn9KubCt41LjszRpKIXcWZDh54dTyC5GfaZ/gTKXu6Th2IvxkULRyPiKWynwpT3fFy9fEvda0Laz7f/32dW4yADf2MQsumXdTsxgGzq9523b+5FvGK+jQ4JZG20C4diL8OIrKvn/HlNr00JSN0gjXJ008QkOUknAJr/gBv7GIWXTLup2YwDZ1e9GLeU+oJEf4vGWpkuLmX/dF+MhASOqS4KARHznyQ/HaOpLerv5/zydOGcHdHIQVNXtukfEVlXz/jkzw1RABCEfHJJWSIRguv5CJ1xIEwTmtJIV98Xef8eU2vTQlI3SB8GlOObRU7AstYoofl6NzbN0IrKvn/HJnhqiACDK3wOp7t9IcP+7OZZYrzGA2LDseLf06fUwZbSKogAgyt8I34Xo0GkIDfRHecwi+4F7bpSS47M0aSiF3FmQ4eeLvXoAjC1kZzdOEhGOT9BZW9NLjszRpK6qTPVBcUZ5hV2b43bm/YgLbWuL4cbx7VSN7gGWhbMLt/4B8n0q824OOTO8ilf14e0F66HDk7rNd+vAS1yy/7xjQDpvpaw1icTqUc/48pzCowCcysa17PJz/6gUYABjYbXrSvlnmw/+OTRbHIiz4A71wSaRDeAk+z+15DgjNiLxNgNMeg7OLnvyrpWhA+U4lN9HHym412fZ/WImdKu8delR8JgNDdxUXT6zkFsovnuBV7xuQW1Q7sNqVyozlGkNOHNoU0KZ7T9J8UkCSEtCXyLQJIS+RfDyMa3SSRUX4yKi/GRUX4yKi/GRPAAA/v6WgAAAABjwyil7g+r91sMeE6JU3fmOUsn/f7jt+9s8A/SsRkM47gNolTY2mkvjicgchZgA/d5GEvtmsvtmkmPIVE/FSA+K75ysq+qDz9xWVJ4AQYOFeRfoHso6Q6kZJTNHJ338drx10/dXeIP8FcKf5tRnsf98puIGmODkmuvTZapflrzTHlsk/7Bxs1cgA6rNxcsMstuvDNJZevpPEtuvw9fpTqDAX7J+3RazUbiz99uwUMkSftf/zhZO5UHJy6SJ4LQxugW3Wqvx335fRSvNA8RBJLm+TBN/ZicSMJyhCTRn/m5M7SywfJOamMycLt52AImPvHs9hDzts+l8UxEW3Dq4lp+pdOOhAHeVBW7ydL74cyMeO5qlUn5iLewNZvzuH23mdqO94baakD8MWTO3+q2iqphoF1RGx2gITju3T7CXXjIIgqIMkmLNgquB4fMhlhvBwAaYb4IBVp38P8yq2lAsk3ljCENWHkMp6H3cE8tuvRThEWvLmdHkgQahbTWCRe4ev1HB5XpVMCeY30cn2WMiQ5vSh1ehK2AroACq5ZkHX8jcYzo9HECgVl9qYk6zMC1rr+Q0IIQUthup2VaxcJruZ8g35kLOMVCKEJp75wwMNNJ1YEPZO4Tt62jcdwpsKEviQDy73yqN+knvi+s7WkWT2LxU3gtfYgxGlJ2jglomoUQpEuHJeVMIRu/OuSKXUABL6sGmSQyMGHQ9fBmzL8//JgaCVVFv5ECicVE69GKsuh45ZbdLZ0XI1HGP5y8MG4Lf4Y8D0Yltlq5So8mXjmdp9O2vHp3/IqkXBvn3eSzqIk7njdh7nr1BJj8vFCCjyhQEsYSeV0iPCC3v3xHQZuPX6iEdxmMquQkmgQvIwwwN015VZHII/t1tBQPxVf+ZBfdgOSjSRoys8nxTZK+PPJhfCBUPEmnJQL9dpchyNwJv8yVuQi3scv7dxfu8N983R1/L4G/9mK4vhEgLIHI8zhH+e2zA/l/wXAUBlpwBsSBdGLpPvjAldWiJ06ROYmLglrcmSwYX2oewDdu9X7lfjyIPKLWI0s2ENhRTWb8avDpU3+rqjJOfy+8Gq1VvJDD2SC7EkfR96pGcUfXAe0Kea1N33TOimMVgehwn/7AkxBWDDNNmUcgAgWdQJm2KgcwBF3D9e9fwOiwNO1u6+bxQ6t/YIbWwa+vcn3R4T7xZ68ROJ8DmHo3qxTQNM43FyR7l8Y3/+GOUg611ql7vqSXAoM3Y+3UUVH2l1o064xtzNtWpzNKgeejjfRw8XBGSSz9HX8ihu7+wWVSVyJ7PAtWMv/xuWv0HvZxn7ritYt7lmcJoNB7xVaAbjR8WCintFxdC+O9Wc12Z45pPYOWUrFEYvfii3KDsGDwaJ8Osw5/pXKicrWU7ZyoACNDs9aMToIq0AyYA0KooRWe0sJzeYR8dPCjZlOoQisKZzg9CEn4rAhEa60h1hUWkgC6Lkpy91DaOcMiFVOJgbjfPGx+MgDCeVlxRM0NKrCSjSyuHmDDLPVEE1buLC7sPdvfCoPWuxs8PaI8Hc2W2zy4O3fUdKrv2actagjr+RVMtfgfZkNxIC8FeV1IqW08JW5sZG97OhqPcf+L1+wXopkyK9WMNvN5AybbpuyvSqhfmCwv0timX/uJoVTgeiUJ0etCjOW+UtWcoHxhN0ycL/yscMLtBOtIwPrSmBWJJaB2IkVgsJ7sAgeayoqByX6xRhAB3jHv+kK39WCE14EoRZqxSEhg3XTTqokuoUitVJ9Tg1TinOiqTCwtqj148086wWRzYliiiNytDUFrNdoqsDWbCvx1cJsw82IFdFo11ZEqDKLh+QDGbcEJNIR1/IqmWBlmhPHB0JuGf/vZHLDnfqeWq1G/+dgYXfiTjT4Ygta5gPCGTSGMMqaLeZBXbBB/WPHO4Ml4VCERym4Wr3QrNAfbB6kinckXMq2jIcFFTpumIJrZC/OOr56IHRlsC8v28VsM5hHLAKdoKoKD2GisFgPsaMnpm+Xe2F/GmfpbPEXDY+thftK3zVk3bXPN1Ds/cTKj7iAUcqzzoybXk5NDNqfOMI+zHbjRUhhlaWk5hBUmkXFuZ2sNSVTjP+dc6f2cOSz9HX8iqZYECIuMNCmK20aH/fVGsipL4OpA+MFM7RC2Zhed1L8MzFwq02lNTxDi+1VLsJ3Arxhj9VIOsAKDmQUQjZVa9R1NHms1NCaEkqnb2VA9qbJOu6jMZqbGNPBw0iEVgsIN/A+ZEXolfeUvJDW3YYfFjT9etY7xISU7Ea4kPsIeG0maR5k9X3O1zkyJ8DUt7TIgT43gI5hZknQ2gYsiioku5LgCP8wrKeo9OgxdWrLViyO+ZH8u9ULuB0i2IBhgXX8iqZYECdxXL3WeT5uYHM0fEWKb1nnqLsXYGYGa/OWDueB2BgXGEDHpsbPwW8wJzTgF02kcKnZaF17ZooLl6McgllM/aeELiZKt/WlmoX1rj8y2tRMoZJCGtEisFvpkPyiMReTBfO1/slRKIEZxa6bB8jZmVrXNOAAQB239UVvVLx/VlrODOmUMsZqgOj/jf10cyxFegosKqccliynExL5RwdlTtKdtxWAManJcS6qHM2SZUBaQjr+RVMsFeqfBUPuUua/DSqgl10vgOln/UnbRkKlni/lfsz/kuCfepnJFATarfwDe282z+DUM1RP4x/jbKJfhWT8mxPJbLVEhWGNRIJaLN78plsCtzYPmfHq8unkHRyCewYkp9RI3BkM5OdxneNjmlX883imVkCGua8/HANFL6fg9FhVAyMrSYO++r9rxfEtZOAXUnNXb2RR5KKFuRLPIsS4xiV++dLRmHR94UINiJFYMDTVCj8WlyOy13GHtezrcxYOtA9O6MIm7kaau8nLvYZ5Ne4iXOodMPTzBdGt+1yOltnn6zSNNfYfM/DKR9gIcXib4HsPpgfns9sJB6VXEtTIN7Kys0vct1sNm4n7jW+KxO8xqpLGke8OE8sxYeOUSaX92dU5JfOrk1/HoUKgh5yF/HP1ROPouReTEcAb8LBxy4DmSQb7QTMrO0fxSIOaAw079351M13AxFeNf/1vJEZ2Igp44wB8CwwwLr+RVMsFGGrgXF/VspbQoKviNrYo1NI5Hn3nKeroMl13XUqVXXwkPB+OXO0BWDUP+NXcy7acEiUge/+oN9Pjf2z3+US9kgydfN7BEHBslMuHaqI/49G/Sr+iOGQ+3okibheNG019PUbhBV/Vo/pgQCVnWL6zM5bsQnQrc7uRxvXj8iWDHWPazpISULaka8uTRHF5yHJ7CIccVa9DOHkZkwZRNJ5lM/MOlcOfn/JSsj9HXzT/jSIRWC3IKSJPoWVGRpt/KwWrjLp4x0Bu7EJj3SN0y3uFyb1MWNJVDf+OSsmHnMW92UlrPLkzXUFJ/JSNYks9vDFGBfUGOOHxtdaw/W7Hs6mN9aRLo+7WlyY7PTIzANwBZv/SdzT+xb6ka2oYgJ/wwa1qo3xGyFTWzJnCk7bz44/A5sGCC/l4F7xlUQuv5FUywht7aqmTQkJSzfAVCDlp8gwKWIFpYq+4aVibDQtsIhpkouBRyHrZkVPxENohS3qvVnONydidXEwTHdO97XUJjTtmh9MLiA1n4Eu7OGn01MuDjNB1ddL+GK0kRp4QAIOGkQisF10Tgla3uEMs2kP8q1NAQ4QvgYlUbIu0uHezW3xlelyd9C3VZsRw+CmaNYkXdfq0zG62wak8x9MKH9KgcdlE1Yj9BD6BbRKANf44qunqfmiFWfn5uHQCNuNNHrXOLKMB6s/V6wCyoC0hHX8iqZYSLgOt/xitQ4lu0ISG1CL9RFgUq1L6N31MsR2VPSrq4M90N0iFn5VPK8ZDXRQ6KEy8DiA0KpjO7Fc3ZtXyaY8MMWzOXNsqF13d7bHFHI/4v94M9jAgoaRCKwXbUzqmo8K0IB+p1NnjcyywG2OXjO6y+fzt3tWBHA2P1zQ2P01xbMVUDlHzEExFwH3WHQomEhWf0fhowKWIrBZEAARETT8Z/mLTMpL0pfvashBPtYJU9KaeAsPK/MQLtQLSEdfyKplgmYZqJBBFo2W65+TbPlmsCl7qk3f9wmTmW7Fddvy08+rcHwy5MbdsJNLxBuO+YbWaEhzNMjaynhMw0HwSTwcwqWEnV/tlJ7pxVnKjoQAcMAQbNKl30QO1jejspBy/vdPyH5GkQisFoYxnFJMo6K+Y9iVUShyYJ2KQ3AX/Eo61H8iZFxNmwPiYUjjGdArOMrZdDZd7NUm+sN+fDVEcOv10vvM0orwN528Xm3JYGbbDV/XadEbuqnT/kSd654hkcpVsAZT8bfnbRagjr+RVMsI9t//ivI9u4jv47klQJqgb23lUvXxBvxmHTt0syK6BU2nCiHewR0NsQLSFQHsINOqePnY/O6XGgYYCOPtubJ63rnIGJuooAHhG0wkDAnKpgwG3q66HGotja9BnAIrBcIyUMxZNEYsWX7CaC3YVG9CI5gpkPnMHtUymiQVEi8CL6tcBHym19ipIcjJYm0ZOdwX3gGnXg7zAR1d3EmhvlxSulxl/J+WQ0O3xcQRUC1RnP/AdGJBlkUZknzSSREqyxKgLSEdfyKplhDUtsbdOYjZTeuQB3YameCT5y8j1gjy3crLcJ8cpPU8SJsW+9apwYpBjOTDAImKb+9i46lJwREd+e5+BofDKHxq6GfRjQWxmka2kpHMjtmDk7wwdo+rqKGM+BV0DQFAGJsCBwg4aRCKwX8ej4LGbpmO/hy//4Xe4k8W+R+a3rsvukxep9EqZNQYECemrPRSe6nmuG/hhIb0BEKnjYNw4BLvG3wW7DAxTgmaH/N1lRwYAuie36zo2W6e9X4KiK4jUtzf5gzvVF3fBde8lm19wzmusAZti1BHX8iqZYNbMjbIM+gmQNzImwFMmza5OJFkeVP6/roxC8DNBkdU3I0jVOxI4y7kBkTTiDPjC+L5f+lOi01Bp33fRckqbmAfA3tF/OXKOUjBoW83D356Gr0tLL4apbS/JFAfA5l/Cd+Q4TRucJBe7OxEi1LfLd2CAMd/R++hooM01moii4/pCDVdJ5grYBoCR726eJv+6SsaA33B0Lrgsoz90PKfrrhWzZR5BxN07Wp4Jl/4XO+bzepdAFDbBtmnply7vl5imd8d23CGpvknjfZZh/NrST+gdGNDhBPz3A0nqqCl2sbm6DBXIv23CimMjz7eLzbBpSs6br/8J/09A0JACpvSpi+2jkSFMPczUEdfyLWcp/uDiIRK+7OOXEpLadWmsEK8PM/SxJ6XpuYjOQaBr6R1Yd4SPo0mUxAlMoWDx1HGKHgrOhm45fQif5nX5zERZaXpm3G50ycIWscbI4pq/vRdDhuFQB0L32TR1x4ZU/YYBN0nVvUssmdge+zKziUfuBDywFUD+vwWFa9F9FnNe1L3zCGRG5QigBnCaU8d4CkiUh5QSxcqfcwojXwzGkXsaY9FRXDhbpUIus05PEuEcXP0d8LLShl70gnFlN6t2bbBuv8JVgYFKWCLyJel1Xrw3TFGn0oQsYmHON+jY7OSqe773XUZn42IHdD9vMfJT4cXtYuxDllCMaaEtU3o/t2GArF2DP0dfyKBjP1cADvoCu9fsdN1wjgpEx4C5LxCae2EP2QdSG3tXTnRYFsTY6efdc1e8ohP4J06L6YjJlxfHM7A+N7acEFM1CJyki+LL2COucBlzJdYFfZvqDRE8YtcILu5nzhJmLSUmg3AbaYa0Sq5R1ofJPNQ5NskkIg57B9sUmkFfVBzKuUZmgseXdHUZ2wlCcaoe19oXJN4IvosTrab8ap83e9yUp+XeasP4XzOGXLIyGx297Xk4R41qZuY7RSvHyD3T94iJa12IUhsW//Vn4fp5apdLTAtTatao9Ql2xWC18zUsgqdUuTuemKHnUb+ZRqGGhZvhSPFUIukTC94p/g88nujCJZbGlcV4v9I/VtUa+w22PkPIlDhDEmqwBD3VvHXC9NFJka0vU/LwTCeZl5NCSrxzYmYAvSCrbAhsAAAAAAAAAAAAAAAAAA' + +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"] +}