diff --git a/.dockerignore b/.dockerignore index ef390949..6a89b14b 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,6 +1,8 @@ target/ web/node_modules web/dist +webnext/node_modules +webnext/dist .volumes/ .github/ docs/ diff --git a/.github/workflows/lint-web.yml b/.github/workflows/lint-web.yml index 71f55bb8..529ef8a4 100644 --- a/.github/workflows/lint-web.yml +++ b/.github/workflows/lint-web.yml @@ -32,13 +32,13 @@ jobs: with: node-version: 24 - name: install deps - working-directory: ./web + working-directory: ./webnext run: | npm i -g pnpm pnpm i --frozen-lockfile - name: Lint - working-directory: ./web + working-directory: ./webnext run: pnpm lint - name: Audit - working-directory: ./web + working-directory: ./webnext run: pnpm audit --prod diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a103012f..f7071a71 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -111,18 +111,20 @@ jobs: with: version: 10 - - name: Use Node.js 24 + - name: Use Node.js uses: actions/setup-node@v4 with: node-version: 24 + cache: "pnpm" + cache-dependency-path: ./webnext/pnpm-lock.yaml - name: Install frontend dependencies run: pnpm install --ignore-scripts --frozen-lockfile - working-directory: web + working-directory: webnext - name: Build frontend run: pnpm build - working-directory: web + working-directory: webnext - name: Build release binary uses: actions-rs/cargo@v1 diff --git a/Cargo.lock b/Cargo.lock index a77db2e7..9383da9d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -69,9 +69,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "ammonia" -version = "4.1.1" +version = "4.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6b346764dd0814805de8abf899fe03065bcee69bb1a4771c785817e39f3978f" +checksum = "17e913097e1a2124b46746c980134e8c954bc17a6a59bb3fde96f088d126dde6" dependencies = [ "cssparser", "html5ever", diff --git a/Dockerfile b/Dockerfile index f50a857f..c33ba166 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,10 @@ FROM node:24-alpine AS web WORKDIR /app -COPY web/package.json . -COPY web/pnpm-lock.yaml . -COPY web/.npmrc . +COPY webnext/package.json webnext/pnpm-lock.yaml webnext/.npmrc ./ RUN npm i -g pnpm RUN pnpm install --ignore-scripts --frozen-lockfile -COPY web/ . +COPY webnext/ . RUN pnpm run generate-translation-types RUN pnpm build @@ -31,8 +29,7 @@ COPY --from=planner /build/recipe.json recipe.json RUN cargo chef cook --release --recipe-path recipe.json # build project -COPY --from=web /app/dist ./web/dist -COPY web/src/shared/images/svg ./web/src/shared/images/svg +COPY --from=web /app/dist ./webnext/dist RUN apt-get update && apt-get -y install protobuf-compiler libprotobuf-dev COPY Cargo.toml Cargo.lock build.rs ./ # for vergen diff --git a/README.md b/README.md index ae3f49bd..7e93dad5 100644 --- a/README.md +++ b/README.md @@ -23,27 +23,30 @@ Find us on Matrix: [#defguard:teonite.com](https://matrix.to/#/#defguard:teonite Please review the [Contributing guide](https://defguard.gitbook.io/defguard/for-developers/contributing) for information on how to get started contributing to the project. You might also find our [environment setup guide](https://defguard.gitbook.io/defguard/for-developers/dev-env-setup) handy. - ## Development Clone repository: + ```bash git@github.com:DefGuard/client.git ``` Initialize `proto` submodule: + ```bash git submodule update --init --recursive ``` To run API server: + ```bash cargo run ``` To run webapp dev server: + ```bash -cd web/ +cd webnext/ pnpm install pnpm run dev ``` @@ -76,5 +79,3 @@ All release assets (binaries, packages, etc.) include SHA256 checksums that are # Linux/macOS echo known_sha256_checksum_of_the_file path/to/file | sha256sum --check ``` - - diff --git a/src/assets.rs b/src/assets.rs index 0ae3ddc7..aef15711 100644 --- a/src/assets.rs +++ b/src/assets.rs @@ -15,17 +15,9 @@ pub async fn index() -> impl IntoResponse { web_asset(Uri::from_static("/index.html")).await } -pub async fn svg(uri: Uri) -> impl IntoResponse { - let mut path = uri.path().trim_start_matches('/').to_string(); - // Rewrite the path to match the structure of the embedded files - path.insert_str(0, "src/shared/images/"); - StaticFile(path) -} - #[derive(Embed)] -#[folder = "web/"] +#[folder = "webnext/"] #[include = "dist/*"] -#[include = "src/shared/images/*"] struct WebAsset; pub struct StaticFile(pub T); diff --git a/src/http.rs b/src/http.rs index 840eff6c..47b39738 100644 --- a/src/http.rs +++ b/src/http.rs @@ -33,7 +33,7 @@ use tracing::{info_span, Level}; use url::Url; use crate::{ - assets::{index, svg, web_asset}, + assets::{index, web_asset}, config::Config, enterprise::handlers::openid_login::{self, FlowType}, error::ApiError, @@ -265,7 +265,6 @@ pub async fn run_server(config: Config) -> anyhow::Result<()> { .route("/{*path}", get(index)) .route("/fonts/{*path}", get(web_asset)) .route("/assets/{*path}", get(web_asset)) - .route("/svg/{*path}", get(svg)) .nest( "/api/v1", Router::new() diff --git a/webnext/.editorconfig b/webnext/.editorconfig new file mode 100644 index 00000000..73f41032 --- /dev/null +++ b/webnext/.editorconfig @@ -0,0 +1,11 @@ +root = false + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 2 + +[*.{ts,tsx,js,jsx,scss,html,json,yaml}] +rulers = 90 diff --git a/webnext/.gitattributes b/webnext/.gitattributes new file mode 100644 index 00000000..ee7f45a3 --- /dev/null +++ b/webnext/.gitattributes @@ -0,0 +1,36 @@ +* text=auto eol=lf + +*.js text eol=lf +*.jsx text eol=lf +*.ts text eol=lf +*.tsx text eol=lf +*.css text eol=lf +*.scss text eol=lf +*.json text eol=lf +*.html text eol=lf +*.md text eol=lf +*.yml text eol=lf +*.yaml text eol=lf +*.lock text eol=lf + +*.woff binary +*.woff2 binary +*.ttf binary +*.otf binary +*.eot binary +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.webp binary +*.avif binary +*.ico binary +*.mp4 binary +*.webm binary +*.ogg binary +*.mp3 binary +*.wav binary +*.pdf binary +*.zip binary +*.tar binary +*.gz binary diff --git a/webnext/.gitignore b/webnext/.gitignore new file mode 100644 index 00000000..5d08e8d1 --- /dev/null +++ b/webnext/.gitignore @@ -0,0 +1,26 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local +project.inlang/cache + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? +.tanstack diff --git a/webnext/.prettierignore b/webnext/.prettierignore new file mode 100644 index 00000000..74dbecd5 --- /dev/null +++ b/webnext/.prettierignore @@ -0,0 +1,4 @@ +/src/i18n/*.ts +/src/i18n/*.tsx +/src/**/*.tsx +/src/**/*.ts diff --git a/webnext/.prettierrc b/webnext/.prettierrc new file mode 100644 index 00000000..71a0f329 --- /dev/null +++ b/webnext/.prettierrc @@ -0,0 +1,8 @@ +{ + "semi": true, + "tabWidth": 2, + "singleQuote": true, + "useTabs": false, + "printWidth": 90, + "endOfLine": "lf" +} diff --git a/webnext/.stylelintrc.json b/webnext/.stylelintrc.json new file mode 100644 index 00000000..6a4e2133 --- /dev/null +++ b/webnext/.stylelintrc.json @@ -0,0 +1,10 @@ +{ + "extends": ["stylelint-config-standard-scss"], + "plugins": ["stylelint-scss"], + "rules": { + "at-rule-no-unknown": null, + "scss/at-rule-no-unknown": true, + "custom-property-empty-line-before": null, + "value-keyword-case": null + } +} diff --git a/webnext/.vscode/extensions.json b/webnext/.vscode/extensions.json new file mode 100644 index 00000000..116d6852 --- /dev/null +++ b/webnext/.vscode/extensions.json @@ -0,0 +1,5 @@ +{ + "recommendations": [ + "inlang.vs-code-extension" + ] +} \ No newline at end of file diff --git a/webnext/README.md b/webnext/README.md new file mode 100644 index 00000000..e69de29b diff --git a/webnext/biome.json b/webnext/biome.json new file mode 100644 index 00000000..b583f360 --- /dev/null +++ b/webnext/biome.json @@ -0,0 +1,67 @@ +{ + "$schema": "https://biomejs.dev/schemas/2.2.4/schema.json", + "vcs": { + "enabled": false, + "clientKind": "git", + "useIgnoreFile": false + }, + "files": { + "ignoreUnknown": false, + "includes": [ + "src/**", + "!src/messages", + "!src/paraglide/**/*.js", + "!src/routeTree.gen.ts" + ] + }, + "formatter": { + "enabled": true, + "formatWithErrors": false, + "attributePosition": "auto", + "bracketSameLine": false, + "bracketSpacing": true, + "expand": "auto", + "lineEnding": "lf", + "lineWidth": 90, + "indentStyle": "space", + "useEditorconfig": true + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "a11y": "off", + "correctness": { + "useUniqueElementIds": "off" + }, + "style": { + "useLiteralEnumMembers": "off", + "useBlockStatements": "off" + }, + "suspicious": { + "noArrayIndexKey": "off" + } + } + }, + "javascript": { + "formatter": { + "quoteStyle": "single", + "jsxQuoteStyle": "double", + "quoteProperties": "asNeeded", + "trailingCommas": "all", + "semicolons": "always", + "arrowParentheses": "always", + "attributePosition": "auto", + "bracketSameLine": false, + "bracketSpacing": true + } + }, + "assist": { + "enabled": true, + "actions": { + "source": { + "organizeImports": "on" + } + } + } +} diff --git a/webnext/index.html b/webnext/index.html new file mode 100644 index 00000000..5796a7c7 --- /dev/null +++ b/webnext/index.html @@ -0,0 +1,16 @@ + + + + + + + Defguard + + + +
+
+ + + + diff --git a/webnext/messages/de.json b/webnext/messages/de.json new file mode 100644 index 00000000..006f618a --- /dev/null +++ b/webnext/messages/de.json @@ -0,0 +1,3 @@ +{ + "$schema": "https://inlang.com/schema/inlang-message-format" +} diff --git a/webnext/messages/en.json b/webnext/messages/en.json new file mode 100644 index 00000000..fce4b1cd --- /dev/null +++ b/webnext/messages/en.json @@ -0,0 +1,52 @@ +{ + "$schema": "https://inlang.com/schema/inlang-message-format", + "controls_back": "Back", + "controls_continue": "Continue", + "form_error_min_len": "Minimum length of {length}", + "form_error_email": "Enter valid email", + "form_error_required": "Field is required", + "cmp_enrol_step": "Step {current}/{max}", + "cmp_enrol_final": "Final step", + "start_footer_contact": "If you need assistance, please contact your defguard administrator at", + "start_footer_copyright": "Copyright ©2023-{currentYear} Defguard Sp. z o.o.", + "start_multi_title": "Get Started with Defguard", + "start_multi_subtitle": "Please select the option that suits your needs.", + "start_multi_enrollment_title": "Enrollment process", + "start_multi_enrollment_subtitle": "Configure your device in a few simple steps to access your corporate VPN.", + "start_multi_enrollment_button": "Launch enrollment", + "start_multi_password_title": "Password reset", + "start_multi_password_subtitle": "Use this option to reset your internal Defguard access password.", + "start_multi_password_button": "Reset password", + "password_start_title": "Reset password", + "password_start_subtitle": "Please enter your email associated with your defguard account.", + "password_start_form_explain": "After you submit the request, a password reset link will be sent to the email you provide. It may take a few minutes. If you do not receive the email in several minutes, please check your spam folder.", + "password_start_form_label_email": "Email", + "password_start_submit": "Send request", + "password_sent_title": "Your request has been sent.", + "password_sent_subTitle": "If the provided email address is assigned to any account, the password reset will be initiated and you will receive an email with further instructions.", + "password_sent_link": "Back to main page", + "password_form_title": "Create new password", + "password_form_subtitle": "Set up a strong password to protect your account.", + "password_form_labels_password": "Create new password", + "password_form_labels_repeat": "Confirm new password", + "password_form_check_title": "Your password must include:", + "password_form_check_number": "At least one number required", + "password_form_check_special": "At least one special character", + "password_form_check_lowercase": "At least one lowercase character", + "password_form_check_uppercase": "At least one uppercase character", + "password_form_check_minimum": "Minimum length of 8", + "password_form_check_repeat_match": "Password's doesn't match", + "password_form_special_error": "Password doesn't meet the requirements. Please check the list below.", + "password_form_submit": "Submit new password", + "password_end_title": "Password successfully updated.", + "password_end_subtitle": "Password successfully updated.", + "password_end_link": "Go to Log in", + "client_download_title": "Download defguard application", + "client_download_subtitle": "Download the client/app you want to activate VPN access on.", + "client_download_label_desktop": "Desktop clients", + "client_download_label_mobile": "Mobile applications", + "client_download_for": "Defguard for {platform}", + "client_download_supports_newer": "Supports {platform} and newer.", + "client_download_supports_and": "Supports {platform} and {other}.", + "client_download_works_with": "Works with {platform}." +} diff --git a/webnext/package.json b/webnext/package.json new file mode 100644 index 00000000..fbafaf5e --- /dev/null +++ b/webnext/package.json @@ -0,0 +1,56 @@ +{ + "name": "webnext", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "check-types": "tsc --noEmit", + "preview": "vite preview", + "biome": "biome", + "lint": "biome check ./src/ && prettier src/**/*.scss --check --log-level error && stylelint \"src/**/*.scss\" -c ./.stylelintrc.json", + "fix": "biome check ./src/ --write --unsafe && prettier src/**/*.scss -w --log-level silent" + }, + "dependencies": { + "@axa-ch/react-polymorphic-types": "^1.4.1", + "@floating-ui/react": "^0.27.16", + "@inlang/paraglide-js": "^2.3.2", + "@tanstack/react-devtools": "^0.6.9", + "@tanstack/react-form": "^1.21.2", + "@tanstack/react-query": "^5.89.0", + "@tanstack/react-query-devtools": "^5.89.0", + "@tanstack/react-router": "^1.131.48", + "@tanstack/react-router-devtools": "^1.131.48", + "@uidotdev/usehooks": "^2.4.1", + "axios": "^1.12.2", + "clsx": "^2.1.1", + "motion": "^12.23.15", + "qs": "^6.14.0", + "react": "^19.1.1", + "react-dom": "^19.1.1", + "zod": "^4.1.11", + "zustand": "^5.0.8" + }, + "devDependencies": { + "@biomejs/biome": "2.2.4", + "@inlang/paraglide-js": "2.3.2", + "@tanstack/router-plugin": "^1.131.48", + "@types/node": "^24.5.2", + "@types/qs": "^6.14.0", + "@types/react": "^19.1.13", + "@types/react-dom": "^19.1.9", + "@vitejs/plugin-react-swc": "^4.1.0", + "globals": "^16.4.0", + "prettier": "^3.6.2", + "sass": "^1.92.1", + "sharp": "^0.34.4", + "stylelint": "^16.24.0", + "stylelint-config-standard-scss": "^16.0.0", + "stylelint-scss": "^6.12.1", + "typescript": "~5.9.2", + "typescript-eslint": "^8.44.0", + "vite": "^7.1.6", + "vite-plugin-image-optimizer": "^2.0.2" + } +} diff --git a/webnext/pnpm-lock.yaml b/webnext/pnpm-lock.yaml new file mode 100644 index 00000000..eb5ed855 --- /dev/null +++ b/webnext/pnpm-lock.yaml @@ -0,0 +1,4775 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@axa-ch/react-polymorphic-types': + specifier: ^1.4.1 + version: 1.4.1(@types/react@19.1.13)(react@19.1.1) + '@floating-ui/react': + specifier: ^0.27.16 + version: 0.27.16(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@inlang/paraglide-js': + specifier: ^2.3.2 + version: 2.3.2 + '@tanstack/react-devtools': + specifier: ^0.6.9 + version: 0.6.9(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(csstype@3.1.3)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.9) + '@tanstack/react-form': + specifier: ^1.21.2 + version: 1.21.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@tanstack/react-query': + specifier: ^5.89.0 + version: 5.89.0(react@19.1.1) + '@tanstack/react-query-devtools': + specifier: ^5.89.0 + version: 5.89.0(@tanstack/react-query@5.89.0(react@19.1.1))(react@19.1.1) + '@tanstack/react-router': + specifier: ^1.131.48 + version: 1.131.48(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@tanstack/react-router-devtools': + specifier: ^1.131.48 + version: 1.131.48(@tanstack/react-router@1.131.48(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@tanstack/router-core@1.131.48)(csstype@3.1.3)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.9)(tiny-invariant@1.3.3) + '@uidotdev/usehooks': + specifier: ^2.4.1 + version: 2.4.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + axios: + specifier: ^1.12.2 + version: 1.12.2 + clsx: + specifier: ^2.1.1 + version: 2.1.1 + motion: + specifier: ^12.23.15 + version: 12.23.15(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + qs: + specifier: ^6.14.0 + version: 6.14.0 + react: + specifier: ^19.1.1 + version: 19.1.1 + react-dom: + specifier: ^19.1.1 + version: 19.1.1(react@19.1.1) + zod: + specifier: ^4.1.11 + version: 4.1.11 + zustand: + specifier: ^5.0.8 + version: 5.0.8(@types/react@19.1.13)(react@19.1.1)(use-sync-external-store@1.5.0(react@19.1.1)) + devDependencies: + '@biomejs/biome': + specifier: 2.2.4 + version: 2.2.4 + '@tanstack/router-plugin': + specifier: ^1.131.48 + version: 1.131.48(@tanstack/react-router@1.131.48(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(vite@7.1.6(@types/node@24.5.2)(sass@1.92.1)(tsx@4.20.5)) + '@types/node': + specifier: ^24.5.2 + version: 24.5.2 + '@types/qs': + specifier: ^6.14.0 + version: 6.14.0 + '@types/react': + specifier: ^19.1.13 + version: 19.1.13 + '@types/react-dom': + specifier: ^19.1.9 + version: 19.1.9(@types/react@19.1.13) + '@vitejs/plugin-react-swc': + specifier: ^4.1.0 + version: 4.1.0(vite@7.1.6(@types/node@24.5.2)(sass@1.92.1)(tsx@4.20.5)) + globals: + specifier: ^16.4.0 + version: 16.4.0 + prettier: + specifier: ^3.6.2 + version: 3.6.2 + sass: + specifier: ^1.92.1 + version: 1.92.1 + sharp: + specifier: ^0.34.4 + version: 0.34.4 + stylelint: + specifier: ^16.24.0 + version: 16.24.0(typescript@5.9.2) + stylelint-config-standard-scss: + specifier: ^16.0.0 + version: 16.0.0(postcss@8.5.6)(stylelint@16.24.0(typescript@5.9.2)) + stylelint-scss: + specifier: ^6.12.1 + version: 6.12.1(stylelint@16.24.0(typescript@5.9.2)) + typescript: + specifier: ~5.9.2 + version: 5.9.2 + typescript-eslint: + specifier: ^8.44.0 + version: 8.44.0(eslint@9.35.0)(typescript@5.9.2) + vite: + specifier: ^7.1.6 + version: 7.1.6(@types/node@24.5.2)(sass@1.92.1)(tsx@4.20.5) + vite-plugin-image-optimizer: + specifier: ^2.0.2 + version: 2.0.2(sharp@0.34.4)(vite@7.1.6(@types/node@24.5.2)(sass@1.92.1)(tsx@4.20.5)) + +packages: + + '@axa-ch/react-polymorphic-types@1.4.1': + resolution: {integrity: sha512-2lo5a9slPZbc9hVCC5Z7fXWimd+UWCtETi88uGxsZ6GG5s6sAnwxPDPZKZ8qR/riFSWROglxDGNBtK+8jKz2eQ==} + peerDependencies: + '@types/react': ^18.0.0 || ^19.0.0 + react: ^18.0.0 || ^19.0.0 + + '@babel/code-frame@7.27.1': + resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.28.4': + resolution: {integrity: sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.28.4': + resolution: {integrity: sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.28.3': + resolution: {integrity: sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-annotate-as-pure@7.27.3': + resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.27.2': + resolution: {integrity: sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-create-class-features-plugin@7.28.3': + resolution: {integrity: sha512-V9f6ZFIYSLNEbuGA/92uOvYsGCJNsuA8ESZ4ldc09bWk/j8H8TKiPw8Mk1eG6olpnO0ALHJmYfZvF4MEE4gajg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-globals@7.28.0': + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-member-expression-to-functions@7.27.1': + resolution: {integrity: sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.27.1': + resolution: {integrity: sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.28.3': + resolution: {integrity: sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-optimise-call-expression@7.27.1': + resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-plugin-utils@7.27.1': + resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-replace-supers@7.27.1': + resolution: {integrity: sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.27.1': + resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.27.1': + resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.28.4': + resolution: {integrity: sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.28.4': + resolution: {integrity: sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-syntax-jsx@7.27.1': + resolution: {integrity: sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.27.1': + resolution: {integrity: sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-commonjs@7.27.1': + resolution: {integrity: sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typescript@7.28.0': + resolution: {integrity: sha512-4AEiDEBPIZvLQaWlc9liCavE0xRM0dNca41WtBeM3jgFptfUOSG9z0uteLhq6+3rq+WB6jIvUwKDTpXEHPJ2Vg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/preset-typescript@7.27.1': + resolution: {integrity: sha512-l7WfQfX0WK4M0v2RudjuQK4u99BS6yLHYEmdtVPP7lKV013zr9DygFuWNlnbvQ9LR+LS0Egz/XAvGx5U9MX0fQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/template@7.27.2': + resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.28.4': + resolution: {integrity: sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.28.4': + resolution: {integrity: sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==} + engines: {node: '>=6.9.0'} + + '@biomejs/biome@2.2.4': + resolution: {integrity: sha512-TBHU5bUy/Ok6m8c0y3pZiuO/BZoY/OcGxoLlrfQof5s8ISVwbVBdFINPQZyFfKwil8XibYWb7JMwnT8wT4WVPg==} + engines: {node: '>=14.21.3'} + hasBin: true + + '@biomejs/cli-darwin-arm64@2.2.4': + resolution: {integrity: sha512-RJe2uiyaloN4hne4d2+qVj3d3gFJFbmrr5PYtkkjei1O9c+BjGXgpUPVbi8Pl8syumhzJjFsSIYkcLt2VlVLMA==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [darwin] + + '@biomejs/cli-darwin-x64@2.2.4': + resolution: {integrity: sha512-cFsdB4ePanVWfTnPVaUX+yr8qV8ifxjBKMkZwN7gKb20qXPxd/PmwqUH8mY5wnM9+U0QwM76CxFyBRJhC9tQwg==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [darwin] + + '@biomejs/cli-linux-arm64-musl@2.2.4': + resolution: {integrity: sha512-7TNPkMQEWfjvJDaZRSkDCPT/2r5ESFPKx+TEev+I2BXDGIjfCZk2+b88FOhnJNHtksbOZv8ZWnxrA5gyTYhSsQ==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [linux] + + '@biomejs/cli-linux-arm64@2.2.4': + resolution: {integrity: sha512-M/Iz48p4NAzMXOuH+tsn5BvG/Jb07KOMTdSVwJpicmhN309BeEyRyQX+n1XDF0JVSlu28+hiTQ2L4rZPvu7nMw==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [linux] + + '@biomejs/cli-linux-x64-musl@2.2.4': + resolution: {integrity: sha512-m41nFDS0ksXK2gwXL6W6yZTYPMH0LughqbsxInSKetoH6morVj43szqKx79Iudkp8WRT5SxSh7qVb8KCUiewGg==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [linux] + + '@biomejs/cli-linux-x64@2.2.4': + resolution: {integrity: sha512-orr3nnf2Dpb2ssl6aihQtvcKtLySLta4E2UcXdp7+RTa7mfJjBgIsbS0B9GC8gVu0hjOu021aU8b3/I1tn+pVQ==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [linux] + + '@biomejs/cli-win32-arm64@2.2.4': + resolution: {integrity: sha512-NXnfTeKHDFUWfxAefa57DiGmu9VyKi0cDqFpdI+1hJWQjGJhJutHPX0b5m+eXvTKOaf+brU+P0JrQAZMb5yYaQ==} + engines: {node: '>=14.21.3'} + cpu: [arm64] + os: [win32] + + '@biomejs/cli-win32-x64@2.2.4': + resolution: {integrity: sha512-3Y4V4zVRarVh/B/eSHczR4LYoSVyv3Dfuvm3cWs5w/HScccS0+Wt/lHOcDTRYeHjQmMYVC3rIRWqyN2EI52+zg==} + engines: {node: '>=14.21.3'} + cpu: [x64] + os: [win32] + + '@cacheable/memoize@2.0.1': + resolution: {integrity: sha512-WBLH37SynkCa39S6IrTSMQF3Wdv4/51WxuU5TuCNEqZcLgLGHme8NUxRTcDIO8ZZFXlslWbh9BD3DllixgPg6Q==} + + '@cacheable/memory@2.0.1': + resolution: {integrity: sha512-Ufc7iQnRKFC8gjZVGOTOsMwM/vZtmsw3LafvctVXPm835ElgK3DpMe1U5i9sd6OieSkyJhXbAT2Q2FosXBBbAQ==} + + '@cacheable/utils@2.0.1': + resolution: {integrity: sha512-sxHjO6wKn4/0wHCFYbh6tljj+ciP9BKgyBi09NLsor3sN+nu/Rt3FwLw6bYp7bp8usHpmcwUozrB/u4RuSw/eg==} + + '@csstools/css-parser-algorithms@3.0.5': + resolution: {integrity: sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/css-tokenizer@3.0.4': + resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} + engines: {node: '>=18'} + + '@csstools/media-query-list-parser@4.0.3': + resolution: {integrity: sha512-HAYH7d3TLRHDOUQK4mZKf9k9Ph/m8Akstg66ywKR4SFAigjs3yBiUeZtFxywiTm5moZMAp/5W/ZuFnNXXYLuuQ==} + engines: {node: '>=18'} + peerDependencies: + '@csstools/css-parser-algorithms': ^3.0.5 + '@csstools/css-tokenizer': ^3.0.4 + + '@csstools/selector-specificity@5.0.0': + resolution: {integrity: sha512-PCqQV3c4CoVm3kdPhyeZ07VmBRdH2EpMFA/pd9OASpOEC3aXNGoqPDAZ80D0cLpMBxnmk0+yNhGsEx31hq7Gtw==} + engines: {node: '>=18'} + peerDependencies: + postcss-selector-parser: ^7.0.0 + + '@dual-bundle/import-meta-resolve@4.2.1': + resolution: {integrity: sha512-id+7YRUgoUX6CgV0DtuhirQWodeeA7Lf4i2x71JS/vtA5pRb/hIGWlw+G6MeXvsM+MXrz0VAydTGElX1rAfgPg==} + + '@emnapi/runtime@1.5.0': + resolution: {integrity: sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ==} + + '@esbuild/aix-ppc64@0.25.10': + resolution: {integrity: sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.25.10': + resolution: {integrity: sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.25.10': + resolution: {integrity: sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.25.10': + resolution: {integrity: sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.25.10': + resolution: {integrity: sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.10': + resolution: {integrity: sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.25.10': + resolution: {integrity: sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.10': + resolution: {integrity: sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.25.10': + resolution: {integrity: sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.25.10': + resolution: {integrity: sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.25.10': + resolution: {integrity: sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.25.10': + resolution: {integrity: sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.25.10': + resolution: {integrity: sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.25.10': + resolution: {integrity: sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.10': + resolution: {integrity: sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.25.10': + resolution: {integrity: sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.25.10': + resolution: {integrity: sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.10': + resolution: {integrity: sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.10': + resolution: {integrity: sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.10': + resolution: {integrity: sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.10': + resolution: {integrity: sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.25.10': + resolution: {integrity: sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.25.10': + resolution: {integrity: sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.25.10': + resolution: {integrity: sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.25.10': + resolution: {integrity: sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.25.10': + resolution: {integrity: sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.9.0': + resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.1': + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.21.0': + resolution: {integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/config-helpers@0.3.1': + resolution: {integrity: sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.15.2': + resolution: {integrity: sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.3.1': + resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.35.0': + resolution: {integrity: sha512-30iXE9whjlILfWobBkNerJo+TXYsgVM5ERQwMcMKCHckHflCmf7wXDAHlARoWnh0s1U72WqlbeyE7iAcCzuCPw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.6': + resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.3.5': + resolution: {integrity: sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@floating-ui/core@1.7.3': + resolution: {integrity: sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==} + + '@floating-ui/dom@1.7.4': + resolution: {integrity: sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==} + + '@floating-ui/react-dom@2.1.6': + resolution: {integrity: sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==} + peerDependencies: + react: '>=16.8.0' + react-dom: '>=16.8.0' + + '@floating-ui/react@0.27.16': + resolution: {integrity: sha512-9O8N4SeG2z++TSM8QA/KTeKFBVCNEz/AGS7gWPJf6KFRzmRWixFRnCnkPHRDwSVZW6QPDO6uT0P2SpWNKCc9/g==} + peerDependencies: + react: '>=17.0.0' + react-dom: '>=17.0.0' + + '@floating-ui/utils@0.2.10': + resolution: {integrity: sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==} + + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.7': + resolution: {integrity: sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.4.3': + resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} + engines: {node: '>=18.18'} + + '@img/colour@1.0.0': + resolution: {integrity: sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==} + engines: {node: '>=18'} + + '@img/sharp-darwin-arm64@0.34.4': + resolution: {integrity: sha512-sitdlPzDVyvmINUdJle3TNHl+AG9QcwiAMsXmccqsCOMZNIdW2/7S26w0LyU8euiLVzFBL3dXPwVCq/ODnf2vA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [darwin] + + '@img/sharp-darwin-x64@0.34.4': + resolution: {integrity: sha512-rZheupWIoa3+SOdF/IcUe1ah4ZDpKBGWcsPX6MT0lYniH9micvIU7HQkYTfrx5Xi8u+YqwLtxC/3vl8TQN6rMg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-darwin-arm64@1.2.3': + resolution: {integrity: sha512-QzWAKo7kpHxbuHqUC28DZ9pIKpSi2ts2OJnoIGI26+HMgq92ZZ4vk8iJd4XsxN+tYfNJxzH6W62X5eTcsBymHw==} + cpu: [arm64] + os: [darwin] + + '@img/sharp-libvips-darwin-x64@1.2.3': + resolution: {integrity: sha512-Ju+g2xn1E2AKO6YBhxjj+ACcsPQRHT0bhpglxcEf+3uyPY+/gL8veniKoo96335ZaPo03bdDXMv0t+BBFAbmRA==} + cpu: [x64] + os: [darwin] + + '@img/sharp-libvips-linux-arm64@1.2.3': + resolution: {integrity: sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linux-arm@1.2.3': + resolution: {integrity: sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA==} + cpu: [arm] + os: [linux] + + '@img/sharp-libvips-linux-ppc64@1.2.3': + resolution: {integrity: sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg==} + cpu: [ppc64] + os: [linux] + + '@img/sharp-libvips-linux-s390x@1.2.3': + resolution: {integrity: sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w==} + cpu: [s390x] + os: [linux] + + '@img/sharp-libvips-linux-x64@1.2.3': + resolution: {integrity: sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg==} + cpu: [x64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-arm64@1.2.3': + resolution: {integrity: sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw==} + cpu: [arm64] + os: [linux] + + '@img/sharp-libvips-linuxmusl-x64@1.2.3': + resolution: {integrity: sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g==} + cpu: [x64] + os: [linux] + + '@img/sharp-linux-arm64@0.34.4': + resolution: {integrity: sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linux-arm@0.34.4': + resolution: {integrity: sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm] + os: [linux] + + '@img/sharp-linux-ppc64@0.34.4': + resolution: {integrity: sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ppc64] + os: [linux] + + '@img/sharp-linux-s390x@0.34.4': + resolution: {integrity: sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [s390x] + os: [linux] + + '@img/sharp-linux-x64@0.34.4': + resolution: {integrity: sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-linuxmusl-arm64@0.34.4': + resolution: {integrity: sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [linux] + + '@img/sharp-linuxmusl-x64@0.34.4': + resolution: {integrity: sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [linux] + + '@img/sharp-wasm32@0.34.4': + resolution: {integrity: sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [wasm32] + + '@img/sharp-win32-arm64@0.34.4': + resolution: {integrity: sha512-2Q250do/5WXTwxW3zjsEuMSv5sUU4Tq9VThWKlU2EYLm4MB7ZeMwF+SFJutldYODXF6jzc6YEOC+VfX0SZQPqA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [arm64] + os: [win32] + + '@img/sharp-win32-ia32@0.34.4': + resolution: {integrity: sha512-3ZeLue5V82dT92CNL6rsal6I2weKw1cYu+rGKm8fOCCtJTR2gYeUfY3FqUnIJsMUPIH68oS5jmZ0NiJ508YpEw==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [ia32] + os: [win32] + + '@img/sharp-win32-x64@0.34.4': + resolution: {integrity: sha512-xIyj4wpYs8J18sVN3mSQjwrw7fKUqRw+Z5rnHNCy5fYTxigBz81u5mOMPmFumwjcn8+ld1ppptMBCLic1nz6ig==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + cpu: [x64] + os: [win32] + + '@inlang/paraglide-js@2.3.2': + resolution: {integrity: sha512-mF7ku1AaXQxa6fnbBczXiEAM7lxhYzaAH7FnDVvAbpzNtgRJESi11KN0bzpCH0YhsKLdimFrQlzjaSVlo9Uh+Q==} + hasBin: true + + '@inlang/recommend-sherlock@0.2.1': + resolution: {integrity: sha512-ckv8HvHy/iTqaVAEKrr+gnl+p3XFNwe5D2+6w6wJk2ORV2XkcRkKOJ/XsTUJbPSiyi4PI+p+T3bqbmNx/rDUlg==} + + '@inlang/sdk@2.4.9': + resolution: {integrity: sha512-cvz/C1rF5WBxzHbEoiBoI6Sz6q6M+TdxfWkEGBYTD77opY8i8WN01prUWXEM87GPF4SZcyIySez9U0Ccm12oFQ==} + engines: {node: '>=18.0.0'} + + '@jridgewell/gen-mapping@0.3.13': + resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} + + '@jridgewell/remapping@2.3.5': + resolution: {integrity: sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/sourcemap-codec@1.5.5': + resolution: {integrity: sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@keyv/bigmap@1.0.1': + resolution: {integrity: sha512-dZ7TMshK6brpuGPPRoq4pHNzNH4KTWaxVPB7KEnPErlgJpc+jG1Oyx3sw6nBFiZ0OCKwC1zU6skMEG7H421f9g==} + engines: {node: '>= 20'} + + '@keyv/serialize@1.1.1': + resolution: {integrity: sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==} + + '@lix-js/sdk@0.4.7': + resolution: {integrity: sha512-pRbW+joG12L0ULfMiWYosIW0plmW4AsUdiPCp+Z8rAsElJ+wJ6in58zhD3UwUcd4BNcpldEGjg6PdA7e0RgsDQ==} + engines: {node: '>=18'} + + '@lix-js/server-protocol-schema@0.1.1': + resolution: {integrity: sha512-jBeALB6prAbtr5q4vTuxnRZZv1M2rKe8iNqRQhFJ4Tv7150unEa0vKyz0hs8Gl3fUGsWaNJBh3J8++fpbrpRBQ==} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@parcel/watcher-android-arm64@2.5.1': + resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [android] + + '@parcel/watcher-darwin-arm64@2.5.1': + resolution: {integrity: sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [darwin] + + '@parcel/watcher-darwin-x64@2.5.1': + resolution: {integrity: sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [darwin] + + '@parcel/watcher-freebsd-x64@2.5.1': + resolution: {integrity: sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [freebsd] + + '@parcel/watcher-linux-arm-glibc@2.5.1': + resolution: {integrity: sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + + '@parcel/watcher-linux-arm-musl@2.5.1': + resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==} + engines: {node: '>= 10.0.0'} + cpu: [arm] + os: [linux] + + '@parcel/watcher-linux-arm64-glibc@2.5.1': + resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + + '@parcel/watcher-linux-arm64-musl@2.5.1': + resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [linux] + + '@parcel/watcher-linux-x64-glibc@2.5.1': + resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + + '@parcel/watcher-linux-x64-musl@2.5.1': + resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [linux] + + '@parcel/watcher-win32-arm64@2.5.1': + resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==} + engines: {node: '>= 10.0.0'} + cpu: [arm64] + os: [win32] + + '@parcel/watcher-win32-ia32@2.5.1': + resolution: {integrity: sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==} + engines: {node: '>= 10.0.0'} + cpu: [ia32] + os: [win32] + + '@parcel/watcher-win32-x64@2.5.1': + resolution: {integrity: sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==} + engines: {node: '>= 10.0.0'} + cpu: [x64] + os: [win32] + + '@parcel/watcher@2.5.1': + resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==} + engines: {node: '>= 10.0.0'} + + '@rolldown/pluginutils@1.0.0-beta.35': + resolution: {integrity: sha512-slYrCpoxJUqzFDDNlvrOYRazQUNRvWPjXA17dAOISY3rDMxX6k8K4cj2H+hEYMHF81HO3uNd5rHVigAWRM5dSg==} + + '@rollup/rollup-android-arm-eabi@4.51.0': + resolution: {integrity: sha512-VyfldO8T/C5vAXBGIobrAnUE+VJNVLw5z9h4NgSDq/AJZWt/fXqdW+0PJbk+M74xz7yMDRiHtlsuDV7ew6K20w==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.51.0': + resolution: {integrity: sha512-Z3ujzDZgsEVSokgIhmOAReh9SGT2qloJJX2Xo1Q3nPU1EhCXrV0PbpR3r7DWRgozqnjrPZQkLe5cgBPIYp70Vg==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.51.0': + resolution: {integrity: sha512-T3gskHgArUdR6TCN69li5VELVAZK+iQ4iwMoSMNYixoj+56EC9lTj35rcxhXzIJt40YfBkvDy3GS+t5zh7zM6g==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.51.0': + resolution: {integrity: sha512-Hh7n/fh0g5UjH6ATDF56Qdf5bzdLZKIbhp5KftjMYG546Ocjeyg15dxphCpH1FFY2PJ2G6MiOVL4jMq5VLTyrQ==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.51.0': + resolution: {integrity: sha512-0EddADb6FBvfqYoxwVom3hAbAvpSVUbZqmR1wmjk0MSZ06hn/UxxGHKRqEQDMkts7XiZjejVB+TLF28cDTU+gA==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.51.0': + resolution: {integrity: sha512-MpqaEDLo3JuVPF+wWV4mK7V8akL76WCz8ndfz1aVB7RhvXFO3k7yT7eu8OEuog4VTSyNu5ibvN9n6lgjq/qLEQ==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.51.0': + resolution: {integrity: sha512-WEWAGFNFFpvSWAIT3MYvxTkYHv/cJl9yWKpjhheg7ONfB0hetZt/uwBnM3GZqSHrk5bXCDYTFXg3jQyk/j7eXQ==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.51.0': + resolution: {integrity: sha512-9bxtxj8QoAp++LOq5PGDGkEEOpCDk9rOEHUcXadnijedDH8IXrBt6PnBa4Y6NblvGWdoxvXZYghZLaliTCmAng==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.51.0': + resolution: {integrity: sha512-DdqA+fARqIsfqDYkKo2nrWMp0kvu/wPJ2G8lZ4DjYhn+8QhrjVuzmsh7tTkhULwjvHTN59nWVzAixmOi6rqjNA==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.51.0': + resolution: {integrity: sha512-2XVRNzcUJE1UJua8P4a1GXS5jafFWE+pQ6zhUbZzptOu/70p1F6+0FTi6aGPd6jNtnJqGMjtBCXancC2dhYlWw==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loong64-gnu@4.51.0': + resolution: {integrity: sha512-R8QhY0kLIPCAVXWi2yftDSpn7Jtejey/WhMoBESSfwGec5SKdFVupjxFlKoQ7clVRuaDpiQf7wNx3EBZf4Ey6g==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-ppc64-gnu@4.51.0': + resolution: {integrity: sha512-I498RPfxx9cMv1KTHQ9tg2Ku1utuQm+T5B+Xro+WNu3FzAFSKp4awKfgMoZwjoPgNbaFGINaOM25cQW6WuBhiQ==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.51.0': + resolution: {integrity: sha512-o8COudsb8lvtdm9ixg9aKjfX5aeoc2x9KGE7WjtrmQFquoCRZ9jtzGlonujE4WhvXFepTraWzT4RcwyDDeHXjA==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-riscv64-musl@4.51.0': + resolution: {integrity: sha512-0shJPgSXMdYzOQzpM5BJN2euXY1f8uV8mS6AnrbMcH2KrkNsbpMxWB1wp8UEdiJ1NtyBkCk3U/HfX5mEONBq6w==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.51.0': + resolution: {integrity: sha512-L7pV+ny7865jamSCQwyozBYjFRUKaTsPqDz7ClOtJCDu4paf2uAa0mrcHwSt4XxZP2ogFZS9uuitH3NXdeBEJA==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.51.0': + resolution: {integrity: sha512-4YHhP+Rv3T3+H3TPbUvWOw5tuSwhrVhkHHZhk4hC9VXeAOKR26/IsUAT4FsB4mT+kfIdxxb1BezQDEg/voPO8A==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.51.0': + resolution: {integrity: sha512-P7U7U03+E5w7WgJtvSseNLOX1UhknVPmEaqgUENFWfNxNBa1OhExT6qYGmyF8gepcxWSaSfJsAV5UwhWrYefdQ==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-openharmony-arm64@4.51.0': + resolution: {integrity: sha512-FuD8g3u9W6RPwdO1R45hZFORwa1g9YXEMesAKP/sOi7mDqxjbni8S3zAXJiDcRfGfGBqpRYVuH54Gu3FTuSoEw==} + cpu: [arm64] + os: [openharmony] + + '@rollup/rollup-win32-arm64-msvc@4.51.0': + resolution: {integrity: sha512-zST+FdMCX3QAYfmZX3dp/Fy8qLUetfE17QN5ZmmFGPrhl86qvRr+E9u2bk7fzkIXsfQR30Z7ZRS7WMryPPn4rQ==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.51.0': + resolution: {integrity: sha512-U+qhoCVAZmTHCmUKxdQxw1jwAFNFXmOpMME7Npt5GTb1W/7itfgAgNluVOvyeuSeqW+dEQLFuNZF3YZPO8XkMg==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.51.0': + resolution: {integrity: sha512-z6UpFzMhXSD8NNUfCi2HO+pbpSzSWIIPgb1TZsEZjmZYtk6RUIC63JYjlFBwbBZS3jt3f1q6IGfkj3g+GnBt2Q==} + cpu: [x64] + os: [win32] + + '@sinclair/typebox@0.31.28': + resolution: {integrity: sha512-/s55Jujywdw/Jpan+vsy6JZs1z2ZTGxTmbZTPiuSL2wz9mfzA2gN1zzaqmvfi4pq+uOt7Du85fkiwv5ymW84aQ==} + + '@solid-primitives/event-listener@2.4.3': + resolution: {integrity: sha512-h4VqkYFv6Gf+L7SQj+Y6puigL/5DIi7x5q07VZET7AWcS+9/G3WfIE9WheniHWJs51OEkRB43w6lDys5YeFceg==} + peerDependencies: + solid-js: ^1.6.12 + + '@solid-primitives/keyboard@1.3.3': + resolution: {integrity: sha512-9dQHTTgLBqyAI7aavtO+HnpTVJgWQA1ghBSrmLtMu1SMxLPDuLfuNr+Tk5udb4AL4Ojg7h9JrKOGEEDqsJXWJA==} + peerDependencies: + solid-js: ^1.6.12 + + '@solid-primitives/rootless@1.5.2': + resolution: {integrity: sha512-9HULb0QAzL2r47CCad0M+NKFtQ+LrGGNHZfteX/ThdGvKIg2o2GYhBooZubTCd/RTu2l2+Nw4s+dEfiDGvdrrQ==} + peerDependencies: + solid-js: ^1.6.12 + + '@solid-primitives/utils@6.3.2': + resolution: {integrity: sha512-hZ/M/qr25QOCcwDPOHtGjxTD8w2mNyVAYvcfgwzBHq2RwNqHNdDNsMZYap20+ruRwW4A3Cdkczyoz0TSxLCAPQ==} + peerDependencies: + solid-js: ^1.6.12 + + '@sqlite.org/sqlite-wasm@3.48.0-build4': + resolution: {integrity: sha512-hI6twvUkzOmyGZhQMza1gpfqErZxXRw6JEsiVjUbo7tFanVD+8Oil0Ih3l2nGzHdxPI41zFmfUQG7GHqhciKZQ==} + hasBin: true + + '@swc/core-darwin-arm64@1.13.5': + resolution: {integrity: sha512-lKNv7SujeXvKn16gvQqUQI5DdyY8v7xcoO3k06/FJbHJS90zEwZdQiMNRiqpYw/orU543tPaWgz7cIYWhbopiQ==} + engines: {node: '>=10'} + cpu: [arm64] + os: [darwin] + + '@swc/core-darwin-x64@1.13.5': + resolution: {integrity: sha512-ILd38Fg/w23vHb0yVjlWvQBoE37ZJTdlLHa8LRCFDdX4WKfnVBiblsCU9ar4QTMNdeTBEX9iUF4IrbNWhaF1Ng==} + engines: {node: '>=10'} + cpu: [x64] + os: [darwin] + + '@swc/core-linux-arm-gnueabihf@1.13.5': + resolution: {integrity: sha512-Q6eS3Pt8GLkXxqz9TAw+AUk9HpVJt8Uzm54MvPsqp2yuGmY0/sNaPPNVqctCX9fu/Nu8eaWUen0si6iEiCsazQ==} + engines: {node: '>=10'} + cpu: [arm] + os: [linux] + + '@swc/core-linux-arm64-gnu@1.13.5': + resolution: {integrity: sha512-aNDfeN+9af+y+M2MYfxCzCy/VDq7Z5YIbMqRI739o8Ganz6ST+27kjQFd8Y/57JN/hcnUEa9xqdS3XY7WaVtSw==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + + '@swc/core-linux-arm64-musl@1.13.5': + resolution: {integrity: sha512-9+ZxFN5GJag4CnYnq6apKTnnezpfJhCumyz0504/JbHLo+Ue+ZtJnf3RhyA9W9TINtLE0bC4hKpWi8ZKoETyOQ==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + + '@swc/core-linux-x64-gnu@1.13.5': + resolution: {integrity: sha512-WD530qvHrki8Ywt/PloKUjaRKgstQqNGvmZl54g06kA+hqtSE2FTG9gngXr3UJxYu/cNAjJYiBifm7+w4nbHbA==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + + '@swc/core-linux-x64-musl@1.13.5': + resolution: {integrity: sha512-Luj8y4OFYx4DHNQTWjdIuKTq2f5k6uSXICqx+FSabnXptaOBAbJHNbHT/06JZh6NRUouaf0mYXN0mcsqvkhd7Q==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + + '@swc/core-win32-arm64-msvc@1.13.5': + resolution: {integrity: sha512-cZ6UpumhF9SDJvv4DA2fo9WIzlNFuKSkZpZmPG1c+4PFSEMy5DFOjBSllCvnqihCabzXzpn6ykCwBmHpy31vQw==} + engines: {node: '>=10'} + cpu: [arm64] + os: [win32] + + '@swc/core-win32-ia32-msvc@1.13.5': + resolution: {integrity: sha512-C5Yi/xIikrFUzZcyGj9L3RpKljFvKiDMtyDzPKzlsDrKIw2EYY+bF88gB6oGY5RGmv4DAX8dbnpRAqgFD0FMEw==} + engines: {node: '>=10'} + cpu: [ia32] + os: [win32] + + '@swc/core-win32-x64-msvc@1.13.5': + resolution: {integrity: sha512-YrKdMVxbYmlfybCSbRtrilc6UA8GF5aPmGKBdPvjrarvsmf4i7ZHGCEnLtfOMd3Lwbs2WUZq3WdMbozYeLU93Q==} + engines: {node: '>=10'} + cpu: [x64] + os: [win32] + + '@swc/core@1.13.5': + resolution: {integrity: sha512-WezcBo8a0Dg2rnR82zhwoR6aRNxeTGfK5QCD6TQ+kg3xx/zNT02s/0o+81h/3zhvFSB24NtqEr8FTw88O5W/JQ==} + engines: {node: '>=10'} + peerDependencies: + '@swc/helpers': '>=0.5.17' + peerDependenciesMeta: + '@swc/helpers': + optional: true + + '@swc/counter@0.1.3': + resolution: {integrity: sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==} + + '@swc/types@0.1.25': + resolution: {integrity: sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g==} + + '@tanstack/devtools-event-bus@0.3.2': + resolution: {integrity: sha512-yJT2As/drc+Epu0nsqCsJaKaLcaNGufiNxSlp/+/oeTD0jsBxF9/PJBfh66XVpYXkKr97b8689mSu7QMef0Rrw==} + engines: {node: '>=18'} + + '@tanstack/devtools-event-client@0.2.5': + resolution: {integrity: sha512-iVdqw879KETXyyPHc3gQR5Ld0GjlPLk7bKenBUhzr3+z1FiQZvsbfgYfRRokTSPcgwANAV7aA2Uv05nx5xWT8A==} + engines: {node: '>=18'} + + '@tanstack/devtools-ui@0.3.5': + resolution: {integrity: sha512-DU8OfLntngnph+Tb7ivQvh4F4w+rDu6r01fXlhjq/Nmgdr0gtsOox4kdmyq5rCs+C6aPgP3M7+BE+fv4dN+VvA==} + engines: {node: '>=18'} + peerDependencies: + solid-js: '>=1.9.7' + + '@tanstack/devtools@0.6.13': + resolution: {integrity: sha512-EHSqMwo3lhVxeFV+6u7aNoWeqNpSLDzvft7i/JeUt8ZbfjopyOtugNFY1cGEaqy7qzudqQP4pk7dUKWACQ0gCQ==} + engines: {node: '>=18'} + peerDependencies: + solid-js: '>=1.9.7' + + '@tanstack/form-core@1.21.2': + resolution: {integrity: sha512-Yp9ZFLSXDZzWapR+nD++YwC9zN8dxdBzWzleHkN184VzIfOhtVMrR+95QSUuxzS0nFFttd2Egc7XLte7/Osyag==} + + '@tanstack/history@1.131.2': + resolution: {integrity: sha512-cs1WKawpXIe+vSTeiZUuSBy8JFjEuDgdMKZFRLKwQysKo8y2q6Q1HvS74Yw+m5IhOW1nTZooa6rlgdfXcgFAaw==} + engines: {node: '>=12'} + + '@tanstack/query-core@5.89.0': + resolution: {integrity: sha512-joFV1MuPhSLsKfTzwjmPDrp8ENfZ9N23ymFu07nLfn3JCkSHy0CFgsyhHTJOmWaumC/WiNIKM0EJyduCF/Ih/Q==} + + '@tanstack/query-devtools@5.87.3': + resolution: {integrity: sha512-LkzxzSr2HS1ALHTgDmJH5eGAVsSQiuwz//VhFW5OqNk0OQ+Fsqba0Tsf+NzWRtXYvpgUqwQr4b2zdFZwxHcGvg==} + + '@tanstack/react-devtools@0.6.9': + resolution: {integrity: sha512-1RD7k6d2f3x6ZZem3Qi+LMJzxev1KCC6SkQWIKmD3NRbMhh3W0VNOwlIpui0Al4p5VutyAUtk8R1ocnTEZTdLw==} + engines: {node: '>=18'} + peerDependencies: + '@types/react': '>=16.8' + '@types/react-dom': '>=16.8' + react: '>=16.8' + react-dom: '>=16.8' + + '@tanstack/react-form@1.21.2': + resolution: {integrity: sha512-MeKD9ahwG287NlBVGHz6k+6C56BK1OsbcOiay8iVbABzc31aPKQjttw8psX9VgatJaI6rzVEOlGm+Peboih/FA==} + peerDependencies: + '@tanstack/react-start': ^1.130.10 + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@tanstack/react-start': + optional: true + + '@tanstack/react-query-devtools@5.89.0': + resolution: {integrity: sha512-Syc4UjZeIJCkXCRGyQcWwlnv89JNb98MMg/DAkFCV3rwOcknj98+nG3Nm6xLXM6ne9sK6RZeDJMPLKZUh6NUGA==} + peerDependencies: + '@tanstack/react-query': ^5.89.0 + react: ^18 || ^19 + + '@tanstack/react-query@5.89.0': + resolution: {integrity: sha512-SXbtWSTSRXyBOe80mszPxpEbaN4XPRUp/i0EfQK1uyj3KCk/c8FuPJNIRwzOVe/OU3rzxrYtiNabsAmk1l714A==} + peerDependencies: + react: ^18 || ^19 + + '@tanstack/react-router-devtools@1.131.48': + resolution: {integrity: sha512-b0D2Zvab60+uotkl25bhU2NXOdCMMWRennY5YDeV6TS1ZRG5m17DZAzIspw9SCi51eC+H/j8inVcxIrQYaB5AQ==} + engines: {node: '>=12'} + peerDependencies: + '@tanstack/react-router': ^1.131.48 + react: '>=18.0.0 || >=19.0.0' + react-dom: '>=18.0.0 || >=19.0.0' + + '@tanstack/react-router@1.131.48': + resolution: {integrity: sha512-iT9k/+J4vkoXyI1lBu0StSCLXgfOIMf/IDPh+pZ5HhMPab/wx0PDgIFFgEq9qM1CCykDnKqqeDY0QZWBUS4V1A==} + engines: {node: '>=12'} + peerDependencies: + react: '>=18.0.0 || >=19.0.0' + react-dom: '>=18.0.0 || >=19.0.0' + + '@tanstack/react-store@0.7.5': + resolution: {integrity: sha512-A+WZtEnHZpvbKXm8qR+xndNKywBLez2KKKKEQc7w0Qs45GvY1LpRI3BTZNmELwEVim8+Apf99iEDH2J+MUIzlQ==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + '@tanstack/router-core@1.131.48': + resolution: {integrity: sha512-Zw024eJECTLn57bR8oncR4YUTvQ8P41pDnVEXevWPuR6wdKRsIUmhfJowzgf4ppF9Lgl5DUWEhOcj4Awr4tTOQ==} + engines: {node: '>=12'} + + '@tanstack/router-devtools-core@1.131.48': + resolution: {integrity: sha512-QHX8ta3PEBoU7674N9jF7k/HlnOHZ/SHerT4zb9c9McZM4ZydPGyBt9wjMxONgSrceYvhFgNBRhrkMp2X4+iiw==} + engines: {node: '>=12'} + peerDependencies: + '@tanstack/router-core': ^1.131.48 + csstype: ^3.0.10 + solid-js: '>=1.9.5' + tiny-invariant: ^1.3.3 + peerDependenciesMeta: + csstype: + optional: true + + '@tanstack/router-generator@1.131.48': + resolution: {integrity: sha512-spLqLJ1pD6y8wTxdKSRUS7fMINbuqsTEk1Ot0wxdrD1lKwJT8F7yKovSfl+h2WcifFN84B1gc5F3ZRmcp7fTeA==} + engines: {node: '>=12'} + + '@tanstack/router-plugin@1.131.48': + resolution: {integrity: sha512-5Bt7M3rP6bYNIwFYhLj5AjPdfBqWmrjIliq06rV1iCQ8GJvXPVSuZHwT+jDzxEsyRzHUjk5kuK3ytimXmexpSQ==} + engines: {node: '>=12'} + peerDependencies: + '@rsbuild/core': '>=1.0.2' + '@tanstack/react-router': ^1.131.48 + vite: '>=5.0.0 || >=6.0.0' + vite-plugin-solid: ^2.11.2 + webpack: '>=5.92.0' + peerDependenciesMeta: + '@rsbuild/core': + optional: true + '@tanstack/react-router': + optional: true + vite: + optional: true + vite-plugin-solid: + optional: true + webpack: + optional: true + + '@tanstack/router-utils@1.131.2': + resolution: {integrity: sha512-sr3x0d2sx9YIJoVth0QnfEcAcl+39sQYaNQxThtHmRpyeFYNyM2TTH+Ud3TNEnI3bbzmLYEUD+7YqB987GzhDA==} + engines: {node: '>=12'} + + '@tanstack/store@0.7.5': + resolution: {integrity: sha512-qd/OjkjaFRKqKU4Yjipaen/EOB9MyEg6Wr9fW103RBPACf1ZcKhbhcu2S5mj5IgdPib6xFIgCUti/mKVkl+fRw==} + + '@tanstack/virtual-file-routes@1.131.2': + resolution: {integrity: sha512-VEEOxc4mvyu67O+Bl0APtYjwcNRcL9it9B4HKbNgcBTIOEalhk+ufBl4kiqc8WP1sx1+NAaiS+3CcJBhrqaSRg==} + engines: {node: '>=12'} + + '@types/estree@1.0.8': + resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/node@24.5.2': + resolution: {integrity: sha512-FYxk1I7wPv3K2XBaoyH2cTnocQEu8AOZ60hPbsyukMPLv5/5qr7V1i8PLHdl6Zf87I+xZXFvPCXYjiTFq+YSDQ==} + + '@types/qs@6.14.0': + resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==} + + '@types/react-dom@19.1.9': + resolution: {integrity: sha512-qXRuZaOsAdXKFyOhRBg6Lqqc0yay13vN7KrIg4L7N4aaHN68ma9OK3NE1BoDFgFOTfM7zg+3/8+2n8rLUH3OKQ==} + peerDependencies: + '@types/react': ^19.0.0 + + '@types/react@19.1.13': + resolution: {integrity: sha512-hHkbU/eoO3EG5/MZkuFSKmYqPbSVk5byPFa3e7y/8TybHiLMACgI8seVYlicwk7H5K/rI2px9xrQp/C+AUDTiQ==} + + '@typescript-eslint/eslint-plugin@8.44.0': + resolution: {integrity: sha512-EGDAOGX+uwwekcS0iyxVDmRV9HX6FLSM5kzrAToLTsr9OWCIKG/y3lQheCq18yZ5Xh78rRKJiEpP0ZaCs4ryOQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.44.0 + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/parser@8.44.0': + resolution: {integrity: sha512-VGMpFQGUQWYT9LfnPcX8ouFojyrZ/2w3K5BucvxL/spdNehccKhB4jUyB1yBCXpr2XFm0jkECxgrpXBW2ipoAw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/project-service@8.44.0': + resolution: {integrity: sha512-ZeaGNraRsq10GuEohKTo4295Z/SuGcSq2LzfGlqiuEvfArzo/VRrT0ZaJsVPuKZ55lVbNk8U6FcL+ZMH8CoyVA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/scope-manager@8.44.0': + resolution: {integrity: sha512-87Jv3E+al8wpD+rIdVJm/ItDBe/Im09zXIjFoipOjr5gHUhJmTzfFLuTJ/nPTMc2Srsroy4IBXwcTCHyRR7KzA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/tsconfig-utils@8.44.0': + resolution: {integrity: sha512-x5Y0+AuEPqAInc6yd0n5DAcvtoQ/vyaGwuX5HE9n6qAefk1GaedqrLQF8kQGylLUb9pnZyLf+iEiL9fr8APDtQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/type-utils@8.44.0': + resolution: {integrity: sha512-9cwsoSxJ8Sak67Be/hD2RNt/fsqmWnNE1iHohG8lxqLSNY8xNfyY7wloo5zpW3Nu9hxVgURevqfcH6vvKCt6yg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/types@8.44.0': + resolution: {integrity: sha512-ZSl2efn44VsYM0MfDQe68RKzBz75NPgLQXuGypmym6QVOWL5kegTZuZ02xRAT9T+onqvM6T8CdQk0OwYMB6ZvA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@8.44.0': + resolution: {integrity: sha512-lqNj6SgnGcQZwL4/SBJ3xdPEfcBuhCG8zdcwCPgYcmiPLgokiNDKlbPzCwEwu7m279J/lBYWtDYL+87OEfn8Jw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/utils@8.44.0': + resolution: {integrity: sha512-nktOlVcg3ALo0mYlV+L7sWUD58KG4CMj1rb2HUVOO4aL3K/6wcD+NERqd0rrA5Vg06b42YhF6cFxeixsp9Riqg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + '@typescript-eslint/visitor-keys@8.44.0': + resolution: {integrity: sha512-zaz9u8EJ4GBmnehlrpoKvj/E3dNbuQ7q0ucyZImm3cLqJ8INTc970B1qEqDX/Rzq65r3TvVTN7kHWPBoyW7DWw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@uidotdev/usehooks@2.4.1': + resolution: {integrity: sha512-1I+RwWyS+kdv3Mv0Vmc+p0dPYH0DTRAo04HLyXReYBL9AeseDWUJyi4THuksBJcu9F0Pih69Ak150VDnqbVnXg==} + engines: {node: '>=16'} + peerDependencies: + react: '>=18.0.0' + react-dom: '>=18.0.0' + + '@vitejs/plugin-react-swc@4.1.0': + resolution: {integrity: sha512-Ff690TUck0Anlh7wdIcnsVMhofeEVgm44Y4OYdeeEEPSKyZHzDI9gfVBvySEhDfXtBp8tLCbfsVKPWEMEjq8/g==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + vite: ^4 || ^5 || ^6 || ^7 + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn@8.15.0: + resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} + engines: {node: '>=0.4.0'} + hasBin: true + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + + ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansis@4.1.0: + resolution: {integrity: sha512-BGcItUBWSMRgOCe+SVZJ+S7yTRG0eGt9cXAHev72yuGcY23hnLA7Bky5L/xLyPINoSN95geovfBkqoTlNZYa7w==} + engines: {node: '>=14'} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + array-timsort@1.0.3: + resolution: {integrity: sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + ast-types@0.16.1: + resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} + engines: {node: '>=4'} + + astral-regex@2.0.0: + resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} + engines: {node: '>=8'} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + axios@1.12.2: + resolution: {integrity: sha512-vMJzPewAlRyOgxV2dU0Cuz2O8zzzx9VYtbJOaBgXFeLc4IV/Eg50n4LowmehOOR61S8ZMpc2K5Sa7g6A4jfkUw==} + + babel-dead-code-elimination@1.0.10: + resolution: {integrity: sha512-DV5bdJZTzZ0zn0DC24v3jD7Mnidh6xhKa4GfKCbq3sfW8kaWhDdZjP3i81geA8T33tdYqWKw4D3fVv0CwEgKVA==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + balanced-match@2.0.0: + resolution: {integrity: sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==} + + baseline-browser-mapping@2.8.6: + resolution: {integrity: sha512-wrH5NNqren/QMtKUEEJf7z86YjfqW/2uw3IL3/xpqZUC95SSVIFXYQeeGjL6FT/X68IROu6RMehZQS5foy2BXw==} + hasBin: true + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + brace-expansion@1.1.12: + resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} + + brace-expansion@2.0.2: + resolution: {integrity: sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.26.2: + resolution: {integrity: sha512-ECFzp6uFOSB+dcZ5BK/IBaGWssbSYBHvuMeMt3MMFyhI0Z8SqGgEkBLARgpRH3hutIgPVsALcMwbDrJqPxQ65A==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + cacheable@2.0.1: + resolution: {integrity: sha512-MSKxcybpxB5kcWKpj+1tPBm2os4qKKGxDovsZmLhZmWIDYp8EgtC45C5zk1fLe1IC9PpI4ZE4eyryQH0N10PKA==} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + caniuse-lite@1.0.30001743: + resolution: {integrity: sha512-e6Ojr7RV14Un7dz6ASD0aZDmQPT/A+eZU+nuTNfjqmRrmkmQlnTNWH0SKmqagx9PeW87UVqapSurtAXifmtdmw==} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + colord@2.9.3: + resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + commander@11.1.0: + resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} + engines: {node: '>=16'} + + comment-json@4.2.5: + resolution: {integrity: sha512-bKw/r35jR3HGt5PEPm1ljsQQGyCrR8sFGNiN5L+ykDHdpO8Smxkrkla9Yi6NkQyUrb8V54PGhfMs6NrIwtxtdw==} + engines: {node: '>= 6'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + consola@3.4.0: + resolution: {integrity: sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA==} + engines: {node: ^14.18.0 || >=16.10.0} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + cookie-es@1.2.2: + resolution: {integrity: sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==} + + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + + cosmiconfig@9.0.0: + resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + css-functions-list@3.2.3: + resolution: {integrity: sha512-IQOkD3hbR5KrN93MtcYuad6YPuTSUhntLHDuLEbFWE+ff2/XSZNdZG+LcbbIW5AXKg/WFIfYItIzVoHngHXZzA==} + engines: {node: '>=12 || >=16'} + + css-tree@3.1.0: + resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decode-formdata@0.9.0: + resolution: {integrity: sha512-q5uwOjR3Um5YD+ZWPOF/1sGHVW9A5rCrRwITQChRXlmPkxDFBqCm4jNTIVdGHNH9OnR+V9MoZVgRhsFb+ARbUw==} + + dedent@1.5.1: + resolution: {integrity: sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==} + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + detect-libc@1.0.3: + resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} + engines: {node: '>=0.10'} + hasBin: true + + detect-libc@2.1.0: + resolution: {integrity: sha512-vEtk+OcP7VBRtQZ1EJ3bdgzSfBjgnEalLTp5zjJrS+2Z1w2KZly4SBdac/WDU3hhsNAZ9E8SC96ME4Ey8MZ7cg==} + engines: {node: '>=8'} + + devalue@5.3.2: + resolution: {integrity: sha512-UDsjUbpQn9kvm68slnrs+mfxwFkIflOhkanmyabZ8zOYk8SMEIbJ3TK+88g70hSIeytu4y18f0z/hYHMTrXIWw==} + + diff@8.0.2: + resolution: {integrity: sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg==} + engines: {node: '>=0.3.1'} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + electron-to-chromium@1.5.222: + resolution: {integrity: sha512-gA7psSwSwQRE60CEoLz6JBCQPIxNeuzB2nL8vE03GK/OHxlvykbLyeiumQy1iH5C2f3YbRAZpGCMT12a/9ih9w==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + + error-ex@1.3.4: + resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + esbuild@0.25.10: + resolution: {integrity: sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + eslint-scope@8.4.0: + resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.2.1: + resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint@9.35.0: + resolution: {integrity: sha512-QePbBFMJFjgmlE+cXAlbHZbHpdFVS2E/6vzCy7aKlebddvl1vadiC4JFV5u/wqTkNUwEV8WrQi257jf5f06hrg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@10.4.0: + resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fast-uri@3.1.0: + resolution: {integrity: sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==} + + fastest-levenshtein@1.0.16: + resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==} + engines: {node: '>= 4.9.1'} + + fastq@1.19.1: + resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + file-entry-cache@10.1.4: + resolution: {integrity: sha512-5XRUFc0WTtUbjfGzEwXc42tiGxQHBmtbUG1h9L2apu4SulCGN3Hqm//9D6FAolf8MYNL7f/YlJl9vy08pj5JuA==} + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flat-cache@6.1.14: + resolution: {integrity: sha512-ExZSCSV9e7v/Zt7RzCbX57lY2dnPdxzU/h3UE6WJ6NtEMfwBd8jmi1n4otDEUfz+T/R+zxrFDpICFdjhD3H/zw==} + + flatted@3.3.3: + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + + follow-redirects@1.15.11: + resolution: {integrity: sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + form-data@4.0.4: + resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==} + engines: {node: '>= 6'} + + framer-motion@12.23.15: + resolution: {integrity: sha512-MBxUEHjWr/fRQ2aHg2CgdcjJpHMJ9ttHiPeClHDGiOJOYgmde3OXZUrbWDeeE8yvFrWA62hsPS4+rKQ9OJaoQA==} + peerDependencies: + '@emotion/is-prop-valid': '*' + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@emotion/is-prop-valid': + optional: true + react: + optional: true + react-dom: + optional: true + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-tsconfig@4.10.1: + resolution: {integrity: sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + global-modules@2.0.0: + resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==} + engines: {node: '>=6'} + + global-prefix@3.0.0: + resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==} + engines: {node: '>=6'} + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + globals@16.4.0: + resolution: {integrity: sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==} + engines: {node: '>=18'} + + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + globjoin@0.1.4: + resolution: {integrity: sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==} + + goober@2.1.16: + resolution: {integrity: sha512-erjk19y1U33+XAMe1VTvIONHYoSqE4iS7BYUZfHaqeohLmnC0FdxEh7rQU+6MZ4OajItzjZFSRtVANrQwNq6/g==} + peerDependencies: + csstype: ^3.0.10 + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-own-prop@2.0.0: + resolution: {integrity: sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==} + engines: {node: '>=8'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + hookified@1.12.1: + resolution: {integrity: sha512-xnKGl+iMIlhrZmGHB729MqlmPoWBznctSQTYCpFKqNsCgimJQmithcW0xSQMMFzYnV2iKUh25alswn6epgxS0Q==} + + html-tags@3.3.1: + resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} + engines: {node: '>=8'} + + human-id@4.1.1: + resolution: {integrity: sha512-3gKm/gCSUipeLsRYZbbdA1BD83lBoWUkZ7G9VFrhWPAU76KwYo5KR8V28bpoPm/ygy0x5/GCbpRQdY7VLYCoIg==} + hasBin: true + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} + engines: {node: '>= 4'} + + immutable@5.1.3: + resolution: {integrity: sha512-+chQdDfvscSF1SJqv2gn4SRO2ZyS3xL3r7IW/wWEEzrzLisnOlKiQu5ytC/BVNcS15C39WT2Hg/bjKjDMcu+zg==} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-plain-object@5.0.0: + resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} + engines: {node: '>=0.10.0'} + + isbot@5.1.30: + resolution: {integrity: sha512-3wVJEonAns1OETX83uWsk5IAne2S5zfDcntD2hbtU23LelSqNXzXs9zKjMPOLMzroCgIjCfjYAEHrd2D6FOkiA==} + engines: {node: '>=18'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + js-sha256@0.11.1: + resolution: {integrity: sha512-o6WSo/LUvY2uC4j7mO50a2ms7E/EAdbP0swigLV+nzHKTTaYnaLIWJ02VdXrsJX0vGedDESQnLsOekr94ryfjg==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + keyv@5.5.2: + resolution: {integrity: sha512-TXcFHbmm/z7MGd1u9ASiCSfTS+ei6Z8B3a5JHzx3oPa/o7QzWVtPRpc4KGER5RR469IC+/nfg4U5YLIuDUua2g==} + + kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + + known-css-properties@0.36.0: + resolution: {integrity: sha512-A+9jP+IUmuQsNdsLdcg6Yt7voiMF/D4K83ew0OpJtpu+l34ef7LaohWV0Rc6KNvzw6ZDizkqfyB5JznZnzuKQA==} + + known-css-properties@0.37.0: + resolution: {integrity: sha512-JCDrsP4Z1Sb9JwG0aJ8Eo2r7k4Ou5MwmThS/6lcIe1ICyb7UBJKGRIUUdqc2ASdE/42lgz6zFUnzAIhtXnBVrQ==} + + kysely@0.27.6: + resolution: {integrity: sha512-FIyV/64EkKhJmjgC0g2hygpBv5RNWVPyNCqSAD7eTCv6eFWNIi4PN1UvdSJGicN/o35bnevgis4Y0UDC0qi8jQ==} + engines: {node: '>=14.0.0'} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash.truncate@4.4.2: + resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + mathml-tag-names@2.1.3: + resolution: {integrity: sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==} + + mdn-data@2.12.2: + resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==} + + mdn-data@2.24.0: + resolution: {integrity: sha512-i97fklrJl03tL1tdRVw0ZfLLvuDsdb6wxL+TrJ+PKkCbLrp2PCu2+OYdCKychIUm19nSM/35S6qz7pJpnXttoA==} + + meow@13.2.0: + resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==} + engines: {node: '>=18'} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + motion-dom@12.23.12: + resolution: {integrity: sha512-RcR4fvMCTESQBD/uKQe49D5RUeDOokkGRmz4ceaJKDBgHYtZtntC/s2vLvY38gqGaytinij/yi3hMcWVcEF5Kw==} + + motion-utils@12.23.6: + resolution: {integrity: sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==} + + motion@12.23.15: + resolution: {integrity: sha512-KOxnEDztmHM/cIdWap9PYs36cOlVe8pqBJjhmmY0NxDnnN4gokQFDrpxUkh56RyQ+gnT0daaDy5g0T6sHfVBJg==} + peerDependencies: + '@emotion/is-prop-valid': '*' + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@emotion/is-prop-valid': + optional: true + react: + optional: true + react-dom: + optional: true + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + node-addon-api@7.1.1: + resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} + + node-releases@2.0.21: + resolution: {integrity: sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + picomatch@4.0.3: + resolution: {integrity: sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==} + engines: {node: '>=12'} + + postcss-media-query-parser@0.2.3: + resolution: {integrity: sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==} + + postcss-resolve-nested-selector@0.1.6: + resolution: {integrity: sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==} + + postcss-safe-parser@7.0.1: + resolution: {integrity: sha512-0AioNCJZ2DPYz5ABT6bddIqlhgwhpHZ/l65YAYo0BCIn0xiDpsnTHz0gnoTGk0OXZW0JRs+cDwL8u/teRdz+8A==} + engines: {node: '>=18.0'} + peerDependencies: + postcss: ^8.4.31 + + postcss-scss@4.0.9: + resolution: {integrity: sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.4.29 + + postcss-selector-parser@7.1.0: + resolution: {integrity: sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==} + engines: {node: '>=4'} + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + + postcss@8.5.6: + resolution: {integrity: sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==} + engines: {node: ^10 || ^12 || >=14} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + prettier@3.6.2: + resolution: {integrity: sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==} + engines: {node: '>=14'} + hasBin: true + + proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + qs@6.14.0: + resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} + engines: {node: '>=0.6'} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + react-dom@19.1.1: + resolution: {integrity: sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==} + peerDependencies: + react: ^19.1.1 + + react@19.1.1: + resolution: {integrity: sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==} + engines: {node: '>=0.10.0'} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + + recast@0.23.11: + resolution: {integrity: sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==} + engines: {node: '>= 4'} + + repeat-string@1.6.1: + resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} + engines: {node: '>=0.10'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rollup@4.51.0: + resolution: {integrity: sha512-7cR0XWrdp/UAj2HMY/Y4QQEUjidn3l2AY1wSeZoFjMbD8aOMPoV9wgTFYbrJpPzzvejDEini1h3CiUP8wLzxQA==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + sass@1.92.1: + resolution: {integrity: sha512-ffmsdbwqb3XeyR8jJR6KelIXARM9bFQe8A6Q3W4Klmwy5Ckd5gz7jgUNHo4UOqutU5Sk1DtKLbpDP0nLCg1xqQ==} + engines: {node: '>=14.0.0'} + hasBin: true + + scheduler@0.26.0: + resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.7.2: + resolution: {integrity: sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==} + engines: {node: '>=10'} + hasBin: true + + seroval-plugins@1.3.3: + resolution: {integrity: sha512-16OL3NnUBw8JG1jBLUoZJsLnQq0n5Ua6aHalhJK4fMQkz1lqR7Osz1sA30trBtd9VUDc2NgkuRCn8+/pBwqZ+w==} + engines: {node: '>=10'} + peerDependencies: + seroval: ^1.0 + + seroval@1.3.2: + resolution: {integrity: sha512-RbcPH1n5cfwKrru7v7+zrZvjLurgHhGyso3HTyGtRivGWgYjbOmGuivCQaORNELjNONoK35nj28EoWul9sb1zQ==} + engines: {node: '>=10'} + + sharp@0.34.4: + resolution: {integrity: sha512-FUH39xp3SBPnxWvd5iib1X8XY7J0K0X7d93sie9CJg2PO8/7gmg89Nve6OjItK53/MlAushNNxteBYfM6DEuoA==} + engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + slice-ansi@4.0.0: + resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} + engines: {node: '>=10'} + + solid-js@1.9.9: + resolution: {integrity: sha512-A0ZBPJQldAeGCTW0YRYJmt7RCeh5rbFfPZ2aOttgYnctHE7HgKeHCBB/PVc2P7eOfmNXqMFFFoYYdm3S4dcbkA==} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + source-map@0.7.6: + resolution: {integrity: sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==} + engines: {node: '>= 12'} + + sqlite-wasm-kysely@0.3.0: + resolution: {integrity: sha512-TzjBNv7KwRw6E3pdKdlRyZiTmUIE0UttT/Sl56MVwVARl/u5gp978KepazCJZewFUnlWHz9i3NQd4kOtP/Afdg==} + peerDependencies: + kysely: '*' + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + stylelint-config-recommended-scss@16.0.1: + resolution: {integrity: sha512-wfpU6kmTUwPEHMACYdpt5wLM/aS44+sqE8yk82LkOkA7yVpAuTZDwd3m9762d0mRnNCn0JMUx4XfDVDmbb8hTA==} + engines: {node: '>=20'} + peerDependencies: + postcss: ^8.3.3 + stylelint: ^16.23.1 + peerDependenciesMeta: + postcss: + optional: true + + stylelint-config-recommended@17.0.0: + resolution: {integrity: sha512-WaMSdEiPfZTSFVoYmJbxorJfA610O0tlYuU2aEwY33UQhSPgFbClrVJYWvy3jGJx+XW37O+LyNLiZOEXhKhJmA==} + engines: {node: '>=18.12.0'} + peerDependencies: + stylelint: ^16.23.0 + + stylelint-config-standard-scss@16.0.0: + resolution: {integrity: sha512-/FHECLUu+med/e6OaPFpprG86ShC4SYT7Tzb2PTVdDjJsehhFBOioSlWqYFqJxmGPIwO3AMBxNo+kY3dxrbczA==} + engines: {node: '>=20'} + peerDependencies: + postcss: ^8.3.3 + stylelint: ^16.23.1 + peerDependenciesMeta: + postcss: + optional: true + + stylelint-config-standard@39.0.0: + resolution: {integrity: sha512-JabShWORb8Bmc1A47ZyJstran60P3yUdI1zWMpGYPeFiC6xzHXJMkpKAd8EjIhq3HPUplIWWMDJ/xu0AiPd+kA==} + engines: {node: '>=18.12.0'} + peerDependencies: + stylelint: ^16.23.0 + + stylelint-scss@6.12.1: + resolution: {integrity: sha512-UJUfBFIvXfly8WKIgmqfmkGKPilKB4L5j38JfsDd+OCg2GBdU0vGUV08Uw82tsRZzd4TbsUURVVNGeOhJVF7pA==} + engines: {node: '>=18.12.0'} + peerDependencies: + stylelint: ^16.0.2 + + stylelint@16.24.0: + resolution: {integrity: sha512-7ksgz3zJaSbTUGr/ujMXvLVKdDhLbGl3R/3arNudH7z88+XZZGNLMTepsY28WlnvEFcuOmUe7fg40Q3lfhOfSQ==} + engines: {node: '>=18.12.0'} + hasBin: true + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-hyperlinks@3.2.0: + resolution: {integrity: sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==} + engines: {node: '>=14.18'} + + svg-tags@1.0.0: + resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==} + + tabbable@6.2.0: + resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==} + + table@6.9.0: + resolution: {integrity: sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==} + engines: {node: '>=10.0.0'} + + tiny-invariant@1.3.3: + resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} + + tiny-warning@1.0.3: + resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==} + + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + ts-api-utils@2.1.0: + resolution: {integrity: sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tsx@4.20.5: + resolution: {integrity: sha512-+wKjMNU9w/EaQayHXb7WA7ZaHY6hN8WgfvHNQ3t1PnU91/7O8TcTnIhCDYTZwnt8JsO9IBqZ30Ln1r7pPF52Aw==} + engines: {node: '>=18.0.0'} + hasBin: true + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + typescript-eslint@8.44.0: + resolution: {integrity: sha512-ib7mCkYuIzYonCq9XWF5XNw+fkj2zg629PSa9KNIQ47RXFF763S5BIX4wqz1+FLPogTZoiw8KmCiRPRa8bL3qw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + + typescript@5.9.2: + resolution: {integrity: sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@7.12.0: + resolution: {integrity: sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ==} + + unplugin@2.3.10: + resolution: {integrity: sha512-6NCPkv1ClwH+/BGE9QeoTIl09nuiAt0gS28nn1PvYXsGKRwM2TCbFA2QiilmehPDTXIe684k4rZI1yl3A1PCUw==} + engines: {node: '>=18.12.0'} + + update-browserslist-db@1.1.3: + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + urlpattern-polyfill@10.1.0: + resolution: {integrity: sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw==} + + use-sync-external-store@1.5.0: + resolution: {integrity: sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + uuid@10.0.0: + resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} + hasBin: true + + uuid@13.0.0: + resolution: {integrity: sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w==} + hasBin: true + + vite-plugin-image-optimizer@2.0.2: + resolution: {integrity: sha512-BYK27SpSScRIaveJVjbP7EjSrawuCc+ffESGvKVRhByAu6RGvwE3EyGg9ZeqQiLUE8e1hKSCr8v5ZfvQNiqvJQ==} + engines: {node: '>=18.17.0'} + peerDependencies: + sharp: '>=0.34.0' + svgo: '>=4' + vite: '>=5' + peerDependenciesMeta: + sharp: + optional: true + svgo: + optional: true + + vite@7.1.6: + resolution: {integrity: sha512-SRYIB8t/isTwNn8vMB3MR6E+EQZM/WG1aKmmIUCfDXfVvKfc20ZpamngWHKzAmmu9ppsgxsg4b2I7c90JZudIQ==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + jiti: '>=1.21.0' + less: ^4.0.0 + lightningcss: ^1.21.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + webpack-virtual-modules@0.6.2: + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + + which@1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + write-file-atomic@5.0.1: + resolution: {integrity: sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + + ws@8.18.3: + resolution: {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 + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + + zod@4.1.11: + resolution: {integrity: sha512-WPsqwxITS2tzx1bzhIKsEs19ABD5vmCVa4xBo2tq/SrV4RNZtfws1EnCWQXM6yh8bD08a1idvkB5MZSBiZsjwg==} + + zustand@5.0.8: + resolution: {integrity: sha512-gyPKpIaxY9XcO2vSMrLbiER7QMAMGOQZVRdJ6Zi782jkbzZygq5GI9nG8g+sMgitRtndwaBSl7uiqC49o1SSiw==} + engines: {node: '>=12.20.0'} + peerDependencies: + '@types/react': '>=18.0.0' + immer: '>=9.0.6' + react: '>=18.0.0' + use-sync-external-store: '>=1.2.0' + peerDependenciesMeta: + '@types/react': + optional: true + immer: + optional: true + react: + optional: true + use-sync-external-store: + optional: true + +snapshots: + + '@axa-ch/react-polymorphic-types@1.4.1(@types/react@19.1.13)(react@19.1.1)': + dependencies: + '@types/react': 19.1.13 + react: 19.1.1 + + '@babel/code-frame@7.27.1': + dependencies: + '@babel/helper-validator-identifier': 7.27.1 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.28.4': {} + + '@babel/core@7.28.4': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.3 + '@babel/helper-compilation-targets': 7.27.2 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.4) + '@babel/helpers': 7.28.4 + '@babel/parser': 7.28.4 + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.4 + '@babel/types': 7.28.4 + '@jridgewell/remapping': 2.3.5 + convert-source-map: 2.0.0 + debug: 4.4.3 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/generator@7.28.3': + dependencies: + '@babel/parser': 7.28.4 + '@babel/types': 7.28.4 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-annotate-as-pure@7.27.3': + dependencies: + '@babel/types': 7.28.4 + + '@babel/helper-compilation-targets@7.27.2': + dependencies: + '@babel/compat-data': 7.28.4 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.26.2 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-create-class-features-plugin@7.28.3(@babel/core@7.28.4)': + dependencies: + '@babel/core': 7.28.4 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-member-expression-to-functions': 7.27.1 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/helper-replace-supers': 7.27.1(@babel/core@7.28.4) + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/traverse': 7.28.4 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-globals@7.28.0': {} + + '@babel/helper-member-expression-to-functions@7.27.1': + dependencies: + '@babel/traverse': 7.28.4 + '@babel/types': 7.28.4 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-imports@7.27.1': + dependencies: + '@babel/traverse': 7.28.4 + '@babel/types': 7.28.4 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.28.3(@babel/core@7.28.4)': + dependencies: + '@babel/core': 7.28.4 + '@babel/helper-module-imports': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + '@babel/traverse': 7.28.4 + transitivePeerDependencies: + - supports-color + + '@babel/helper-optimise-call-expression@7.27.1': + dependencies: + '@babel/types': 7.28.4 + + '@babel/helper-plugin-utils@7.27.1': {} + + '@babel/helper-replace-supers@7.27.1(@babel/core@7.28.4)': + dependencies: + '@babel/core': 7.28.4 + '@babel/helper-member-expression-to-functions': 7.27.1 + '@babel/helper-optimise-call-expression': 7.27.1 + '@babel/traverse': 7.28.4 + transitivePeerDependencies: + - supports-color + + '@babel/helper-skip-transparent-expression-wrappers@7.27.1': + dependencies: + '@babel/traverse': 7.28.4 + '@babel/types': 7.28.4 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.27.1': {} + + '@babel/helper-validator-option@7.27.1': {} + + '@babel/helpers@7.28.4': + dependencies: + '@babel/template': 7.27.2 + '@babel/types': 7.28.4 + + '@babel/parser@7.28.4': + dependencies: + '@babel/types': 7.28.4 + + '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.28.4)': + dependencies: + '@babel/core': 7.28.4 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-syntax-typescript@7.27.1(@babel/core@7.28.4)': + dependencies: + '@babel/core': 7.28.4 + '@babel/helper-plugin-utils': 7.27.1 + + '@babel/plugin-transform-modules-commonjs@7.27.1(@babel/core@7.28.4)': + dependencies: + '@babel/core': 7.28.4 + '@babel/helper-module-transforms': 7.28.3(@babel/core@7.28.4) + '@babel/helper-plugin-utils': 7.27.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-typescript@7.28.0(@babel/core@7.28.4)': + dependencies: + '@babel/core': 7.28.4 + '@babel/helper-annotate-as-pure': 7.27.3 + '@babel/helper-create-class-features-plugin': 7.28.3(@babel/core@7.28.4) + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.4) + transitivePeerDependencies: + - supports-color + + '@babel/preset-typescript@7.27.1(@babel/core@7.28.4)': + dependencies: + '@babel/core': 7.28.4 + '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-validator-option': 7.27.1 + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-modules-commonjs': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-transform-typescript': 7.28.0(@babel/core@7.28.4) + transitivePeerDependencies: + - supports-color + + '@babel/template@7.27.2': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/parser': 7.28.4 + '@babel/types': 7.28.4 + + '@babel/traverse@7.28.4': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/generator': 7.28.3 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.28.4 + '@babel/template': 7.27.2 + '@babel/types': 7.28.4 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.28.4': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.27.1 + + '@biomejs/biome@2.2.4': + optionalDependencies: + '@biomejs/cli-darwin-arm64': 2.2.4 + '@biomejs/cli-darwin-x64': 2.2.4 + '@biomejs/cli-linux-arm64': 2.2.4 + '@biomejs/cli-linux-arm64-musl': 2.2.4 + '@biomejs/cli-linux-x64': 2.2.4 + '@biomejs/cli-linux-x64-musl': 2.2.4 + '@biomejs/cli-win32-arm64': 2.2.4 + '@biomejs/cli-win32-x64': 2.2.4 + + '@biomejs/cli-darwin-arm64@2.2.4': + optional: true + + '@biomejs/cli-darwin-x64@2.2.4': + optional: true + + '@biomejs/cli-linux-arm64-musl@2.2.4': + optional: true + + '@biomejs/cli-linux-arm64@2.2.4': + optional: true + + '@biomejs/cli-linux-x64-musl@2.2.4': + optional: true + + '@biomejs/cli-linux-x64@2.2.4': + optional: true + + '@biomejs/cli-win32-arm64@2.2.4': + optional: true + + '@biomejs/cli-win32-x64@2.2.4': + optional: true + + '@cacheable/memoize@2.0.1': + dependencies: + '@cacheable/utils': 2.0.1 + + '@cacheable/memory@2.0.1': + dependencies: + '@cacheable/memoize': 2.0.1 + '@cacheable/utils': 2.0.1 + '@keyv/bigmap': 1.0.1 + hookified: 1.12.1 + keyv: 5.5.2 + + '@cacheable/utils@2.0.1': {} + + '@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/css-tokenizer@3.0.4': {} + + '@csstools/media-query-list-parser@4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4)': + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + + '@csstools/selector-specificity@5.0.0(postcss-selector-parser@7.1.0)': + dependencies: + postcss-selector-parser: 7.1.0 + + '@dual-bundle/import-meta-resolve@4.2.1': {} + + '@emnapi/runtime@1.5.0': + dependencies: + tslib: 2.8.1 + optional: true + + '@esbuild/aix-ppc64@0.25.10': + optional: true + + '@esbuild/android-arm64@0.25.10': + optional: true + + '@esbuild/android-arm@0.25.10': + optional: true + + '@esbuild/android-x64@0.25.10': + optional: true + + '@esbuild/darwin-arm64@0.25.10': + optional: true + + '@esbuild/darwin-x64@0.25.10': + optional: true + + '@esbuild/freebsd-arm64@0.25.10': + optional: true + + '@esbuild/freebsd-x64@0.25.10': + optional: true + + '@esbuild/linux-arm64@0.25.10': + optional: true + + '@esbuild/linux-arm@0.25.10': + optional: true + + '@esbuild/linux-ia32@0.25.10': + optional: true + + '@esbuild/linux-loong64@0.25.10': + optional: true + + '@esbuild/linux-mips64el@0.25.10': + optional: true + + '@esbuild/linux-ppc64@0.25.10': + optional: true + + '@esbuild/linux-riscv64@0.25.10': + optional: true + + '@esbuild/linux-s390x@0.25.10': + optional: true + + '@esbuild/linux-x64@0.25.10': + optional: true + + '@esbuild/netbsd-arm64@0.25.10': + optional: true + + '@esbuild/netbsd-x64@0.25.10': + optional: true + + '@esbuild/openbsd-arm64@0.25.10': + optional: true + + '@esbuild/openbsd-x64@0.25.10': + optional: true + + '@esbuild/openharmony-arm64@0.25.10': + optional: true + + '@esbuild/sunos-x64@0.25.10': + optional: true + + '@esbuild/win32-arm64@0.25.10': + optional: true + + '@esbuild/win32-ia32@0.25.10': + optional: true + + '@esbuild/win32-x64@0.25.10': + optional: true + + '@eslint-community/eslint-utils@4.9.0(eslint@9.35.0)': + dependencies: + eslint: 9.35.0 + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.1': {} + + '@eslint/config-array@0.21.0': + dependencies: + '@eslint/object-schema': 2.1.6 + debug: 4.4.3 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/config-helpers@0.3.1': {} + + '@eslint/core@0.15.2': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.1': + dependencies: + ajv: 6.12.6 + debug: 4.4.3 + espree: 10.4.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.35.0': {} + + '@eslint/object-schema@2.1.6': {} + + '@eslint/plugin-kit@0.3.5': + dependencies: + '@eslint/core': 0.15.2 + levn: 0.4.1 + + '@floating-ui/core@1.7.3': + dependencies: + '@floating-ui/utils': 0.2.10 + + '@floating-ui/dom@1.7.4': + dependencies: + '@floating-ui/core': 1.7.3 + '@floating-ui/utils': 0.2.10 + + '@floating-ui/react-dom@2.1.6(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + dependencies: + '@floating-ui/dom': 1.7.4 + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) + + '@floating-ui/react@0.27.16(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + dependencies: + '@floating-ui/react-dom': 2.1.6(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@floating-ui/utils': 0.2.10 + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) + tabbable: 6.2.0 + + '@floating-ui/utils@0.2.10': {} + + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.7': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.4.3 + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.4.3': {} + + '@img/colour@1.0.0': {} + + '@img/sharp-darwin-arm64@0.34.4': + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.2.3 + optional: true + + '@img/sharp-darwin-x64@0.34.4': + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.2.3 + optional: true + + '@img/sharp-libvips-darwin-arm64@1.2.3': + optional: true + + '@img/sharp-libvips-darwin-x64@1.2.3': + optional: true + + '@img/sharp-libvips-linux-arm64@1.2.3': + optional: true + + '@img/sharp-libvips-linux-arm@1.2.3': + optional: true + + '@img/sharp-libvips-linux-ppc64@1.2.3': + optional: true + + '@img/sharp-libvips-linux-s390x@1.2.3': + optional: true + + '@img/sharp-libvips-linux-x64@1.2.3': + optional: true + + '@img/sharp-libvips-linuxmusl-arm64@1.2.3': + optional: true + + '@img/sharp-libvips-linuxmusl-x64@1.2.3': + optional: true + + '@img/sharp-linux-arm64@0.34.4': + optionalDependencies: + '@img/sharp-libvips-linux-arm64': 1.2.3 + optional: true + + '@img/sharp-linux-arm@0.34.4': + optionalDependencies: + '@img/sharp-libvips-linux-arm': 1.2.3 + optional: true + + '@img/sharp-linux-ppc64@0.34.4': + optionalDependencies: + '@img/sharp-libvips-linux-ppc64': 1.2.3 + optional: true + + '@img/sharp-linux-s390x@0.34.4': + optionalDependencies: + '@img/sharp-libvips-linux-s390x': 1.2.3 + optional: true + + '@img/sharp-linux-x64@0.34.4': + optionalDependencies: + '@img/sharp-libvips-linux-x64': 1.2.3 + optional: true + + '@img/sharp-linuxmusl-arm64@0.34.4': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-arm64': 1.2.3 + optional: true + + '@img/sharp-linuxmusl-x64@0.34.4': + optionalDependencies: + '@img/sharp-libvips-linuxmusl-x64': 1.2.3 + optional: true + + '@img/sharp-wasm32@0.34.4': + dependencies: + '@emnapi/runtime': 1.5.0 + optional: true + + '@img/sharp-win32-arm64@0.34.4': + optional: true + + '@img/sharp-win32-ia32@0.34.4': + optional: true + + '@img/sharp-win32-x64@0.34.4': + optional: true + + '@inlang/paraglide-js@2.3.2': + dependencies: + '@inlang/recommend-sherlock': 0.2.1 + '@inlang/sdk': 2.4.9 + commander: 11.1.0 + consola: 3.4.0 + json5: 2.2.3 + unplugin: 2.3.10 + urlpattern-polyfill: 10.1.0 + transitivePeerDependencies: + - babel-plugin-macros + + '@inlang/recommend-sherlock@0.2.1': + dependencies: + comment-json: 4.2.5 + + '@inlang/sdk@2.4.9': + dependencies: + '@lix-js/sdk': 0.4.7 + '@sinclair/typebox': 0.31.28 + kysely: 0.27.6 + sqlite-wasm-kysely: 0.3.0(kysely@0.27.6) + uuid: 10.0.0 + transitivePeerDependencies: + - babel-plugin-macros + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.5.5 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/remapping@2.3.5': + dependencies: + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/sourcemap-codec@1.5.5': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.5 + + '@keyv/bigmap@1.0.1': + dependencies: + hookified: 1.12.1 + + '@keyv/serialize@1.1.1': {} + + '@lix-js/sdk@0.4.7': + dependencies: + '@lix-js/server-protocol-schema': 0.1.1 + dedent: 1.5.1 + human-id: 4.1.1 + js-sha256: 0.11.1 + kysely: 0.27.6 + sqlite-wasm-kysely: 0.3.0(kysely@0.27.6) + uuid: 10.0.0 + transitivePeerDependencies: + - babel-plugin-macros + + '@lix-js/server-protocol-schema@0.1.1': {} + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.19.1 + + '@parcel/watcher-android-arm64@2.5.1': + optional: true + + '@parcel/watcher-darwin-arm64@2.5.1': + optional: true + + '@parcel/watcher-darwin-x64@2.5.1': + optional: true + + '@parcel/watcher-freebsd-x64@2.5.1': + optional: true + + '@parcel/watcher-linux-arm-glibc@2.5.1': + optional: true + + '@parcel/watcher-linux-arm-musl@2.5.1': + optional: true + + '@parcel/watcher-linux-arm64-glibc@2.5.1': + optional: true + + '@parcel/watcher-linux-arm64-musl@2.5.1': + optional: true + + '@parcel/watcher-linux-x64-glibc@2.5.1': + optional: true + + '@parcel/watcher-linux-x64-musl@2.5.1': + optional: true + + '@parcel/watcher-win32-arm64@2.5.1': + optional: true + + '@parcel/watcher-win32-ia32@2.5.1': + optional: true + + '@parcel/watcher-win32-x64@2.5.1': + optional: true + + '@parcel/watcher@2.5.1': + dependencies: + detect-libc: 1.0.3 + is-glob: 4.0.3 + micromatch: 4.0.8 + node-addon-api: 7.1.1 + 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 + optional: true + + '@rolldown/pluginutils@1.0.0-beta.35': {} + + '@rollup/rollup-android-arm-eabi@4.51.0': + optional: true + + '@rollup/rollup-android-arm64@4.51.0': + optional: true + + '@rollup/rollup-darwin-arm64@4.51.0': + optional: true + + '@rollup/rollup-darwin-x64@4.51.0': + optional: true + + '@rollup/rollup-freebsd-arm64@4.51.0': + optional: true + + '@rollup/rollup-freebsd-x64@4.51.0': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.51.0': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.51.0': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.51.0': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.51.0': + optional: true + + '@rollup/rollup-linux-loong64-gnu@4.51.0': + optional: true + + '@rollup/rollup-linux-ppc64-gnu@4.51.0': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.51.0': + optional: true + + '@rollup/rollup-linux-riscv64-musl@4.51.0': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.51.0': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.51.0': + optional: true + + '@rollup/rollup-linux-x64-musl@4.51.0': + optional: true + + '@rollup/rollup-openharmony-arm64@4.51.0': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.51.0': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.51.0': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.51.0': + optional: true + + '@sinclair/typebox@0.31.28': {} + + '@solid-primitives/event-listener@2.4.3(solid-js@1.9.9)': + dependencies: + '@solid-primitives/utils': 6.3.2(solid-js@1.9.9) + solid-js: 1.9.9 + + '@solid-primitives/keyboard@1.3.3(solid-js@1.9.9)': + dependencies: + '@solid-primitives/event-listener': 2.4.3(solid-js@1.9.9) + '@solid-primitives/rootless': 1.5.2(solid-js@1.9.9) + '@solid-primitives/utils': 6.3.2(solid-js@1.9.9) + solid-js: 1.9.9 + + '@solid-primitives/rootless@1.5.2(solid-js@1.9.9)': + dependencies: + '@solid-primitives/utils': 6.3.2(solid-js@1.9.9) + solid-js: 1.9.9 + + '@solid-primitives/utils@6.3.2(solid-js@1.9.9)': + dependencies: + solid-js: 1.9.9 + + '@sqlite.org/sqlite-wasm@3.48.0-build4': {} + + '@swc/core-darwin-arm64@1.13.5': + optional: true + + '@swc/core-darwin-x64@1.13.5': + optional: true + + '@swc/core-linux-arm-gnueabihf@1.13.5': + optional: true + + '@swc/core-linux-arm64-gnu@1.13.5': + optional: true + + '@swc/core-linux-arm64-musl@1.13.5': + optional: true + + '@swc/core-linux-x64-gnu@1.13.5': + optional: true + + '@swc/core-linux-x64-musl@1.13.5': + optional: true + + '@swc/core-win32-arm64-msvc@1.13.5': + optional: true + + '@swc/core-win32-ia32-msvc@1.13.5': + optional: true + + '@swc/core-win32-x64-msvc@1.13.5': + optional: true + + '@swc/core@1.13.5': + dependencies: + '@swc/counter': 0.1.3 + '@swc/types': 0.1.25 + optionalDependencies: + '@swc/core-darwin-arm64': 1.13.5 + '@swc/core-darwin-x64': 1.13.5 + '@swc/core-linux-arm-gnueabihf': 1.13.5 + '@swc/core-linux-arm64-gnu': 1.13.5 + '@swc/core-linux-arm64-musl': 1.13.5 + '@swc/core-linux-x64-gnu': 1.13.5 + '@swc/core-linux-x64-musl': 1.13.5 + '@swc/core-win32-arm64-msvc': 1.13.5 + '@swc/core-win32-ia32-msvc': 1.13.5 + '@swc/core-win32-x64-msvc': 1.13.5 + + '@swc/counter@0.1.3': {} + + '@swc/types@0.1.25': + dependencies: + '@swc/counter': 0.1.3 + + '@tanstack/devtools-event-bus@0.3.2': + dependencies: + ws: 8.18.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@tanstack/devtools-event-client@0.2.5': {} + + '@tanstack/devtools-ui@0.3.5(csstype@3.1.3)(solid-js@1.9.9)': + dependencies: + clsx: 2.1.1 + goober: 2.1.16(csstype@3.1.3) + solid-js: 1.9.9 + transitivePeerDependencies: + - csstype + + '@tanstack/devtools@0.6.13(csstype@3.1.3)(solid-js@1.9.9)': + dependencies: + '@solid-primitives/keyboard': 1.3.3(solid-js@1.9.9) + '@tanstack/devtools-event-bus': 0.3.2 + '@tanstack/devtools-ui': 0.3.5(csstype@3.1.3)(solid-js@1.9.9) + clsx: 2.1.1 + goober: 2.1.16(csstype@3.1.3) + solid-js: 1.9.9 + transitivePeerDependencies: + - bufferutil + - csstype + - utf-8-validate + + '@tanstack/form-core@1.21.2': + dependencies: + '@tanstack/devtools-event-client': 0.2.5 + '@tanstack/store': 0.7.5 + uuid: 13.0.0 + + '@tanstack/history@1.131.2': {} + + '@tanstack/query-core@5.89.0': {} + + '@tanstack/query-devtools@5.87.3': {} + + '@tanstack/react-devtools@0.6.9(@types/react-dom@19.1.9(@types/react@19.1.13))(@types/react@19.1.13)(csstype@3.1.3)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.9)': + dependencies: + '@tanstack/devtools': 0.6.13(csstype@3.1.3)(solid-js@1.9.9) + '@types/react': 19.1.13 + '@types/react-dom': 19.1.9(@types/react@19.1.13) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) + transitivePeerDependencies: + - bufferutil + - csstype + - solid-js + - utf-8-validate + + '@tanstack/react-form@1.21.2(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + dependencies: + '@tanstack/form-core': 1.21.2 + '@tanstack/react-store': 0.7.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + decode-formdata: 0.9.0 + devalue: 5.3.2 + react: 19.1.1 + transitivePeerDependencies: + - react-dom + + '@tanstack/react-query-devtools@5.89.0(@tanstack/react-query@5.89.0(react@19.1.1))(react@19.1.1)': + dependencies: + '@tanstack/query-devtools': 5.87.3 + '@tanstack/react-query': 5.89.0(react@19.1.1) + react: 19.1.1 + + '@tanstack/react-query@5.89.0(react@19.1.1)': + dependencies: + '@tanstack/query-core': 5.89.0 + react: 19.1.1 + + '@tanstack/react-router-devtools@1.131.48(@tanstack/react-router@1.131.48(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(@tanstack/router-core@1.131.48)(csstype@3.1.3)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)(solid-js@1.9.9)(tiny-invariant@1.3.3)': + dependencies: + '@tanstack/react-router': 1.131.48(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@tanstack/router-devtools-core': 1.131.48(@tanstack/router-core@1.131.48)(csstype@3.1.3)(solid-js@1.9.9)(tiny-invariant@1.3.3) + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) + transitivePeerDependencies: + - '@tanstack/router-core' + - csstype + - solid-js + - tiny-invariant + + '@tanstack/react-router@1.131.48(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + dependencies: + '@tanstack/history': 1.131.2 + '@tanstack/react-store': 0.7.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + '@tanstack/router-core': 1.131.48 + isbot: 5.1.30 + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) + tiny-invariant: 1.3.3 + tiny-warning: 1.0.3 + + '@tanstack/react-store@0.7.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + dependencies: + '@tanstack/store': 0.7.5 + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) + use-sync-external-store: 1.5.0(react@19.1.1) + + '@tanstack/router-core@1.131.48': + dependencies: + '@tanstack/history': 1.131.2 + '@tanstack/store': 0.7.5 + cookie-es: 1.2.2 + seroval: 1.3.2 + seroval-plugins: 1.3.3(seroval@1.3.2) + tiny-invariant: 1.3.3 + tiny-warning: 1.0.3 + + '@tanstack/router-devtools-core@1.131.48(@tanstack/router-core@1.131.48)(csstype@3.1.3)(solid-js@1.9.9)(tiny-invariant@1.3.3)': + dependencies: + '@tanstack/router-core': 1.131.48 + clsx: 2.1.1 + goober: 2.1.16(csstype@3.1.3) + solid-js: 1.9.9 + tiny-invariant: 1.3.3 + optionalDependencies: + csstype: 3.1.3 + + '@tanstack/router-generator@1.131.48': + dependencies: + '@tanstack/router-core': 1.131.48 + '@tanstack/router-utils': 1.131.2 + '@tanstack/virtual-file-routes': 1.131.2 + prettier: 3.6.2 + recast: 0.23.11 + source-map: 0.7.6 + tsx: 4.20.5 + zod: 3.25.76 + transitivePeerDependencies: + - supports-color + + '@tanstack/router-plugin@1.131.48(@tanstack/react-router@1.131.48(react-dom@19.1.1(react@19.1.1))(react@19.1.1))(vite@7.1.6(@types/node@24.5.2)(sass@1.92.1)(tsx@4.20.5))': + dependencies: + '@babel/core': 7.28.4 + '@babel/plugin-syntax-jsx': 7.27.1(@babel/core@7.28.4) + '@babel/plugin-syntax-typescript': 7.27.1(@babel/core@7.28.4) + '@babel/template': 7.27.2 + '@babel/traverse': 7.28.4 + '@babel/types': 7.28.4 + '@tanstack/router-core': 1.131.48 + '@tanstack/router-generator': 1.131.48 + '@tanstack/router-utils': 1.131.2 + '@tanstack/virtual-file-routes': 1.131.2 + babel-dead-code-elimination: 1.0.10 + chokidar: 3.6.0 + unplugin: 2.3.10 + zod: 3.25.76 + optionalDependencies: + '@tanstack/react-router': 1.131.48(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + vite: 7.1.6(@types/node@24.5.2)(sass@1.92.1)(tsx@4.20.5) + transitivePeerDependencies: + - supports-color + + '@tanstack/router-utils@1.131.2': + dependencies: + '@babel/core': 7.28.4 + '@babel/generator': 7.28.3 + '@babel/parser': 7.28.4 + '@babel/preset-typescript': 7.27.1(@babel/core@7.28.4) + ansis: 4.1.0 + diff: 8.0.2 + transitivePeerDependencies: + - supports-color + + '@tanstack/store@0.7.5': {} + + '@tanstack/virtual-file-routes@1.131.2': {} + + '@types/estree@1.0.8': {} + + '@types/json-schema@7.0.15': {} + + '@types/node@24.5.2': + dependencies: + undici-types: 7.12.0 + + '@types/qs@6.14.0': {} + + '@types/react-dom@19.1.9(@types/react@19.1.13)': + dependencies: + '@types/react': 19.1.13 + + '@types/react@19.1.13': + dependencies: + csstype: 3.1.3 + + '@typescript-eslint/eslint-plugin@8.44.0(@typescript-eslint/parser@8.44.0(eslint@9.35.0)(typescript@5.9.2))(eslint@9.35.0)(typescript@5.9.2)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.44.0(eslint@9.35.0)(typescript@5.9.2) + '@typescript-eslint/scope-manager': 8.44.0 + '@typescript-eslint/type-utils': 8.44.0(eslint@9.35.0)(typescript@5.9.2) + '@typescript-eslint/utils': 8.44.0(eslint@9.35.0)(typescript@5.9.2) + '@typescript-eslint/visitor-keys': 8.44.0 + eslint: 9.35.0 + graphemer: 1.4.0 + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.1.0(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.44.0(eslint@9.35.0)(typescript@5.9.2)': + dependencies: + '@typescript-eslint/scope-manager': 8.44.0 + '@typescript-eslint/types': 8.44.0 + '@typescript-eslint/typescript-estree': 8.44.0(typescript@5.9.2) + '@typescript-eslint/visitor-keys': 8.44.0 + debug: 4.4.3 + eslint: 9.35.0 + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/project-service@8.44.0(typescript@5.9.2)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.44.0(typescript@5.9.2) + '@typescript-eslint/types': 8.44.0 + debug: 4.4.3 + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@8.44.0': + dependencies: + '@typescript-eslint/types': 8.44.0 + '@typescript-eslint/visitor-keys': 8.44.0 + + '@typescript-eslint/tsconfig-utils@8.44.0(typescript@5.9.2)': + dependencies: + typescript: 5.9.2 + + '@typescript-eslint/type-utils@8.44.0(eslint@9.35.0)(typescript@5.9.2)': + dependencies: + '@typescript-eslint/types': 8.44.0 + '@typescript-eslint/typescript-estree': 8.44.0(typescript@5.9.2) + '@typescript-eslint/utils': 8.44.0(eslint@9.35.0)(typescript@5.9.2) + debug: 4.4.3 + eslint: 9.35.0 + ts-api-utils: 2.1.0(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@8.44.0': {} + + '@typescript-eslint/typescript-estree@8.44.0(typescript@5.9.2)': + dependencies: + '@typescript-eslint/project-service': 8.44.0(typescript@5.9.2) + '@typescript-eslint/tsconfig-utils': 8.44.0(typescript@5.9.2) + '@typescript-eslint/types': 8.44.0 + '@typescript-eslint/visitor-keys': 8.44.0 + debug: 4.4.3 + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.2 + ts-api-utils: 2.1.0(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.44.0(eslint@9.35.0)(typescript@5.9.2)': + dependencies: + '@eslint-community/eslint-utils': 4.9.0(eslint@9.35.0) + '@typescript-eslint/scope-manager': 8.44.0 + '@typescript-eslint/types': 8.44.0 + '@typescript-eslint/typescript-estree': 8.44.0(typescript@5.9.2) + eslint: 9.35.0 + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@8.44.0': + dependencies: + '@typescript-eslint/types': 8.44.0 + eslint-visitor-keys: 4.2.1 + + '@uidotdev/usehooks@2.4.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1)': + dependencies: + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) + + '@vitejs/plugin-react-swc@4.1.0(vite@7.1.6(@types/node@24.5.2)(sass@1.92.1)(tsx@4.20.5))': + dependencies: + '@rolldown/pluginutils': 1.0.0-beta.35 + '@swc/core': 1.13.5 + vite: 7.1.6(@types/node@24.5.2)(sass@1.92.1)(tsx@4.20.5) + transitivePeerDependencies: + - '@swc/helpers' + + acorn-jsx@5.3.2(acorn@8.15.0): + dependencies: + acorn: 8.15.0 + + acorn@8.15.0: {} + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ajv@8.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.1.0 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ansi-colors@4.1.3: {} + + ansi-regex@5.0.1: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansis@4.1.0: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + argparse@2.0.1: {} + + array-timsort@1.0.3: {} + + array-union@2.1.0: {} + + ast-types@0.16.1: + dependencies: + tslib: 2.8.1 + + astral-regex@2.0.0: {} + + asynckit@0.4.0: {} + + axios@1.12.2: + dependencies: + follow-redirects: 1.15.11 + form-data: 4.0.4 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + + babel-dead-code-elimination@1.0.10: + dependencies: + '@babel/core': 7.28.4 + '@babel/parser': 7.28.4 + '@babel/traverse': 7.28.4 + '@babel/types': 7.28.4 + transitivePeerDependencies: + - supports-color + + balanced-match@1.0.2: {} + + balanced-match@2.0.0: {} + + baseline-browser-mapping@2.8.6: {} + + binary-extensions@2.3.0: {} + + brace-expansion@1.1.12: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.2: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.26.2: + dependencies: + baseline-browser-mapping: 2.8.6 + caniuse-lite: 1.0.30001743 + electron-to-chromium: 1.5.222 + node-releases: 2.0.21 + update-browserslist-db: 1.1.3(browserslist@4.26.2) + + cacheable@2.0.1: + dependencies: + '@cacheable/memoize': 2.0.1 + '@cacheable/memory': 2.0.1 + '@cacheable/utils': 2.0.1 + hookified: 1.12.1 + keyv: 5.5.2 + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + callsites@3.1.0: {} + + caniuse-lite@1.0.30001743: {} + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + + clsx@2.1.1: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + colord@2.9.3: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + commander@11.1.0: {} + + comment-json@4.2.5: + dependencies: + array-timsort: 1.0.3 + core-util-is: 1.0.3 + esprima: 4.0.1 + has-own-prop: 2.0.0 + repeat-string: 1.6.1 + + concat-map@0.0.1: {} + + consola@3.4.0: {} + + convert-source-map@2.0.0: {} + + cookie-es@1.2.2: {} + + core-util-is@1.0.3: {} + + cosmiconfig@9.0.0(typescript@5.9.2): + dependencies: + env-paths: 2.2.1 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + parse-json: 5.2.0 + optionalDependencies: + typescript: 5.9.2 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + css-functions-list@3.2.3: {} + + css-tree@3.1.0: + dependencies: + mdn-data: 2.12.2 + source-map-js: 1.2.1 + + cssesc@3.0.0: {} + + csstype@3.1.3: {} + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + decode-formdata@0.9.0: {} + + dedent@1.5.1: {} + + deep-is@0.1.4: {} + + delayed-stream@1.0.0: {} + + detect-libc@1.0.3: + optional: true + + detect-libc@2.1.0: {} + + devalue@5.3.2: {} + + diff@8.0.2: {} + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + electron-to-chromium@1.5.222: {} + + emoji-regex@8.0.0: {} + + env-paths@2.2.1: {} + + error-ex@1.3.4: + dependencies: + is-arrayish: 0.2.1 + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + esbuild@0.25.10: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.10 + '@esbuild/android-arm': 0.25.10 + '@esbuild/android-arm64': 0.25.10 + '@esbuild/android-x64': 0.25.10 + '@esbuild/darwin-arm64': 0.25.10 + '@esbuild/darwin-x64': 0.25.10 + '@esbuild/freebsd-arm64': 0.25.10 + '@esbuild/freebsd-x64': 0.25.10 + '@esbuild/linux-arm': 0.25.10 + '@esbuild/linux-arm64': 0.25.10 + '@esbuild/linux-ia32': 0.25.10 + '@esbuild/linux-loong64': 0.25.10 + '@esbuild/linux-mips64el': 0.25.10 + '@esbuild/linux-ppc64': 0.25.10 + '@esbuild/linux-riscv64': 0.25.10 + '@esbuild/linux-s390x': 0.25.10 + '@esbuild/linux-x64': 0.25.10 + '@esbuild/netbsd-arm64': 0.25.10 + '@esbuild/netbsd-x64': 0.25.10 + '@esbuild/openbsd-arm64': 0.25.10 + '@esbuild/openbsd-x64': 0.25.10 + '@esbuild/openharmony-arm64': 0.25.10 + '@esbuild/sunos-x64': 0.25.10 + '@esbuild/win32-arm64': 0.25.10 + '@esbuild/win32-ia32': 0.25.10 + '@esbuild/win32-x64': 0.25.10 + + escalade@3.2.0: {} + + escape-string-regexp@4.0.0: {} + + eslint-scope@8.4.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.1: {} + + eslint@9.35.0: + dependencies: + '@eslint-community/eslint-utils': 4.9.0(eslint@9.35.0) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.21.0 + '@eslint/config-helpers': 0.3.1 + '@eslint/core': 0.15.2 + '@eslint/eslintrc': 3.3.1 + '@eslint/js': 9.35.0 + '@eslint/plugin-kit': 0.3.5 + '@humanfs/node': 0.16.7 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.3 + '@types/estree': 1.0.8 + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.3 + escape-string-regexp: 4.0.0 + eslint-scope: 8.4.0 + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + 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.4 + transitivePeerDependencies: + - supports-color + + espree@10.4.0: + dependencies: + acorn: 8.15.0 + acorn-jsx: 5.3.2(acorn@8.15.0) + eslint-visitor-keys: 4.2.1 + + esprima@4.0.1: {} + + esquery@1.6.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@5.3.0: {} + + esutils@2.0.3: {} + + fast-deep-equal@3.1.3: {} + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fast-uri@3.1.0: {} + + fastest-levenshtein@1.0.16: {} + + fastq@1.19.1: + dependencies: + reusify: 1.1.0 + + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + + file-entry-cache@10.1.4: + dependencies: + flat-cache: 6.1.14 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.3.3 + keyv: 4.5.4 + + flat-cache@6.1.14: + dependencies: + cacheable: 2.0.1 + flatted: 3.3.3 + hookified: 1.12.1 + + flatted@3.3.3: {} + + follow-redirects@1.15.11: {} + + form-data@4.0.4: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + hasown: 2.0.2 + mime-types: 2.1.35 + + framer-motion@12.23.15(react-dom@19.1.1(react@19.1.1))(react@19.1.1): + dependencies: + motion-dom: 12.23.12 + motion-utils: 12.23.6 + tslib: 2.8.1 + optionalDependencies: + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + gensync@1.0.0-beta.2: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + get-tsconfig@4.10.1: + dependencies: + resolve-pkg-maps: 1.0.0 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + global-modules@2.0.0: + dependencies: + global-prefix: 3.0.0 + + global-prefix@3.0.0: + dependencies: + ini: 1.3.8 + kind-of: 6.0.3 + which: 1.3.1 + + globals@14.0.0: {} + + globals@16.4.0: {} + + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.3 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + + globjoin@0.1.4: {} + + goober@2.1.16(csstype@3.1.3): + dependencies: + csstype: 3.1.3 + + gopd@1.2.0: {} + + graphemer@1.4.0: {} + + has-flag@4.0.0: {} + + has-own-prop@2.0.0: {} + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + hookified@1.12.1: {} + + html-tags@3.3.1: {} + + human-id@4.1.1: {} + + ignore@5.3.2: {} + + ignore@7.0.5: {} + + immutable@5.1.3: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + imurmurhash@0.1.4: {} + + ini@1.3.8: {} + + is-arrayish@0.2.1: {} + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-number@7.0.0: {} + + is-plain-object@5.0.0: {} + + isbot@5.1.30: {} + + isexe@2.0.0: {} + + js-sha256@0.11.1: {} + + js-tokens@4.0.0: {} + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + jsesc@3.1.0: {} + + json-buffer@3.0.1: {} + + json-parse-even-better-errors@2.3.1: {} + + json-schema-traverse@0.4.1: {} + + json-schema-traverse@1.0.0: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json5@2.2.3: {} + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + keyv@5.5.2: + dependencies: + '@keyv/serialize': 1.1.1 + + kind-of@6.0.3: {} + + known-css-properties@0.36.0: {} + + known-css-properties@0.37.0: {} + + kysely@0.27.6: {} + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lines-and-columns@1.2.4: {} + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash.merge@4.6.2: {} + + lodash.truncate@4.4.2: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + math-intrinsics@1.1.0: {} + + mathml-tag-names@2.1.3: {} + + mdn-data@2.12.2: {} + + mdn-data@2.24.0: {} + + meow@13.2.0: {} + + merge2@1.4.1: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.12 + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.2 + + motion-dom@12.23.12: + dependencies: + motion-utils: 12.23.6 + + motion-utils@12.23.6: {} + + motion@12.23.15(react-dom@19.1.1(react@19.1.1))(react@19.1.1): + dependencies: + framer-motion: 12.23.15(react-dom@19.1.1(react@19.1.1))(react@19.1.1) + tslib: 2.8.1 + optionalDependencies: + react: 19.1.1 + react-dom: 19.1.1(react@19.1.1) + + ms@2.1.3: {} + + nanoid@3.3.11: {} + + natural-compare@1.4.0: {} + + node-addon-api@7.1.1: + optional: true + + node-releases@2.0.21: {} + + normalize-path@3.0.0: {} + + object-inspect@1.13.4: {} + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.27.1 + error-ex: 1.3.4 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + path-exists@4.0.0: {} + + path-key@3.1.1: {} + + path-type@4.0.0: {} + + pathe@2.0.3: {} + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + picomatch@4.0.3: {} + + postcss-media-query-parser@0.2.3: {} + + postcss-resolve-nested-selector@0.1.6: {} + + postcss-safe-parser@7.0.1(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + + postcss-scss@4.0.9(postcss@8.5.6): + dependencies: + postcss: 8.5.6 + + postcss-selector-parser@7.1.0: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-value-parser@4.2.0: {} + + postcss@8.5.6: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prelude-ls@1.2.1: {} + + prettier@3.6.2: {} + + proxy-from-env@1.1.0: {} + + punycode@2.3.1: {} + + qs@6.14.0: + dependencies: + side-channel: 1.1.0 + + queue-microtask@1.2.3: {} + + react-dom@19.1.1(react@19.1.1): + dependencies: + react: 19.1.1 + scheduler: 0.26.0 + + react@19.1.1: {} + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + + readdirp@4.1.2: {} + + recast@0.23.11: + dependencies: + ast-types: 0.16.1 + esprima: 4.0.1 + source-map: 0.6.1 + tiny-invariant: 1.3.3 + tslib: 2.8.1 + + repeat-string@1.6.1: {} + + require-from-string@2.0.2: {} + + resolve-from@4.0.0: {} + + resolve-from@5.0.0: {} + + resolve-pkg-maps@1.0.0: {} + + reusify@1.1.0: {} + + rollup@4.51.0: + dependencies: + '@types/estree': 1.0.8 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.51.0 + '@rollup/rollup-android-arm64': 4.51.0 + '@rollup/rollup-darwin-arm64': 4.51.0 + '@rollup/rollup-darwin-x64': 4.51.0 + '@rollup/rollup-freebsd-arm64': 4.51.0 + '@rollup/rollup-freebsd-x64': 4.51.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.51.0 + '@rollup/rollup-linux-arm-musleabihf': 4.51.0 + '@rollup/rollup-linux-arm64-gnu': 4.51.0 + '@rollup/rollup-linux-arm64-musl': 4.51.0 + '@rollup/rollup-linux-loong64-gnu': 4.51.0 + '@rollup/rollup-linux-ppc64-gnu': 4.51.0 + '@rollup/rollup-linux-riscv64-gnu': 4.51.0 + '@rollup/rollup-linux-riscv64-musl': 4.51.0 + '@rollup/rollup-linux-s390x-gnu': 4.51.0 + '@rollup/rollup-linux-x64-gnu': 4.51.0 + '@rollup/rollup-linux-x64-musl': 4.51.0 + '@rollup/rollup-openharmony-arm64': 4.51.0 + '@rollup/rollup-win32-arm64-msvc': 4.51.0 + '@rollup/rollup-win32-ia32-msvc': 4.51.0 + '@rollup/rollup-win32-x64-msvc': 4.51.0 + fsevents: 2.3.3 + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + sass@1.92.1: + dependencies: + chokidar: 4.0.3 + immutable: 5.1.3 + source-map-js: 1.2.1 + optionalDependencies: + '@parcel/watcher': 2.5.1 + + scheduler@0.26.0: {} + + semver@6.3.1: {} + + semver@7.7.2: {} + + seroval-plugins@1.3.3(seroval@1.3.2): + dependencies: + seroval: 1.3.2 + + seroval@1.3.2: {} + + sharp@0.34.4: + dependencies: + '@img/colour': 1.0.0 + detect-libc: 2.1.0 + semver: 7.7.2 + optionalDependencies: + '@img/sharp-darwin-arm64': 0.34.4 + '@img/sharp-darwin-x64': 0.34.4 + '@img/sharp-libvips-darwin-arm64': 1.2.3 + '@img/sharp-libvips-darwin-x64': 1.2.3 + '@img/sharp-libvips-linux-arm': 1.2.3 + '@img/sharp-libvips-linux-arm64': 1.2.3 + '@img/sharp-libvips-linux-ppc64': 1.2.3 + '@img/sharp-libvips-linux-s390x': 1.2.3 + '@img/sharp-libvips-linux-x64': 1.2.3 + '@img/sharp-libvips-linuxmusl-arm64': 1.2.3 + '@img/sharp-libvips-linuxmusl-x64': 1.2.3 + '@img/sharp-linux-arm': 0.34.4 + '@img/sharp-linux-arm64': 0.34.4 + '@img/sharp-linux-ppc64': 0.34.4 + '@img/sharp-linux-s390x': 0.34.4 + '@img/sharp-linux-x64': 0.34.4 + '@img/sharp-linuxmusl-arm64': 0.34.4 + '@img/sharp-linuxmusl-x64': 0.34.4 + '@img/sharp-wasm32': 0.34.4 + '@img/sharp-win32-arm64': 0.34.4 + '@img/sharp-win32-ia32': 0.34.4 + '@img/sharp-win32-x64': 0.34.4 + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + side-channel-list@1.0.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + signal-exit@4.1.0: {} + + slash@3.0.0: {} + + slice-ansi@4.0.0: + dependencies: + ansi-styles: 4.3.0 + astral-regex: 2.0.0 + is-fullwidth-code-point: 3.0.0 + + solid-js@1.9.9: + dependencies: + csstype: 3.1.3 + seroval: 1.3.2 + seroval-plugins: 1.3.3(seroval@1.3.2) + + source-map-js@1.2.1: {} + + source-map@0.6.1: {} + + source-map@0.7.6: {} + + sqlite-wasm-kysely@0.3.0(kysely@0.27.6): + dependencies: + '@sqlite.org/sqlite-wasm': 3.48.0-build4 + kysely: 0.27.6 + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-json-comments@3.1.1: {} + + stylelint-config-recommended-scss@16.0.1(postcss@8.5.6)(stylelint@16.24.0(typescript@5.9.2)): + dependencies: + postcss-scss: 4.0.9(postcss@8.5.6) + stylelint: 16.24.0(typescript@5.9.2) + stylelint-config-recommended: 17.0.0(stylelint@16.24.0(typescript@5.9.2)) + stylelint-scss: 6.12.1(stylelint@16.24.0(typescript@5.9.2)) + optionalDependencies: + postcss: 8.5.6 + + stylelint-config-recommended@17.0.0(stylelint@16.24.0(typescript@5.9.2)): + dependencies: + stylelint: 16.24.0(typescript@5.9.2) + + stylelint-config-standard-scss@16.0.0(postcss@8.5.6)(stylelint@16.24.0(typescript@5.9.2)): + dependencies: + stylelint: 16.24.0(typescript@5.9.2) + stylelint-config-recommended-scss: 16.0.1(postcss@8.5.6)(stylelint@16.24.0(typescript@5.9.2)) + stylelint-config-standard: 39.0.0(stylelint@16.24.0(typescript@5.9.2)) + optionalDependencies: + postcss: 8.5.6 + + stylelint-config-standard@39.0.0(stylelint@16.24.0(typescript@5.9.2)): + dependencies: + stylelint: 16.24.0(typescript@5.9.2) + stylelint-config-recommended: 17.0.0(stylelint@16.24.0(typescript@5.9.2)) + + stylelint-scss@6.12.1(stylelint@16.24.0(typescript@5.9.2)): + dependencies: + css-tree: 3.1.0 + is-plain-object: 5.0.0 + known-css-properties: 0.36.0 + mdn-data: 2.24.0 + postcss-media-query-parser: 0.2.3 + postcss-resolve-nested-selector: 0.1.6 + postcss-selector-parser: 7.1.0 + postcss-value-parser: 4.2.0 + stylelint: 16.24.0(typescript@5.9.2) + + stylelint@16.24.0(typescript@5.9.2): + dependencies: + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + '@csstools/media-query-list-parser': 4.0.3(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/selector-specificity': 5.0.0(postcss-selector-parser@7.1.0) + '@dual-bundle/import-meta-resolve': 4.2.1 + balanced-match: 2.0.0 + colord: 2.9.3 + cosmiconfig: 9.0.0(typescript@5.9.2) + css-functions-list: 3.2.3 + css-tree: 3.1.0 + debug: 4.4.3 + fast-glob: 3.3.3 + fastest-levenshtein: 1.0.16 + file-entry-cache: 10.1.4 + global-modules: 2.0.0 + globby: 11.1.0 + globjoin: 0.1.4 + html-tags: 3.3.1 + ignore: 7.0.5 + imurmurhash: 0.1.4 + is-plain-object: 5.0.0 + known-css-properties: 0.37.0 + mathml-tag-names: 2.1.3 + meow: 13.2.0 + micromatch: 4.0.8 + normalize-path: 3.0.0 + picocolors: 1.1.1 + postcss: 8.5.6 + postcss-resolve-nested-selector: 0.1.6 + postcss-safe-parser: 7.0.1(postcss@8.5.6) + postcss-selector-parser: 7.1.0 + postcss-value-parser: 4.2.0 + resolve-from: 5.0.0 + string-width: 4.2.3 + supports-hyperlinks: 3.2.0 + svg-tags: 1.0.0 + table: 6.9.0 + write-file-atomic: 5.0.1 + transitivePeerDependencies: + - supports-color + - typescript + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-hyperlinks@3.2.0: + dependencies: + has-flag: 4.0.0 + supports-color: 7.2.0 + + svg-tags@1.0.0: {} + + tabbable@6.2.0: {} + + table@6.9.0: + dependencies: + ajv: 8.17.1 + lodash.truncate: 4.4.2 + slice-ansi: 4.0.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + tiny-invariant@1.3.3: {} + + tiny-warning@1.0.3: {} + + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + ts-api-utils@2.1.0(typescript@5.9.2): + dependencies: + typescript: 5.9.2 + + tslib@2.8.1: {} + + tsx@4.20.5: + dependencies: + esbuild: 0.25.10 + get-tsconfig: 4.10.1 + optionalDependencies: + fsevents: 2.3.3 + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + typescript-eslint@8.44.0(eslint@9.35.0)(typescript@5.9.2): + dependencies: + '@typescript-eslint/eslint-plugin': 8.44.0(@typescript-eslint/parser@8.44.0(eslint@9.35.0)(typescript@5.9.2))(eslint@9.35.0)(typescript@5.9.2) + '@typescript-eslint/parser': 8.44.0(eslint@9.35.0)(typescript@5.9.2) + '@typescript-eslint/typescript-estree': 8.44.0(typescript@5.9.2) + '@typescript-eslint/utils': 8.44.0(eslint@9.35.0)(typescript@5.9.2) + eslint: 9.35.0 + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + + typescript@5.9.2: {} + + undici-types@7.12.0: {} + + unplugin@2.3.10: + dependencies: + '@jridgewell/remapping': 2.3.5 + acorn: 8.15.0 + picomatch: 4.0.3 + webpack-virtual-modules: 0.6.2 + + update-browserslist-db@1.1.3(browserslist@4.26.2): + dependencies: + browserslist: 4.26.2 + escalade: 3.2.0 + picocolors: 1.1.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + urlpattern-polyfill@10.1.0: {} + + use-sync-external-store@1.5.0(react@19.1.1): + dependencies: + react: 19.1.1 + + util-deprecate@1.0.2: {} + + uuid@10.0.0: {} + + uuid@13.0.0: {} + + vite-plugin-image-optimizer@2.0.2(sharp@0.34.4)(vite@7.1.6(@types/node@24.5.2)(sass@1.92.1)(tsx@4.20.5)): + dependencies: + ansi-colors: 4.1.3 + pathe: 2.0.3 + vite: 7.1.6(@types/node@24.5.2)(sass@1.92.1)(tsx@4.20.5) + optionalDependencies: + sharp: 0.34.4 + + vite@7.1.6(@types/node@24.5.2)(sass@1.92.1)(tsx@4.20.5): + dependencies: + esbuild: 0.25.10 + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + postcss: 8.5.6 + rollup: 4.51.0 + tinyglobby: 0.2.15 + optionalDependencies: + '@types/node': 24.5.2 + fsevents: 2.3.3 + sass: 1.92.1 + tsx: 4.20.5 + + webpack-virtual-modules@0.6.2: {} + + which@1.3.1: + dependencies: + isexe: 2.0.0 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + word-wrap@1.2.5: {} + + write-file-atomic@5.0.1: + dependencies: + imurmurhash: 0.1.4 + signal-exit: 4.1.0 + + ws@8.18.3: {} + + yallist@3.1.1: {} + + yocto-queue@0.1.0: {} + + zod@3.25.76: {} + + zod@4.1.11: {} + + zustand@5.0.8(@types/react@19.1.13)(react@19.1.1)(use-sync-external-store@1.5.0(react@19.1.1)): + optionalDependencies: + '@types/react': 19.1.13 + react: 19.1.1 + use-sync-external-store: 1.5.0(react@19.1.1) diff --git a/webnext/pnpm-workspace.yaml b/webnext/pnpm-workspace.yaml new file mode 100644 index 00000000..17a31e5c --- /dev/null +++ b/webnext/pnpm-workspace.yaml @@ -0,0 +1,5 @@ +onlyBuiltDependencies: + - '@parcel/watcher' + - '@swc/core' + - esbuild + - sharp diff --git a/webnext/project.inlang/project_id b/webnext/project.inlang/project_id new file mode 100644 index 00000000..bf8352df --- /dev/null +++ b/webnext/project.inlang/project_id @@ -0,0 +1 @@ +tfONT6HVsJdzBGusYZ \ No newline at end of file diff --git a/webnext/project.inlang/settings.json b/webnext/project.inlang/settings.json new file mode 100644 index 00000000..62d77adb --- /dev/null +++ b/webnext/project.inlang/settings.json @@ -0,0 +1,15 @@ +{ + "$schema": "https://inlang.com/schema/project-settings", + "baseLocale": "en", + "locales": [ + "en", + "de" + ], + "modules": [ + "https://cdn.jsdelivr.net/npm/@inlang/plugin-message-format@4/dist/index.js", + "https://cdn.jsdelivr.net/npm/@inlang/plugin-m-function-matcher@2/dist/index.js" + ], + "plugin.inlang.messageFormat": { + "pathPattern": "./messages/{locale}.json" + } +} \ No newline at end of file diff --git a/webnext/public/fonts/geist/Geist-Bold.woff2 b/webnext/public/fonts/geist/Geist-Bold.woff2 new file mode 100644 index 00000000..46f524f4 Binary files /dev/null and b/webnext/public/fonts/geist/Geist-Bold.woff2 differ diff --git a/webnext/public/fonts/geist/Geist-BoldItalic.woff2 b/webnext/public/fonts/geist/Geist-BoldItalic.woff2 new file mode 100644 index 00000000..240acb99 Binary files /dev/null and b/webnext/public/fonts/geist/Geist-BoldItalic.woff2 differ diff --git a/webnext/public/fonts/geist/Geist-Medium.woff2 b/webnext/public/fonts/geist/Geist-Medium.woff2 new file mode 100644 index 00000000..ef6dbb21 Binary files /dev/null and b/webnext/public/fonts/geist/Geist-Medium.woff2 differ diff --git a/webnext/public/fonts/geist/Geist-MediumItalic.woff2 b/webnext/public/fonts/geist/Geist-MediumItalic.woff2 new file mode 100644 index 00000000..344fedaf Binary files /dev/null and b/webnext/public/fonts/geist/Geist-MediumItalic.woff2 differ diff --git a/webnext/public/fonts/geist/Geist-Regular.woff2 b/webnext/public/fonts/geist/Geist-Regular.woff2 new file mode 100644 index 00000000..0db0f194 Binary files /dev/null and b/webnext/public/fonts/geist/Geist-Regular.woff2 differ diff --git a/webnext/public/fonts/geist/Geist-RegularItalic.woff2 b/webnext/public/fonts/geist/Geist-RegularItalic.woff2 new file mode 100644 index 00000000..33e9948b Binary files /dev/null and b/webnext/public/fonts/geist/Geist-RegularItalic.woff2 differ diff --git a/webnext/public/fonts/geist/Geist-SemiBold.woff2 b/webnext/public/fonts/geist/Geist-SemiBold.woff2 new file mode 100644 index 00000000..83845230 Binary files /dev/null and b/webnext/public/fonts/geist/Geist-SemiBold.woff2 differ diff --git a/webnext/public/fonts/geist/Geist-SemiBoldItalic.woff2 b/webnext/public/fonts/geist/Geist-SemiBoldItalic.woff2 new file mode 100644 index 00000000..2f53ced4 Binary files /dev/null and b/webnext/public/fonts/geist/Geist-SemiBoldItalic.woff2 differ diff --git a/webnext/public/fonts/source_code_pro/SourceCodePro-Regular.woff2 b/webnext/public/fonts/source_code_pro/SourceCodePro-Regular.woff2 new file mode 100644 index 00000000..40826f1a Binary files /dev/null and b/webnext/public/fonts/source_code_pro/SourceCodePro-Regular.woff2 differ diff --git a/webnext/src/app/App.tsx b/webnext/src/app/App.tsx new file mode 100644 index 00000000..ada329c7 --- /dev/null +++ b/webnext/src/app/App.tsx @@ -0,0 +1,12 @@ +import { QueryClientProvider } from '@tanstack/react-query'; +import { RouterProvider } from '@tanstack/react-router'; +import { queryClient } from './query'; +import { router } from './router'; + +export const App = () => { + return ( + + + + ); +}; diff --git a/webnext/src/app/query.ts b/webnext/src/app/query.ts new file mode 100644 index 00000000..23934e42 --- /dev/null +++ b/webnext/src/app/query.ts @@ -0,0 +1,29 @@ +import { MutationCache, QueryClient, type QueryKey } from '@tanstack/react-query'; + +type InvalidateMeta = { invalidate?: QueryKey[] }; + +let queryClient: QueryClient; + +const mutationCache = new MutationCache({ + onSuccess: async (_data, _variables, _context, mutation) => { + const keys = (mutation.meta as InvalidateMeta | undefined)?.invalidate; + if (!keys?.length) return; + await Promise.all( + keys.map((key) => queryClient.invalidateQueries({ queryKey: key })), + ); + }, +}); + +queryClient = new QueryClient({ + mutationCache, + defaultOptions: { + queries: { + staleTime: Infinity, + refetchOnWindowFocus: false, + refetchOnReconnect: false, + retry: false, + }, + }, +}); + +export { queryClient }; diff --git a/webnext/src/app/router.ts b/webnext/src/app/router.ts new file mode 100644 index 00000000..99936c4f --- /dev/null +++ b/webnext/src/app/router.ts @@ -0,0 +1,10 @@ +import { createRouter } from '@tanstack/react-router'; +import { routeTree } from '../routeTree.gen'; + +export const router = createRouter({ routeTree, defaultPreloadStaleTime: 0 }); + +declare module '@tanstack/react-router' { + interface Register { + router: typeof router; + } +} diff --git a/webnext/src/main.tsx b/webnext/src/main.tsx new file mode 100644 index 00000000..abcf38d5 --- /dev/null +++ b/webnext/src/main.tsx @@ -0,0 +1,27 @@ +import './shared/defguard-ui/scss/index.scss'; + +import { TanStackDevtools } from '@tanstack/react-devtools'; +import { ReactQueryDevtoolsPanel } from '@tanstack/react-query-devtools'; +import { TanStackRouterDevtoolsPanel } from '@tanstack/react-router-devtools'; +import { StrictMode } from 'react'; +import { createRoot } from 'react-dom/client'; +import { App } from './app/App'; + +// biome-ignore lint/style/noNonNullAssertion: always there +createRoot(document.getElementById('root')!).render( + + + , + }, + { + name: 'TanStack Query', + render: , + }, + ]} + /> + , +); diff --git a/webnext/src/pages/ClientDownload/ClientDownloadPage.tsx b/webnext/src/pages/ClientDownload/ClientDownloadPage.tsx new file mode 100644 index 00000000..37a88202 --- /dev/null +++ b/webnext/src/pages/ClientDownload/ClientDownloadPage.tsx @@ -0,0 +1,140 @@ +import './style.scss'; +import { useNavigate } from '@tanstack/react-router'; +import { m } from '../../paraglide/messages'; +import { Page } from '../../shared/components/Page/Page'; +import { PageNavigation } from '../../shared/components/PageNavigation/PageNavigation'; +import { EnrollmentStep } from '../../shared/components/Step/Step'; +import { Button } from '../../shared/defguard-ui/components/Button/Button'; +import { Icon } from '../../shared/defguard-ui/components/Icon'; +import type { IconKindValue } from '../../shared/defguard-ui/components/Icon/icon-types'; +import { SizedBox } from '../../shared/defguard-ui/components/SizedBox/SizedBox'; +import { ThemeSpacing } from '../../shared/defguard-ui/types'; +import androidIcon from './assets/android.png'; +import iosIcon from './assets/ios.png'; +import laptopIcon from './assets/laptop.png'; +import desktopIcon from './assets/pc-tower.png'; + +export const ClientDownloadPage = () => { + const navigate = useNavigate(); + + return ( + + +
+

{m.client_download_title()}

+

{m.client_download_subtitle()}

+
+ +
+
+

{m.client_download_label_desktop()}

+
+ + + +
+ +
+
+

{m.client_download_label_mobile()}

+
+ + +
+ { + navigate({ + to: '/', + replace: true, + }); + }} + nextText={m.controls_continue()} + onNext={() => { + console.log('todo'); + }} + /> +
+ ); +}; + +const Platform = ({ + buttonIconKind, + buttonText, + icon, + subtitle, + title, + testId, +}: { + icon: string; + title: string; + subtitle: string; + buttonText: string; + buttonIconKind: IconKindValue; + testId: string; +}) => { + return ( +
+ +
+

{title}

+

{subtitle}

+
+
+ ); +}; diff --git a/webnext/src/pages/ClientDownload/assets/android.png b/webnext/src/pages/ClientDownload/assets/android.png new file mode 100644 index 00000000..5e29acfc Binary files /dev/null and b/webnext/src/pages/ClientDownload/assets/android.png differ diff --git a/webnext/src/pages/ClientDownload/assets/ios.png b/webnext/src/pages/ClientDownload/assets/ios.png new file mode 100644 index 00000000..ab63bd09 Binary files /dev/null and b/webnext/src/pages/ClientDownload/assets/ios.png differ diff --git a/webnext/src/pages/ClientDownload/assets/laptop.png b/webnext/src/pages/ClientDownload/assets/laptop.png new file mode 100644 index 00000000..0831ff8b Binary files /dev/null and b/webnext/src/pages/ClientDownload/assets/laptop.png differ diff --git a/webnext/src/pages/ClientDownload/assets/pc-tower.png b/webnext/src/pages/ClientDownload/assets/pc-tower.png new file mode 100644 index 00000000..1d02efeb Binary files /dev/null and b/webnext/src/pages/ClientDownload/assets/pc-tower.png differ diff --git a/webnext/src/pages/ClientDownload/style.scss b/webnext/src/pages/ClientDownload/style.scss new file mode 100644 index 00000000..00425584 --- /dev/null +++ b/webnext/src/pages/ClientDownload/style.scss @@ -0,0 +1,57 @@ +#client-download-page .page-content { + .platforms { + width: 100%; + display: flex; + flex-flow: column; + row-gap: var(--spacing-md); + flex: none; + + & > .label { + display: flex; + flex-flow: row nowrap; + align-items: center; + justify-content: flex-start; + + p { + font: var(--t-body-sm-400); + color: var(--fg-muted); + } + } + + .platform { + width: 100%; + box-sizing: border-box; + border: 1px solid var(--border-default); + border-radius: var(--radius-lg); + display: grid; + grid-template-columns: 60px 1fr auto; + grid-template-rows: 1fr; + column-gap: var(--spacing-xl); + align-items: center; + padding: var(--spacing-md); + + & > img { + width: 60px; + height: 60px; + } + + & > .btn { + min-width: 212px; + } + + & > .description { + p { + &:nth-child(1) { + font: var(--t-body-primary-600); + padding-bottom: var(--spacing-xs); + } + + &:nth-child(2) { + font: var(--t-body-sm-400); + color: var(--fg-neutral); + } + } + } + } + } +} diff --git a/webnext/src/pages/Home/HomePage.tsx b/webnext/src/pages/Home/HomePage.tsx new file mode 100644 index 00000000..e03e12ea --- /dev/null +++ b/webnext/src/pages/Home/HomePage.tsx @@ -0,0 +1,28 @@ +import './style.scss'; + +import { m } from '../../paraglide/messages'; +import { Page } from '../../shared/components/Page/Page'; +import { SizedBox } from '../../shared/defguard-ui/components/SizedBox/SizedBox'; +import { ThemeSpacing } from '../../shared/defguard-ui/types'; +import { HomeChoice } from './components/HomeChoice'; + +const currentYear = new Date().getFullYear(); + +export const HomePage = () => { + return ( + +

{m.start_multi_title()}

+ +

{m.start_multi_subtitle()}

+ + +
+

{m.start_footer_contact()}

+ +

{m.start_footer_copyright({ currentYear: currentYear.toString() })}

+ +
+ +
+ ); +}; diff --git a/webnext/src/pages/Home/components/HomeChoice.tsx b/webnext/src/pages/Home/components/HomeChoice.tsx new file mode 100644 index 00000000..6ebfacbb --- /dev/null +++ b/webnext/src/pages/Home/components/HomeChoice.tsx @@ -0,0 +1,92 @@ +import './style.scss'; + +import { Link } from '@tanstack/react-router'; +import clsx from 'clsx'; +import { m } from '../../../paraglide/messages'; +import { Button } from '../../../shared/defguard-ui/components/Button/Button'; +import type { IconKindValue } from '../../../shared/defguard-ui/components/Icon/icon-types'; +import { SizedBox } from '../../../shared/defguard-ui/components/SizedBox/SizedBox'; +import { ThemeSpacing } from '../../../shared/defguard-ui/types'; +import enrollDefaultImage from './assets/enroll-default.png'; +import enrollHoverImage from './assets/enroll-hover.png'; +import passwordDefaultImage from './assets/password-default.png'; +import passwordHoverImage from './assets/password-hover.png'; + +export const HomeChoice = () => { + return ( +
+ {}} + /> + {}} + /> +
+ ); +}; + +type CardProps = { + img: 'enroll' | 'password'; + link: '/password' | '/download'; + buttonIcon: IconKindValue; + buttonText: string; + subtitle: string; + title: string; + card?: boolean; + onClick: () => void; +}; + +const Card = ({ + buttonIcon, + buttonText, + subtitle, + title, + onClick, + link, + img, +}: CardProps) => { + return ( +
+
+ {img === 'enroll' && ( + <> + + + + )} + {img === 'password' && ( + <> + + + + )} +
+ +

{title}

+ +

{subtitle}

+ + +
+ ); +}; diff --git a/webnext/src/pages/Home/components/assets/enroll-default.png b/webnext/src/pages/Home/components/assets/enroll-default.png new file mode 100644 index 00000000..5991582c Binary files /dev/null and b/webnext/src/pages/Home/components/assets/enroll-default.png differ diff --git a/webnext/src/pages/Home/components/assets/enroll-hover.png b/webnext/src/pages/Home/components/assets/enroll-hover.png new file mode 100644 index 00000000..5d61d661 Binary files /dev/null and b/webnext/src/pages/Home/components/assets/enroll-hover.png differ diff --git a/webnext/src/pages/Home/components/assets/password-default.png b/webnext/src/pages/Home/components/assets/password-default.png new file mode 100644 index 00000000..143c5472 Binary files /dev/null and b/webnext/src/pages/Home/components/assets/password-default.png differ diff --git a/webnext/src/pages/Home/components/assets/password-hover.png b/webnext/src/pages/Home/components/assets/password-hover.png new file mode 100644 index 00000000..1f335d16 Binary files /dev/null and b/webnext/src/pages/Home/components/assets/password-hover.png differ diff --git a/webnext/src/pages/Home/components/style.scss b/webnext/src/pages/Home/components/style.scss new file mode 100644 index 00000000..fac64f25 --- /dev/null +++ b/webnext/src/pages/Home/components/style.scss @@ -0,0 +1,65 @@ +#home-choice { + display: grid; + grid-template-columns: 1fr 1fr; + grid-template-rows: 1fr; + column-gap: var(--spacing-4xl); + + & > .choice { + --border-color: var(--border-default); + + box-sizing: border-box; + padding: var(--spacing-3xl); + border-radius: var(--radius-xl); + border: 1px solid var(--border-color); + transition-timing-function: ease-out; + transition-duration: 400ms; + transition-property: border-color; + + .title { + color: var(--fg-faded); + font: var(--t-titles-h3); + } + + .subtitle { + color: var(--fg-muted); + font: var(--t-body-primary-400); + } + + .image { + width: 100%; + max-width: 100%; + overflow: hidden; + display: grid; + grid-template-columns: 1fr; + grid-template-rows: 1fr; + user-select: none; + + img { + width: 100%; + height: unset; + grid-column: 1 / 2; + grid-row: 1; + opacity: 1; + transition-timing-function: ease-out; + transition-duration: 400ms; + transition-property: opacity; + + &:nth-child(2) { + opacity: 0; + } + } + } + + &:hover { + --border-color: var(--border-action); + + .image { + img { + &:nth-child(2) { + opacity: 1; + } + } + } + } + } +} diff --git a/webnext/src/pages/Home/style.scss b/webnext/src/pages/Home/style.scss new file mode 100644 index 00000000..168c3a09 --- /dev/null +++ b/webnext/src/pages/Home/style.scss @@ -0,0 +1,39 @@ +#home-page { + .page-content { + display: flex; + flex-flow: column; + align-items: center; + max-width: 100%; + overflow-x: hidden; + + h1 { + font-size: 52px; + font-weight: 500; + line-height: 44px; + text-align: center; + } + + & > .subtitle { + text-align: center; + } + + & > footer { + margin-top: auto; + padding-top: 50px; + + p { + text-align: center; + + &:nth-child(1) { + font: var(--t-body-sm-400); + color: var(--fg-neutral); + } + + &:nth-child(3) { + font: var(--t-body-xs-400); + color: var(--fg-muted); + } + } + } + } +} diff --git a/webnext/src/pages/PasswordForm/PasswordFormPage.tsx b/webnext/src/pages/PasswordForm/PasswordFormPage.tsx new file mode 100644 index 00000000..3faaa8af --- /dev/null +++ b/webnext/src/pages/PasswordForm/PasswordFormPage.tsx @@ -0,0 +1,245 @@ +import z from 'zod'; +import { m } from '../../paraglide/messages'; +import { Container } from '../../shared/components/Container/Container'; +import { Page } from '../../shared/components/Page/Page'; +import './style.scss'; +import { revalidateLogic, useStore } from '@tanstack/react-form'; +import { useNavigate } from '@tanstack/react-router'; +import clsx from 'clsx'; +import { useCallback } from 'react'; +import { Button } from '../../shared/defguard-ui/components/Button/Button'; +import { Icon } from '../../shared/defguard-ui/components/Icon'; +import type { IconKindValue } from '../../shared/defguard-ui/components/Icon/icon-types'; +import { SizedBox } from '../../shared/defguard-ui/components/SizedBox/SizedBox'; +import { useAppForm, withForm } from '../../shared/defguard-ui/form'; +import { ThemeSpacing } from '../../shared/defguard-ui/types'; + +const PasswordErrorCode = { + Number: 'password_form_check_number', + Special: 'password_form_check_special', + Lowercase: 'password_form_check_lowercase', + Uppercase: 'password_form_check_uppercase', + Minimum: 'password_form_check_minimum', +} as const; + +const errorCodes = Object.values(PasswordErrorCode); + +type PasswordErrorCodeValue = (typeof PasswordErrorCode)[keyof typeof PasswordErrorCode]; + +const errorIsCustomCode = (value: string): value is PasswordErrorCodeValue => { + return (errorCodes as readonly string[]).includes(value); +}; + +const mapPasswordFieldError = (errorValue: string): string => { + if (errorIsCustomCode(errorValue)) { + return m.password_form_special_error(); + } + return errorValue; +}; + +const hasNumber = /[0-9]/; + +const hasUppercase = /[A-Z]/; + +const hasLowercase = /[a-z]/; + +const hasSpecialChar = /[^a-zA-Z0-9]/; + +const formSchema = z + .object({ + password: z.string().trim().min(1, m.form_error_required()), + repeat: z.string().trim().min(1, m.form_error_required()), + }) + .superRefine(({ password, repeat }, ctx) => { + if (password.length < 8) { + ctx.addIssue({ + message: PasswordErrorCode.Minimum, + code: 'custom', + path: ['password'], + continue: true, + }); + } + if (!hasNumber.test(password)) { + ctx.addIssue({ + message: PasswordErrorCode.Number, + code: 'custom', + path: ['password'], + continue: true, + }); + } + if (!hasUppercase.test(password)) { + ctx.addIssue({ + message: PasswordErrorCode.Uppercase, + code: 'custom', + path: ['password'], + continue: true, + }); + } + if (!hasLowercase.test(password)) { + ctx.addIssue({ + message: PasswordErrorCode.Lowercase, + code: 'custom', + continue: true, + path: ['password'], + }); + } + if (!hasSpecialChar.test(password)) { + ctx.addIssue({ + message: PasswordErrorCode.Special, + code: 'custom', + continue: true, + path: ['password'], + }); + } + if (repeat.length) { + ctx.addIssue({ + message: m.password_form_check_repeat_match(), + code: 'custom', + path: ['repeat'], + continue: true, + }); + } + }); + +type FormFields = z.infer; + +const defaultFormValues: FormFields = { + password: '', + repeat: '', +}; + +export const PasswordFormPage = () => { + const navigate = useNavigate(); + + const form = useAppForm({ + defaultValues: defaultFormValues, + validationLogic: revalidateLogic({ + mode: 'change', + modeAfterSubmission: 'change', + }), + validators: { + onDynamic: formSchema, + }, + onSubmit: (values) => { + console.table(values); + navigate({ + to: '/password/form/finish', + replace: true, + }); + }, + }); + + return ( + +
+

{m.password_form_title()}

+

{m.password_form_subtitle()}

+
+ + +
{ + e.preventDefault(); + e.stopPropagation(); + }} + > + + + {(field) => ( + + )} + + + {(field) => ( + + )} + + + + ); +}; diff --git a/webnext/src/shared/defguard-ui/components/Button/style.scss b/webnext/src/shared/defguard-ui/components/Button/style.scss new file mode 100644 index 00000000..a5c7fcb3 --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Button/style.scss @@ -0,0 +1,192 @@ +.btn { + --btn-font: var(--t-button-label-primary); + --btn-size: var(--button-size-primary); + --border-color: transparent; + --bg-color: transparent; + --text-color: var(--fg-default); + --loader-bg: transparent; + --loader-track: transparent; + --loader-part: transparent; + + height: var(--btn-size); + border: none; + box-sizing: border-box; + border-radius: var(--button-border-radius-primary); + background: var(--bg-color); + box-shadow: 0 0 0 1px var(--border-color); + color: var(--text-color); + min-height: var(--button-size-primary); + padding: var(--spacing-sm) var(--spacing-lg); + background-clip: padding-box; + position: relative; + user-select: none; + display: grid; + grid-template-columns: auto; + grid-template-rows: 1fr; + align-items: center; + column-gap: var(--button-icons-spacing); + text-decoration: none !important; + + @include animate(background-color, border-color, opacity, box-shadow); + + &:not(.disabled, .loading) { + cursor: pointer; + } + + &.disabled { + cursor: not-allowed; + pointer-events: none; + } + + .icon { + svg { + path { + fill: var(--loader-part); + + @include animate(fill); + } + } + } + + .text { + font: var(--btn-font); + color: inherit; + + @include animate(color); + } + + &.icon-left { + grid-template-columns: 20px auto; + } + + &.icon-right { + grid-template-columns: auto 20px; + } + + &.icon-both { + grid-template-columns: 20px auto 20px; + } + + &.size-primary { + --btn-size: var(--button-size-primary); + } + + &.size-big { + --btn-font: var(--t-button-label-lg); + --btn-size: var(--button-size-lg); + } + + &.variant-primary { + --bg-color: var(--fg-action); + --border-color: var(--fg-action); + --text-color: var(--fg-white); + --loader-track: var(--c-white-50); + --loader-part: var(--c-white); + --loader-bg: var(--bg-action-emphasis); + + &:hover { + --bg-color: var(--bg-action-emphasis); + --border-color: var(--bg-color); + } + + &.disabled { + --bg-color: var(--fg-blue-transparent-2); + --border-color: var(--bg-color); + --text-color: var(--fg-action-muted); + } + } + + &.variant-secondary { + --bg-color: var(--bg-emphasis); + --border-color: var(--bg-color); + --text-color: var(--fg-default); + --loader-track: var(--c-neutral-400); + --loader-part: var(--c-neutral-800); + --loader-bg: var(--bg-active); + + &:hover { + --bg-color: var(--bg-active); + } + + &.disabled { + --bg-color: var(--bg-disabled); + --text-color: var(--fg-disabled); + } + } + + &.variant-critical { + --bg-color: var(--bg-critical); + --border-color: var(--bg-color); + --text-color: var(--fg-white); + --loader-track: var(--c-white-50); + --loader-part: var(--c-white); + --loader-bg: var(--bg-critical-faded); + + &:hover { + --bg-color: var(--bg-critical-faded); + } + + &.disabled { + --bg-color: var(--bg-critical-muted); + --text-color: var(--fg-white-transparent); + } + } + + &.variant-outlined { + --bg-color: transparent; + --border-color: var(--border-action); + --loader-track: var(--c-blue-200); + --loader-part: var(--c-blue-500); + --loader-bg: var(--bg-action-muted); + --text-color: var(--fg-action); + + &:hover { + --bg-color: var(--bg-action-muted); + --border-color: var(--border-action); + } + + &.disabled { + --bg-color: var(--fg-blue-transparent-2); + --border-color: var(--bg-color); + --text-color: var(--fg-action-muted); + } + } + + // since box-shadow adds on top of element it's needed to be set with loader overlay + &:not(.disabled).loading { + --border-color: var(--loader-bg); + } + + .loader-overlay { + background-color: var(--loader-bg); + border: none; + border-radius: inherit; + position: absolute; + inset: 0; + width: 100%; + height: 100%; + display: flex; + flex-flow: row; + align-items: center; + justify-content: center; + + svg { + & > path { + stroke: var(--loader-part); + fill: none; + + @include animate(stroke); + } + + & > circle { + stroke: var(--loader-track); + + @include animate(stroke); + } + } + } +} + +a:has(.btn) { + text-decoration: none; +} diff --git a/webnext/src/shared/defguard-ui/components/Button/types.ts b/webnext/src/shared/defguard-ui/components/Button/types.ts new file mode 100644 index 00000000..6f00702e --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Button/types.ts @@ -0,0 +1,22 @@ +import type { ButtonHTMLAttributes, Ref } from 'react'; +import type { IconKindValue } from '../Icon/icon-types'; + +type DefaultButtonProps = ButtonHTMLAttributes; + +type ButtonVariant = 'primary' | 'secondary' | 'critical' | 'outlined'; + +type ButtonSize = 'primary' | 'big'; + +export type ButtonProps = { + text: string; + variant?: ButtonVariant; + size?: ButtonSize; + type?: DefaultButtonProps['type']; + iconLeft?: IconKindValue; + iconRight?: IconKindValue; + testId?: string; + disabled?: boolean; + loading?: boolean; + onClick?: () => void; + ref?: Ref; +}; diff --git a/webnext/src/shared/defguard-ui/components/Checkbox/Checkbox.tsx b/webnext/src/shared/defguard-ui/components/Checkbox/Checkbox.tsx new file mode 100644 index 00000000..72be6a26 --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Checkbox/Checkbox.tsx @@ -0,0 +1,245 @@ +import clsx from 'clsx'; +import './style.scss'; +import { useHover } from '@uidotdev/usehooks'; +import { useId, useMemo } from 'react'; +import { isPresent } from '../../utils/isPresent'; + +type Props = { + canError?: boolean; + active?: boolean; + error?: string; + disabled?: boolean; + text?: string; + onClick?: () => void; +}; + +// todo: Include error text when it will be needed +export const Checkbox = ({ + text, + error, + canError = false, + active = false, + disabled = false, + onClick, +}: Props) => { + const hasError = isPresent(error); + + const [ref, hover] = useHover(); + + const ContentRender = useMemo(() => { + if (disabled) { + if (!active) return StateDefaultDisabled; + return StateSelectedDisabled; + } + if (active) { + return StateSelected; + } + if (hasError) { + return StateError; + } + if (hover) { + return StateHover; + } + return StateDefault; + }, [hover, active, hasError, disabled]); + + return ( +
+ + {isPresent(text) && {text}} +
+ ); +}; + +const StateDefault = () => { + const id = useId(); + return ( + + + + + + + + ); +}; +const StateDefaultDisabled = () => { + return ( + + + + + ); +}; +const StateHover = () => { + return ( + + + + + + + + ); +}; +const StateSelected = () => { + return ( + + + + + ); +}; +const StateSelectedDisabled = () => { + return ( + + + + + ); +}; +// const StateMixed = () => { +// return ( +// +// +// +// +// ); +// }; +// const StateMixedDisabled = () => { +// return ( +// +// +// +// +// ); +// }; +const StateError = () => { + return ( + + + + + + + + ); +}; diff --git a/webnext/src/shared/defguard-ui/components/Checkbox/style.scss b/webnext/src/shared/defguard-ui/components/Checkbox/style.scss new file mode 100644 index 00000000..5830091b --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Checkbox/style.scss @@ -0,0 +1,29 @@ +.checkbox { + display: inline-block; + user-select: none; + + &:not(.disabled) { + cursor: pointer; + } + + .can-error { + padding-bottom: var(--form-field-error-space); + } + + &.disabled { + pointer-events: none; + cursor: not-allowed; + } + + &.text { + display: grid; + grid-template-columns: 24px auto; + grid-template-rows: 1fr; + column-gap: var(--spacing-sm); + align-items: center; + } + + span { + font: var(--t-body-sm-400); + } +} diff --git a/webnext/src/shared/defguard-ui/components/CounterLabel/CounterLabel.tsx b/webnext/src/shared/defguard-ui/components/CounterLabel/CounterLabel.tsx new file mode 100644 index 00000000..5f22bc2f --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/CounterLabel/CounterLabel.tsx @@ -0,0 +1,27 @@ +import clsx from 'clsx'; +import './style.scss'; +import type { Ref } from 'react'; + +type Variant = 'neutral' | 'default' | 'action' | 'critical' | 'warning'; + +type Props = { + ref?: Ref; + className?: string; + testId?: string; + id?: string; + value?: number; + variant?: Variant; +}; + +export const CounterLabel = ({ ref, className, id, testId, value, variant }: Props) => { + return ( +
+ {value ?? 0} +
+ ); +}; diff --git a/webnext/src/shared/defguard-ui/components/CounterLabel/style.scss b/webnext/src/shared/defguard-ui/components/CounterLabel/style.scss new file mode 100644 index 00000000..6864cf14 --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/CounterLabel/style.scss @@ -0,0 +1,46 @@ +.counter-label { + --color: var(--fg-white); + --bg-color: transparent; + + color: var(--color); + background-color: var(--bg-color); + border-radius: 8px; + user-select: none; + pointer-events: none; + box-sizing: border-box; + padding: 0 var(--spacing-xs); + min-width: 20px; + display: inline-flex; + align-items: center; + justify-content: center; + flex-flow: row; + flex: none; + height: auto; + + &.variant-neutral { + --color: var(--fg-neutral); + --bg-color: var(--bg-emphasis); + } + + &.variant-action { + --bg-color: var(--bg-action); + } + + &.variant-critical { + --bg-color: var(--bg-critical); + } + + &.variant-warning { + --bg-color: var(--bg-warning); + } + + &.variant-default { + --bg-color: var(--bg-dark); + } + + span { + font: var(--t-body-xxs-600); + color: inherit; + text-align: center; + } +} diff --git a/webnext/src/shared/defguard-ui/components/Divider/Divider.tsx b/webnext/src/shared/defguard-ui/components/Divider/Divider.tsx new file mode 100644 index 00000000..22123376 --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Divider/Divider.tsx @@ -0,0 +1,39 @@ +import './style.scss'; +import clsx from 'clsx'; +import type { OrientationValue } from '../../types'; +import { isPresent } from '../../utils/isPresent'; + +type Props = { + text?: string; + orientation?: OrientationValue; +}; + +export const Divider = ({ text, orientation }: Props) => { + const textPresent = isPresent(text) && text.length > 0; + + return ( +
+ {orientation === 'horizontal' && ( + <> + {textPresent && ( + <> + + {text} + + + )} + {!textPresent && } + + )} + {orientation === 'vertical' && } +
+ ); +}; + +const Line = () => { + return
; +}; diff --git a/webnext/src/shared/defguard-ui/components/Divider/style.scss b/webnext/src/shared/defguard-ui/components/Divider/style.scss new file mode 100644 index 00000000..a692a9ee --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Divider/style.scss @@ -0,0 +1,53 @@ +.divider { + --divider-line-size: 1px; + --divider-color: var(--bg-active); + + user-select: none; + + .line { + content: ' '; + display: block; + background-color: var(--divider-color); + border-radius: 0; + margin: 0; + padding: 0; + } + + &.vertical { + display: inline-block; + height: 10px; + + .line { + height: inherit; + width: var(--divider-line-size); + } + } + + &.horizontal { + width: 100%; + + .line { + width: 100%; + height: var(--divider-line-size); + } + } + + &.horizontal.text { + --divider-color: var(--bg-action-faded); + + display: grid; + grid-template-columns: 1fr auto 1fr; + grid-template-rows: 1fr; + column-gap: var(--spacing-lg); + align-items: center; + + .line { + width: 100%; + } + } + + span { + font: var(--t-body-sm-400); + color: var(--fg-action); + } +} diff --git a/webnext/src/shared/defguard-ui/components/EmptyState/EmptyState.tsx b/webnext/src/shared/defguard-ui/components/EmptyState/EmptyState.tsx new file mode 100644 index 00000000..7c2be3e4 --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/EmptyState/EmptyState.tsx @@ -0,0 +1,74 @@ +import type { Ref } from 'react'; +import './style.scss'; +import clsx from 'clsx'; +import { ThemeSpacing } from '../../types'; +import { isPresent } from '../../utils/isPresent'; +import { Button } from '../Button/Button'; +import type { ButtonProps } from '../Button/types'; +import { Icon } from '../Icon'; +import type { IconKindValue } from '../Icon/icon-types'; +import { SizedBox } from '../SizedBox/SizedBox'; + +type Props = { + ref?: Ref; + title?: string; + subtitle?: string; + icon?: IconKindValue; + className?: string; + testId?: string; + id?: string; + primaryAction?: ButtonProps; + secondaryAction?: () => void; + secondaryActionText?: string; +}; + +//TODO: icon is incompatible, remove it when this will be needed +export const EmptyState = ({ + ref, + icon, + primaryAction, + secondaryAction, + secondaryActionText, + subtitle, + title, + className, + id, + testId, +}: Props) => { + return ( +
+ {isPresent(icon) && ( + <> +
+ +
+ + + )} + {isPresent(title) && ( + <> +

{title}

+ + + )} + {isPresent(subtitle) &&

{subtitle}

} + + {isPresent(primaryAction) && ( + <> + + )} +
+ ); +}; diff --git a/webnext/src/shared/defguard-ui/components/EmptyState/style.scss b/webnext/src/shared/defguard-ui/components/EmptyState/style.scss new file mode 100644 index 00000000..90a3b596 --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/EmptyState/style.scss @@ -0,0 +1,46 @@ +.empty-state { + display: flex; + flex-flow: column; + flex: none; + align-items: center; + justify-content: flex-start; + height: auto; + user-select: none; + + & > p, + & > span { + text-align: center; + } + + .title { + color: var(--fg-muted); + font: var(--t-body-primary-500); + } + + .subtitle { + color: var(--fg-muted); + font: var(--t-body-sm-400); + } + + .secondary-action { + background-color: transparent; + text-align: center; + color: var(--fg-action); + border: none; + padding: 0; + margin: 0; + } + + .empty-icon { + width: 40px; + height: 40px; + display: flex; + flex-flow: row; + align-items: center; + justify-content: center; + flex: none; + padding: 4px; + border: 1px dashed var(--border-faded); + border-radius: 100px; + } +} diff --git a/webnext/src/shared/defguard-ui/components/FieldError/FieldError.tsx b/webnext/src/shared/defguard-ui/components/FieldError/FieldError.tsx new file mode 100644 index 00000000..ef70d77f --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/FieldError/FieldError.tsx @@ -0,0 +1,35 @@ +import { motion } from 'motion/react'; +import './style.scss'; +import { motionTransitionStandard } from '../../../consts'; +import { isPresent } from '../../utils/isPresent'; + +type Props = { + error?: string; +}; + +export const FieldError = ({ error }: Props) => { + return ( + <> + {isPresent(error) && error.length > 0 && ( + + {error} + + )} + + ); +}; diff --git a/webnext/src/shared/defguard-ui/components/FieldError/style.scss b/webnext/src/shared/defguard-ui/components/FieldError/style.scss new file mode 100644 index 00000000..49d746b8 --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/FieldError/style.scss @@ -0,0 +1,6 @@ +.field-error { + padding-top: 8px; + font: var(--t-input-error-message); + color: var(--fg-critical); + user-select: none; +} diff --git a/webnext/src/shared/defguard-ui/components/FieldLabel/FieldLabel.tsx b/webnext/src/shared/defguard-ui/components/FieldLabel/FieldLabel.tsx new file mode 100644 index 00000000..0146b230 --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/FieldLabel/FieldLabel.tsx @@ -0,0 +1,39 @@ +import './style.scss'; + +import clsx from 'clsx'; +import type { Ref } from 'react'; + +type Props = { + ref?: Ref; + htmlFor?: string; + text: string; + required?: boolean; +}; + +export const FieldLabel = ({ text, htmlFor, ref, required }: Props) => { + return ( + + ); +}; diff --git a/webnext/src/shared/defguard-ui/components/FieldLabel/style.scss b/webnext/src/shared/defguard-ui/components/FieldLabel/style.scss new file mode 100644 index 00000000..a20369d6 --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/FieldLabel/style.scss @@ -0,0 +1,17 @@ +.field-label { + position: relative; + padding-bottom: var(--input-spacing-xs); + display: block; + font: var(--t-input-title); + color: var(--fg-neutral); + + svg { + position: absolute; + left: 0; + top: 3.5px; + } + + &.required { + padding-left: 8px; + } +} diff --git a/webnext/src/shared/defguard-ui/components/Icon/Icon.tsx b/webnext/src/shared/defguard-ui/components/Icon/Icon.tsx new file mode 100644 index 00000000..53ea8180 --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Icon/Icon.tsx @@ -0,0 +1,127 @@ +import { type CSSProperties, type Ref, useMemo } from 'react'; +import type { IconKindValue } from './icon-types'; +import './style.scss'; +import type { Direction } from '../../types'; +import { IconAndroid } from './icons/IconAndroid'; +import { IconApple } from './icons/IconApple'; +import { IconAppStore } from './icons/IconAppstore'; +import { IconArrowBig } from './icons/IconArrowBig'; +import { IconArrowSmall } from './icons/IconArrowSmall'; +import { IconCheckCircle } from './icons/IconCheckCircle'; +import { IconCheckFilled } from './icons/IconCheckFilled'; +import { IconDesktop } from './icons/IconDesktop'; +import { IconEmptyPoint } from './icons/IconEmptyPoint'; +import { IconLinux } from './icons/IconLinux'; +import { IconLoader } from './icons/IconLoader'; +import { IconLockOpen } from './icons/IconLock'; +import { IconMobile } from './icons/IconMobile'; +import { IconPlus } from './icons/IconPlus'; +import { IconStatusSimple } from './icons/IconStatusSimple'; +import { IconWindows } from './icons/IconWindows'; + +type Props = { + icon: T; + size?: number; + rotationDirection?: Direction; + customRotation?: number; + ref?: Ref; +}; + +type RotationMap = Record; + +const mapRotation = (kind: IconKindValue, direction: Direction): number => { + switch (kind) { + case 'arrow-small': + case 'arrow-big': { + const map: RotationMap = { + down: 90, + right: 0, + up: -90, + left: 180, + }; + return map[direction]; + } + } + console.error(`Unimplemented rotation mapping for icon kind of ${kind}`); + // safe return for unimplemented + return 0; +}; + +// Color should be set by css bcs some icons have different structures like 'loader' +export const Icon = ({ + icon: iconKind, + rotationDirection, + customRotation, + ref, + size = 20, +}: Props) => { + const IconToRender = useMemo(() => { + switch (iconKind) { + case 'arrow-big': + return IconArrowBig; + case 'arrow-small': + return IconArrowSmall; + case 'loader': + return IconLoader; + case 'plus': + return IconPlus; + case 'status-simple': + return IconStatusSimple; + case 'lock-open': + return IconLockOpen; + case 'check-circle': + return IconCheckCircle; + case 'check-filled': + return IconCheckFilled; + case 'empty-point': + return IconEmptyPoint; + case 'desktop': + return IconDesktop; + case 'mobile': + return IconMobile; + case 'windows': + return IconWindows; + case 'linux': + return IconLinux; + case 'app-store': + return IconAppStore; + case 'apple': + return IconApple; + case 'android': + return IconAndroid; + default: + throw Error('Unimplemented icon kind'); + } + }, [iconKind]); + + const getStyle = useMemo((): CSSProperties => { + const styles: CSSProperties = {}; + const transform: string[] = []; + // kind specific configurations + switch (iconKind) { + case 'arrow-big': + case 'arrow-small': + if (rotationDirection) { + transform.push(`rotate(${mapRotation(iconKind, rotationDirection)}deg)`); + } + break; + } + if (customRotation && !rotationDirection) { + transform.push(`rotate(${customRotation}deg)`); + } + if (size) { + styles.width = size; + styles.height = size; + } + if (transform.length) { + styles.transform = transform.join(' '); + } + return styles; + }, [iconKind, size, rotationDirection, customRotation]); + + return ( +
+ +
+ ); +}; diff --git a/webnext/src/shared/defguard-ui/components/Icon/icon-types.ts b/webnext/src/shared/defguard-ui/components/Icon/icon-types.ts new file mode 100644 index 00000000..eacdc835 --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Icon/icon-types.ts @@ -0,0 +1,91 @@ +export const IconKind = { + ArrowBig: 'arrow-big', + ArrowSmall: 'arrow-small', + PlusCircle: 'plus-circle', + MinusCircle: 'minus-circle', + Edit: 'edit', + Show: 'show', + Analytics: 'analytics', + Search: 'search', + Delete: 'delete', + Transactions: 'transactions', + Copy: 'copy', + Settings: 'settings', + Close: 'close', + Plus: 'plus', + Support: 'support', + Menu: 'menu', + Check: 'check', + Date: 'date', + CreditCard: 'credit-card', + Archive: 'archive', + PieChart: 'pie-chart', + Notification: 'notification', + Globe: 'globe', + Groups: 'groups', + OpenInNewWindow: 'open-in-new-window', + Users: 'users', + Mail: 'mail', + Filter: 'filter', + User: 'user', + LockOpen: 'lock-open', + Servers: 'servers', + Protection: 'protection', + NavigationCollapse: 'navigation-collapse', + NavigationUncollapse: 'navigation-uncollapse', + Devices: 'devices', + Logout: 'logout', + YubiKeys: 'yubi-keys', + OpenId: 'openid', + Webhooks: 'webhooks', + Help: 'help', + ActivityNotes: 'activity-notes', + Activity: 'activity', + AccessSettings: 'access-settings', + Profile: 'profile', + Attension: 'attension', + Warning: 'warning', + Download: 'download', + Code: 'code', + Deploy: 'deploy', + Expand: 'expand', + Collapse: 'collapse', + CheckCircle: 'check-circle', + Location: 'location', + InfoOutlined: 'info-outlined', + InfoFilled: 'info-filled', + LocationPreview: 'location-preview', + AddUser: 'add-user', + QR: 'qr', + File: 'file', + LocationTracking: 'location-tracking', + Config: 'config', + Gift: 'gift', + Hamburger: 'hamburger', + Sort: 'sort', + Gateway: 'gateway', + EmptyPoint: 'empty-point', + DevicesActive: 'devices-active', + UserActive: 'user-active', + Windows: 'windows', + AppStore: 'app-store', + Apple: 'apple', + Desktop: 'desktop', + Mobile: 'mobile', + Android: 'android', + Pdf: 'pdf', + Linux: 'linux', + Clear: 'clear', + CheckFilled: 'check-filled', + Enter: 'enter', + Github: 'github', + OneTimePassword: 'one-time-password', + Loader: 'loader', + ManageKeys: 'manage-keys', + StatusSimple: 'status-simple', + StatusAttention: 'status-attention', + StatusAvailable: 'status-available', + StatusImportant: 'status-important', +} as const; + +export type IconKindValue = (typeof IconKind)[keyof typeof IconKind]; diff --git a/webnext/src/shared/defguard-ui/components/Icon/icons/IconAndroid.tsx b/webnext/src/shared/defguard-ui/components/Icon/icons/IconAndroid.tsx new file mode 100644 index 00000000..bf37eaa5 --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Icon/icons/IconAndroid.tsx @@ -0,0 +1,31 @@ +import type { SVGProps } from 'react'; + +export const IconAndroid = (props: SVGProps) => { + return ( + + + + + + + ); +}; diff --git a/webnext/src/shared/defguard-ui/components/Icon/icons/IconApple.tsx b/webnext/src/shared/defguard-ui/components/Icon/icons/IconApple.tsx new file mode 100644 index 00000000..d0bb87ae --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Icon/icons/IconApple.tsx @@ -0,0 +1,23 @@ +import type { SVGProps } from 'react'; + +export const IconApple = (props: SVGProps) => { + return ( + + + + + ); +}; diff --git a/webnext/src/shared/defguard-ui/components/Icon/icons/IconAppstore.tsx b/webnext/src/shared/defguard-ui/components/Icon/icons/IconAppstore.tsx new file mode 100644 index 00000000..1f75861a --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Icon/icons/IconAppstore.tsx @@ -0,0 +1,47 @@ +import type { SVGProps } from 'react'; + +export const IconAppStore = (props: SVGProps) => { + return ( + + + + + + + + + + + ); +}; diff --git a/webnext/src/shared/defguard-ui/components/Icon/icons/IconArrowBig.tsx b/webnext/src/shared/defguard-ui/components/Icon/icons/IconArrowBig.tsx new file mode 100644 index 00000000..3d80a851 --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Icon/icons/IconArrowBig.tsx @@ -0,0 +1,16 @@ +import type { SVGProps } from 'react'; + +export const IconArrowBig = (props: SVGProps) => { + return ( + + + + ); +}; diff --git a/webnext/src/shared/defguard-ui/components/Icon/icons/IconArrowSmall.tsx b/webnext/src/shared/defguard-ui/components/Icon/icons/IconArrowSmall.tsx new file mode 100644 index 00000000..cb5ac0c4 --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Icon/icons/IconArrowSmall.tsx @@ -0,0 +1,20 @@ +import type { SVGProps } from 'react'; + +export const IconArrowSmall = (props: SVGProps) => { + return ( + + + + ); +}; diff --git a/webnext/src/shared/defguard-ui/components/Icon/icons/IconCheckCircle.tsx b/webnext/src/shared/defguard-ui/components/Icon/icons/IconCheckCircle.tsx new file mode 100644 index 00000000..9a94792c --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Icon/icons/IconCheckCircle.tsx @@ -0,0 +1,19 @@ +import type { SVGProps } from 'react'; + +export const IconCheckCircle = (props: SVGProps) => { + return ( + + + + ); +}; diff --git a/webnext/src/shared/defguard-ui/components/Icon/icons/IconCheckFilled.tsx b/webnext/src/shared/defguard-ui/components/Icon/icons/IconCheckFilled.tsx new file mode 100644 index 00000000..0fc9b090 --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Icon/icons/IconCheckFilled.tsx @@ -0,0 +1,19 @@ +import type { SVGProps } from 'react'; + +export const IconCheckFilled = (props: SVGProps) => { + return ( + + + + ); +}; diff --git a/webnext/src/shared/defguard-ui/components/Icon/icons/IconDesktop.tsx b/webnext/src/shared/defguard-ui/components/Icon/icons/IconDesktop.tsx new file mode 100644 index 00000000..335b047c --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Icon/icons/IconDesktop.tsx @@ -0,0 +1,19 @@ +import type { SVGProps } from 'react'; + +export const IconDesktop = (props: SVGProps) => { + return ( + + + + ); +}; diff --git a/webnext/src/shared/defguard-ui/components/Icon/icons/IconEmptyPoint.tsx b/webnext/src/shared/defguard-ui/components/Icon/icons/IconEmptyPoint.tsx new file mode 100644 index 00000000..a5b5323b --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Icon/icons/IconEmptyPoint.tsx @@ -0,0 +1,19 @@ +import type { SVGProps } from 'react'; + +export const IconEmptyPoint = (props: SVGProps) => { + return ( + + + + ); +}; diff --git a/webnext/src/shared/defguard-ui/components/Icon/icons/IconLinux.tsx b/webnext/src/shared/defguard-ui/components/Icon/icons/IconLinux.tsx new file mode 100644 index 00000000..6cf5276a --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Icon/icons/IconLinux.tsx @@ -0,0 +1,21 @@ +import type { SVGProps } from 'react'; + +export const IconLinux = (props: SVGProps) => { + return ( + + + + ); +}; diff --git a/webnext/src/shared/defguard-ui/components/Icon/icons/IconLoader.tsx b/webnext/src/shared/defguard-ui/components/Icon/icons/IconLoader.tsx new file mode 100644 index 00000000..117773e4 --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Icon/icons/IconLoader.tsx @@ -0,0 +1,17 @@ +export const IconLoader = () => { + return ( + + + + + ); +}; diff --git a/webnext/src/shared/defguard-ui/components/Icon/icons/IconLock.tsx b/webnext/src/shared/defguard-ui/components/Icon/icons/IconLock.tsx new file mode 100644 index 00000000..9bd4ef7f --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Icon/icons/IconLock.tsx @@ -0,0 +1,16 @@ +export const IconLockOpen = () => { + return ( + + + + ); +}; diff --git a/webnext/src/shared/defguard-ui/components/Icon/icons/IconMobile.tsx b/webnext/src/shared/defguard-ui/components/Icon/icons/IconMobile.tsx new file mode 100644 index 00000000..a9a3c591 --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Icon/icons/IconMobile.tsx @@ -0,0 +1,19 @@ +import type { SVGProps } from 'react'; + +export const IconMobile = (props: SVGProps) => { + return ( + + + + ); +}; diff --git a/webnext/src/shared/defguard-ui/components/Icon/icons/IconPlus.tsx b/webnext/src/shared/defguard-ui/components/Icon/icons/IconPlus.tsx new file mode 100644 index 00000000..b375db67 --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Icon/icons/IconPlus.tsx @@ -0,0 +1,16 @@ +import type { SVGProps } from 'react'; + +export const IconPlus = (props: SVGProps) => { + return ( + + + + ); +}; diff --git a/webnext/src/shared/defguard-ui/components/Icon/icons/IconStatusSimple.tsx b/webnext/src/shared/defguard-ui/components/Icon/icons/IconStatusSimple.tsx new file mode 100644 index 00000000..8ca913e8 --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Icon/icons/IconStatusSimple.tsx @@ -0,0 +1,16 @@ +import type { SVGProps } from 'react'; + +export const IconStatusSimple = (props: SVGProps) => { + return ( + + + + ); +}; diff --git a/webnext/src/shared/defguard-ui/components/Icon/icons/IconWindows.tsx b/webnext/src/shared/defguard-ui/components/Icon/icons/IconWindows.tsx new file mode 100644 index 00000000..773876cc --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Icon/icons/IconWindows.tsx @@ -0,0 +1,19 @@ +import type { SVGProps } from 'react'; + +export const IconWindows = (props: SVGProps) => { + return ( + + + + ); +}; diff --git a/webnext/src/shared/defguard-ui/components/Icon/index.ts b/webnext/src/shared/defguard-ui/components/Icon/index.ts new file mode 100644 index 00000000..c15633da --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Icon/index.ts @@ -0,0 +1,2 @@ +export { Icon } from './Icon'; +export type { IconKind } from './icon-types'; diff --git a/webnext/src/shared/defguard-ui/components/Icon/style.scss b/webnext/src/shared/defguard-ui/components/Icon/style.scss new file mode 100644 index 00000000..b73c09cc --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Icon/style.scss @@ -0,0 +1,21 @@ +.icon { + display: inline-block; + overflow: hidden; + user-select: none; + + svg { + width: inherit; + height: inherit; + transition-property: transform; + + @include animate; + + path { + @include animate(fill); + } + + circle { + @include animate(stroke); + } + } +} diff --git a/webnext/src/shared/defguard-ui/components/IconButton/IconButton.tsx b/webnext/src/shared/defguard-ui/components/IconButton/IconButton.tsx new file mode 100644 index 00000000..a0976442 --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/IconButton/IconButton.tsx @@ -0,0 +1,30 @@ +import './style.scss'; +import clsx from 'clsx'; +import type { Ref } from 'react'; +import { Icon } from '../Icon/Icon'; +import type { IconKindValue } from '../Icon/icon-types'; + +type Props = { + icon: IconKindValue; + disabled?: boolean; + ref?: Ref; + onClick?: () => void; +}; + +export const IconButton = ({ icon, ref, disabled = false, onClick }: Props) => { + return ( +
{ + if (!disabled) { + onClick?.(); + } + }} + > + +
+ ); +}; diff --git a/webnext/src/shared/defguard-ui/components/IconButton/style.scss b/webnext/src/shared/defguard-ui/components/IconButton/style.scss new file mode 100644 index 00000000..d2197d8b --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/IconButton/style.scss @@ -0,0 +1,33 @@ +.icon-button { + --icon-button-icon-color: var(--fg-neutral); + + background-color: transparent; + border-radius: var(--button-border-radius-sm); + height: var(--button-size-primary); + width: var(--button-size-primary); + display: inline-flex; + flex-flow: column; + align-items: center; + justify-content: center; + + @include animate(background-color); + + &:not(.disabled) { + cursor: pointer; + + &:hover { + background-color: var(--bg-emphasis); + } + } + + &.disabled { + cursor: not-allowed; + --icon-button-icon-color: var(--fg-disabled); + } + + & > .icon svg path { + fill: var(--icon-button-icon-color); + + @include animate(fill); + } +} diff --git a/webnext/src/shared/defguard-ui/components/Input/Input.tsx b/webnext/src/shared/defguard-ui/components/Input/Input.tsx new file mode 100644 index 00000000..c24d6a57 --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Input/Input.tsx @@ -0,0 +1,62 @@ +import { useId, useRef } from 'react'; +import './style.scss'; +import clsx from 'clsx'; +import { isPresent } from '../../utils/isPresent'; +import { mergeRefs } from '../../utils/mergeRefs'; +import { FieldError } from '../FieldError/FieldError'; +import { FieldLabel } from '../FieldLabel/FieldLabel'; +import type { InputProps } from './types'; + +export const Input = ({ + value, + error, + label, + ref, + name, + size = 'default', + type = 'text', + required = false, + disabled = false, + onChange, + onBlur, + onFocus, + placeholder, +}: InputProps) => { + const innerRef = useRef(null); + const id = useId(); + return ( +
+
+ {isPresent(label) && } +
{ + innerRef.current?.focus(); + }} + > + { + onChange?.(e.target.value); + }} + /> +
+ +
+
+ ); +}; diff --git a/webnext/src/shared/defguard-ui/components/Input/style.scss b/webnext/src/shared/defguard-ui/components/Input/style.scss new file mode 100644 index 00000000..34047cba --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Input/style.scss @@ -0,0 +1,83 @@ +.input { + & > .inner { + box-sizing: border-box; + + &.error { + padding-bottom: var(--form-field-error-space); + } + + .field-label { + cursor: pointer; + user-select: none; + } + + .track { + --outline-width: 0; + --border-color: var(--border-default); + --background-color: var(--bg-default); + --input-size: var(--input-size-primary); + + box-sizing: border-box; + cursor: pointer; + border: 1px solid var(--border-color); + border-radius: var(--input-border-radius); + position: relative; + padding: var(--input-spacing-sm) var(--input-spacing-lg); + display: flex; + flex-flow: row; + align-items: center; + outline: var(--outline-width) solid var(--border-action); + outline-offset: -2px; + + @include animate(border-color, background-color); + + input { + font: var(--t-input-text-primary); + color: var(--fg-default); + border: none; + background: none; + border-radius: 0; + height: var(--input-size); + width: 100%; + margin: 0; + padding: 0; + + &::placeholder { + font: var(--t-input-text-primary); + color: var(--fg-muted); + } + } + + &:not(.disabled) { + &:hover { + --border-color: var(--border-emphasis); + } + + &:focus-within { + --border-colo: var(--border-default); + --outline-width: 2px; + } + } + + &.disabled { + --border-color: var(--border-disabled); + --background-color: var(--bg-disabled); + + cursor: not-allowed; + pointer-events: none; + } + } + + &.disabled { + pointer-events: none; + + & > .field-label { + cursor: not-allowed; + } + } + + &.size-big { + --input-size: var(--input-size-lg); + } + } +} diff --git a/webnext/src/shared/defguard-ui/components/Input/types.ts b/webnext/src/shared/defguard-ui/components/Input/types.ts new file mode 100644 index 00000000..4af97b19 --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Input/types.ts @@ -0,0 +1,22 @@ +import type { HTMLAttributes, HTMLInputTypeAttribute, Ref } from 'react'; + +export type InputProps = { + value: string | null; + size?: 'default' | 'big'; + type?: HTMLInputTypeAttribute; + ref?: Ref; + error?: string; + name?: string; + label?: string; + required?: boolean; + disabled?: boolean; + placeholder?: string; + onChange?: (value: string) => void; +} & Pick, 'onBlur' | 'onFocus'>; + +export type FormInputProps = Pick< + InputProps, + 'name' | 'placeholder' | 'disabled' | 'required' | 'label' +> & { + mapError?: (error: string) => string | undefined; +}; diff --git a/webnext/src/shared/defguard-ui/components/LoaderSpinner/LoaderSpinner.tsx b/webnext/src/shared/defguard-ui/components/LoaderSpinner/LoaderSpinner.tsx new file mode 100644 index 00000000..27196295 --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/LoaderSpinner/LoaderSpinner.tsx @@ -0,0 +1,14 @@ +import { Icon } from '../Icon'; +import './style.scss'; + +type Props = { + size?: number; +}; + +export const LoaderSpinner = ({ size = 20 }: Props) => { + return ( +
+ +
+ ); +}; diff --git a/webnext/src/shared/defguard-ui/components/LoaderSpinner/style.scss b/webnext/src/shared/defguard-ui/components/LoaderSpinner/style.scss new file mode 100644 index 00000000..b0832f7a --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/LoaderSpinner/style.scss @@ -0,0 +1,18 @@ +.loader-spinner { + display: inline-block; + user-select: none; + + & > .icon { + animation: spin 1s ease-in-out infinite; + } +} + +@keyframes spin { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } +} diff --git a/webnext/src/shared/defguard-ui/components/Radio/Radio.tsx b/webnext/src/shared/defguard-ui/components/Radio/Radio.tsx new file mode 100644 index 00000000..91cf260c --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Radio/Radio.tsx @@ -0,0 +1,128 @@ +import './style.scss'; +import { useHover } from '@uidotdev/usehooks'; +import clsx from 'clsx'; +import { useMemo } from 'react'; +import { isPresent } from '../../utils/isPresent'; + +type Props = { + text?: string; + active?: boolean; + disabled?: boolean; + onClick?: () => void; +}; + +export const Radio = ({ text, active, disabled, onClick }: Props) => { + const [ref, hover] = useHover(); + + const RenderIcon = useMemo(() => { + if (active) { + if (disabled) { + return StateSelectedDisabled; + } + return StateSelected; + } + if (disabled) { + return StateDefaultDisabled; + } + if (hover) { + return StateDefaultHover; + } + return StateDefault; + }, [active, disabled, hover]); + + return ( +
+ + {isPresent(text) && {text}} +
+ ); +}; + +const StateDefault = () => { + return ( + + + + ); +}; + +const StateDefaultHover = () => { + return ( + + + + ); +}; + +const StateDefaultDisabled = () => { + return ( + + + + ); +}; + +const StateSelected = () => { + return ( + + + + + ); +}; + +const StateSelectedDisabled = () => { + return ( + + + + + ); +}; diff --git a/webnext/src/shared/defguard-ui/components/Radio/style.scss b/webnext/src/shared/defguard-ui/components/Radio/style.scss new file mode 100644 index 00000000..264c497d --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Radio/style.scss @@ -0,0 +1,67 @@ +.radio { + user-select: none; + cursor: pointer; + + &.disabled { + cursor: not-allowed; + } + + &.text { + display: grid; + grid-template-columns: 24px auto; + grid-template-rows: 1fr; + column-gap: var(--spacing-sm); + } + + span { + font: var(--t-body-sm-400); + } +} + +// state colors +.radio svg { + &.icon-default { + circle { + stroke: var(--border-default); + fill: var(--bg-default); + } + } + + &.icon-hover { + circle { + stroke: var(--border-emphasis); + fill: var(--bg-default); + } + } + + &.icon-disabled { + circle { + fill: var(--bg-disabled); + stroke: var(--border-disabled); + } + } + + &.icon-selected { + circle { + &:nth-child(1) { + fill: var(--bg-action); + } + + &:nth-child(2) { + fill: var(--c-white); + } + } + } + + &.icon-selected-disabled { + circle { + &:nth-child(1) { + fill: var(--bg-faded); + } + + &:nth-child(2) { + fill: var(--bg-disabled); + } + } + } +} diff --git a/webnext/src/shared/defguard-ui/components/SizedBox/SizedBox.tsx b/webnext/src/shared/defguard-ui/components/SizedBox/SizedBox.tsx new file mode 100644 index 00000000..544312fd --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/SizedBox/SizedBox.tsx @@ -0,0 +1,19 @@ +import './style.scss'; + +type Props = { + height: string | number; + width?: string | number; +}; + +/**Spawns a block with a strict size, meant to fill spaces that are not regular like layouts that can't utilize "gap" css property due to irregular gaps in across same axis*/ +export const SizedBox = ({ width, height }: Props) => { + return ( +
+ ); +}; diff --git a/webnext/src/shared/defguard-ui/components/SizedBox/style.scss b/webnext/src/shared/defguard-ui/components/SizedBox/style.scss new file mode 100644 index 00000000..7a0173b6 --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/SizedBox/style.scss @@ -0,0 +1,6 @@ +.sized-box { + display: block; + user-select: none; + pointer-events: none; + content: ''; +} diff --git a/webnext/src/shared/defguard-ui/components/Text/Text.tsx b/webnext/src/shared/defguard-ui/components/Text/Text.tsx new file mode 100644 index 00000000..b72e9768 --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/Text/Text.tsx @@ -0,0 +1,59 @@ +import type { + PolymorphicForwardedRef, + PolymorphicProps, +} from '@axa-ch/react-polymorphic-types'; +import type React from 'react'; +import { createElement, type ElementType } from 'react'; +import type { TextStyleValue } from '../../types'; + +type TextDefault = 'p'; +type TextAllowed = + | TextDefault + | 'span' + | 'strong' + | 'em' + | 'small' + | 'label' + | 'code' + | 'kbd' + | 'mark' + | 'sup' + | 'sub' + | 'time' + | 'abbr' + | 'q' + | 'cite' + | 'del' + | 'ins' + | 'pre' + | 'blockquote' + | 'h1' + | 'h2' + | 'h3' + | 'h4' + | 'h5' + | 'h6'; + +type OwnProps = React.ComponentPropsWithoutRef & { + font: TextStyleValue; +}; + +type TextProps = PolymorphicProps< + OwnProps, + T, + TextAllowed +> & { + ref?: PolymorphicForwardedRef; +}; + +export const AppText = ({ + as, + children, + style, + font, + ...rest +}: TextProps) => { + const Component = (as ?? ('p' satisfies ElementType)) as ElementType; + const computedStyle = { ...style, font }; + return createElement(Component, { ...rest, style: computedStyle }, children); +}; diff --git a/webnext/src/shared/defguard-ui/components/form/FormInput/FormInput.tsx b/webnext/src/shared/defguard-ui/components/form/FormInput/FormInput.tsx new file mode 100644 index 00000000..2e0a935d --- /dev/null +++ b/webnext/src/shared/defguard-ui/components/form/FormInput/FormInput.tsx @@ -0,0 +1,43 @@ +import { useStore } from '@tanstack/react-form'; +import { useMemo } from 'react'; +import type { z } from 'zod'; +import { useFieldContext } from '../../../form'; +import { isPresent } from '../../../utils/isPresent'; +import { Input } from '../../Input/Input'; +import type { FormInputProps } from '../../Input/types'; + +export const FormInput = ({ mapError, ...props }: FormInputProps) => { + const field = useFieldContext(); + + const isPristine = useStore(field.store, (state) => state.meta.isPristine); + + const errorState = useStore( + field.store, + (state) => state.meta.errors as z.core.$ZodIssue[], + ); + + const errorMessage = useMemo(() => { + // ignore errors unless some touches the field or submit's the form + if (isPristine) return undefined; + + const fieldZodError = errorState[0]; + + if (fieldZodError) { + if (isPresent(mapError)) { + return mapError(fieldZodError.message); + } + return fieldZodError.message; + } + return undefined; + }, [mapError, errorState[0], isPristine]); + + return ( + + ); +}; diff --git a/webnext/src/shared/defguard-ui/form.tsx b/webnext/src/shared/defguard-ui/form.tsx new file mode 100644 index 00000000..b9561edc --- /dev/null +++ b/webnext/src/shared/defguard-ui/form.tsx @@ -0,0 +1,14 @@ +import { createFormHook, createFormHookContexts } from '@tanstack/react-form'; +import { FormInput } from './components/form/FormInput/FormInput'; + +export const { fieldContext, formContext, useFieldContext, useFormContext } = + createFormHookContexts(); + +export const { useAppForm, withFieldGroup, withForm } = createFormHook({ + fieldContext, + formContext, + fieldComponents: { + FormInput, + }, + formComponents: {}, +}); diff --git a/webnext/src/shared/defguard-ui/scss/_base.scss b/webnext/src/shared/defguard-ui/scss/_base.scss new file mode 100644 index 00000000..29412a26 --- /dev/null +++ b/webnext/src/shared/defguard-ui/scss/_base.scss @@ -0,0 +1,85 @@ +/* stylelint-disable font-family-name-quotes */ +html, +body, +h1, +h2, +h3, +h4, +h5, +h6, +p, +ul, +li { + margin: 0; + padding: 0; +} + +h1 { + font: var(--t-title-h1); +} + +h2 { + font: var(--t-title-h2); +} + +h3 { + font: var(--t-title-h3); +} + +h4 { + font: var(--t-title-h4); +} + +h5 { + font: var(--t-title-h5); +} + +#root { + position: relative; + min-height: 100dvh; + width: 100%; +} + +#root, +body { + background-color: var(--bg-default); +} + +p, +span, +div, +section, +a, +h1, +h2, +h3, +h4, +h5, +h6 { + color: var(--fg-default); + font-family: + geist, + system-ui, + -apple-system, + BlinkMacSystemFont, + 'Segoe UI', + Roboto, + Oxygen, + Ubuntu, + Cantarell, + 'Open Sans', + 'Helvetica Neue', + sans-serif; +} + +.icon path { + fill: var(--fg-muted); +} + +*:focus { + outline: none; +} + +*:-moz-focus-inner { + border: 0; +} diff --git a/webnext/src/shared/defguard-ui/scss/_fonts.scss b/webnext/src/shared/defguard-ui/scss/_fonts.scss new file mode 100644 index 00000000..79664bd2 --- /dev/null +++ b/webnext/src/shared/defguard-ui/scss/_fonts.scss @@ -0,0 +1,75 @@ +/* stylelint-disable font-family-name-quotes */ +// fonts.scss +@font-face { + font-family: 'Geist'; + src: url('/fonts/geist/Geist-Regular.woff2') format('woff2'); + font-weight: 400; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'Geist'; + src: url('/fonts/geist/Geist-RegularItalic.woff2') format('woff2'); + font-weight: 400; + font-style: italic; + font-display: swap; +} + +@font-face { + font-family: 'Geist'; + src: url('/fonts/geist/Geist-Medium.woff2') format('woff2'); + font-weight: 500; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'Geist'; + src: url('/fonts/geist/Geist-MediumItalic.woff2') format('woff2'); + font-weight: 500; + font-style: italic; + font-display: swap; +} + +@font-face { + font-family: 'Geist'; + src: url('/fonts/geist/Geist-SemiBold.woff2') format('woff2'); + font-weight: 600; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'Geist'; + src: url('/fonts/geist/Geist-SemiBoldItalic.woff2') format('woff2'); + font-weight: 600; + font-style: italic; + font-display: swap; +} + +@font-face { + font-family: 'Geist'; + src: url('/fonts/geist/Geist-Bold.woff2') format('woff2'); + font-weight: 700; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'Geist'; + src: url('/fonts/geist/Geist-BoldItalic.woff2') format('woff2'); + font-weight: 700; + font-style: italic; + font-display: swap; +} + +// source-code-pro + +@font-face { + font-family: 'Source Code Pro'; + src: url('/fonts/source_code_pro/SourceCodePro-Regular.woff2') format('woff2'); + font-weight: 400; + font-style: normal; + font-display: swap; +} diff --git a/webnext/src/shared/defguard-ui/scss/_shared_tokens.scss b/webnext/src/shared/defguard-ui/scss/_shared_tokens.scss new file mode 100644 index 00000000..c8bf9e70 --- /dev/null +++ b/webnext/src/shared/defguard-ui/scss/_shared_tokens.scss @@ -0,0 +1,220 @@ +$font-fallback: + system-ui, + -apple-system, + BlinkMacSystemFont, + 'Segoe UI', + Roboto, + Oxygen, + Ubuntu, + Cantarell, + 'Open Sans', + 'Helvetica Neue', + sans-serif; +$geist: + geist, + #{$font-fallback}; +$source-code-pro: + 'Source Code Pro', + #{$font-fallback}; +/* stylelint-disable value-keyword-case */ +:root { + // font settings + --font-family-title: #{$geist}; + --font-family-body: #{$geist}; + --font-family-component: #{geist}; + --font-family-code: #{$source-code-pro}; + + --t-body-xxs-600: normal 600 11px/14px #{$geist}; + --t-body-xxs-400: normal 400 11px/14px #{$geist}; + + --t-body-xs-600: normal 600 12px/16px #{$geist}; + --t-body-xs-500: normal 500 12px/16px #{$geist}; + --t-body-xs-400: normal 400 12px/16px #{$geist}; + + --t-body-sm-600: normal 600 14px/20px #{$geist}; + --t-body-sm-500: normal 500 14px/20px #{$geist}; + --t-body-sm-400: normal 400 14px/20px #{$geist}; + + --t-body-primary-400: normal 400 16px/24px #{$geist}; + --t-body-primary-600: normal 600 16px/24px #{$geist}; + --t-body-primary-500: normal 500 16px/24px #{$geist}; + + --t-title-h5: normal 600 18px/28px #{$geist}; + --t-title-h4: normal 600 20px/28px #{$geist}; + --t-title-h3: normal 600 24px/32px #{$geist}; + --t-title-h2: normal 600 28px/40px #{$geist}; + --t-title-h1: normal 600 32px/44px #{$geist}; + + // border width + --border-1: 1px; + --border-2: 2px; + + // border-radius + --radius-sm: 4px; + --radius-md: 8px; + --radius-lg: 12px; + --radius-xl: 16px; + --radius-xxl: 24px; + --radius-xxxl: 32px; + --radius-full: 100px; + + // scale + --size-xs: 16px; + --size-sm: 20px; + --size-md: 24px; + --size-xl: 32px; + --size-2xl: 36px; + --size-3xl: 40px; + --size-4xl: 44px; + --size-5xl: 60px; + + // spacing + --spacing-xs: 4px; + --spacing-sm: 8px; + --spacing-md: 12px; + --spacing-lg: 16px; + --spacing-xl: 20px; + --spacing-2xl: 24px; + --spacing-3xl: 32px; + --spacing-4xl: 40px; + --spacing-5xl: 48px; + --spacing-6xl: 64px; + --spacing-7xl: 80px; + --spacing-8xl: 96px; + --spacing-9xl: 120px; + + // color basis + --c-neutral-1400: rgb(20 21 23); + --c-neutral-1300: rgb(25 26 28); + --c-neutral-1200: rgb(36 38 41); + --c-neutral-1100: rgb(46 49 54); + --c-neutral-1000: rgb(50 54 60); + --c-neutral-900: rgb(61 67 75); + --c-neutral-800: rgb(74 80 89); + --c-neutral-700: rgb(94 102 114); + --c-neutral-600: rgb(126 135 148); + --c-neutral-500: rgb(147 156 169); + --c-neutral-400: rgb(162 172 186); + --c-neutral-300: rgb(184 192 205); + --c-neutral-200: rgb(223 227 233); + --c-neutral-100: rgb(240 242 245); + --c-neutral-50: rgb(247 248 250); + + --c-white: rgb(255 255 255); + --c-white-50: rgb(255 255 255 / 50%); + --c-transparent: rgb(0 0 0 / 0%); + + --c-additional-error: rgb(204 60 60); + --c-additional-warning: rgb(255 149 0); + --c-additional-success: rgb(3 128 38); + --c-additional-code: rgb(112 75 172); + + --c-green-700: rgb(2 78 23); + --c-green-600: rgb(2 90 27); + --c-green-500: rgb(3 128 38); + --c-green-400: rgb(46 150 75); + --c-green-300: rgb(109 181 129); + --c-green-200: rgb(152 203 166); + --c-green-100: rgb(230 242 233); + --c-green-500-transparent: rgb(3 128 38 / 8%); + + --c-orange-700: rgb(156 91 0); + --c-orange-600: rgb(179 104 0); + --c-orange-500: rgb(255 149 0); + --c-orange-400: rgb(255 167 43); + --c-orange-300: rgb(255 194 107); + --c-orange-200: rgb(255 212 150); + --c-orange-100: rgb(255 244 230); + --c-orange-500-transparent: rgb(255 149 0 / 8%); + + --c-violet-700: rgb(53 36 82); + --c-violet-600: rgb(83 55 128); + --c-violet-500: rgb(102 55 178); + --c-violet-400: rgb(136 106 186); + --c-violet-300: rgb(172 151 207); + --c-violet-200: rgb(196 181 221); + --c-violet-100: rgb(241 237 247); + + --c-blue-700: rgb(38 57 115); + --c-blue-600: rgb(51 77 156); + --c-blue-500: rgb(57 97 219); + --c-blue-400: rgb(87 119 217); + --c-blue-300: rgb(140 161 222); + --c-blue-200: rgb(180 196 242); + --c-blue-100: rgb(237 241 252); + --c-blue-500-transparent: rgb(50 92 219 / 8%); + + --c-red-700: rgb(124 37 37); + --c-red-600: rgb(143 42 42); + --c-red-500: rgb(204 60 60); + --c-red-400: rgb(213 93 93); + --c-red-300: rgb(225 142 142); + --c-red-200: rgb(234 175 175); + --c-red-100: rgb(250 236 236); + --c-red-500-transparent: rgb(204 60 60 / 8%); + + // Components + + // Menu + --t-menu-title: 600 12px/24px #{$geist}; + --t-menu-body: 400 14px/24px #{$geist}; + --menu-spacing-icon: var(--spacing-md); + --menu-padding-sides: var(--spacing-sm); + --menu-border-radius-group: var(--radius-lg); + --menu-border-radius-item: var(--radius-md); + --menu-height: var(--size-2xl); + + // Icons + + --icon-size-lg: 32px; + --icon-size: 20px; + --icon-size-xs: 16px; + + // Modals + + --modal-title-size: 16px; + --modal-size-md: 640px; + --modal-size-sm: 480px; + --modal-spacing: var(--spacing-md); + --modal-spacing-sides: var(--spacing-lg); + --modal-border-radius: var(--radius-lg); + + // Buttons + + --t-button-label-lg: normal 400 16px / normal #{$geist}; + --t-button-label-primary: normal 400 14px / normal #{$geist}; + --button-border-radius-sm: var(--radius-md); + --button-border-radius-primary: var(--radius-md); + --button-border-radius-xl: var(--radius-full); + --button-size-primary: var(--size-2xl); + --button-size-lg: var(--size-4xl); + --button-size-xl: var(--size-5xl); + --button-icons-spacing: var(--spacing-sm); + + // Badge + --badge-border-radius: var(--radius-md); + --badge-spacing: var(--spacing-sm); + --badge-gap: var(--spacing-xs); + --t-badge: normal 500 12px / 16px #{$geist}; + --t-badge-spacing: 0.3px; + + // Inputs + --t-input-title: normal 400 12px / 16px #{$geist}; + --t-input-text-primary: normal 400 12px / 20px #{$geist}; + --t-input-text-big: normal 400 16px / 20px #{$geist}; + --t-input-error-message: normal 400 12px / 16px #{$geist}; + --input-border-radius: var(--radius-md); + --input-size-primary: 20px; + --input-size-lg: 28px; + --input-spacing-xs: var(--spacing-xs); + --input-spacing-sm: var(--spacing-sm); + --input-spacing-lg: var(--spacing-md); + + // custom + + // how much space does error message in all takes + --form-field-error-space: 24px; + + // how much space error should gap from main container + --form-field-error-gap: 8px; +} diff --git a/webnext/src/shared/defguard-ui/scss/_themes.scss b/webnext/src/shared/defguard-ui/scss/_themes.scss new file mode 100644 index 00000000..55f17925 --- /dev/null +++ b/webnext/src/shared/defguard-ui/scss/_themes.scss @@ -0,0 +1,113 @@ +:root[data-theme='light'] { + --bg-default: var(--c-white); + --bg-dark: var(--c-neutral-1300); + --bg-white: var(--c-white); + --bg-faded: var(--c-neutral-300); + --bg-disabled: var(--c-neutral-50); + --bg-muted: var(--c-neutral-50); + --bg-emphasis: var(--c-neutral-100); + --bg-active: var(--c-neutral-200); + --bg-inverted: var(--c-neutral-1300); + + --bg-action: var(--c-blue-500); + --bg-action-emphasis: var(--c-blue-400); + --bg-action-faded: var(--c-blue-300); + --bg-action-muted: var(--c-blue-100); + + --bg-critical-emphasis: var(--c-red-600); + --bg-critical: var(--c-red-500); + --bg-critical-faded: var(--c-red-400); + --bg-critical-muted: var(--c-red-200); + + --bg-success: var(--c-green-500); + --bg-warning: var(--c-orange-500); + + --border-action: var(--c-blue-500); + --border-action-disabled: var(--c-blue-300); + --border-default: var(--c-neutral-200); + --border-disabled: var(--c-neutral-200); + --border-emphasis: var(--c-neutral-500); + --border-muted: var(--c-neutral-200); + --border-faded: var(--c-neutral-400); + --border-critical: var(--c-red-500); + --border-success: var(--c-green-300); + --border-warning: var(--c-orange-300); + + --fg-action: var(--c-blue-500); + --fg-action-emphasis: var(--c-blue-600); + --fg-action-muted: var(--c-blue-300); + --fg-attention: var(--c-orange-500); + --fg-critical: var(--c-red-500); + --fg-critical-muted: var(--c-red-200); + + --fg-default: var(--c-neutral-1400); + --fg-faded: var(--c-neutral-900); + --fg-neutral: var(--c-neutral-800); + --fg-muted: var(--c-neutral-600); + --fg-disabled: var(--c-neutral-500); + + --fg-success: var(--c-green-500); + --fg-success-muted: var(--c-green-100); + --fg-code: var(--c-violet-500); + --fg-inverted: var(--c-white); + --fg-white: var(--c-white); + --fg-white-transparent: var(--c-white-50); + --fg-blue-transparent-2: var(--c-blue-500-transparent); +} + +:root[data-theme='dark'] { + --bg-default: var(--c-neutral-1400); + --bg-dark: var(--c-neutral-1100); + --bg-white: var(--c-white); + --bg-faded: var(--c-neutral-900); + --bg-disabled: var(--c-neutral-1300); + --bg-muted: var(--c-neutral-1200); + --bg-emphasis: var(--c-neutral-1200); + --bg-active: var(--c-neutral-1100); + --bg-inverted: var(--c-neutral-100); + + --bg-action: var(--c-blue-500); + --bg-action-emphasis: var(--c-blue-600); + --bg-action-faded: var(--c-blue-400); + --bg-action-muted: var(--c-blue-300); + + --bg-critical-emphasis: var(--c-red-600); + --bg-critical: var(--c-red-500); + --bg-critical-faded: var(--c-red-400); + --bg-critical-muted: var(--c-red-200); + + --bg-success: var(--c-green-500); + --bg-warning: var(--c-orange-500); + + --border-action: var(--c-blue-500); + --border-action-disabled: var(--c-blue-300); + --border-default: var(--c-neutral-900); + --border-disabled: var(--c-neutral-1000); + --border-emphasis: var(--c-neutral-500); + --border-muted: var(--c-neutral-1100); + --border-faded: var(--c-neutral-800); + --border-critical: var(--c-red-500); + --border-success: var(--c-green-300); + --border-warning: var(--c-orange-300); + + --fg-action: var(--c-blue-500); + --fg-action-emphasis: var(--c-blue-600); + --fg-action-muted: var(--c-blue-300); + --fg-attention: var(--c-orange-500); + --fg-critical: var(--c-red-500); + --fg-critical-muted: var(--c-red-200); + + --fg-default: var(--c-white); + --fg-faded: var(--c-neutral-400); + --fg-neutral: var(--c-neutral-300); + --fg-muted: var(--c-neutral-200); + --fg-disabled: var(--c-neutral-700); + + --fg-success: var(--c-green-500); + --fg-success-muted: var(--c-green-100); + --fg-code: var(--c-violet-500); + --fg-inverted: var(--c-neutral-1400); + --fg-white: var(--c-white); + --fg-white-transparent: var(--c-white-50); + --fg-blue-transparent-2: var(--c-blue-500-transparent); +} diff --git a/webnext/src/shared/defguard-ui/scss/global/_animate.scss b/webnext/src/shared/defguard-ui/scss/global/_animate.scss new file mode 100644 index 00000000..024cc924 --- /dev/null +++ b/webnext/src/shared/defguard-ui/scss/global/_animate.scss @@ -0,0 +1,11 @@ +@use 'sass:list'; + +// for now no prop required +@mixin animate($properties...) { + transition-timing-function: ease-out; + transition-duration: 160ms; + + @if list.length($properties) > 0 { + transition-property: $properties; + } +} diff --git a/webnext/src/shared/defguard-ui/scss/global/_breakpoints.scss b/webnext/src/shared/defguard-ui/scss/global/_breakpoints.scss new file mode 100644 index 00000000..d99b76ff --- /dev/null +++ b/webnext/src/shared/defguard-ui/scss/global/_breakpoints.scss @@ -0,0 +1,104 @@ +@use 'sass:map'; +@use 'sass:list'; + +$grid-breakpoints: ( + xs: 0, + sm: 320px, + md: 768px, + lg: 992px, + xl: 1200px, + xxl: 1600px, +); + +@function break-next( + $name, + $breakpoints: $grid-breakpoints, + $breakpoint-names: map.keys($breakpoints) +) { + $n: list.index($breakpoint-names, $name); + + @if not $n { + @error "breakpoint `#{$name}` not found in `#{$breakpoints}`"; + } + + @return if( + $n < list.length($breakpoint-names), + list.nth($breakpoint-names, $n + 1), + null + ); +} + +@function break-min($name, $breakpoints: $grid-breakpoints) { + $min: map.get($breakpoints, $name); + + @return if($min != 0, $min, null); +} + +@function break-max($name, $breakpoints: $grid-breakpoints) { + $max: map.get($breakpoints, $name); + + @return if($max and $max > 0, $max - 0.02, null); +} + +@mixin break-up($name, $breakpoints: $grid-breakpoints) { + $min: break-min($name, $breakpoints); + + @if $min { + @media (min-width: $min) { + @content; + } + } @else { + @content; + } +} + +@mixin break-down($name, $breakpoints: $grid-breakpoints) { + $max: break-max($name, $breakpoints); + + @if $max { + @media (max-width: $max) { + @content; + } + } @else { + @content; + } +} + +@mixin break-between($lower, $upper, $breakpoints: $grid-breakpoints) { + $min: break-min($lower, $breakpoints); + $max: break-max($upper, $breakpoints); + + @if $min != null and $max != null { + @media (min-width: $min) and (max-width: $max) { + @content; + } + } @else if $max == null { + @include break-up($lower, $breakpoints) { + @content; + } + } @else if $min == null { + @include break-down($upper, $breakpoints) { + @content; + } + } +} + +@mixin break-only($name, $breakpoints: $grid-breakpoints) { + $min: break-min($name, $breakpoints); + $next: break-next($name, $breakpoints); + $max: break-max($next, $breakpoints); + + @if $min != null and $max != null { + @media (min-width: $min) and (max-width: $max) { + @content; + } + } @else if $max == null { + @include break-up($name, $breakpoints) { + @content; + } + } @else if $min == null { + @include break-down($next, $breakpoints) { + @content; + } + } +} diff --git a/webnext/src/shared/defguard-ui/scss/global/index.scss b/webnext/src/shared/defguard-ui/scss/global/index.scss new file mode 100644 index 00000000..87546734 --- /dev/null +++ b/webnext/src/shared/defguard-ui/scss/global/index.scss @@ -0,0 +1,2 @@ +@forward './animate'; +@forward './breakpoints'; diff --git a/webnext/src/shared/defguard-ui/scss/index.scss b/webnext/src/shared/defguard-ui/scss/index.scss new file mode 100644 index 00000000..55a38126 --- /dev/null +++ b/webnext/src/shared/defguard-ui/scss/index.scss @@ -0,0 +1,4 @@ +@use './fonts'; +@use './shared_tokens'; +@use './themes'; +@use './base'; diff --git a/webnext/src/shared/defguard-ui/types.ts b/webnext/src/shared/defguard-ui/types.ts new file mode 100644 index 00000000..2a71ddd0 --- /dev/null +++ b/webnext/src/shared/defguard-ui/types.ts @@ -0,0 +1,135 @@ +import type { SVGProps } from 'react'; + +export const Direction = { + UP: 'up', + DOWN: 'down', + LEFT: 'left', + RIGHT: 'right', +} as const; + +export type Direction = (typeof Direction)[keyof typeof Direction]; + +export type TSSvgProps = SVGProps; + +export const ThemeVariable = { + BgDefault: 'var(--bg-default)', + BgDark: 'var(--bg-dark)', + BgWhite: 'var(--bg-white)', + BgFaded: 'var(--bg-faded)', + BgDisabled: 'var(--bg-disabled)', + BgMuted: 'var(--bg-muted)', + BgEmphasis: 'var(--bg-emphasis)', + BgActive: 'var(--bg-active)', + BgInverted: 'var(--bg-inverted)', + BgAction: 'var(--bg-action)', + BgActionEmphasis: 'var(--bg-action-emphasis)', + BgActionFaded: 'var(--bg-action-faded)', + BgActionMuted: 'var(--bg-action-muted)', + BgCriticalEmphasis: 'var(--bg-critical-emphasis)', + BgCritical: 'var(--bg-critical)', + BgCriticalFaded: 'var(--bg-critical-faded)', + BgCriticalMuted: 'var(--bg-critical-muted)', + BgSuccess: 'var(--bg-success)', + BgWarning: 'var(--bg-warning)', + BorderAction: 'var(--border-action)', + BorderActionDisabled: 'var(--border-action-disabled)', + BorderDefault: 'var(--border-default)', + BorderDisabled: 'var(--border-disabled)', + BorderEmphasis: 'var(--border-emphasis)', + BorderMuted: 'var(--border-muted)', + BorderFaded: 'var(--border-faded)', + BorderCritical: 'var(--border-critical)', + BorderSuccess: 'var(--border-success)', + BorderWarning: 'var(--border-warning)', + FgAction: 'var(--fg-action)', + FgActionEmphasis: 'var(--fg-action-emphasis)', + FgActionMuted: 'var(--fg-action-muted)', + FgAttention: 'var(--fg-attention)', + FgCritical: 'var(--fg-critical)', + FgCriticalMuted: 'var(--fg-critical-muted)', + FgDefault: 'var(--fg-default)', + FgFaded: 'var(--fg-faded)', + FgNeutral: 'var(--fg-neutral)', + FgMuted: 'var(--fg-muted)', + FgDisabled: 'var(--fg-disabled)', + FgSuccess: 'var(--fg-success)', + FgSuccessMuted: 'var(--fg-success-muted)', + FgCode: 'var(--fg-code)', + FgInverted: 'var(--fg-inverted)', + FgWhite: 'var(--fg-white)', + FgWhiteTransparent: 'var(--fg-white-transparent)', + FgBlueTransparent2: 'var(--fg-blue-transparent-2)', +} as const; + +export type ThemeVariableValue = (typeof ThemeVariable)[keyof typeof ThemeVariable]; + +export const TextStyle = { + TBodyXxs600: 'var(--t-body-xxs-600)', + TBodyXxs400: 'var(--t-body-xxs-400)', + TBodyXs600: 'var(--t-body-xs-600)', + TBodyXs500: 'var(--t-body-xs-500)', + TBodyXs400: 'var(--t-body-xs-400)', + TBodySm600: 'var(--t-body-sm-600)', + TBodySm500: 'var(--t-body-sm-500)', + TBodySm400: 'var(--t-body-sm-400)', + TBodyPrimary400: 'var(--t-body-primary-400)', + TBodyPrimary600: 'var(--t-body-primary-600)', + TBodyPrimary500: 'var(--t-body-primary-500)', + TTitleH5: 'var(--t-title-h5)', + TTitleH4: 'var(--t-title-h4)', + TTitleH3: 'var(--t-title-h3)', + TTitleH2: 'var(--t-title-h2)', + TTitleH1: 'var(--t-title-h1)', +} as const; + +export type TextStyleValue = (typeof TextStyle)[keyof typeof TextStyle]; + +export const BorderRadius = { + Sm: 'var(--radius-sm)', + Md: 'var(--radius-md)', + Lg: 'var(--radius-lg)', + Xl: 'var(--radius-xl)', + Xxl: 'var(--radius-xxl)', + Xxxl: 'var(--radius-xxl)', + Full: 'var(--radius-full)', +} as const; + +export type BorderRadiusValue = (typeof BorderRadius)[keyof typeof BorderRadius]; + +export const Orientation = { + Horizontal: 'horizontal', + Vertical: 'vertical', +} as const; + +export type OrientationValue = (typeof Orientation)[keyof typeof Orientation]; + +export const ThemeSize = { + Xs: 'var(--size-xs)', + Sm: 'var(--size-sm)', + Md: 'var(--size-md)', + Xl: 'var(--size-xl)', + Xl2: 'var(--size-2xl)', + Xl3: 'var(--size-3xl)', + Xl4: 'var(--size-4xl)', + Xl5: 'var(--size-5xl)', +}; + +export type ThemeSizeValue = (typeof ThemeSize)[keyof typeof ThemeSize]; + +export const ThemeSpacing = { + Xs: 'var(--spacing-xs)', + Sm: 'var(--spacing-sm)', + Md: 'var(--spacing-md)', + Lg: 'var(--spacing-lg)', + Xl: 'var(--spacing-xl)', + Xl2: 'var(--spacing-2xl)', + Xl3: 'var(--spacing-3xl)', + Xl4: 'var(--spacing-4xl)', + Xl5: 'var(--spacing-5xl)', + Xl6: 'var(--spacing-6xl)', + Xl7: 'var(--spacing-7xl)', + Xl8: 'var(--spacing-8xl)', + Xl9: 'var(--spacing-9xl)', +}; + +export type ThemeSpacingValue = (typeof ThemeSpacing)[keyof typeof ThemeSpacing]; diff --git a/webnext/src/shared/defguard-ui/utils/detectClickOutside.ts b/webnext/src/shared/defguard-ui/utils/detectClickOutside.ts new file mode 100644 index 00000000..933609a8 --- /dev/null +++ b/webnext/src/shared/defguard-ui/utils/detectClickOutside.ts @@ -0,0 +1,22 @@ +/** + * Checks if mouse event clicked within any of provided rects + */ +export const detectClickInside = (event: MouseEvent, rects: DOMRect[]) => { + for (const domRect of rects) { + if (domRect) { + const start_x = domRect?.x; + const start_y = domRect?.y; + const end_x = start_x + domRect?.width; + const end_y = start_y + domRect.height; + if ( + event.clientX >= start_x && + event.clientX <= end_x && + event.clientY >= start_y && + event.clientY <= end_y + ) { + return true; + } + } + } + return false; +}; diff --git a/webnext/src/shared/defguard-ui/utils/isComparable.ts b/webnext/src/shared/defguard-ui/utils/isComparable.ts new file mode 100644 index 00000000..120180f1 --- /dev/null +++ b/webnext/src/shared/defguard-ui/utils/isComparable.ts @@ -0,0 +1,10 @@ +export const isComparableWithStrictEquality = (val: unknown) => { + const t = typeof val; + return ( + t === 'number' || + t === 'string' || + t === 'boolean' || + t === 'undefined' || + val === null + ); +}; diff --git a/webnext/src/shared/defguard-ui/utils/isPresent.ts b/webnext/src/shared/defguard-ui/utils/isPresent.ts new file mode 100644 index 00000000..510ce8d4 --- /dev/null +++ b/webnext/src/shared/defguard-ui/utils/isPresent.ts @@ -0,0 +1,3 @@ +export const isPresent = (value: T): value is NonNullable => { + return value !== null && value !== undefined; +}; diff --git a/webnext/src/shared/defguard-ui/utils/mergeRefs.ts b/webnext/src/shared/defguard-ui/utils/mergeRefs.ts new file mode 100644 index 00000000..5d13c288 --- /dev/null +++ b/webnext/src/shared/defguard-ui/utils/mergeRefs.ts @@ -0,0 +1,29 @@ +// extracted from https://github.com/gregberge/react-merge-refs +import type { Ref, RefCallback } from 'react'; + +function assignRef( + ref: Ref | undefined | null, + value: T | null, +): ReturnType> { + if (typeof ref === 'function') { + return ref(value); + } else if (ref) { + ref.current = value; + } +} + +export function mergeRefs(refs: (Ref | undefined)[]): Ref { + return (value: T | null) => { + const cleanups: (() => void)[] = []; + + for (const ref of refs) { + const cleanup = assignRef(ref, value); + const isCleanup = typeof cleanup === 'function'; + cleanups.push(isCleanup ? cleanup : () => assignRef(ref, null)); + } + + return () => { + for (const cleanup of cleanups) cleanup(); + }; + }; +} diff --git a/webnext/src/test_components/page/TestPage.tsx b/webnext/src/test_components/page/TestPage.tsx new file mode 100644 index 00000000..52284719 --- /dev/null +++ b/webnext/src/test_components/page/TestPage.tsx @@ -0,0 +1,143 @@ +import { type PropsWithChildren, useState } from 'react'; +import { Page } from '../../shared/components/Page/Page'; +import './style.scss'; +import { Avatar } from '../../shared/defguard-ui/components/Avatar/Avatar'; +import { Badge } from '../../shared/defguard-ui/components/Badge/Badge'; +import { Button } from '../../shared/defguard-ui/components/Button/Button'; +import { Checkbox } from '../../shared/defguard-ui/components/Checkbox/Checkbox'; +import { CounterLabel } from '../../shared/defguard-ui/components/CounterLabel/CounterLabel'; +import { Divider } from '../../shared/defguard-ui/components/Divider/Divider'; +import { EmptyState } from '../../shared/defguard-ui/components/EmptyState/EmptyState'; +import { IconButton } from '../../shared/defguard-ui/components/IconButton/IconButton'; +import { Radio } from '../../shared/defguard-ui/components/Radio/Radio'; + +export const TestPage = () => { + return ( + + +

Test ground

+
+ +