From 426518c70af80ba8f9b758575441284e4f08a53c Mon Sep 17 00:00:00 2001 From: zuiidea Date: Tue, 14 Apr 2026 18:04:41 +0800 Subject: [PATCH] chore: initial import --- .gitignore | 44 + README.md | 182 + apps/with-lingui/.gitignore | 36 + apps/with-lingui/.oxfmt.toml | 25 + apps/with-lingui/.vite-hooks/pre-commit | 1 + apps/with-lingui/AGENTS.md | 84 + apps/with-lingui/README.md | 182 + apps/with-lingui/e2e/helpers.ts | 16 + apps/with-lingui/e2e/login.spec.ts | 27 + apps/with-lingui/e2e/users.spec.ts | 43 + apps/with-lingui/index.html | 20 + apps/with-lingui/lingui.config.ts | 13 + apps/with-lingui/package.json | 62 + apps/with-lingui/playwright.config.ts | 30 + apps/with-lingui/pnpm-lock.yaml | 4876 +++++++++++++++++ apps/with-lingui/public/favicon.svg | 24 + apps/with-lingui/public/mockServiceWorker.js | 336 ++ apps/with-lingui/src/api/auth.ts | 11 + apps/with-lingui/src/api/schemas.ts | 131 + apps/with-lingui/src/api/user.ts | 10 + apps/with-lingui/src/auth/session.ts | 18 + .../src/components/Aurora/index.css | 88 + .../src/components/Aurora/index.tsx | 14 + .../with-lingui/src/components/Auth/index.tsx | 13 + .../components/DataTable/DataTableEmpty.tsx | 64 + .../DataTable/DataTableSkeleton.tsx | 298 + .../src/components/DataTable/index.css | 35 + .../src/components/DataTable/index.tsx | 125 + .../src/components/FilterToolbar/index.tsx | 168 + .../src/components/FormModal/index.tsx | 51 + .../src/components/Icon/GitHub.tsx | 11 + .../with-lingui/src/components/Icon/Theme.tsx | 21 + .../with-lingui/src/components/Icon/index.tsx | 2 + .../src/components/Layout/AppFooter/index.tsx | 41 + .../src/components/Layout/Header/index.tsx | 164 + .../components/Layout/MainLayout/index.tsx | 39 + .../src/components/Layout/Sidebar/index.css | 62 + .../src/components/Layout/Sidebar/index.tsx | 405 ++ .../src/components/Layout/UserMenu/index.css | 7 + .../src/components/Layout/UserMenu/index.tsx | 105 + .../src/components/NotFound/index.tsx | 70 + apps/with-lingui/src/hooks/usePermission.ts | 10 + apps/with-lingui/src/hooks/useResourceCRUD.ts | 82 + apps/with-lingui/src/index.css | 44 + apps/with-lingui/src/lingui.d.ts | 4 + apps/with-lingui/src/locales/en/messages.po | 317 ++ apps/with-lingui/src/locales/zh/messages.po | 317 ++ apps/with-lingui/src/main.tsx | 50 + apps/with-lingui/src/mocks/browser.ts | 4 + apps/with-lingui/src/mocks/createHandler.ts | 57 + apps/with-lingui/src/mocks/data.ts | 26 + apps/with-lingui/src/mocks/filterUtils.ts | 47 + apps/with-lingui/src/mocks/handlers/auth.ts | 37 + apps/with-lingui/src/mocks/handlers/index.ts | 4 + apps/with-lingui/src/mocks/handlers/user.ts | 53 + apps/with-lingui/src/routeTree.gen.ts | 180 + apps/with-lingui/src/routes/404/index.tsx | 6 + apps/with-lingui/src/routes/__root.tsx | 52 + apps/with-lingui/src/routes/_auth.tsx | 21 + .../src/routes/_auth/403/index.tsx | 41 + .../src/routes/_auth/dashboard/index.css | 42 + .../src/routes/_auth/dashboard/index.tsx | 310 ++ .../src/routes/_auth/users/-FormModal.tsx | 62 + .../src/routes/_auth/users/-Toolbar.tsx | 96 + .../src/routes/_auth/users/index.tsx | 493 ++ apps/with-lingui/src/routes/index.tsx | 7 + apps/with-lingui/src/routes/login/index.css | 7 + apps/with-lingui/src/routes/login/index.tsx | 237 + apps/with-lingui/src/stores/auth.ts | 57 + .../src/stores/createPersistentStore.ts | 29 + apps/with-lingui/src/stores/settings.ts | 40 + apps/with-lingui/src/theme/index.ts | 5 + apps/with-lingui/src/theme/tokenBuilders.ts | 119 + apps/with-lingui/src/theme/useAppTheme.ts | 10 + apps/with-lingui/src/utils/appMenu.ts | 143 + apps/with-lingui/src/utils/avatarUrl.ts | 4 + apps/with-lingui/src/utils/constants.ts | 7 + apps/with-lingui/src/utils/http.ts | 89 + apps/with-lingui/src/vite-env.d.ts | 1 + apps/with-lingui/tsconfig.json | 32 + apps/with-lingui/vite.config.ts | 44 + package.json | 18 + pnpm-lock.yaml | 4841 ++++++++++++++++ pnpm-workspace.yaml | 3 + turbo.json | 22 + 85 files changed, 16024 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 apps/with-lingui/.gitignore create mode 100644 apps/with-lingui/.oxfmt.toml create mode 100755 apps/with-lingui/.vite-hooks/pre-commit create mode 100644 apps/with-lingui/AGENTS.md create mode 100644 apps/with-lingui/README.md create mode 100644 apps/with-lingui/e2e/helpers.ts create mode 100644 apps/with-lingui/e2e/login.spec.ts create mode 100644 apps/with-lingui/e2e/users.spec.ts create mode 100644 apps/with-lingui/index.html create mode 100644 apps/with-lingui/lingui.config.ts create mode 100644 apps/with-lingui/package.json create mode 100644 apps/with-lingui/playwright.config.ts create mode 100644 apps/with-lingui/pnpm-lock.yaml create mode 100644 apps/with-lingui/public/favicon.svg create mode 100644 apps/with-lingui/public/mockServiceWorker.js create mode 100644 apps/with-lingui/src/api/auth.ts create mode 100644 apps/with-lingui/src/api/schemas.ts create mode 100644 apps/with-lingui/src/api/user.ts create mode 100644 apps/with-lingui/src/auth/session.ts create mode 100644 apps/with-lingui/src/components/Aurora/index.css create mode 100644 apps/with-lingui/src/components/Aurora/index.tsx create mode 100644 apps/with-lingui/src/components/Auth/index.tsx create mode 100644 apps/with-lingui/src/components/DataTable/DataTableEmpty.tsx create mode 100644 apps/with-lingui/src/components/DataTable/DataTableSkeleton.tsx create mode 100644 apps/with-lingui/src/components/DataTable/index.css create mode 100644 apps/with-lingui/src/components/DataTable/index.tsx create mode 100644 apps/with-lingui/src/components/FilterToolbar/index.tsx create mode 100644 apps/with-lingui/src/components/FormModal/index.tsx create mode 100644 apps/with-lingui/src/components/Icon/GitHub.tsx create mode 100644 apps/with-lingui/src/components/Icon/Theme.tsx create mode 100644 apps/with-lingui/src/components/Icon/index.tsx create mode 100644 apps/with-lingui/src/components/Layout/AppFooter/index.tsx create mode 100644 apps/with-lingui/src/components/Layout/Header/index.tsx create mode 100644 apps/with-lingui/src/components/Layout/MainLayout/index.tsx create mode 100644 apps/with-lingui/src/components/Layout/Sidebar/index.css create mode 100644 apps/with-lingui/src/components/Layout/Sidebar/index.tsx create mode 100644 apps/with-lingui/src/components/Layout/UserMenu/index.css create mode 100644 apps/with-lingui/src/components/Layout/UserMenu/index.tsx create mode 100644 apps/with-lingui/src/components/NotFound/index.tsx create mode 100644 apps/with-lingui/src/hooks/usePermission.ts create mode 100644 apps/with-lingui/src/hooks/useResourceCRUD.ts create mode 100644 apps/with-lingui/src/index.css create mode 100644 apps/with-lingui/src/lingui.d.ts create mode 100644 apps/with-lingui/src/locales/en/messages.po create mode 100644 apps/with-lingui/src/locales/zh/messages.po create mode 100644 apps/with-lingui/src/main.tsx create mode 100644 apps/with-lingui/src/mocks/browser.ts create mode 100644 apps/with-lingui/src/mocks/createHandler.ts create mode 100644 apps/with-lingui/src/mocks/data.ts create mode 100644 apps/with-lingui/src/mocks/filterUtils.ts create mode 100644 apps/with-lingui/src/mocks/handlers/auth.ts create mode 100644 apps/with-lingui/src/mocks/handlers/index.ts create mode 100644 apps/with-lingui/src/mocks/handlers/user.ts create mode 100644 apps/with-lingui/src/routeTree.gen.ts create mode 100644 apps/with-lingui/src/routes/404/index.tsx create mode 100644 apps/with-lingui/src/routes/__root.tsx create mode 100644 apps/with-lingui/src/routes/_auth.tsx create mode 100644 apps/with-lingui/src/routes/_auth/403/index.tsx create mode 100644 apps/with-lingui/src/routes/_auth/dashboard/index.css create mode 100644 apps/with-lingui/src/routes/_auth/dashboard/index.tsx create mode 100644 apps/with-lingui/src/routes/_auth/users/-FormModal.tsx create mode 100644 apps/with-lingui/src/routes/_auth/users/-Toolbar.tsx create mode 100644 apps/with-lingui/src/routes/_auth/users/index.tsx create mode 100644 apps/with-lingui/src/routes/index.tsx create mode 100644 apps/with-lingui/src/routes/login/index.css create mode 100644 apps/with-lingui/src/routes/login/index.tsx create mode 100644 apps/with-lingui/src/stores/auth.ts create mode 100644 apps/with-lingui/src/stores/createPersistentStore.ts create mode 100644 apps/with-lingui/src/stores/settings.ts create mode 100644 apps/with-lingui/src/theme/index.ts create mode 100644 apps/with-lingui/src/theme/tokenBuilders.ts create mode 100644 apps/with-lingui/src/theme/useAppTheme.ts create mode 100644 apps/with-lingui/src/utils/appMenu.ts create mode 100644 apps/with-lingui/src/utils/avatarUrl.ts create mode 100644 apps/with-lingui/src/utils/constants.ts create mode 100644 apps/with-lingui/src/utils/http.ts create mode 100644 apps/with-lingui/src/vite-env.d.ts create mode 100644 apps/with-lingui/tsconfig.json create mode 100644 apps/with-lingui/vite.config.ts create mode 100644 package.json create mode 100644 pnpm-lock.yaml create mode 100644 pnpm-workspace.yaml create mode 100644 turbo.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d67bdf6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,44 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# Dependencies +node_modules +.pnp +.pnp.js + +# Local env files +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# Testing +coverage + +# Turbo +.turbo + +# Vercel +.vercel + +# Build Outputs +.next/ +out/ +build +dist + + +# Debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Misc +.DS_Store +*.pem + +.pnpm-store + +# Git worktrees +.worktrees/ +.cursor \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..8c1aa73 --- /dev/null +++ b/README.md @@ -0,0 +1,182 @@ +

+ + antd-admin-logo + +

+ +

Antd Admin

+ +
+ +Balanced admin scaffold: i18n (Lingui), MSW mocks, minimal RBAC, full CRUD, and Playwright E2E — built with React 19, Ant Design 6, and Vite+. AI-friendly with clear patterns, shared abstractions, scoped AI instructions, and type-safe contracts at every boundary. + +[![antd](https://img.shields.io/badge/AntD-^6.0.0-1890ff?style=flat-square&logo=ant-design)](https://github.com/ant-design/ant-design) +[![react](https://img.shields.io/badge/React-19.2-61dafb?style=flat-square&logo=react)](https://react.dev) +[![vite](https://img.shields.io/badge/Vite+-Latest-646cff?style=flat-square&logo=vite)](https://viteplus.dev) +[![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-3178c6?style=flat-square&logo=typescript)](https://www.typescriptlang.org/) +[![GitHub issues](https://img.shields.io/github/issues/zuiidea/antd-admin?style=flat-square)](https://github.com/zuiidea/antd-admin/issues) +[![GitHub stars](https://img.shields.io/github/stars/zuiidea/antd-admin?style=flat-square)](https://github.com/zuiidea/antd-admin/stargazers) +[![License](https://img.shields.io/badge/License-MIT-blue?style=flat-square)](http://opensource.org/licenses/MIT) +[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen?style=flat-square)](https://github.com/zuiidea/antd-admin/pulls) + +
+ +## Tech Stack + +| Category | Technology | +| ------------ | ---------------------------------------------------------------------- | +| Build Tool | [Vite+](https://viteplus.dev) (VoidZero unified toolchain) | +| UI Framework | [Ant Design 6.x](https://ant.design) | +| Routing | [TanStack Router](https://tanstack.com/router) (file-based, type-safe) | +| Async State | [TanStack Query v5](https://tanstack.com/query) | +| Local State | [Zustand](https://zustand.docs.pmnd.rs) (persisted auth & settings) | +| Validation | [Zod v4](https://zod.dev) (schemas, API contracts, form validation) | +| i18n | [LinguiJS](https://lingui.dev) (en + zh catalogs) | +| Icons | [lucide-react](https://lucide.dev/guide/packages/lucide-react) | +| API Mocking | [MSW 2.x](https://mswjs.io) (Service Worker based) | +| E2E Testing | [Playwright](https://playwright.dev) | +| Language | TypeScript 5.9 (strict mode) | + +## Features + +- **JWT Authentication** — Login with access/refresh token flow, persisted via Zustand +- **Dynamic Menu & RBAC** — Backend-driven sidebar menu with permission guards and 403 page +- **URL-First State** — Table search params (page, pageSize, keyword, sort) synced to URL +- **i18n** — LinguiJS with English (`en`) and Chinese (`zh`); Ant Design locales wired in root +- **Dark Mode** — One-click toggle with Ant Design theme algorithm +- **Full Type Safety** — Zod schemas validate API boundaries at runtime where used +- **Zero-Config Mocking** — MSW intercepts API calls in development, no backend needed + +## Getting Started + +### Prerequisites + +- [Node.js](https://nodejs.org) >= 20 +- [Vite+](https://viteplus.dev/guide/) CLI (`vp`) + +### Install & Run + +```bash +vp install +vp dev +``` + +Open [http://localhost:5173](http://localhost:5173) — you'll be redirected to the login page. + +**Default credentials:** `admin` / `admin` + +### Build + +```bash +vp build +vp preview +``` + +### E2E Tests + +```bash +vp run test:e2e +vp run test:e2e:core +vp run test:e2e:ui # interactive UI mode +``` + +`test:e2e:core` runs the scaffold's highest-value flows only: login and users CRUD. + +## Project Structure + +``` +src/ +├── api/ # Zod schemas, endpoint constants, type exports +│ ├── schemas.ts # Domain models (User, AuthTokens, MenuItem, etc.) +│ ├── auth.ts # Auth endpoint constants +│ └── user.ts # User CRUD endpoint constants +├── components/ +│ ├── Aurora/ # Login background effect +│ ├── Auth/ # Auth (permission gate): index.tsx +│ ├── DataTable/ # Shared table shell, skeleton, empty state +│ ├── FilterToolbar/ # Shared filter/action toolbar +│ ├── FormModal/ # Reusable modal + form shell +│ ├── Icon/ # Shared icons and theme toggle icon +│ └── Layout/ # Admin shell (sidebar, header, main) +│ ├── MainLayout/ # Main layout shell: index.tsx +│ ├── AppFooter/ # Login footer: Powered by + GitHub → zuiidea/antd-admin +│ ├── Sidebar/ # Dynamic menu sidebar: index.tsx +│ ├── UserMenu/ # User dropdown in sidebar: index.tsx + index.css +│ └── Header/ # Top bar: index.tsx +├── hooks/ +│ ├── usePermission.ts # Permission check hook +│ └── useResourceCRUD.ts # Shared CRUD query/mutation wiring +├── utils/ +│ ├── constants.ts # API base URL, static assets +│ └── http.ts # HTTP client with JWT injection & error handling +├── locales/ # LinguiJS catalogs (.po + compiled .js) +│ ├── en/messages.po +│ └── zh/messages.po +├── mocks/ +│ ├── browser.ts # MSW worker setup +│ ├── createHandler.ts # Shared MSW success/error/delay helpers +│ ├── data.ts # Mock seed data (users, menus) +│ ├── filterUtils.ts # Mock-only filtering and pagination helpers +│ └── handlers/ # Request handlers (auth, user CRUD) +├── routes/ # TanStack Router file-based routes +│ ├── __root.tsx # Root layout (QueryClient, ConfigProvider, I18n) +│ ├── _auth.tsx # Auth guard layout (redirects to /login) +│ ├── _auth/dashboard/index.tsx +│ ├── _auth/users/index.tsx # Full CRUD with URL-synced search params +│ ├── _auth/403/index.tsx +│ ├── login/index.tsx +│ ├── 404/index.tsx +│ └── index.tsx # Redirects / → /login +├── stores/ +│ ├── auth.ts # Auth store (tokens, user, menus, permissions) +│ ├── createPersistentStore.ts # Shared persisted-store factory +│ └── settings.ts # Settings store (darkMode, locale, sidebar) +├── theme/ +│ ├── tokenBuilders.ts # Shared Ant Design token/config builders +│ └── useAppTheme.ts # Theme selection hook +└── main.tsx # Entry point (MSW init → React render) + +tests/ +└── e2e/ # Playwright E2E tests + ├── helpers.ts + ├── login.spec.ts + └── users.spec.ts +``` + +## Internationalization (i18n) + +The project uses [LinguiJS](https://lingui.dev) with compile-time macros. Locales: `**en**` (source) and `**zh**`. + +### Workflow + +```bash +vp run i18n:extract +vp run i18n:compile +``` + +Ant Design strings follow the active locale via `ConfigProvider` in `__root.tsx`. + +## Extending the template + +- **Real backend:** Point `VITE_API_BASE_URL` in env and disable or remove MSW in `main.tsx` when you no longer need mocks. +- **Drop i18n:** Remove Lingui packages, vite/swc plugins, and replace `t` macros with plain strings (larger refactor). + +## Developer Notes + +- Prefer Vite+ commands for installs, checks, and scripts. This repo is configured around `vp`. +- Run `vp check --no-fmt` for type/lint validation. +- Core regression coverage lives in the login and users E2E flows. + +## Pages + +| Route | Description | +| ------------ | ----------------------------------------------------------- | +| `/login` | Login form with validation | +| `/dashboard` | Statistics overview cards | +| `/users` | User CRUD table with search, pagination, create/edit/delete | +| `/403` | Forbidden error page | +| `/404` | Not found error page | + +## License + +MIT diff --git a/apps/with-lingui/.gitignore b/apps/with-lingui/.gitignore new file mode 100644 index 0000000..a96778c --- /dev/null +++ b/apps/with-lingui/.gitignore @@ -0,0 +1,36 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# LinguiJS compiled catalogs +src/locales/*/messages.js + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +.agent +.pnpm-store +.cursor +.tanstack + +# Playwright +playwright-report +test-results \ No newline at end of file diff --git a/apps/with-lingui/.oxfmt.toml b/apps/with-lingui/.oxfmt.toml new file mode 100644 index 0000000..7764085 --- /dev/null +++ b/apps/with-lingui/.oxfmt.toml @@ -0,0 +1,25 @@ +# oxfmt configuration for antd-admin +# Reference: https://oxc.rs/docs/guide/formatter + +# Line width for formatting +line_width = 100 + +# Indentation +indent_width = 2 +use_tabs = false + +# Semicolons +semi = true + +# Quotes +single_quote = false + +# Trailing commas +trailing_comma = "es5" + +# Arrows +arrow_parens = "always" + +# Spaces +bracket_spacing = true +space_before_function_parentheses = false diff --git a/apps/with-lingui/.vite-hooks/pre-commit b/apps/with-lingui/.vite-hooks/pre-commit new file mode 100755 index 0000000..85fb65b --- /dev/null +++ b/apps/with-lingui/.vite-hooks/pre-commit @@ -0,0 +1 @@ +vp staged diff --git a/apps/with-lingui/AGENTS.md b/apps/with-lingui/AGENTS.md new file mode 100644 index 0000000..49ea51f --- /dev/null +++ b/apps/with-lingui/AGENTS.md @@ -0,0 +1,84 @@ +# Using Vite+, the Unified Toolchain for the Web + +This project is using Vite+, a unified toolchain built on top of Vite, Rolldown, Vitest, tsdown, Oxlint, Oxfmt, and Vite Task. Vite+ wraps runtime management, package management, and frontend tooling in a single global CLI called `vp`. Vite+ is distinct from Vite, but it invokes Vite through `vp dev` and `vp build`. + +## Vite+ Workflow + +`vp` is a global binary that handles the full development lifecycle. Run `vp help` to print a list of commands and `vp --help` for information about a specific command. + +### Start + +- create - Create a new project from a template +- migrate - Migrate an existing project to Vite+ +- config - Configure hooks and agent integration +- staged - Run linters on staged files +- install (`i`) - Install dependencies +- env - Manage Node.js versions + +### Develop + +- dev - Run the development server +- check - Run format, lint, and TypeScript type checks +- lint - Lint code +- fmt - Format code +- test - Run tests + +### Execute + +- run - Run monorepo tasks +- exec - Execute a command from local `node_modules/.bin` +- dlx - Execute a package binary without installing it as a dependency +- cache - Manage the task cache + +### Build + +- build - Build for production +- pack - Build libraries +- preview - Preview production build + +### Manage Dependencies + +Vite+ automatically detects and wraps the underlying package manager such as pnpm, npm, or Yarn through the `packageManager` field in `package.json` or package manager-specific lockfiles. + +- add - Add packages to dependencies +- remove (`rm`, `un`, `uninstall`) - Remove packages from dependencies +- update (`up`) - Update packages to latest versions +- dedupe - Deduplicate dependencies +- outdated - Check for outdated packages +- list (`ls`) - List installed packages +- why (`explain`) - Show why a package is installed +- info (`view`, `show`) - View package information from the registry +- link (`ln`) / unlink - Manage local package links +- pm - Forward a command to the package manager + +### Maintain + +- upgrade - Update `vp` itself to the latest version + +These commands map to their corresponding tools. For example, `vp dev --port 3000` runs Vite's dev server and works the same as Vite. `vp test` runs JavaScript tests through the bundled Vitest. The version of all tools can be checked using `vp --version`. This is useful when researching documentation, features, and bugs. + +## Common Pitfalls + +- **Using the package manager directly:** Do not use pnpm, npm, or Yarn directly. Vite+ can handle all package manager operations. +- **Always use Vite commands to run tools:** Don't attempt to run `vp vitest` or `vp oxlint`. They do not exist. Use `vp test` and `vp lint` instead. +- **Running scripts:** Vite+ commands take precedence over `package.json` scripts. If there is a `test` script defined in `scripts` that conflicts with the built-in `vp test` command, run it using `vp run test`. +- **Do not install Vitest, Oxlint, Oxfmt, or tsdown directly:** Vite+ wraps these tools. They must not be installed directly. You cannot upgrade these tools by installing their latest versions. Always use Vite+ commands. +- **Use Vite+ wrappers for one-off binaries:** Use `vp dlx` instead of package-manager-specific `dlx`/`npx` commands. +- **Import JavaScript modules from `vite-plus`:** Instead of importing from `vite` or `vitest`, all modules should be imported from the project's `vite-plus` dependency. For example, `import { defineConfig } from 'vite-plus';` or `import { expect, test, vi } from 'vite-plus/test';`. You must not install `vitest` to import test utilities. +- **Type-Aware Linting:** There is no need to install `oxlint-tsgolint`, `vp lint --type-aware` works out of the box. + +## Review Checklist for Agents + +- Run `vp install` after pulling remote changes and before getting started. +- Run `vp check` and `vp test` to validate changes. + +## AI Instruction Files + +This repository also uses scoped AI instruction files in `.github/instructions/`. + +- `frontend.instructions.md` for UI/routes/components/style work +- `testing.instructions.md` for Playwright/MSW/test updates +- `api.instructions.md` for API/schema/handler changes +- `refactor.instructions.md` for behavior-preserving cleanup + +See `.github/instructions/README.md` for usage and authoring rules. diff --git a/apps/with-lingui/README.md b/apps/with-lingui/README.md new file mode 100644 index 0000000..99a8fa4 --- /dev/null +++ b/apps/with-lingui/README.md @@ -0,0 +1,182 @@ +

+ + antd-admin-logo + +

+ +

Antd Admin

+ +
+ +Balanced admin scaffold: i18n (Lingui), MSW mocks, minimal RBAC, full CRUD, and Playwright E2E — built with React 19, Ant Design 6, and Vite+. AI-friendly with clear patterns, shared abstractions, scoped AI instructions, and type-safe contracts at every boundary. + +[![antd](https://img.shields.io/badge/AntD-^6.0.0-1890ff?style=flat-square&logo=ant-design)](https://github.com/ant-design/ant-design) +[![react](https://img.shields.io/badge/React-19.2-61dafb?style=flat-square&logo=react)](https://react.dev) +[![vite](https://img.shields.io/badge/Vite+-Latest-646cff?style=flat-square&logo=vite)](https://viteplus.dev) +[![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-3178c6?style=flat-square&logo=typescript)](https://www.typescriptlang.org/) +[![GitHub issues](https://img.shields.io/github/issues/zuiidea/antd-admin?style=flat-square)](https://github.com/zuiidea/antd-admin/issues) +[![GitHub stars](https://img.shields.io/github/stars/zuiidea/antd-admin?style=flat-square)](https://github.com/zuiidea/antd-admin/stargazers) +[![License](https://img.shields.io/badge/License-MIT-blue?style=flat-square)](http://opensource.org/licenses/MIT) +[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen?style=flat-square)](https://github.com/zuiidea/antd-admin/pulls) + +
+ +## Tech Stack + +| Category | Technology | +| ------------ | ---------------------------------------------------------------------- | +| Build Tool | [Vite+](https://viteplus.dev) (VoidZero unified toolchain) | +| UI Framework | [Ant Design 6.x](https://ant.design) | +| Routing | [TanStack Router](https://tanstack.com/router) (file-based, type-safe) | +| Async State | [TanStack Query v5](https://tanstack.com/query) | +| Local State | [Zustand](https://zustand.docs.pmnd.rs) (persisted auth & settings) | +| Validation | [Zod v4](https://zod.dev) (schemas, API contracts, form validation) | +| i18n | [LinguiJS](https://lingui.dev) (en + zh catalogs) | +| Icons | [lucide-react](https://lucide.dev/guide/packages/lucide-react) | +| API Mocking | [MSW 2.x](https://mswjs.io) (Service Worker based) | +| E2E Testing | [Playwright](https://playwright.dev) | +| Language | TypeScript 5.9 (strict mode) | + +## Features + +- **JWT Authentication** — Login with access/refresh token flow, persisted via Zustand +- **Dynamic Menu & RBAC** — Backend-driven sidebar menu with permission guards and 403 page +- **URL-First State** — Table search params (page, pageSize, keyword, sort) synced to URL +- **i18n** — LinguiJS with English (`en`) and Chinese (`zh`); Ant Design locales wired in root +- **Dark Mode** — One-click toggle with Ant Design theme algorithm +- **Full Type Safety** — Zod schemas validate API boundaries at runtime where used +- **Zero-Config Mocking** — MSW intercepts API calls in development, no backend needed + +## Getting Started + +### Prerequisites + +- [Node.js](https://nodejs.org) >= 20 +- [Vite+](https://viteplus.dev/guide/) CLI (`vp`) + +### Install & Run + +```bash +vp install +vp dev +``` + +Open [http://localhost:5173](http://localhost:5173) — you'll be redirected to the login page. + +**Default credentials:** `admin` / `admin` + +### Build + +```bash +vp build +vp preview +``` + +### E2E Tests + +```bash +vp run test:e2e +vp run test:e2e:core +vp run test:e2e:ui # interactive UI mode +``` + +`test:e2e:core` runs the scaffold's highest-value flows only: login and users CRUD. + +## Project Structure + +``` +src/ +├── api/ # Zod schemas, endpoint constants, type exports +│ ├── schemas.ts # Domain models (User, AuthTokens, MenuItem, etc.) +│ ├── auth.ts # Auth endpoint constants +│ └── user.ts # User CRUD endpoint constants +├── components/ +│ ├── Aurora/ # Login background effect +│ ├── Auth/ # Auth (permission gate): index.tsx +│ ├── DataTable/ # Shared table shell, skeleton, empty state +│ ├── FilterToolbar/ # Shared filter/action toolbar +│ ├── FormModal/ # Reusable modal + form shell +│ ├── Icon/ # Shared icons and theme toggle icon +│ └── Layout/ # Admin shell (sidebar, header, main) +│ ├── MainLayout/ # Main layout shell: index.tsx +│ ├── AppFooter/ # Login footer: Powered by + GitHub → zuiidea/antd-admin +│ ├── Sidebar/ # Dynamic menu sidebar: index.tsx +│ ├── UserMenu/ # User dropdown in sidebar: index.tsx + index.css +│ └── Header/ # Top bar: index.tsx +├── hooks/ +│ ├── usePermission.ts # Permission check hook +│ └── useResourceCRUD.ts # Shared CRUD query/mutation wiring +├── utils/ +│ ├── constants.ts # API base URL, static assets +│ └── http.ts # HTTP client with JWT injection & error handling +├── locales/ # LinguiJS catalogs (.po + compiled .js) +│ ├── en/messages.po +│ └── zh/messages.po +├── mocks/ +│ ├── browser.ts # MSW worker setup +│ ├── createHandler.ts # Shared MSW success/error/delay helpers +│ ├── data.ts # Mock seed data (users, menus) +│ ├── filterUtils.ts # Mock-only filtering and pagination helpers +│ └── handlers/ # Request handlers (auth, user CRUD) +├── routes/ # TanStack Router file-based routes +│ ├── __root.tsx # Root layout (QueryClient, ConfigProvider, I18n) +│ ├── _auth.tsx # Auth guard layout (redirects to /login) +│ ├── _auth/dashboard/index.tsx +│ ├── _auth/users/index.tsx # Full CRUD with URL-synced search params +│ ├── _auth/403/index.tsx +│ ├── login/index.tsx +│ ├── 404/index.tsx +│ └── index.tsx # Redirects / → /login +├── stores/ +│ ├── auth.ts # Auth store (tokens, user, menus, permissions) +│ ├── createPersistentStore.ts # Shared persisted-store factory +│ └── settings.ts # Settings store (darkMode, locale, sidebar) +├── theme/ +│ ├── tokenBuilders.ts # Shared Ant Design token/config builders +│ └── useAppTheme.ts # Theme selection hook +└── main.tsx # Entry point (MSW init → React render) + +tests/ +└── e2e/ # Playwright E2E tests + ├── helpers.ts + ├── login.spec.ts + └── users.spec.ts +``` + +## Internationalization (i18n) + +The project uses [LinguiJS](https://lingui.dev) with compile-time macros. Locales: `**en**` (source) and `**zh**`. + +### Workflow + +```bash +vp run i18n:extract +vp run i18n:compile +``` + +Ant Design strings follow the active locale via `ConfigProvider` in `__root.tsx`. + +## Extending the template + +- **Real backend:** Point `VITE_API_BASE_URL` in env and disable or remove MSW in `main.tsx` when you no longer need mocks. +- **Drop i18n:** Remove Lingui packages, vite/swc plugins, and replace `t` macros with plain strings (larger refactor). + +## Developer Notes + +- Prefer Vite+ commands for installs, checks, and scripts. This repo is configured around `vp`. +- Run `vp check --no-fmt` for type/lint validation. +- Core regression coverage lives in the login and users E2E flows. + +## Pages + +| Route | Description | +| ------------ | ----------------------------------------------------------- | +| `/login` | Login form with validation | +| `/dashboard` | Statistics overview cards | +| `/users` | User CRUD table with search, pagination, create/edit/delete | +| `/403` | Forbidden error page | +| `/404` | Not found error page | + +## License + +MIT diff --git a/apps/with-lingui/e2e/helpers.ts b/apps/with-lingui/e2e/helpers.ts new file mode 100644 index 0000000..ae5ec6b --- /dev/null +++ b/apps/with-lingui/e2e/helpers.ts @@ -0,0 +1,16 @@ +import { expect } from "@playwright/test"; +import type { Page } from "@playwright/test"; + +export async function loginAsAdmin(page: Page) { + await page.goto("/login"); + await page.getByLabel(/Username|用户名/).fill("admin"); + await page.getByLabel(/Password|密码/).fill("admin"); + await page.getByRole("button", { name: /Sign In|登录/ }).click(); + await expect(page).toHaveURL(/dashboard/); +} + +export async function gotoUsers(page: Page) { + await loginAsAdmin(page); + await page.goto("/users"); + await expect(page).toHaveURL(/users/); +} diff --git a/apps/with-lingui/e2e/login.spec.ts b/apps/with-lingui/e2e/login.spec.ts new file mode 100644 index 0000000..c0304d7 --- /dev/null +++ b/apps/with-lingui/e2e/login.spec.ts @@ -0,0 +1,27 @@ +import { test, expect } from "@playwright/test"; +import { loginAsAdmin } from "./helpers"; + +test.describe("Login Flow", () => { + test.beforeEach(async ({ page }) => { + await page.goto("/login"); + }); + + test("should display login form", async ({ page }) => { + await expect(page.getByLabel(/Username|用户名/)).toBeVisible(); + await expect(page.getByLabel(/Password|密码/)).toBeVisible(); + await expect(page.getByRole("button", { name: /Sign In|登录/ })).toBeVisible(); + }); + + test("should login successfully with admin/admin", async ({ page }) => { + await loginAsAdmin(page); + await expect(page.getByText("Total Revenue")).toBeVisible(); + }); + + test("should show error for wrong credentials", async ({ page }) => { + await page.getByLabel(/Username|用户名/).fill("wrong"); + await page.getByLabel(/Password|密码/).fill("wrong"); + await page.getByRole("button", { name: /Sign In|登录/ }).click(); + + await expect(page.getByText("Invalid username or password")).toBeVisible(); + }); +}); diff --git a/apps/with-lingui/e2e/users.spec.ts b/apps/with-lingui/e2e/users.spec.ts new file mode 100644 index 0000000..e187e5e --- /dev/null +++ b/apps/with-lingui/e2e/users.spec.ts @@ -0,0 +1,43 @@ +import { test, expect } from "@playwright/test"; +import { gotoUsers, loginAsAdmin } from "./helpers"; + +test.describe("User Management", () => { + test.beforeEach(async ({ page }) => { + await gotoUsers(page); + }); + + test("should display user table", async ({ page }) => { + const thead = page.locator(".ant-table-thead"); + await expect(thead.getByText(/Username|用户名/)).toBeVisible(); + await expect(thead.getByText(/Email|邮箱/)).toBeVisible(); + await expect(thead.getByText(/Roles|角色/)).toBeVisible(); + }); + + test("should search users", async ({ page }) => { + const searchInput = page.getByPlaceholder(/Search User|搜索用户/); + await searchInput.fill("zhao.ming"); + await searchInput.press("Enter"); + await expect(page).toHaveURL(/keyword=zhao\.ming/); + /* Avoid strict-mode match on email cell containing substring "zhao.ming" */ + await expect(page.getByText("zhao.ming", { exact: true })).toBeVisible(); + }); + + test("should open create user modal", async ({ page }) => { + await page.getByRole("button", { name: /Create User|创建用户/ }).click(); + await expect(page.getByRole("dialog").getByText(/New User|新建用户/)).toBeVisible(); + }); +}); + +/** Avoid a second full `page.goto` after `/users`: reload can land on login before auth rehydrates. */ +test.describe("User Management — role in URL", () => { + test.beforeEach(async ({ page }) => { + await loginAsAdmin(page); + await page.goto("/users?role=admin"); + await expect(page.getByPlaceholder(/Search User|搜索用户/)).toBeVisible({ timeout: 15_000 }); + }); + + test("should filter users by role", async ({ page }) => { + await expect(page).toHaveURL(/role=admin/); + await expect(page.getByRole("cell", { name: "ops.admin@northstar.io" })).toBeVisible(); + }); +}); diff --git a/apps/with-lingui/index.html b/apps/with-lingui/index.html new file mode 100644 index 0000000..9232c24 --- /dev/null +++ b/apps/with-lingui/index.html @@ -0,0 +1,20 @@ + + + + + + + + + Antd Admin + + + +
+ + + diff --git a/apps/with-lingui/lingui.config.ts b/apps/with-lingui/lingui.config.ts new file mode 100644 index 0000000..5f2cdfe --- /dev/null +++ b/apps/with-lingui/lingui.config.ts @@ -0,0 +1,13 @@ +const config = { + locales: ["en", "zh"], + sourceLocale: "en", + catalogs: [ + { + path: "src/locales/{locale}/messages", + include: ["src"], + }, + ], + format: "po", +}; + +export default config; diff --git a/apps/with-lingui/package.json b/apps/with-lingui/package.json new file mode 100644 index 0000000..e58e4c0 --- /dev/null +++ b/apps/with-lingui/package.json @@ -0,0 +1,62 @@ +{ + "name": "antd-admin", + "version": "6.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vp dev", + "build": "tsc && vp build", + "preview": "vp preview", + "prepare": "vp config", + "fmt": "vp fmt", + "lint": "vp lint", + "check": "vp check --no-fmt", + "test:e2e": "playwright test", + "test:e2e:core": "playwright test tests/e2e/login.spec.ts tests/e2e/users.spec.ts", + "test:e2e:ui": "playwright test --ui", + "i18n:extract": "vp exec lingui extract", + "i18n:compile": "vp exec lingui compile" + }, + "dependencies": { + "@lingui/core": "^5.9.3", + "@lingui/react": "^5.9.3", + "@tanstack/react-query": "^5.90.21", + "@tanstack/react-router": "^1.167.4", + "antd": "^6.3.3", + "lucide-react": "^1.7.0", + "react": "^19.2.4", + "react-dom": "^19.2.4", + "zod": "^4.3.6", + "zustand": "^5.0.12" + }, + "devDependencies": { + "@lingui/cli": "^5.9.3", + "@lingui/swc-plugin": "^5.11.0", + "@lingui/vite-plugin": "^5.9.3", + "@playwright/test": "^1.58.2", + "@tanstack/router-plugin": "^1.166.13", + "@types/react": "^19.2.14", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react-swc": "^4.3.0", + "msw": "^2.12.12", + "typescript": "~5.9.3", + "vite": "npm:@voidzero-dev/vite-plus-core@latest", + "vite-plus": "latest" + }, + "packageManager": "pnpm@10.32.1", + "pnpm": { + "overrides": { + "vite": "npm:@voidzero-dev/vite-plus-core@latest", + "vitest": "npm:@voidzero-dev/vite-plus-test@latest" + }, + "onlyBuiltDependencies": [ + "esbuild", + "msw" + ] + }, + "msw": { + "workerDirectory": [ + "public" + ] + } +} diff --git a/apps/with-lingui/playwright.config.ts b/apps/with-lingui/playwright.config.ts new file mode 100644 index 0000000..b04afbf --- /dev/null +++ b/apps/with-lingui/playwright.config.ts @@ -0,0 +1,30 @@ +import { defineConfig, devices } from "@playwright/test"; + +/** Node global when `tsconfig` does not include `@types/node` (pre-commit may lint before lockfile updates). */ +declare const process: { env: { CI?: string } }; + +const ci = Boolean(process.env.CI); + +export default defineConfig({ + testDir: "./tests/e2e", + fullyParallel: true, + forbidOnly: ci, + retries: ci ? 2 : 0, + workers: ci ? 1 : undefined, + reporter: "html", + use: { + baseURL: "http://localhost:5173", + trace: "on-first-retry", + }, + projects: [ + { + name: "chromium", + use: { ...devices["Desktop Chrome"] }, + }, + ], + webServer: { + command: "vp dev", + url: "http://localhost:5173", + reuseExistingServer: !ci, + }, +}); diff --git a/apps/with-lingui/pnpm-lock.yaml b/apps/with-lingui/pnpm-lock.yaml new file mode 100644 index 0000000..f587706 --- /dev/null +++ b/apps/with-lingui/pnpm-lock.yaml @@ -0,0 +1,4876 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +overrides: + vite: npm:@voidzero-dev/vite-plus-core@latest + vitest: npm:@voidzero-dev/vite-plus-test@latest + +importers: + + .: + dependencies: + '@lingui/core': + specifier: ^5.9.3 + version: 5.9.3(@lingui/babel-plugin-lingui-macro@5.9.3(babel-plugin-macros@3.1.0)(typescript@5.9.3))(babel-plugin-macros@3.1.0) + '@lingui/react': + specifier: ^5.9.3 + version: 5.9.3(@lingui/babel-plugin-lingui-macro@5.9.3(babel-plugin-macros@3.1.0)(typescript@5.9.3))(babel-plugin-macros@3.1.0)(react@19.2.4) + '@tanstack/react-query': + specifier: ^5.90.21 + version: 5.90.21(react@19.2.4) + '@tanstack/react-router': + specifier: ^1.167.4 + version: 1.167.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + antd: + specifier: ^6.3.3 + version: 6.3.3(date-fns@3.6.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + lucide-react: + specifier: ^1.7.0 + version: 1.7.0(react@19.2.4) + react: + specifier: ^19.2.4 + version: 19.2.4 + react-dom: + specifier: ^19.2.4 + version: 19.2.4(react@19.2.4) + zod: + specifier: ^4.3.6 + version: 4.3.6 + zustand: + specifier: ^5.0.12 + version: 5.0.12(@types/react@19.2.14)(react@19.2.4)(use-sync-external-store@1.6.0(react@19.2.4)) + devDependencies: + '@lingui/cli': + specifier: ^5.9.3 + version: 5.9.3(babel-plugin-macros@3.1.0)(typescript@5.9.3) + '@lingui/swc-plugin': + specifier: ^5.11.0 + version: 5.11.0(@lingui/core@5.9.3(@lingui/babel-plugin-lingui-macro@5.9.3(babel-plugin-macros@3.1.0)(typescript@5.9.3))(babel-plugin-macros@3.1.0)) + '@lingui/vite-plugin': + specifier: ^5.9.3 + version: 5.9.3(@voidzero-dev/vite-plus-core@0.1.12(@types/node@25.6.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(typescript@5.9.3))(babel-plugin-macros@3.1.0)(typescript@5.9.3) + '@playwright/test': + specifier: ^1.58.2 + version: 1.58.2 + '@tanstack/router-plugin': + specifier: ^1.166.13 + version: 1.166.13(@tanstack/react-router@1.167.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@voidzero-dev/vite-plus-core@0.1.12(@types/node@25.6.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(typescript@5.9.3)) + '@types/react': + specifier: ^19.2.14 + version: 19.2.14 + '@types/react-dom': + specifier: ^19.2.3 + version: 19.2.3(@types/react@19.2.14) + '@vitejs/plugin-react-swc': + specifier: ^4.3.0 + version: 4.3.0(@voidzero-dev/vite-plus-core@0.1.12(@types/node@25.6.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(typescript@5.9.3)) + msw: + specifier: ^2.12.12 + version: 2.12.12(@types/node@25.6.0)(typescript@5.9.3) + typescript: + specifier: ~5.9.3 + version: 5.9.3 + vite: + specifier: npm:@voidzero-dev/vite-plus-core@latest + version: '@voidzero-dev/vite-plus-core@0.1.12(@types/node@25.6.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(typescript@5.9.3)' + vite-plus: + specifier: latest + version: 0.1.12(@types/node@25.6.0)(@voidzero-dev/vite-plus-core@0.1.12(@types/node@25.6.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(typescript@5.9.3))(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(typescript@5.9.3) + +packages: + + '@ant-design/colors@8.0.1': + resolution: {integrity: sha512-foPVl0+SWIslGUtD/xBr1p9U4AKzPhNYEseXYRRo5QSzGACYZrQbe11AYJbYfAWnWSpGBx6JjBmSeugUsD9vqQ==} + + '@ant-design/cssinjs-utils@2.1.2': + resolution: {integrity: sha512-5fTHQ158jJJ5dC/ECeyIdZUzKxE/mpEMRZxthyG1sw/AKRHKgJBg00Yi6ACVXgycdje7KahRNvNET/uBccwCnA==} + peerDependencies: + react: '>=18' + react-dom: '>=18' + + '@ant-design/cssinjs@2.1.2': + resolution: {integrity: sha512-2Hy8BnCEH31xPeSLbhhB2ctCPXE2ZnASdi+KbSeS79BNbUhL9hAEe20SkUk+BR8aKTmqb6+FKFruk7w8z0VoRQ==} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + + '@ant-design/fast-color@3.0.1': + resolution: {integrity: sha512-esKJegpW4nckh0o6kV3Tkb7NPIZYbPnnFxmQDUmL08ukXZAvV85TZBr70eGuke/CIArLaP6aw8lt9KILjnWuOw==} + engines: {node: '>=8.x'} + + '@ant-design/icons-svg@4.4.2': + resolution: {integrity: sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==} + + '@ant-design/icons@6.1.0': + resolution: {integrity: sha512-KrWMu1fIg3w/1F2zfn+JlfNDU8dDqILfA5Tg85iqs1lf8ooyGlbkA+TkwfOKKgqpUmAiRY1PTFpuOU2DAIgSUg==} + engines: {node: '>=8'} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + + '@ant-design/react-slick@2.0.0': + resolution: {integrity: sha512-HMS9sRoEmZey8LsE/Yo6+klhlzU12PisjrVcydW3So7RdklyEd2qehyU6a7Yp+OYN72mgsYs3NFCyP2lCPFVqg==} + peerDependencies: + react: ^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^0.14.0 || ^15.0.1 || ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + '@babel/code-frame@7.29.0': + resolution: {integrity: sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.29.0': + resolution: {integrity: sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.29.0': + resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==} + engines: {node: '>=6.9.0'} + + '@babel/generator@7.29.1': + resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.28.6': + resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-globals@7.28.0': + resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.28.6': + resolution: {integrity: sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.28.6': + resolution: {integrity: sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-plugin-utils@7.28.6': + resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} + 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.28.5': + resolution: {integrity: sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.27.1': + resolution: {integrity: sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.29.2': + resolution: {integrity: sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.29.2': + resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-syntax-jsx@7.28.6': + resolution: {integrity: sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.28.6': + resolution: {integrity: sha512-+nDNmQye7nlnuuHDboPbGm00Vqg3oO8niRRL27/4LYHUsHYh0zJ1xWOz0uRwNFmM1Avzk8wZbc6rdiYhomzv/A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/runtime@7.29.2': + resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==} + engines: {node: '>=6.9.0'} + + '@babel/template@7.28.6': + resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.29.0': + resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.29.0': + resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} + engines: {node: '>=6.9.0'} + + '@emotion/hash@0.8.0': + resolution: {integrity: sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==} + + '@emotion/unitless@0.7.5': + resolution: {integrity: sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==} + + '@esbuild/aix-ppc64@0.25.12': + resolution: {integrity: sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/aix-ppc64@0.27.4': + resolution: {integrity: sha512-cQPwL2mp2nSmHHJlCyoXgHGhbEPMrEEU5xhkcy3Hs/O7nGZqEpZ2sUtLaL9MORLtDfRvVl2/3PAuEkYZH0Ty8Q==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.25.12': + resolution: {integrity: sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm64@0.27.4': + resolution: {integrity: sha512-gdLscB7v75wRfu7QSm/zg6Rx29VLdy9eTr2t44sfTW7CxwAtQghZ4ZnqHk3/ogz7xao0QAgrkradbBzcqFPasw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.25.12': + resolution: {integrity: sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-arm@0.27.4': + resolution: {integrity: sha512-X9bUgvxiC8CHAGKYufLIHGXPJWnr0OCdR0anD2e21vdvgCI8lIfqFbnoeOz7lBjdrAGUhqLZLcQo6MLhTO2DKQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.25.12': + resolution: {integrity: sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/android-x64@0.27.4': + resolution: {integrity: sha512-PzPFnBNVF292sfpfhiyiXCGSn9HZg5BcAz+ivBuSsl6Rk4ga1oEXAamhOXRFyMcjwr2DVtm40G65N3GLeH1Lvw==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.25.12': + resolution: {integrity: sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-arm64@0.27.4': + resolution: {integrity: sha512-b7xaGIwdJlht8ZFCvMkpDN6uiSmnxxK56N2GDTMYPr2/gzvfdQN8rTfBsvVKmIVY/X7EM+/hJKEIbbHs9oA4tQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.12': + resolution: {integrity: sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/darwin-x64@0.27.4': + resolution: {integrity: sha512-sR+OiKLwd15nmCdqpXMnuJ9W2kpy0KigzqScqHI3Hqwr7IXxBp3Yva+yJwoqh7rE8V77tdoheRYataNKL4QrPw==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.25.12': + resolution: {integrity: sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-arm64@0.27.4': + resolution: {integrity: sha512-jnfpKe+p79tCnm4GVav68A7tUFeKQwQyLgESwEAUzyxk/TJr4QdGog9sqWNcUbr/bZt/O/HXouspuQDd9JxFSw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.12': + resolution: {integrity: sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.27.4': + resolution: {integrity: sha512-2kb4ceA/CpfUrIcTUl1wrP/9ad9Atrp5J94Lq69w7UwOMolPIGrfLSvAKJp0RTvkPPyn6CIWrNy13kyLikZRZQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.25.12': + resolution: {integrity: sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm64@0.27.4': + resolution: {integrity: sha512-7nQOttdzVGth1iz57kxg9uCz57dxQLHWxopL6mYuYthohPKEK0vU0C3O21CcBK6KDlkYVcnDXY099HcCDXd9dA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.25.12': + resolution: {integrity: sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-arm@0.27.4': + resolution: {integrity: sha512-aBYgcIxX/wd5n2ys0yESGeYMGF+pv6g0DhZr3G1ZG4jMfruU9Tl1i2Z+Wnj9/KjGz1lTLCcorqE2viePZqj4Eg==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.25.12': + resolution: {integrity: sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-ia32@0.27.4': + resolution: {integrity: sha512-oPtixtAIzgvzYcKBQM/qZ3R+9TEUd1aNJQu0HhGyqtx6oS7qTpvjheIWBbes4+qu1bNlo2V4cbkISr8q6gRBFA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.25.12': + resolution: {integrity: sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-loong64@0.27.4': + resolution: {integrity: sha512-8mL/vh8qeCoRcFH2nM8wm5uJP+ZcVYGGayMavi8GmRJjuI3g1v6Z7Ni0JJKAJW+m0EtUuARb6Lmp4hMjzCBWzA==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.25.12': + resolution: {integrity: sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-mips64el@0.27.4': + resolution: {integrity: sha512-1RdrWFFiiLIW7LQq9Q2NES+HiD4NyT8Itj9AUeCl0IVCA459WnPhREKgwrpaIfTOe+/2rdntisegiPWn/r/aAw==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.25.12': + resolution: {integrity: sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-ppc64@0.27.4': + resolution: {integrity: sha512-tLCwNG47l3sd9lpfyx9LAGEGItCUeRCWeAx6x2Jmbav65nAwoPXfewtAdtbtit/pJFLUWOhpv0FpS6GQAmPrHA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.12': + resolution: {integrity: sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-riscv64@0.27.4': + resolution: {integrity: sha512-BnASypppbUWyqjd1KIpU4AUBiIhVr6YlHx/cnPgqEkNoVOhHg+YiSVxM1RLfiy4t9cAulbRGTNCKOcqHrEQLIw==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.25.12': + resolution: {integrity: sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-s390x@0.27.4': + resolution: {integrity: sha512-+eUqgb/Z7vxVLezG8bVB9SfBie89gMueS+I0xYh2tJdw3vqA/0ImZJ2ROeWwVJN59ihBeZ7Tu92dF/5dy5FttA==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.25.12': + resolution: {integrity: sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/linux-x64@0.27.4': + resolution: {integrity: sha512-S5qOXrKV8BQEzJPVxAwnryi2+Iq5pB40gTEIT69BQONqR7JH1EPIcQ/Uiv9mCnn05jff9umq/5nqzxlqTOg9NA==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.12': + resolution: {integrity: sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-arm64@0.27.4': + resolution: {integrity: sha512-xHT8X4sb0GS8qTqiwzHqpY00C95DPAq7nAwX35Ie/s+LO9830hrMd3oX0ZMKLvy7vsonee73x0lmcdOVXFzd6Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.12': + resolution: {integrity: sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.27.4': + resolution: {integrity: sha512-RugOvOdXfdyi5Tyv40kgQnI0byv66BFgAqjdgtAKqHoZTbTF2QqfQrFwa7cHEORJf6X2ht+l9ABLMP0dnKYsgg==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.12': + resolution: {integrity: sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-arm64@0.27.4': + resolution: {integrity: sha512-2MyL3IAaTX+1/qP0O1SwskwcwCoOI4kV2IBX1xYnDDqthmq5ArrW94qSIKCAuRraMgPOmG0RDTA74mzYNQA9ow==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.12': + resolution: {integrity: sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.27.4': + resolution: {integrity: sha512-u8fg/jQ5aQDfsnIV6+KwLOf1CmJnfu1ShpwqdwC0uA7ZPwFws55Ngc12vBdeUdnuWoQYx/SOQLGDcdlfXhYmXQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.25.12': + resolution: {integrity: sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/openharmony-arm64@0.27.4': + resolution: {integrity: sha512-JkTZrl6VbyO8lDQO3yv26nNr2RM2yZzNrNHEsj9bm6dOwwu9OYN28CjzZkH57bh4w0I2F7IodpQvUAEd1mbWXg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + + '@esbuild/sunos-x64@0.25.12': + resolution: {integrity: sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/sunos-x64@0.27.4': + resolution: {integrity: sha512-/gOzgaewZJfeJTlsWhvUEmUG4tWEY2Spp5M20INYRg2ZKl9QPO3QEEgPeRtLjEWSW8FilRNacPOg8R1uaYkA6g==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.25.12': + resolution: {integrity: sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-arm64@0.27.4': + resolution: {integrity: sha512-Z9SExBg2y32smoDQdf1HRwHRt6vAHLXcxD2uGgO/v2jK7Y718Ix4ndsbNMU/+1Qiem9OiOdaqitioZwxivhXYg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.25.12': + resolution: {integrity: sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-ia32@0.27.4': + resolution: {integrity: sha512-DAyGLS0Jz5G5iixEbMHi5KdiApqHBWMGzTtMiJ72ZOLhbu/bzxgAe8Ue8CTS3n3HbIUHQz/L51yMdGMeoxXNJw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.25.12': + resolution: {integrity: sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@esbuild/win32-x64@0.27.4': + resolution: {integrity: sha512-+knoa0BDoeXgkNvvV1vvbZX4+hizelrkwmGJBdT17t8FNPwG2lKemmuMZlmaNQ3ws3DKKCxpb4zRZEIp3UxFCg==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@inquirer/ansi@1.0.2': + resolution: {integrity: sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ==} + engines: {node: '>=18'} + + '@inquirer/confirm@5.1.21': + resolution: {integrity: sha512-KR8edRkIsUayMXV+o3Gv+q4jlhENF9nMYUZs9PA2HzrXeHI8M5uDag70U7RJn9yyiMZSbtF5/UexBtAVtZGSbQ==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/core@10.3.2': + resolution: {integrity: sha512-43RTuEbfP8MbKzedNqBrlhhNKVwoK//vUFNW3Q3vZ88BLcrs4kYpGg+B2mm5p2K/HfygoCxuKwJJiv8PbGmE0A==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@inquirer/figures@1.0.15': + resolution: {integrity: sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==} + engines: {node: '>=18'} + + '@inquirer/type@3.0.10': + resolution: {integrity: sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA==} + engines: {node: '>=18'} + peerDependencies: + '@types/node': '>=18' + peerDependenciesMeta: + '@types/node': + optional: true + + '@isaacs/cliui@9.0.0': + resolution: {integrity: sha512-AokJm4tuBHillT+FpMtxQ60n8ObyXBatq7jD2/JA9dxbDDokKQm8KMht5ibGzLVU9IJDIKK4TPKgMHEYMn3lMg==} + engines: {node: '>=18'} + + '@jest/schemas@29.6.3': + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + '@jest/types@29.6.3': + resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=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==} + + '@lingui/babel-plugin-extract-messages@5.9.3': + resolution: {integrity: sha512-zm6QHDILmhj8olgLL2zHQn18yFA5mf4hX7QzCr1OOI/e815I0IkecCYue1Ych+y+B+V0eLriiW8AcfpDRCQFFw==} + engines: {node: '>=20.0.0'} + + '@lingui/babel-plugin-lingui-macro@5.9.3': + resolution: {integrity: sha512-fLMhBarRsuqBGOq2YuEoqOjEAV2VNezz/+f/Dn0vLFHF/kAjnFwTHb8pL8DRSIMsWG16mPrGnLpdROZBmJlFtA==} + engines: {node: '>=20.0.0'} + peerDependencies: + babel-plugin-macros: 2 || 3 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + + '@lingui/cli@5.9.3': + resolution: {integrity: sha512-KEE0J4eGlfpiLZ+l019qjraWfqfh5mUmQSJeTFw5PulO4v50zvxw5tDX8stpBzJ3QtgUQZlrMUh0OTGdURaAMg==} + engines: {node: '>=20.0.0'} + hasBin: true + + '@lingui/conf@5.9.3': + resolution: {integrity: sha512-hVEoYHmO2A3XmFX4A5RuBgcoVBoM7Xgoqejeq25XELvesJj2s2T15F47TA5n3/S7iTqngd6n/8KxBli9TYwgqQ==} + engines: {node: '>=20.0.0'} + + '@lingui/core@5.9.3': + resolution: {integrity: sha512-3b8LnDjx8POdQ6q6UKBe2DHynyQFCO66vm8/UPQnvlQowUk4Xdu5bK6oet11D9/vrSznrDDS+Qb5JVcNBUImgg==} + engines: {node: '>=20.0.0'} + peerDependencies: + '@lingui/babel-plugin-lingui-macro': 5.9.3 + babel-plugin-macros: 2 || 3 + peerDependenciesMeta: + '@lingui/babel-plugin-lingui-macro': + optional: true + babel-plugin-macros: + optional: true + + '@lingui/format-po@5.9.3': + resolution: {integrity: sha512-+LMnhWl7EmXrdOv10gopE1g8w8vtPY5Fxk72OORrGQFVMGBIioz4BEnKrNdV1ek2M+GxoMZtnUs17KrJN5Jv9A==} + engines: {node: '>=20.0.0'} + + '@lingui/message-utils@5.9.3': + resolution: {integrity: sha512-oAK7HA7lcQrzaEaM6G1T5RwwxJxaSKfG/IFIxpZIl49TSFQv+s9YPNgHnVi+d4DmterpXNxy9ZZ+NtckJx6u7g==} + engines: {node: '>=20.0.0'} + + '@lingui/react@5.9.3': + resolution: {integrity: sha512-aje78l3zGGZ3C75fiGhDVKyVALHfiKlYFjcOlZpgXY/JAVfFuZX+6wUGG9x1A8k7BfxrDy/ofHIBahPvNAqoKw==} + engines: {node: '>=20.0.0'} + peerDependencies: + '@lingui/babel-plugin-lingui-macro': 5.9.3 + babel-plugin-macros: 2 || 3 + react: ^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@lingui/babel-plugin-lingui-macro': + optional: true + babel-plugin-macros: + optional: true + + '@lingui/swc-plugin@5.11.0': + resolution: {integrity: sha512-0PBYyozQOiA4WtxKPsnCyrbA9da9zOYehyZjvrv56Kzt9w81xbgnNjuAQZyjIX7UYuqFFE48GvzBqnB5SLLOFA==} + peerDependencies: + '@lingui/core': '5' + '@swc/core': '*' + next: '*' + peerDependenciesMeta: + '@swc/core': + optional: true + next: + optional: true + + '@lingui/vite-plugin@5.9.3': + resolution: {integrity: sha512-9L9GqWjGWU+WrJAb5MBiH9QxkfagrOOWOFucBSwQgEf9k9612o9TIw8eiFqLnnPhi64ktVUaBgDJhkAYo4XLjw==} + engines: {node: '>=20.0.0'} + peerDependencies: + vite: ^3 || ^4 || ^5.0.9 || ^6 || ^7 || ^8 + + '@messageformat/parser@5.1.1': + resolution: {integrity: sha512-3p0YRGCcTUCYvBKLIxtDDyrJ0YijGIwrTRu1DT8gIviIDZru8H23+FkY6MJBzM1n9n20CiM4VeDYuBsrrwnLjg==} + + '@mswjs/interceptors@0.41.3': + resolution: {integrity: sha512-cXu86tF4VQVfwz8W1SPbhoRyHJkti6mjH/XJIxp40jhO4j2k1m4KYrEykxqWPkFF3vrK4rgQppBh//AwyGSXPA==} + engines: {node: '>=18'} + + '@open-draft/deferred-promise@2.2.0': + resolution: {integrity: sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==} + + '@open-draft/logger@0.3.0': + resolution: {integrity: sha512-X2g45fzhxH238HKO4xbSr7+wBS8Fvw6ixhTDuvLd5mqh6bJJCFAPwU9mPDxbcrRtfxv4u5IHCEH77BmxvXmmxQ==} + + '@open-draft/until@2.1.0': + resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==} + + '@oxc-project/runtime@0.115.0': + resolution: {integrity: sha512-Rg8Wlt5dCbXhQnsXPrkOjL1DTSvXLgb2R/KYfnf1/K+R0k6UMLEmbQXPM+kwrWqSmWA2t0B1EtHy2/3zikQpvQ==} + engines: {node: ^20.19.0 || >=22.12.0} + + '@oxc-project/types@0.115.0': + resolution: {integrity: sha512-4n91DKnebUS4yjUHl2g3/b2T+IUdCfmoZGhmwsovZCDaJSs+QkVAM+0AqqTxHSsHfeiMuueT75cZaZcT/m0pSw==} + + '@oxfmt/binding-android-arm-eabi@0.40.0': + resolution: {integrity: sha512-S6zd5r1w/HmqR8t0CTnGjFTBLDq2QKORPwriCHxo4xFNuhmOTABGjPaNvCJJVnrKBLsohOeiDX3YqQfJPF+FXw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@oxfmt/binding-android-arm64@0.40.0': + resolution: {integrity: sha512-/mbS9UUP/5Vbl2D6osIdcYiP0oie63LKMoTyGj5hyMCK/SFkl3EhtyRAfdjPvuvHC0SXdW6ePaTKkBSq1SNcIw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@oxfmt/binding-darwin-arm64@0.40.0': + resolution: {integrity: sha512-wRt8fRdfLiEhnRMBonlIbKrJWixoEmn6KCjKE9PElnrSDSXETGZfPb8ee+nQNTobXkCVvVLytp2o0obAsxl78Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@oxfmt/binding-darwin-x64@0.40.0': + resolution: {integrity: sha512-fzowhqbOE/NRy+AE5ob0+Y4X243WbWzDb00W+pKwD7d9tOqsAFbtWUwIyqqCoCLxj791m2xXIEeLH/3uz7zCCg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@oxfmt/binding-freebsd-x64@0.40.0': + resolution: {integrity: sha512-agZ9ITaqdBjcerRRFEHB8s0OyVcQW8F9ZxsszjxzeSthQ4fcN2MuOtQFWec1ed8/lDa50jSLHVE2/xPmTgtCfQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@oxfmt/binding-linux-arm-gnueabihf@0.40.0': + resolution: {integrity: sha512-ZM2oQ47p28TP1DVIp7HL1QoMUgqlBFHey0ksHct7tMXoU5BqjNvPWw7888azzMt25lnyPODVuye1wvNbvVUFOA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxfmt/binding-linux-arm-musleabihf@0.40.0': + resolution: {integrity: sha512-RBFPAxRAIsMisKM47Oe6Lwdv6agZYLz02CUhVCD1sOv5ajAcRMrnwCFBPWwGXpazToW2mjnZxFos8TuFjTU15A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxfmt/binding-linux-arm64-gnu@0.40.0': + resolution: {integrity: sha512-Nb2XbQ+wV3W2jSIihXdPj7k83eOxeSgYP3N/SRXvQ6ZYPIk6Q86qEh5Gl/7OitX3bQoQrESqm1yMLvZV8/J7dA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@oxfmt/binding-linux-arm64-musl@0.40.0': + resolution: {integrity: sha512-tGmWhLD/0YMotCdfezlT6tC/MJG/wKpo4vnQ3Cq+4eBk/BwNv7EmkD0VkD5F/dYkT3b8FNU01X2e8vvJuWoM1w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@oxfmt/binding-linux-ppc64-gnu@0.40.0': + resolution: {integrity: sha512-rVbFyM3e7YhkVnp0IVYjaSHfrBWcTRWb60LEcdNAJcE2mbhTpbqKufx0FrhWfoxOrW/+7UJonAOShoFFLigDqQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@oxfmt/binding-linux-riscv64-gnu@0.40.0': + resolution: {integrity: sha512-3ZqBw14JtWeEoLiioJcXSJz8RQyPE+3jLARnYM1HdPzZG4vk+Ua8CUupt2+d+vSAvMyaQBTN2dZK+kbBS/j5mA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@oxfmt/binding-linux-riscv64-musl@0.40.0': + resolution: {integrity: sha512-JJ4PPSdcbGBjPvb+O7xYm2FmAsKCyuEMYhqatBAHMp/6TA6rVlf9Z/sYPa4/3Bommb+8nndm15SPFRHEPU5qFA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@oxfmt/binding-linux-s390x-gnu@0.40.0': + resolution: {integrity: sha512-Kp0zNJoX9Ik77wUya2tpBY3W9f40VUoMQLWVaob5SgCrblH/t2xr/9B2bWHfs0WCefuGmqXcB+t0Lq77sbBmZw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@oxfmt/binding-linux-x64-gnu@0.40.0': + resolution: {integrity: sha512-7YTCNzleWTaQTqNGUNQ66qVjpoV6DjbCOea+RnpMBly2bpzrI/uu7Rr+2zcgRfNxyjXaFTVQKaRKjqVdeUfeVA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@oxfmt/binding-linux-x64-musl@0.40.0': + resolution: {integrity: sha512-hWnSzJ0oegeOwfOEeejYXfBqmnRGHusgtHfCPzmvJvHTwy1s3Neo59UKc1CmpE3zxvrCzJoVHos0rr97GHMNPw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@oxfmt/binding-openharmony-arm64@0.40.0': + resolution: {integrity: sha512-28sJC1lR4qtBJGzSRRbPnSW3GxU2+4YyQFE6rCmsUYqZ5XYH8jg0/w+CvEzQ8TuAQz5zLkcA25nFQGwoU0PT3Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@oxfmt/binding-win32-arm64-msvc@0.40.0': + resolution: {integrity: sha512-cDkRnyT0dqwF5oIX1Cv59HKCeZQFbWWdUpXa3uvnHFT2iwYSSZspkhgjXjU6iDp5pFPaAEAe9FIbMoTgkTmKPg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@oxfmt/binding-win32-ia32-msvc@0.40.0': + resolution: {integrity: sha512-7rPemBJjqm5Gkv6ZRCPvK8lE6AqQ/2z31DRdWazyx2ZvaSgL7QGofHXHNouRpPvNsT9yxRNQJgigsWkc+0qg4w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + + '@oxfmt/binding-win32-x64-msvc@0.40.0': + resolution: {integrity: sha512-/Zmj0yTYSvmha6TG1QnoLqVT7ZMRDqXvFXXBQpIjteEwx9qvUYMBH2xbiOFhDeMUJkGwC3D6fdKsFtaqUvkwNA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@oxlint-tsgolint/darwin-arm64@0.17.0': + resolution: {integrity: sha512-z3XwCDuOAKgk7bO4y5tyH8Zogwr51G56R0XGKC3tlAbrAq8DecoxAd3qhRZqWBMG2Gzl5bWU3Ghu7lrxuLPzYw==} + cpu: [arm64] + os: [darwin] + + '@oxlint-tsgolint/darwin-x64@0.17.0': + resolution: {integrity: sha512-TZgVXy0MtI8nt0MYiceuZhHPwHcwlIZ/YwzFTAKrgdHiTvVzFbqHVdXi5wbZfT/o1nHGw9fbGWPlb6qKZ4uZ9Q==} + cpu: [x64] + os: [darwin] + + '@oxlint-tsgolint/linux-arm64@0.17.0': + resolution: {integrity: sha512-IDfhFl/Y8bjidCvAP6QAxVyBsl78TmfCHlfjtEv2XtJXgYmIwzv6muO18XMp74SZ2qAyD4y2n2dUedrmghGHeA==} + cpu: [arm64] + os: [linux] + + '@oxlint-tsgolint/linux-x64@0.17.0': + resolution: {integrity: sha512-Bgdgqx/m8EnfjmmlRLEeYy9Yhdt1GdFrMr5mTu/NyLRGkB1C9VLAikdxB7U9QambAGTAmjMbHNFDFk8Vx69Huw==} + cpu: [x64] + os: [linux] + + '@oxlint-tsgolint/win32-arm64@0.17.0': + resolution: {integrity: sha512-dO6wyKMDqFWh1vwr+zNZS7/ovlfGgl4S3P1LDy4CKjP6V6NGtdmEwWkWax8j/I8RzGZdfXKnoUfb/qhVg5bx0w==} + cpu: [arm64] + os: [win32] + + '@oxlint-tsgolint/win32-x64@0.17.0': + resolution: {integrity: sha512-lPGYFp3yX2nh6hLTpIuMnJbZnt3Df42VkoA/fSkMYi2a/LXdDytQGpgZOrb5j47TICARd34RauKm0P3OA4Oxbw==} + cpu: [x64] + os: [win32] + + '@oxlint/binding-android-arm-eabi@1.55.0': + resolution: {integrity: sha512-NhvgAhncTSOhRahQSCnkK/4YIGPjTmhPurQQ2dwt2IvwCMTvZRW5vF2K10UBOxFve4GZDMw6LtXZdC2qeuYIVQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@oxlint/binding-android-arm64@1.55.0': + resolution: {integrity: sha512-P9iWRh+Ugqhg+D7rkc7boHX8o3H2h7YPcZHQIgvVBgnua5tk4LR2L+IBlreZs58/95cd2x3/004p5VsQM9z4SA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@oxlint/binding-darwin-arm64@1.55.0': + resolution: {integrity: sha512-esakkJIt7WFAhT30P/Qzn96ehFpzdZ1mNuzpOb8SCW7lI4oB8VsyQnkSHREM671jfpuBb/o2ppzBCx5l0jpgMA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@oxlint/binding-darwin-x64@1.55.0': + resolution: {integrity: sha512-xDMFRCCAEK9fOH6As2z8ELsC+VDGSFRHwIKVSilw+xhgLwTDFu37rtmRbmUlx8rRGS6cWKQPTc47AVxAZEVVPQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@oxlint/binding-freebsd-x64@1.55.0': + resolution: {integrity: sha512-mYZqnwUD7ALCRxGenyLd1uuG+rHCL+OTT6S8FcAbVm/ZT2AZMGjvibp3F6k1SKOb2aeqFATmwRykrE41Q0GWVw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@oxlint/binding-linux-arm-gnueabihf@1.55.0': + resolution: {integrity: sha512-LcX6RYcF9vL9ESGwJW3yyIZ/d/ouzdOKXxCdey1q0XJOW1asrHsIg5MmyKdEBR4plQx+shvYeQne7AzW5f3T1w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxlint/binding-linux-arm-musleabihf@1.55.0': + resolution: {integrity: sha512-C+8GS1rPtK+dI7mJFkqoRBkDuqbrNihnyYQsJPS9ez+8zF9JzfvU19lawqt4l/Y23o5uQswE/DORa8aiXUih3w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxlint/binding-linux-arm64-gnu@1.55.0': + resolution: {integrity: sha512-ErLE4XbmcCopA4/CIDiH6J1IAaDOMnf/KSx/aFObs4/OjAAM3sFKWGZ57pNOMxhhyBdcmcXwYymph9GwcpcqgQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-arm64-musl@1.55.0': + resolution: {integrity: sha512-/kp65avi6zZfqEng56TTuhiy3P/3pgklKIdf38yvYeJ9/PgEeRA2A2AqKAKbZBNAqUzrzHhz9jF6j/PZvhJzTQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@oxlint/binding-linux-ppc64-gnu@1.55.0': + resolution: {integrity: sha512-A6pTdXwcEEwL/nmz0eUJ6WxmxcoIS+97GbH96gikAyre3s5deC7sts38ZVVowjS2QQFuSWkpA4ZmQC0jZSNvJQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-riscv64-gnu@1.55.0': + resolution: {integrity: sha512-clj0lnIN+V52G9tdtZl0LbdTSurnZ1NZj92Je5X4lC7gP5jiCSW+Y/oiDiSauBAD4wrHt2S7nN3pA0zfKYK/6Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-riscv64-musl@1.55.0': + resolution: {integrity: sha512-NNu08pllN5x/O94/sgR3DA8lbrGBnTHsINZZR0hcav1sj79ksTiKKm1mRzvZvacwQ0hUnGinFo+JO75ok2PxYg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@oxlint/binding-linux-s390x-gnu@1.55.0': + resolution: {integrity: sha512-BvfQz3PRlWZRoEZ17dZCqgQsMRdpzGZomJkVATwCIGhHVVeHJMQdmdXPSjcT1DCNUrOjXnVyj1RGDj5+/Je2+Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-x64-gnu@1.55.0': + resolution: {integrity: sha512-ngSOoFCSBMKVQd24H8zkbcBNc7EHhjnF1sv3mC9NNXQ/4rRjI/4Dj9+9XoDZeFEkF1SX1COSBXF1b2Pr9rqdEw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-x64-musl@1.55.0': + resolution: {integrity: sha512-BDpP7W8GlaG7BR6QjGZAleYzxoyKc/D24spZIF2mB3XsfALQJJT/OBmP8YpeTb1rveFSBHzl8T7l0aqwkWNdGA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@oxlint/binding-openharmony-arm64@1.55.0': + resolution: {integrity: sha512-PS6GFvmde/pc3fCA2Srt51glr8Lcxhpf6WIBFfLphndjRrD34NEcses4TSxQrEcxYo6qVywGfylM0ZhSCF2gGA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@oxlint/binding-win32-arm64-msvc@1.55.0': + resolution: {integrity: sha512-P6JcLJGs/q1UOvDLzN8otd9JsH4tsuuPDv+p7aHqHM3PrKmYdmUvkNj4K327PTd35AYcznOCN+l4ZOaq76QzSw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@oxlint/binding-win32-ia32-msvc@1.55.0': + resolution: {integrity: sha512-gzkk4zE2zsE+WmRxFOiAZHpCpUNDFytEakqNXoNHW+PnYEOTPKDdW6nrzgSeTbGKVPXNAKQnRnMgrh7+n3Xueg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + + '@oxlint/binding-win32-x64-msvc@1.55.0': + resolution: {integrity: sha512-ZFALNow2/og75gvYzNP7qe+rREQ5xunktwA+lgykoozHZ6hw9bqg4fn5j2UvG4gIn1FXqrZHkOAXuPf5+GOYTQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@playwright/test@1.58.2': + resolution: {integrity: sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA==} + engines: {node: '>=18'} + hasBin: true + + '@polka/url@1.0.0-next.29': + resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} + + '@rc-component/async-validator@5.1.0': + resolution: {integrity: sha512-n4HcR5siNUXRX23nDizbZBQPO0ZM/5oTtmKZ6/eqL0L2bo747cklFdZGRN2f+c9qWGICwDzrhW0H7tE9PptdcA==} + engines: {node: '>=14.x'} + + '@rc-component/cascader@1.14.0': + resolution: {integrity: sha512-Ip9356xwZUR2nbW5PRVGif4B/bDve4pLa/N+PGbvBaTnjbvmN4PFMBGQSmlDlzKP1ovxaYMvwF/dI9lXNLT4iQ==} + peerDependencies: + react: '>=18.0.0' + react-dom: '>=18.0.0' + + '@rc-component/checkbox@2.0.0': + resolution: {integrity: sha512-3CXGPpAR9gsPKeO2N78HAPOzU30UdemD6HGJoWVJOpa6WleaGB5kzZj3v6bdTZab31YuWgY/RxV3VKPctn0DwQ==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/collapse@1.2.0': + resolution: {integrity: sha512-ZRYSKSS39qsFx93p26bde7JUZJshsUBEQRlRXPuJYlAiNX0vyYlF5TsAm8JZN3LcF8XvKikdzPbgAtXSbkLUkw==} + peerDependencies: + react: '>=18.0.0' + react-dom: '>=18.0.0' + + '@rc-component/color-picker@3.1.1': + resolution: {integrity: sha512-OHaCHLHszCegdXmIq2ZRIZBN/EtpT6Wm8SG/gpzLATHbVKc/avvuKi+zlOuk05FTWvgaMmpxAko44uRJ3M+2pg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/context@2.0.1': + resolution: {integrity: sha512-HyZbYm47s/YqtP6pKXNMjPEMaukyg7P0qVfgMLzr7YiFNMHbK2fKTAGzms9ykfGHSfyf75nBbgWw+hHkp+VImw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/dialog@1.8.4': + resolution: {integrity: sha512-Ay6PM7phkTkquplG8fWfUGFZ2GTLx9diTl4f0d8Eqxd7W1u1KjE9AQooFQHOHnhZf0Ya3z51+5EKCWHmt/dNEw==} + peerDependencies: + react: '>=18.0.0' + react-dom: '>=18.0.0' + + '@rc-component/drawer@1.4.2': + resolution: {integrity: sha512-1ib+fZEp6FBu+YvcIktm+nCQ+Q+qIpwpoaJH6opGr4ofh2QMq+qdr5DLC4oCf5qf3pcWX9lUWPYX652k4ini8Q==} + peerDependencies: + react: '>=18.0.0' + react-dom: '>=18.0.0' + + '@rc-component/dropdown@1.0.2': + resolution: {integrity: sha512-6PY2ecUSYhDPhkNHHb4wfeAya04WhpmUSKzdR60G+kMNVUCX2vjT/AgTS0Lz0I/K6xrPMJ3enQbwVpeN3sHCgg==} + peerDependencies: + react: '>=16.11.0' + react-dom: '>=16.11.0' + + '@rc-component/form@1.7.2': + resolution: {integrity: sha512-5C90rXH7aZvvvxB4M5ew+QxROvimdL/lqhSshR8NsyiR7HKOoGQYSitxdfENnH6/0KNFxEy2ranVe2LrTnHZIw==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/image@1.6.0': + resolution: {integrity: sha512-tSfn2ZE/oP082g4QIOxeehkmgnXB7R+5AFj/lIFr4k7pEuxHBdyGIq9axoCY9qea8NN0DY6p4IB/F07tLqaT5A==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/input-number@1.6.2': + resolution: {integrity: sha512-Gjcq7meZlCOiWN1t1xCC+7/s85humHVokTBI7PJgTfoyw5OWF74y3e6P8PHX104g9+b54jsodFIzyaj6p8LI9w==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/input@1.1.2': + resolution: {integrity: sha512-Q61IMR47piUBudgixJ30CciKIy9b1H95qe7GgEKOmSJVJXvFRWJllJfQry9tif+MX2cWFXWJf/RXz4kaCeq/Fg==} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + + '@rc-component/mentions@1.6.0': + resolution: {integrity: sha512-KIkQNP6habNuTsLhUv0UGEOwG67tlmE7KNIJoQZZNggEZl5lQJTytFDb69sl5CK3TDdISCTjKP3nGEBKgT61CQ==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/menu@1.2.0': + resolution: {integrity: sha512-VWwDuhvYHSnTGj4n6bV3ISrLACcPAzdPOq3d0BzkeiM5cve8BEYfvkEhNoM0PLzv51jpcejeyrLXeMVIJ+QJlg==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/mini-decimal@1.1.3': + resolution: {integrity: sha512-bk/FJ09fLf+NLODMAFll6CfYrHPBioTedhW6lxDBuuWucJEqFUd4l/D/5JgIi3dina6sYahB8iuPAZTNz2pMxw==} + engines: {node: '>=8.x'} + + '@rc-component/motion@1.3.1': + resolution: {integrity: sha512-Wo1mkd0tCcHtvYvpPOmlYJz546z16qlsiwaygmW7NPJpOZOF9GBjhGzdzZSsC2lEJ1IUkWLF4gMHlRA1aSA+Yw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/mutate-observer@2.0.1': + resolution: {integrity: sha512-AyarjoLU5YlxuValRi+w8JRH2Z84TBbFO2RoGWz9d8bSu0FqT8DtugH3xC3BV7mUwlmROFauyWuXFuq4IFbH+w==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/notification@1.2.0': + resolution: {integrity: sha512-OX3J+zVU7rvoJCikjrfW7qOUp7zlDeFBK2eA3SFbGSkDqo63Sl4Ss8A04kFP+fxHSxMDIS9jYVEZtU1FNCFuBA==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/overflow@1.0.0': + resolution: {integrity: sha512-GSlBeoE0XTBi5cf3zl8Qh7Uqhn7v8RrlJ8ajeVpEkNe94HWy5l5BQ0Mwn2TVUq9gdgbfEMUmTX7tJFAg7mz0Rw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/pagination@1.2.0': + resolution: {integrity: sha512-YcpUFE8dMLfSo6OARJlK6DbHHvrxz7pMGPGmC/caZSJJz6HRKHC1RPP001PRHCvG9Z/veD039uOQmazVuLJzlw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/picker@1.9.1': + resolution: {integrity: sha512-9FBYYsvH3HMLICaPDA/1Th5FLaDkFa7qAtangIdlhKb3ZALaR745e9PsOhheJb6asS4QXc12ffiAcjdkZ4C5/g==} + engines: {node: '>=12.x'} + peerDependencies: + date-fns: '>= 2.x' + dayjs: '>= 1.x' + luxon: '>= 3.x' + moment: '>= 2.x' + react: '>=16.9.0' + react-dom: '>=16.9.0' + peerDependenciesMeta: + date-fns: + optional: true + dayjs: + optional: true + luxon: + optional: true + moment: + optional: true + + '@rc-component/portal@2.2.0': + resolution: {integrity: sha512-oc6FlA+uXCMiwArHsJyHcIkX4q6uKyndrPol2eWX8YPkAnztHOPsFIRtmWG4BMlGE5h7YIRE3NiaJ5VS8Lb1QQ==} + engines: {node: '>=12.x'} + peerDependencies: + react: '>=18.0.0' + react-dom: '>=18.0.0' + + '@rc-component/progress@1.0.2': + resolution: {integrity: sha512-WZUnH9eGxH1+xodZKqdrHke59uyGZSWgj5HBM5Kwk5BrTMuAORO7VJ2IP5Qbm9aH3n9x3IcesqHHR0NWPBC7fQ==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/qrcode@1.1.1': + resolution: {integrity: sha512-LfLGNymzKdUPjXUbRP+xOhIWY4jQ+YMj5MmWAcgcAq1Ij8XP7tRmAXqyuv96XvLUBE/5cA8hLFl9eO1JQMujrA==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/rate@1.0.1': + resolution: {integrity: sha512-bkXxeBqDpl5IOC7yL7GcSYjQx9G8H+6kLYQnNZWeBYq2OYIv1MONd6mqKTjnnJYpV0cQIU2z3atdW0j1kttpTw==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/resize-observer@1.1.1': + resolution: {integrity: sha512-NfXXMmiR+SmUuKE1NwJESzEUYUFWIDUn2uXpxCTOLwiRUUakd62DRNFjRJArgzyFW8S5rsL4aX5XlyIXyC/vRA==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/segmented@1.3.0': + resolution: {integrity: sha512-5J/bJ01mbDnoA6P/FW8SxUvKn+OgUSTZJPzCNnTBntG50tzoP7DydGhqxp7ggZXZls7me3mc2EQDXakU3iTVFg==} + peerDependencies: + react: '>=16.0.0' + react-dom: '>=16.0.0' + + '@rc-component/select@1.6.15': + resolution: {integrity: sha512-SyVCWnqxCQZZcQvQJ/CxSjx2bGma6ds/HtnpkIfZVnt6RoEgbqUmHgD6vrzNarNXwbLXerwVzWwq8F3d1sst7g==} + engines: {node: '>=8.x'} + peerDependencies: + react: '*' + react-dom: '*' + + '@rc-component/slider@1.0.1': + resolution: {integrity: sha512-uDhEPU1z3WDfCJhaL9jfd2ha/Eqpdfxsn0Zb0Xcq1NGQAman0TWaR37OWp2vVXEOdV2y0njSILTMpTfPV1454g==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/steps@1.2.2': + resolution: {integrity: sha512-/yVIZ00gDYYPHSY0JP+M+s3ZvuXLu2f9rEjQqiUDs7EcYsUYrpJ/1bLj9aI9R7MBR3fu/NGh6RM9u2qGfqp+Nw==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/switch@1.0.3': + resolution: {integrity: sha512-Jgi+EbOBquje/XNdofr7xbJQZPYJP+BlPfR0h+WN4zFkdtB2EWqEfvkXJWeipflwjWip0/17rNbxEAqs8hVHfw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/table@1.9.1': + resolution: {integrity: sha512-FVI5ZS/GdB3BcgexfCYKi3iHhZS3Fr59EtsxORszYGrfpH1eWr33eDNSYkVfLI6tfJ7vftJDd9D5apfFWqkdJg==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=18.0.0' + react-dom: '>=18.0.0' + + '@rc-component/tabs@1.7.0': + resolution: {integrity: sha512-J48cs2iBi7Ho3nptBxxIqizEliUC+ExE23faspUQKGQ550vaBlv3aGF8Epv/UB1vFWeoJDTW/dNzgIU0Qj5i/w==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/textarea@1.1.2': + resolution: {integrity: sha512-9rMUEODWZDMovfScIEHXWlVZuPljZ2pd1LKNjslJVitn4SldEzq5vO1CL3yy3Dnib6zZal2r2DPtjy84VVpF6A==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/tooltip@1.4.0': + resolution: {integrity: sha512-8Rx5DCctIlLI4raR0I0xHjVTf1aF48+gKCNeAAo5bmF5VoR5YED+A/XEqzXv9KKqrJDRcd3Wndpxh2hyzrTtSg==} + peerDependencies: + react: '>=18.0.0' + react-dom: '>=18.0.0' + + '@rc-component/tour@2.3.0': + resolution: {integrity: sha512-K04K9r32kUC+auBSQfr+Fss4SpSIS9JGe56oq/ALAX0p+i2ylYOI1MgR83yBY7v96eO6ZFXcM/igCQmubps0Ow==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/tree-select@1.8.0': + resolution: {integrity: sha512-iYsPq3nuLYvGqdvFAW+l+I9ASRIOVbMXyA8FGZg2lGym/GwkaWeJGzI4eJ7c9IOEhRj0oyfIN4S92Fl3J05mjQ==} + peerDependencies: + react: '*' + react-dom: '*' + + '@rc-component/tree@1.2.4': + resolution: {integrity: sha512-5Gli43+m4R7NhpYYz3Z61I6LOw9yI6CNChxgVtvrO6xB1qML7iE6QMLVMB3+FTjo2yF6uFdAHtqWPECz/zbX5w==} + engines: {node: '>=10.x'} + peerDependencies: + react: '*' + react-dom: '*' + + '@rc-component/trigger@3.9.0': + resolution: {integrity: sha512-X8btpwfrT27AgrZVOz4swclhEHTZcqaHeQMXXBgveagOiakTa36uObXbdwerXffgV8G9dH1fAAE0DHtVQs8EHg==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=18.0.0' + react-dom: '>=18.0.0' + + '@rc-component/upload@1.1.0': + resolution: {integrity: sha512-LIBV90mAnUE6VK5N4QvForoxZc4XqEYZimcp7fk+lkE4XwHHyJWxpIXQQwMU8hJM+YwBbsoZkGksL1sISWHQxw==} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rc-component/util@1.9.0': + resolution: {integrity: sha512-5uW6AfhIigCWeEQDthTozlxiT4Prn6xYQWeO0xokjcaa186OtwPRHBZJ2o0T0FhbjGhZ3vXdbkv0sx3gAYW7Vg==} + peerDependencies: + react: '>=18.0.0' + react-dom: '>=18.0.0' + + '@rc-component/virtual-list@1.0.2': + resolution: {integrity: sha512-uvTol/mH74FYsn5loDGJxo+7kjkO4i+y4j87Re1pxJBs0FaeuMuLRzQRGaXwnMcV1CxpZLi2Z56Rerj2M00fjQ==} + engines: {node: '>=8.x'} + peerDependencies: + react: '>=16.9.0' + react-dom: '>=16.9.0' + + '@rolldown/pluginutils@1.0.0-rc.7': + resolution: {integrity: sha512-qujRfC8sFVInYSPPMLQByRh7zhwkGFS4+tyMQ83srV1qrxL4g8E2tyxVVyxd0+8QeBM1mIk9KbWxkegRr76XzA==} + + '@sinclair/typebox@0.27.10': + resolution: {integrity: sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==} + + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + + '@swc/core-darwin-arm64@1.15.18': + resolution: {integrity: sha512-+mIv7uBuSaywN3C9LNuWaX1jJJ3SKfiJuE6Lr3bd+/1Iv8oMU7oLBjYMluX1UrEPzwN2qCdY6Io0yVicABoCwQ==} + engines: {node: '>=10'} + cpu: [arm64] + os: [darwin] + + '@swc/core-darwin-x64@1.15.18': + resolution: {integrity: sha512-wZle0eaQhnzxWX5V/2kEOI6Z9vl/lTFEC6V4EWcn+5pDjhemCpQv9e/TDJ0GIoiClX8EDWRvuZwh+Z3dhL1NAg==} + engines: {node: '>=10'} + cpu: [x64] + os: [darwin] + + '@swc/core-linux-arm-gnueabihf@1.15.18': + resolution: {integrity: sha512-ao61HGXVqrJFHAcPtF4/DegmwEkVCo4HApnotLU8ognfmU8x589z7+tcf3hU+qBiU1WOXV5fQX6W9Nzs6hjxDw==} + engines: {node: '>=10'} + cpu: [arm] + os: [linux] + + '@swc/core-linux-arm64-gnu@1.15.18': + resolution: {integrity: sha512-3xnctOBLIq3kj8PxOCgPrGjBLP/kNOddr6f5gukYt/1IZxsITQaU9TDyjeX6jG+FiCIHjCuWuffsyQDL5Ew1bg==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@swc/core-linux-arm64-musl@1.15.18': + resolution: {integrity: sha512-0a+Lix+FSSHBSBOA0XznCcHo5/1nA6oLLjcnocvzXeqtdjnPb+SvchItHI+lfeiuj1sClYPDvPMLSLyXFaiIKw==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@swc/core-linux-x64-gnu@1.15.18': + resolution: {integrity: sha512-wG9J8vReUlpaHz4KOD/5UE1AUgirimU4UFT9oZmupUDEofxJKYb1mTA/DrMj0s78bkBiNI+7Fo2EgPuvOJfuAA==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@swc/core-linux-x64-musl@1.15.18': + resolution: {integrity: sha512-4nwbVvCphKzicwNWRmvD5iBaZj8JYsRGa4xOxJmOyHlMDpsvvJ2OR2cODlvWyGFH6BYL1MfIAK3qph3hp0Az6g==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@swc/core-win32-arm64-msvc@1.15.18': + resolution: {integrity: sha512-zk0RYO+LjiBCat2RTMHzAWaMky0cra9loH4oRrLKLLNuL+jarxKLFDA8xTZWEkCPLjUTwlRN7d28eDLLMgtUcQ==} + engines: {node: '>=10'} + cpu: [arm64] + os: [win32] + + '@swc/core-win32-ia32-msvc@1.15.18': + resolution: {integrity: sha512-yVuTrZ0RccD5+PEkpcLOBAuPbYBXS6rslENvIXfvJGXSdX5QGi1ehC4BjAMl5FkKLiam4kJECUI0l7Hq7T1vwg==} + engines: {node: '>=10'} + cpu: [ia32] + os: [win32] + + '@swc/core-win32-x64-msvc@1.15.18': + resolution: {integrity: sha512-7NRmE4hmUQNCbYU3Hn9Tz57mK9Qq4c97ZS+YlamlK6qG9Fb5g/BB3gPDe0iLlJkns/sYv2VWSkm8c3NmbEGjbg==} + engines: {node: '>=10'} + cpu: [x64] + os: [win32] + + '@swc/core@1.15.18': + resolution: {integrity: sha512-z87aF9GphWp//fnkRsqvtY+inMVPgYW3zSlXH1kJFvRT5H/wiAn+G32qW5l3oEk63KSF1x3Ov0BfHCObAmT8RA==} + 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/history@1.161.6': + resolution: {integrity: sha512-NaOGLRrddszbQj9upGat6HG/4TKvXLvu+osAIgfxPYA+eIvYKv8GKDJOrY2D3/U9MRnKfMWD7bU4jeD4xmqyIg==} + engines: {node: '>=20.19'} + + '@tanstack/query-core@5.90.20': + resolution: {integrity: sha512-OMD2HLpNouXEfZJWcKeVKUgQ5n+n3A2JFmBaScpNDUqSrQSjiveC7dKMe53uJUg1nDG16ttFPz2xfilz6i2uVg==} + + '@tanstack/react-query@5.90.21': + resolution: {integrity: sha512-0Lu6y5t+tvlTJMTO7oh5NSpJfpg/5D41LlThfepTixPYkJ0sE2Jj0m0f6yYqujBwIXlId87e234+MxG3D3g7kg==} + peerDependencies: + react: ^18 || ^19 + + '@tanstack/react-router@1.167.4': + resolution: {integrity: sha512-VpbZh382zX3WF4+X2Z+EUyd8eJhJyjg9C6ByYwrVZiWbhgbMK4+zQQIG2+lCAlIlDi7SV8fDcGL09NA8Z2kpGQ==} + engines: {node: '>=20.19'} + peerDependencies: + react: '>=18.0.0 || >=19.0.0' + react-dom: '>=18.0.0 || >=19.0.0' + + '@tanstack/react-store@0.9.2': + resolution: {integrity: sha512-Vt5usJE5sHG/cMechQfmwvwne6ktGCELe89Lmvoxe3LKRoFrhPa8OCKWs0NliG8HTJElEIj7PLtaBQIcux5pAQ==} + 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.167.4': + resolution: {integrity: sha512-Gk5V9Zr5JFJ4SbLyCheQLJ3MnXddccENPA+DJRz+9g3QxtN8DJB8w8KCUCgDeYlWp4LvmO4nX3fy3tupqVP2Pw==} + engines: {node: '>=20.19'} + hasBin: true + + '@tanstack/router-generator@1.166.12': + resolution: {integrity: sha512-2HdxSTbCkbU9JeYogKVigIlXoLtIJE1x5rbEov+ZLTPjGCO9kicNQuljqg9Js+u2/ahtWewNrE5u1QCAyxmpIg==} + engines: {node: '>=20.19'} + + '@tanstack/router-plugin@1.166.13': + resolution: {integrity: sha512-xG3ND3AlMe6DN9PihJAYUbQJevqJvVdzN1QpZbfU1/jkHurL97ynP2yXfmMTh8Qgi1K+SWRko4bi7iZlYP9SUw==} + engines: {node: '>=20.19'} + hasBin: true + peerDependencies: + '@rsbuild/core': '>=1.0.2' + '@tanstack/react-router': ^1.167.4 + vite: '>=5.0.0 || >=6.0.0 || >=7.0.0' + vite-plugin-solid: ^2.11.10 + 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.161.6': + resolution: {integrity: sha512-nRcYw+w2OEgK6VfjirYvGyPLOK+tZQz1jkYcmH5AjMamQ9PycnlxZF2aEZtPpNoUsaceX2bHptn6Ub5hGXqNvw==} + engines: {node: '>=20.19'} + + '@tanstack/store@0.9.2': + resolution: {integrity: sha512-K013lUJEFJK2ofFQ/hZKJUmCnpcV00ebLyOyFOWQvyQHUOZp/iYO84BM6aOGiV81JzwbX0APTVmW8YI7yiG5oA==} + + '@tanstack/virtual-file-routes@1.161.7': + resolution: {integrity: sha512-olW33+Cn+bsCsZKPwEGhlkqS6w3M2slFv11JIobdnCFKMLG97oAI2kWKdx5/zsywTL8flpnoIgaZZPlQTFYhdQ==} + engines: {node: '>=20.19'} + hasBin: true + + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + + '@types/istanbul-lib-coverage@2.0.6': + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + + '@types/istanbul-lib-report@3.0.3': + resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} + + '@types/istanbul-reports@3.0.4': + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + + '@types/node@25.6.0': + resolution: {integrity: sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==} + + '@types/parse-json@4.0.2': + resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} + + '@types/react-dom@19.2.3': + resolution: {integrity: sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==} + peerDependencies: + '@types/react': ^19.2.0 + + '@types/react@19.2.14': + resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==} + + '@types/statuses@2.0.6': + resolution: {integrity: sha512-xMAgYwceFhRA2zY+XbEA7mxYbA093wdiW8Vu6gZPGWy9cmOyU9XesH1tNcEWsKFd5Vzrqx5T3D38PWx1FIIXkA==} + + '@types/yargs-parser@21.0.3': + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + + '@types/yargs@17.0.35': + resolution: {integrity: sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==} + + '@vitejs/plugin-react-swc@4.3.0': + resolution: {integrity: sha512-mOkXCII839dHyAt/gpoSlm28JIVDwhZ6tnG6wJxUy2bmOx7UaPjvOyIDf3SFv5s7Eo7HVaq6kRcu6YMEzt5Z7w==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + vite: ^4 || ^5 || ^6 || ^7 || ^8 + + '@voidzero-dev/vite-plus-core@0.1.12': + resolution: {integrity: sha512-j8YNe7A+8JcSoddztf5whvom/yJ7OKUO3Y5a3UoLIUmOL8YEKVv5nPANrxJ7eaFfHJoMnBEwzBpq1YVZ+H3uPA==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + '@arethetypeswrong/core': ^0.18.1 + '@tsdown/css': 0.21.3 + '@tsdown/exe': 0.21.3 + '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.0.0-alpha.31 + esbuild: ^0.27.0 + jiti: '>=1.21.0' + less: ^4.0.0 + publint: ^0.3.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 + typescript: ^5.0.0 + unplugin-unused: ^0.5.0 + yaml: ^2.4.2 + peerDependenciesMeta: + '@arethetypeswrong/core': + optional: true + '@tsdown/css': + optional: true + '@tsdown/exe': + optional: true + '@types/node': + optional: true + '@vitejs/devtools': + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + publint: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + typescript: + optional: true + unplugin-unused: + optional: true + yaml: + optional: true + + '@voidzero-dev/vite-plus-darwin-arm64@0.1.12': + resolution: {integrity: sha512-tYQrfmcLxIqqr/de00oN7ayu+rYobEOjyR9AxoeJoNUqRyNQCdT0A5vg78kJNPaQCyL6ctgRRvpEKr0WHVmduQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@voidzero-dev/vite-plus-darwin-x64@0.1.12': + resolution: {integrity: sha512-852hO/Onx9Z5u0tOYOVEUVzYJUmWdlHeqYnNT6pj0IClgVp0+KSabxr7A2paTWEFWp6XbKWvqw5Y5cVwUV3A6Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@voidzero-dev/vite-plus-linux-arm64-gnu@0.1.12': + resolution: {integrity: sha512-/gTh4tGyJKCNBn9SZUs3sq9QVRUmyuyseZefBgS223QRxdwFaxc7tIKaw91X59WXXYOzUYZOD5zsTcaIF4hc9A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@voidzero-dev/vite-plus-linux-x64-gnu@0.1.12': + resolution: {integrity: sha512-9oN9ITjK/Xq9Werx+6G6jnI3+F1S3g9lB36J1VAHyRlAEtuiCDV0E3YMoW2O7KzM/PlodZIZ8LStVkH7aA5ZCw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@voidzero-dev/vite-plus-test@0.1.12': + resolution: {integrity: sha512-EE8Y2vQvqS4c/1qSa7qlhUY9koAG6wYev0NFAtDZsijQCHUqE7nYXGJYnyUInAE6GX4zlQDGg7tf2DAl+CISYw==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} + peerDependencies: + '@edge-runtime/vm': '*' + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/ui': 4.1.0 + happy-dom: '*' + jsdom: '*' + vite: ^6.0.0 || ^7.0.0 || ^8.0.0-0 + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@opentelemetry/api': + optional: true + '@types/node': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + '@voidzero-dev/vite-plus-win32-arm64-msvc@0.1.12': + resolution: {integrity: sha512-JanAb6Y+6BmPhKNLvpZB/syeyY99bt7EPJCaLlbaCt3V0Y2Iw7c7dWBM4Sg4GZ7szGYdGw385fRz0n2M32f1rg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@voidzero-dev/vite-plus-win32-x64-msvc@0.1.12': + resolution: {integrity: sha512-Ei/UtTTp7UgeEGyV83jhDpSMXhwaZZzfS7Xiaj+zj80GGOwsBre0i+oHGZ7+TuVsZ7Im0sD8IZ9enCpKpV//AQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + acorn@8.16.0: + resolution: {integrity: sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==} + engines: {node: '>=0.4.0'} + hasBin: true + + 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'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + ansis@4.2.0: + resolution: {integrity: sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==} + engines: {node: '>=14'} + + antd@6.3.3: + resolution: {integrity: sha512-T8FAQelw36zS96cZw2U/qEjpYny5yFc7hg+1W7DvVr8xMoSXWvyB8WvmiDVH0nS0LPYV4y2sxetsJoGZt7rhhw==} + peerDependencies: + react: '>=18.0.0' + react-dom: '>=18.0.0' + + 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==} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + ast-types@0.16.1: + resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} + engines: {node: '>=4'} + + babel-dead-code-elimination@1.0.12: + resolution: {integrity: sha512-GERT7L2TiYcYDtYk1IpD+ASAYXjKbLTDPhBtYj7X1NuRMDTMtAx9kyBenub1Ev41lo91OHCKdmP+egTDmfQ7Ig==} + + babel-plugin-macros@3.1.0: + resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} + engines: {node: '>=10', npm: '>=6'} + + balanced-match@4.0.4: + resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==} + engines: {node: 18 || 20 || >=22} + + base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + + baseline-browser-mapping@2.10.8: + resolution: {integrity: sha512-PCLz/LXGBsNTErbtB6i5u4eLpHeMfi93aUv5duMmj6caNu6IphS4q6UevDnL36sZQv9lrP11dbPKGMaXPwMKfQ==} + engines: {node: '>=6.0.0'} + hasBin: true + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + bl@4.1.0: + resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + + brace-expansion@5.0.4: + resolution: {integrity: sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==} + engines: {node: 18 || 20 || >=22} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browserslist@4.28.1: + resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + buffer@5.7.1: + resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + caniuse-lite@1.0.30001780: + resolution: {integrity: sha512-llngX0E7nQci5BPJDqoZSbuZ5Bcs9F5db7EtgfwBerX9XGtkkiO4NwfDDIRzHTTwcYC8vC7bmeUEPGrKlR/TkQ==} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chokidar@3.5.1: + resolution: {integrity: sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw==} + engines: {node: '>= 8.10.0'} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + cli-cursor@3.1.0: + resolution: {integrity: sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==} + engines: {node: '>=8'} + + cli-spinners@2.9.2: + resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} + engines: {node: '>=6'} + + cli-table@0.3.11: + resolution: {integrity: sha512-IqLQi4lO0nIB4tcdTpN4LCB9FI3uqrJZK7RC515EnhZ6qBaglkIgICb1wjeAqpdoOabm1+SuQtkXIPdYC93jhQ==} + engines: {node: '>= 0.2.0'} + + cli-width@4.1.0: + resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==} + engines: {node: '>= 12'} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + + clone@1.0.4: + resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} + engines: {node: '>=0.8'} + + 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==} + + colors@1.0.3: + resolution: {integrity: sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==} + engines: {node: '>=0.1.90'} + + commander@10.0.1: + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} + + compute-scroll-into-view@3.1.1: + resolution: {integrity: sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + cookie-es@2.0.0: + resolution: {integrity: sha512-RAj4E421UYRgqokKUmotqAwuplYw15qtdXfY+hGzgCJ/MBjCVZcSoHK/kH9kocfjRjcDME7IiDWR/1WX1TM2Pg==} + + cookie@1.1.1: + resolution: {integrity: sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==} + engines: {node: '>=18'} + + cosmiconfig@7.1.0: + resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} + engines: {node: '>=10'} + + cosmiconfig@8.3.6: + resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + date-fns@3.6.0: + resolution: {integrity: sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==} + + dayjs@1.11.20: + resolution: {integrity: sha512-YbwwqR/uYpeoP4pu043q+LTDLFBLApUP6VxRihdfNTqu4ubqMlGDLd6ErXhEgsyvY0K6nCs7nggYumAN+9uEuQ==} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + defaults@1.0.4: + resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + diff@8.0.3: + resolution: {integrity: sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==} + engines: {node: '>=0.3.1'} + + electron-to-chromium@1.5.313: + resolution: {integrity: sha512-QBMrTWEf00GXZmJyx2lbYD45jpI3TUFnNIzJ5BBc8piGUDwMPa1GV6HJWTZVvY/eiN3fSopl7NRbgGp9sZ9LTA==} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + error-ex@1.3.4: + resolution: {integrity: sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==} + + es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + + esbuild@0.25.12: + resolution: {integrity: sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==} + engines: {node: '>=18'} + hasBin: true + + esbuild@0.27.4: + resolution: {integrity: sha512-Rq4vbHnYkK5fws5NF7MYTU68FPRE1ajX7heQ/8QXXWqNgqqJ/GkmmyxIzUnf2Sr/bakf8l54716CcMGHYhMrrQ==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + esm@3.2.25: + resolution: {integrity: sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==} + engines: {node: '>=6'} + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + + fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + 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-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-tsconfig@4.13.6: + resolution: {integrity: sha512-shZT/QMiSHc/YBLxxOkMtgSid5HFoauqCE3/exfsEcwg1WkeqjG+V40yBbBrsD+jW2HDXcs28xOfcbm2jI8Ddw==} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob@11.1.0: + resolution: {integrity: sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==} + engines: {node: 20 || >=22} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me + hasBin: true + + graphql@16.13.1: + resolution: {integrity: sha512-gGgrVCoDKlIZ8fIqXBBb0pPKqDgki0Z/FSKNiQzSGj2uEYHr1tq5wmBegGwJx6QB5S5cM0khSBpi/JFHMCvsmQ==} + engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + headers-polyfill@4.0.3: + resolution: {integrity: sha512-IScLbePpkvO846sIwOtOTDjutRMWdXdJmXdMvk6gCBHxFO8d+QKOQedyZSxFTTFYRSmlgSTDtXqqq4pcenBXLQ==} + + ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + 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-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + + 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-interactive@1.0.0: + resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} + engines: {node: '>=8'} + + is-mobile@5.0.0: + resolution: {integrity: sha512-Tz/yndySvLAEXh+Uk8liFCxOwVH6YutuR74utvOcu7I9Di+DwM0mtdPVZNaVvvBUM2OXxne/NhOs1zAO7riusQ==} + + is-node-process@1.2.0: + resolution: {integrity: sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-observable@2.1.0: + resolution: {integrity: sha512-DailKdLb0WU+xX8K5w7VsJhapwHLZ9jjmazqCJq4X12CTgqq73TKnbRcnSLuXYPOoLQgV5IrD7ePiX/h1vnkBw==} + engines: {node: '>=8'} + + is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + + isbot@5.1.36: + resolution: {integrity: sha512-C/ZtXyJqDPZ7G7JPr06ApWyYoHjYexQbS6hPYD4WYCzpv2Qes6Z+CCEfTX4Owzf+1EJ933PoI2p+B9v7wpGZBQ==} + engines: {node: '>=18'} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + jackspeak@4.2.3: + resolution: {integrity: sha512-ykkVRwrYvFm1nb2AJfKKYPr0emF6IiXDYUaFx4Zn9ZuIH7MrzEZ3sD5RlqGXNRpHtvUHJyOnCEFxOlNDtGo7wg==} + engines: {node: 20 || >=22} + + jest-get-type@29.6.3: + resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jest-validate@29.7.0: + resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + jiti@2.6.1: + resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} + hasBin: true + + js-sha256@0.10.1: + resolution: {integrity: sha512-5obBtsz9301ULlsgggLg542s/jqtddfOpV5KJc4hajc9JV8GeY2gZHSVpYBn4nWqAUTJ9v+xwtbJ1mIBgIH5Vw==} + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} + hasBin: true + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json2mq@0.2.0: + resolution: {integrity: sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==} + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + + lightningcss-android-arm64@1.32.0: + resolution: {integrity: sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.32.0: + resolution: {integrity: sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.32.0: + resolution: {integrity: sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.32.0: + resolution: {integrity: sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.32.0: + resolution: {integrity: sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.32.0: + resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + lightningcss-linux-arm64-musl@1.32.0: + resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + lightningcss-linux-x64-gnu@1.32.0: + resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + lightningcss-linux-x64-musl@1.32.0: + resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + lightningcss-win32-arm64-msvc@1.32.0: + resolution: {integrity: sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.32.0: + resolution: {integrity: sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.32.0: + resolution: {integrity: sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==} + engines: {node: '>= 12.0.0'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + + lru-cache@11.2.7: + resolution: {integrity: sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==} + engines: {node: 20 || >=22} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + lucide-react@1.7.0: + resolution: {integrity: sha512-yI7BeItCLZJTXikmK4KNUGCKoGzSvbKlfCvw44bU4fXAL6v3gYS4uHD1jzsLkfwODYwI6Drw5Tu9Z5ulDe0TSg==} + peerDependencies: + react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + minimatch@10.2.4: + resolution: {integrity: sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==} + engines: {node: 18 || 20 || >=22} + + minipass@7.1.3: + resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} + engines: {node: '>=16 || 14 >=14.17'} + + moo@0.5.3: + resolution: {integrity: sha512-m2fmM2dDm7GZQsY7KK2cme8agi+AAljILjQnof7p1ZMDe6dQ4bdnSMx0cPppudoeNv5hEFQirN6u+O4fDE0IWA==} + + mrmime@2.0.1: + resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} + engines: {node: '>=10'} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + msw@2.12.12: + resolution: {integrity: sha512-u5tmUr6cO29q61vhOR6CDzasMvq7/WqI4eej6HmyIwjVsTpObtoAin5ac3iwK2vU/9eEo1P4FdY/0tsz7C/4fw==} + engines: {node: '>=18'} + hasBin: true + peerDependencies: + typescript: '>= 4.8.x' + peerDependenciesMeta: + typescript: + optional: true + + mute-stream@2.0.0: + resolution: {integrity: sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA==} + engines: {node: ^18.17.0 || >=20.5.0} + + nanoid@3.3.11: + resolution: {integrity: sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + node-releases@2.0.36: + resolution: {integrity: sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + observable-fns@0.6.1: + resolution: {integrity: sha512-9gRK4+sRWzeN6AOewNBTLXir7Zl/i3GB6Yl26gK4flxz8BXVpD3kt8amREmWNb0mxYOGDotvE5a4N+PtGGKdkg==} + + obug@2.1.1: + resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + + ora@5.4.1: + resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} + engines: {node: '>=10'} + + outvariant@1.4.3: + resolution: {integrity: sha512-+Sl2UErvtsoajRDKCE5/dBz4DIvHXQQnAxtQTF04OJxY0+DyZXSo5P5Bb7XYWOh81syohlYL24hbDwxedPUJCA==} + + oxfmt@0.40.0: + resolution: {integrity: sha512-g0C3I7xUj4b4DcagevM9kgH6+pUHytikxUcn3/VUkvzTNaaXBeyZqb7IBsHwojeXm4mTBEC/aBjBTMVUkZwWUQ==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + oxlint-tsgolint@0.17.0: + resolution: {integrity: sha512-TdrKhDZCgEYqONFo/j+KvGan7/k3tP5Ouz88wCqpOvJtI2QmcLfGsm1fcMvDnTik48Jj6z83IJBqlkmK9DnY1A==} + hasBin: true + + oxlint@1.55.0: + resolution: {integrity: sha512-T+FjepiyWpaZMhekqRpH8Z3I4vNM610p6w+Vjfqgj5TZUxHXl7N8N5IPvmOU8U4XdTRxqtNNTh9Y4hLtr7yvFg==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + oxlint-tsgolint: '>=0.15.0' + peerDependenciesMeta: + oxlint-tsgolint: + optional: true + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + 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-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@2.0.2: + resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==} + engines: {node: 18 || 20 || >=22} + + path-to-regexp@6.3.0: + resolution: {integrity: sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==} + + 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'} + + pixelmatch@7.1.0: + resolution: {integrity: sha512-1wrVzJ2STrpmONHKBy228LM1b84msXDUoAzVEl0R8Mz4Ce6EPr+IVtxm8+yvrqLYMHswREkjYFaMxnyGnaY3Ng==} + hasBin: true + + playwright-core@1.58.2: + resolution: {integrity: sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==} + engines: {node: '>=18'} + hasBin: true + + playwright@1.58.2: + resolution: {integrity: sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==} + engines: {node: '>=18'} + hasBin: true + + pngjs@7.0.0: + resolution: {integrity: sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==} + engines: {node: '>=14.19.0'} + + pofile@1.1.4: + resolution: {integrity: sha512-r6Q21sKsY1AjTVVjOuU02VYKVNQGJNQHjTIvs4dEbeuuYfxgYk/DGD2mqqq4RDaVkwdSq0VEtmQUOPe/wH8X3g==} + + postcss@8.5.8: + resolution: {integrity: sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==} + engines: {node: ^10 || ^12 || >=14} + + prettier@3.8.1: + resolution: {integrity: sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==} + engines: {node: '>=14'} + hasBin: true + + pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + + pseudolocale@2.2.0: + resolution: {integrity: sha512-O+D2eU7fO9wVLqrohvt9V/9fwMadnJQ4jxwiK+LeNEqhMx8JYx4xQHkArDCJFAdPPOp/pQq6z5L37eBvAoc8jw==} + engines: {node: '>=16.0.0'} + hasBin: true + + react-dom@19.2.4: + resolution: {integrity: sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==} + peerDependencies: + react: ^19.2.4 + + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + + react@19.2.4: + resolution: {integrity: sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==} + engines: {node: '>=0.10.0'} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + readdirp@3.5.0: + resolution: {integrity: sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==} + engines: {node: '>=8.10.0'} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + recast@0.23.11: + resolution: {integrity: sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==} + engines: {node: '>= 4'} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + + resolve@1.22.11: + resolution: {integrity: sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==} + engines: {node: '>= 0.4'} + hasBin: true + + restore-cursor@3.1.0: + resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} + engines: {node: '>=8'} + + rettime@0.10.1: + resolution: {integrity: sha512-uyDrIlUEH37cinabq0AX4QbgV4HbFZ/gqoiunWQ1UqBtRvTTytwhNYjE++pO/MjPTZL5KQCf2bEoJ/BJNVQ5Kw==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + scheduler@0.27.0: + resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} + + scroll-into-view-if-needed@3.1.0: + resolution: {integrity: sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + seroval-plugins@1.5.1: + resolution: {integrity: sha512-4FbuZ/TMl02sqv0RTFexu0SP6V+ywaIe5bAWCCEik0fk17BhALgwvUDVF7e3Uvf9pxmwCEJsRPmlkUE6HdzLAw==} + engines: {node: '>=10'} + peerDependencies: + seroval: ^1.0 + + seroval@1.5.1: + resolution: {integrity: sha512-OwrZRZAfhHww0WEnKHDY8OM0U/Qs8OTfIDWhUD4BLpNJUfXK4cGmjiagGze086m+mhI+V2nD0gfbHEnJjb9STA==} + engines: {node: '>=10'} + + 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'} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + sirv@3.0.2: + resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==} + engines: {node: '>=18'} + + 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'} + + statuses@2.0.2: + resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} + engines: {node: '>= 0.8'} + + std-env@4.0.0: + resolution: {integrity: sha512-zUMPtQ/HBY3/50VbpkupYHbRroTRZJPRLvreamgErJVys0ceuzMkD44J/QjqhHjOzK42GQ3QZIeFG1OYfOtKqQ==} + + strict-event-emitter@0.5.1: + resolution: {integrity: sha512-vMgjE/GGEPEFnhFub6pa4FmJBRBVOLpIII2hvCZ8Kzb7K0hlHo7mQv6xYrBvCL2LtAIBwFUK8wvuJgTVSQ5MFQ==} + + string-convert@0.2.1: + resolution: {integrity: sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + stylis@4.3.6: + resolution: {integrity: sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ==} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + tagged-tag@1.0.0: + resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==} + engines: {node: '>=20'} + + threads@1.7.0: + resolution: {integrity: sha512-Mx5NBSHX3sQYR6iI9VYbgHKBLisyB+xROCBGjjWm1O9wb9vfLxdaGtmT/KCjUqMsSNW6nERzCW3T6H43LqjDZQ==} + + throttle-debounce@5.0.2: + resolution: {integrity: sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==} + engines: {node: '>=12.22'} + + 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==} + + tiny-worker@2.3.0: + resolution: {integrity: sha512-pJ70wq5EAqTAEl9IkGzA+fN0836rycEuz2Cn6yeZ6FRzlVS5IDOkFHpIoEsksPRQV34GDqXm65+OlnZqUSyK2g==} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@1.0.4: + resolution: {integrity: sha512-u9r3uZC0bdpGOXtlxUIdwf9pkmvhqJdrVCH9fapQtgy/OeTTMZ1nqH7agtvEfmGui6e1XxjcdrlxvxJvc3sMqw==} + engines: {node: '>=18'} + + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} + + tinypool@2.1.0: + resolution: {integrity: sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw==} + engines: {node: ^20.0.0 || >=22.0.0} + + tldts-core@7.0.26: + resolution: {integrity: sha512-5WJ2SqFsv4G2Dwi7ZFVRnz6b2H1od39QME1lc2y5Ew3eWiZMAeqOAfWpRP9jHvhUl881406QtZTODvjttJs+ew==} + + tldts@7.0.26: + resolution: {integrity: sha512-WiGwQjr0qYdNNG8KpMKlSvpxz652lqa3Rd+/hSaDcY4Uo6SKWZq2LAF+hsAhUewTtYhXlorBKgNF3Kk8hnjGoQ==} + hasBin: true + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} + + tough-cookie@6.0.1: + resolution: {integrity: sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==} + engines: {node: '>=16'} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tsx@4.21.0: + resolution: {integrity: sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==} + engines: {node: '>=18.0.0'} + hasBin: true + + type-fest@5.4.4: + resolution: {integrity: sha512-JnTrzGu+zPV3aXIUhnyWJj4z/wigMsdYajGLIYakqyOW1nPllzXEJee0QQbHj+CTIQtXGlAjuK0UY+2xTyjVAw==} + engines: {node: '>=20'} + + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@7.19.2: + resolution: {integrity: sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==} + + unplugin@2.3.11: + resolution: {integrity: sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==} + engines: {node: '>=18.12.0'} + + until-async@3.0.2: + resolution: {integrity: sha512-IiSk4HlzAMqTUseHHe3VhIGyuFmN90zMTpD3Z3y8jeQbzLIq500MVM7Jq2vUAnTKAFPJrqwkzr6PoTcPhGcOiw==} + + update-browserslist-db@1.2.3: + resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + use-sync-external-store@1.6.0: + resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + vite-plus@0.1.12: + resolution: {integrity: sha512-8s1RzomZkgrJRiwiYWGq3R0txFPYfBBJGp73XNHQnme0KTTVH5dNm/E2GNyBSMFJbeeF7eh1OSgqWVc2FpR6eA==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + wcwidth@1.0.1: + resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + + webpack-virtual-modules@0.6.2: + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + wrap-ansi@6.2.0: + resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} + engines: {node: '>=8'} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + ws@8.19.0: + resolution: {integrity: sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==} + 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 + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yaml@1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + + yoctocolors-cjs@2.1.3: + resolution: {integrity: sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==} + engines: {node: '>=18'} + + zod@3.25.76: + resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + + zod@4.3.6: + resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} + + zustand@5.0.12: + resolution: {integrity: sha512-i77ae3aZq4dhMlRhJVCYgMLKuSiZAaUPAct2AksxQ+gOtimhGMdXljRT21P5BNpeT4kXlLIckvkPM029OljD7g==} + 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: + + '@ant-design/colors@8.0.1': + dependencies: + '@ant-design/fast-color': 3.0.1 + + '@ant-design/cssinjs-utils@2.1.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@ant-design/cssinjs': 2.1.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@babel/runtime': 7.29.2 + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@ant-design/cssinjs@2.1.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@babel/runtime': 7.29.2 + '@emotion/hash': 0.8.0 + '@emotion/unitless': 0.7.5 + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + csstype: 3.2.3 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + stylis: 4.3.6 + + '@ant-design/fast-color@3.0.1': {} + + '@ant-design/icons-svg@4.4.2': {} + + '@ant-design/icons@6.1.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@ant-design/colors': 8.0.1 + '@ant-design/icons-svg': 4.4.2 + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@ant-design/react-slick@2.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@babel/runtime': 7.29.2 + clsx: 2.1.1 + json2mq: 0.2.0 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + throttle-debounce: 5.0.2 + + '@babel/code-frame@7.29.0': + dependencies: + '@babel/helper-validator-identifier': 7.28.5 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.29.0': {} + + '@babel/core@7.29.0': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/helper-compilation-targets': 7.28.6 + '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) + '@babel/helpers': 7.29.2 + '@babel/parser': 7.29.2 + '@babel/template': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + '@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.29.1': + dependencies: + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 + '@jridgewell/gen-mapping': 0.3.13 + '@jridgewell/trace-mapping': 0.3.31 + jsesc: 3.1.0 + + '@babel/helper-compilation-targets@7.28.6': + dependencies: + '@babel/compat-data': 7.29.0 + '@babel/helper-validator-option': 7.27.1 + browserslist: 4.28.1 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-globals@7.28.0': {} + + '@babel/helper-module-imports@7.28.6': + dependencies: + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-module-imports': 7.28.6 + '@babel/helper-validator-identifier': 7.28.5 + '@babel/traverse': 7.29.0 + transitivePeerDependencies: + - supports-color + + '@babel/helper-plugin-utils@7.28.6': {} + + '@babel/helper-string-parser@7.27.1': {} + + '@babel/helper-validator-identifier@7.28.5': {} + + '@babel/helper-validator-option@7.27.1': {} + + '@babel/helpers@7.29.2': + dependencies: + '@babel/template': 7.28.6 + '@babel/types': 7.29.0 + + '@babel/parser@7.29.2': + dependencies: + '@babel/types': 7.29.0 + + '@babel/plugin-syntax-jsx@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.29.0)': + dependencies: + '@babel/core': 7.29.0 + '@babel/helper-plugin-utils': 7.28.6 + + '@babel/runtime@7.29.2': {} + + '@babel/template@7.28.6': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 + + '@babel/traverse@7.29.0': + dependencies: + '@babel/code-frame': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/helper-globals': 7.28.0 + '@babel/parser': 7.29.2 + '@babel/template': 7.28.6 + '@babel/types': 7.29.0 + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.29.0': + dependencies: + '@babel/helper-string-parser': 7.27.1 + '@babel/helper-validator-identifier': 7.28.5 + + '@emotion/hash@0.8.0': {} + + '@emotion/unitless@0.7.5': {} + + '@esbuild/aix-ppc64@0.25.12': + optional: true + + '@esbuild/aix-ppc64@0.27.4': + optional: true + + '@esbuild/android-arm64@0.25.12': + optional: true + + '@esbuild/android-arm64@0.27.4': + optional: true + + '@esbuild/android-arm@0.25.12': + optional: true + + '@esbuild/android-arm@0.27.4': + optional: true + + '@esbuild/android-x64@0.25.12': + optional: true + + '@esbuild/android-x64@0.27.4': + optional: true + + '@esbuild/darwin-arm64@0.25.12': + optional: true + + '@esbuild/darwin-arm64@0.27.4': + optional: true + + '@esbuild/darwin-x64@0.25.12': + optional: true + + '@esbuild/darwin-x64@0.27.4': + optional: true + + '@esbuild/freebsd-arm64@0.25.12': + optional: true + + '@esbuild/freebsd-arm64@0.27.4': + optional: true + + '@esbuild/freebsd-x64@0.25.12': + optional: true + + '@esbuild/freebsd-x64@0.27.4': + optional: true + + '@esbuild/linux-arm64@0.25.12': + optional: true + + '@esbuild/linux-arm64@0.27.4': + optional: true + + '@esbuild/linux-arm@0.25.12': + optional: true + + '@esbuild/linux-arm@0.27.4': + optional: true + + '@esbuild/linux-ia32@0.25.12': + optional: true + + '@esbuild/linux-ia32@0.27.4': + optional: true + + '@esbuild/linux-loong64@0.25.12': + optional: true + + '@esbuild/linux-loong64@0.27.4': + optional: true + + '@esbuild/linux-mips64el@0.25.12': + optional: true + + '@esbuild/linux-mips64el@0.27.4': + optional: true + + '@esbuild/linux-ppc64@0.25.12': + optional: true + + '@esbuild/linux-ppc64@0.27.4': + optional: true + + '@esbuild/linux-riscv64@0.25.12': + optional: true + + '@esbuild/linux-riscv64@0.27.4': + optional: true + + '@esbuild/linux-s390x@0.25.12': + optional: true + + '@esbuild/linux-s390x@0.27.4': + optional: true + + '@esbuild/linux-x64@0.25.12': + optional: true + + '@esbuild/linux-x64@0.27.4': + optional: true + + '@esbuild/netbsd-arm64@0.25.12': + optional: true + + '@esbuild/netbsd-arm64@0.27.4': + optional: true + + '@esbuild/netbsd-x64@0.25.12': + optional: true + + '@esbuild/netbsd-x64@0.27.4': + optional: true + + '@esbuild/openbsd-arm64@0.25.12': + optional: true + + '@esbuild/openbsd-arm64@0.27.4': + optional: true + + '@esbuild/openbsd-x64@0.25.12': + optional: true + + '@esbuild/openbsd-x64@0.27.4': + optional: true + + '@esbuild/openharmony-arm64@0.25.12': + optional: true + + '@esbuild/openharmony-arm64@0.27.4': + optional: true + + '@esbuild/sunos-x64@0.25.12': + optional: true + + '@esbuild/sunos-x64@0.27.4': + optional: true + + '@esbuild/win32-arm64@0.25.12': + optional: true + + '@esbuild/win32-arm64@0.27.4': + optional: true + + '@esbuild/win32-ia32@0.25.12': + optional: true + + '@esbuild/win32-ia32@0.27.4': + optional: true + + '@esbuild/win32-x64@0.25.12': + optional: true + + '@esbuild/win32-x64@0.27.4': + optional: true + + '@inquirer/ansi@1.0.2': {} + + '@inquirer/confirm@5.1.21(@types/node@25.6.0)': + dependencies: + '@inquirer/core': 10.3.2(@types/node@25.6.0) + '@inquirer/type': 3.0.10(@types/node@25.6.0) + optionalDependencies: + '@types/node': 25.6.0 + + '@inquirer/core@10.3.2(@types/node@25.6.0)': + dependencies: + '@inquirer/ansi': 1.0.2 + '@inquirer/figures': 1.0.15 + '@inquirer/type': 3.0.10(@types/node@25.6.0) + cli-width: 4.1.0 + mute-stream: 2.0.0 + signal-exit: 4.1.0 + wrap-ansi: 6.2.0 + yoctocolors-cjs: 2.1.3 + optionalDependencies: + '@types/node': 25.6.0 + + '@inquirer/figures@1.0.15': {} + + '@inquirer/type@3.0.10(@types/node@25.6.0)': + optionalDependencies: + '@types/node': 25.6.0 + + '@isaacs/cliui@9.0.0': {} + + '@jest/schemas@29.6.3': + dependencies: + '@sinclair/typebox': 0.27.10 + + '@jest/types@29.6.3': + dependencies: + '@jest/schemas': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 25.6.0 + '@types/yargs': 17.0.35 + chalk: 4.1.2 + + '@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 + + '@lingui/babel-plugin-extract-messages@5.9.3': {} + + '@lingui/babel-plugin-lingui-macro@5.9.3(babel-plugin-macros@3.1.0)(typescript@5.9.3)': + dependencies: + '@babel/core': 7.29.0 + '@babel/runtime': 7.29.2 + '@babel/types': 7.29.0 + '@lingui/conf': 5.9.3(typescript@5.9.3) + '@lingui/core': 5.9.3(@lingui/babel-plugin-lingui-macro@5.9.3(babel-plugin-macros@3.1.0)(typescript@5.9.3))(babel-plugin-macros@3.1.0) + '@lingui/message-utils': 5.9.3 + optionalDependencies: + babel-plugin-macros: 3.1.0 + transitivePeerDependencies: + - supports-color + - typescript + + '@lingui/cli@5.9.3(babel-plugin-macros@3.1.0)(typescript@5.9.3)': + dependencies: + '@babel/core': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/parser': 7.29.2 + '@babel/runtime': 7.29.2 + '@babel/types': 7.29.0 + '@lingui/babel-plugin-extract-messages': 5.9.3 + '@lingui/babel-plugin-lingui-macro': 5.9.3(babel-plugin-macros@3.1.0)(typescript@5.9.3) + '@lingui/conf': 5.9.3(typescript@5.9.3) + '@lingui/core': 5.9.3(@lingui/babel-plugin-lingui-macro@5.9.3(babel-plugin-macros@3.1.0)(typescript@5.9.3))(babel-plugin-macros@3.1.0) + '@lingui/format-po': 5.9.3(typescript@5.9.3) + '@lingui/message-utils': 5.9.3 + chokidar: 3.5.1 + cli-table: 0.3.11 + commander: 10.0.1 + convert-source-map: 2.0.0 + date-fns: 3.6.0 + esbuild: 0.25.12 + glob: 11.1.0 + micromatch: 4.0.8 + ms: 2.1.3 + normalize-path: 3.0.0 + ora: 5.4.1 + picocolors: 1.1.1 + pofile: 1.1.4 + pseudolocale: 2.2.0 + source-map: 0.7.6 + threads: 1.7.0 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + - typescript + + '@lingui/conf@5.9.3(typescript@5.9.3)': + dependencies: + '@babel/runtime': 7.29.2 + cosmiconfig: 8.3.6(typescript@5.9.3) + jest-validate: 29.7.0 + jiti: 2.6.1 + picocolors: 1.1.1 + transitivePeerDependencies: + - typescript + + '@lingui/core@5.9.3(@lingui/babel-plugin-lingui-macro@5.9.3(babel-plugin-macros@3.1.0)(typescript@5.9.3))(babel-plugin-macros@3.1.0)': + dependencies: + '@babel/runtime': 7.29.2 + '@lingui/message-utils': 5.9.3 + optionalDependencies: + '@lingui/babel-plugin-lingui-macro': 5.9.3(babel-plugin-macros@3.1.0)(typescript@5.9.3) + babel-plugin-macros: 3.1.0 + + '@lingui/format-po@5.9.3(typescript@5.9.3)': + dependencies: + '@lingui/conf': 5.9.3(typescript@5.9.3) + '@lingui/message-utils': 5.9.3 + date-fns: 3.6.0 + pofile: 1.1.4 + transitivePeerDependencies: + - typescript + + '@lingui/message-utils@5.9.3': + dependencies: + '@messageformat/parser': 5.1.1 + js-sha256: 0.10.1 + + '@lingui/react@5.9.3(@lingui/babel-plugin-lingui-macro@5.9.3(babel-plugin-macros@3.1.0)(typescript@5.9.3))(babel-plugin-macros@3.1.0)(react@19.2.4)': + dependencies: + '@babel/runtime': 7.29.2 + '@lingui/core': 5.9.3(@lingui/babel-plugin-lingui-macro@5.9.3(babel-plugin-macros@3.1.0)(typescript@5.9.3))(babel-plugin-macros@3.1.0) + react: 19.2.4 + optionalDependencies: + '@lingui/babel-plugin-lingui-macro': 5.9.3(babel-plugin-macros@3.1.0)(typescript@5.9.3) + babel-plugin-macros: 3.1.0 + + '@lingui/swc-plugin@5.11.0(@lingui/core@5.9.3(@lingui/babel-plugin-lingui-macro@5.9.3(babel-plugin-macros@3.1.0)(typescript@5.9.3))(babel-plugin-macros@3.1.0))': + dependencies: + '@lingui/core': 5.9.3(@lingui/babel-plugin-lingui-macro@5.9.3(babel-plugin-macros@3.1.0)(typescript@5.9.3))(babel-plugin-macros@3.1.0) + + '@lingui/vite-plugin@5.9.3(@voidzero-dev/vite-plus-core@0.1.12(@types/node@25.6.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(typescript@5.9.3))(babel-plugin-macros@3.1.0)(typescript@5.9.3)': + dependencies: + '@lingui/cli': 5.9.3(babel-plugin-macros@3.1.0)(typescript@5.9.3) + '@lingui/conf': 5.9.3(typescript@5.9.3) + vite: '@voidzero-dev/vite-plus-core@0.1.12(@types/node@25.6.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(typescript@5.9.3)' + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + - typescript + + '@messageformat/parser@5.1.1': + dependencies: + moo: 0.5.3 + + '@mswjs/interceptors@0.41.3': + dependencies: + '@open-draft/deferred-promise': 2.2.0 + '@open-draft/logger': 0.3.0 + '@open-draft/until': 2.1.0 + is-node-process: 1.2.0 + outvariant: 1.4.3 + strict-event-emitter: 0.5.1 + + '@open-draft/deferred-promise@2.2.0': {} + + '@open-draft/logger@0.3.0': + dependencies: + is-node-process: 1.2.0 + outvariant: 1.4.3 + + '@open-draft/until@2.1.0': {} + + '@oxc-project/runtime@0.115.0': {} + + '@oxc-project/types@0.115.0': {} + + '@oxfmt/binding-android-arm-eabi@0.40.0': + optional: true + + '@oxfmt/binding-android-arm64@0.40.0': + optional: true + + '@oxfmt/binding-darwin-arm64@0.40.0': + optional: true + + '@oxfmt/binding-darwin-x64@0.40.0': + optional: true + + '@oxfmt/binding-freebsd-x64@0.40.0': + optional: true + + '@oxfmt/binding-linux-arm-gnueabihf@0.40.0': + optional: true + + '@oxfmt/binding-linux-arm-musleabihf@0.40.0': + optional: true + + '@oxfmt/binding-linux-arm64-gnu@0.40.0': + optional: true + + '@oxfmt/binding-linux-arm64-musl@0.40.0': + optional: true + + '@oxfmt/binding-linux-ppc64-gnu@0.40.0': + optional: true + + '@oxfmt/binding-linux-riscv64-gnu@0.40.0': + optional: true + + '@oxfmt/binding-linux-riscv64-musl@0.40.0': + optional: true + + '@oxfmt/binding-linux-s390x-gnu@0.40.0': + optional: true + + '@oxfmt/binding-linux-x64-gnu@0.40.0': + optional: true + + '@oxfmt/binding-linux-x64-musl@0.40.0': + optional: true + + '@oxfmt/binding-openharmony-arm64@0.40.0': + optional: true + + '@oxfmt/binding-win32-arm64-msvc@0.40.0': + optional: true + + '@oxfmt/binding-win32-ia32-msvc@0.40.0': + optional: true + + '@oxfmt/binding-win32-x64-msvc@0.40.0': + optional: true + + '@oxlint-tsgolint/darwin-arm64@0.17.0': + optional: true + + '@oxlint-tsgolint/darwin-x64@0.17.0': + optional: true + + '@oxlint-tsgolint/linux-arm64@0.17.0': + optional: true + + '@oxlint-tsgolint/linux-x64@0.17.0': + optional: true + + '@oxlint-tsgolint/win32-arm64@0.17.0': + optional: true + + '@oxlint-tsgolint/win32-x64@0.17.0': + optional: true + + '@oxlint/binding-android-arm-eabi@1.55.0': + optional: true + + '@oxlint/binding-android-arm64@1.55.0': + optional: true + + '@oxlint/binding-darwin-arm64@1.55.0': + optional: true + + '@oxlint/binding-darwin-x64@1.55.0': + optional: true + + '@oxlint/binding-freebsd-x64@1.55.0': + optional: true + + '@oxlint/binding-linux-arm-gnueabihf@1.55.0': + optional: true + + '@oxlint/binding-linux-arm-musleabihf@1.55.0': + optional: true + + '@oxlint/binding-linux-arm64-gnu@1.55.0': + optional: true + + '@oxlint/binding-linux-arm64-musl@1.55.0': + optional: true + + '@oxlint/binding-linux-ppc64-gnu@1.55.0': + optional: true + + '@oxlint/binding-linux-riscv64-gnu@1.55.0': + optional: true + + '@oxlint/binding-linux-riscv64-musl@1.55.0': + optional: true + + '@oxlint/binding-linux-s390x-gnu@1.55.0': + optional: true + + '@oxlint/binding-linux-x64-gnu@1.55.0': + optional: true + + '@oxlint/binding-linux-x64-musl@1.55.0': + optional: true + + '@oxlint/binding-openharmony-arm64@1.55.0': + optional: true + + '@oxlint/binding-win32-arm64-msvc@1.55.0': + optional: true + + '@oxlint/binding-win32-ia32-msvc@1.55.0': + optional: true + + '@oxlint/binding-win32-x64-msvc@1.55.0': + optional: true + + '@playwright/test@1.58.2': + dependencies: + playwright: 1.58.2 + + '@polka/url@1.0.0-next.29': {} + + '@rc-component/async-validator@5.1.0': + dependencies: + '@babel/runtime': 7.29.2 + + '@rc-component/cascader@1.14.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/select': 1.6.15(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/tree': 1.2.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/checkbox@2.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/collapse@1.2.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@babel/runtime': 7.29.2 + '@rc-component/motion': 1.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/color-picker@3.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@ant-design/fast-color': 3.0.1 + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/context@2.0.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/dialog@1.8.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/motion': 1.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/portal': 2.2.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/drawer@1.4.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/motion': 1.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/portal': 2.2.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/dropdown@1.0.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/trigger': 3.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/form@1.7.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/async-validator': 5.1.0 + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/image@1.6.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/motion': 1.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/portal': 2.2.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/input-number@1.6.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/mini-decimal': 1.1.3 + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/input@1.1.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/mentions@1.6.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/input': 1.1.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/menu': 1.2.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/textarea': 1.1.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/trigger': 3.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/menu@1.2.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/motion': 1.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/overflow': 1.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/trigger': 3.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/mini-decimal@1.1.3': + dependencies: + '@babel/runtime': 7.29.2 + + '@rc-component/motion@1.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/mutate-observer@2.0.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/notification@1.2.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/motion': 1.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/overflow@1.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@babel/runtime': 7.29.2 + '@rc-component/resize-observer': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/pagination@1.2.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/picker@1.9.1(date-fns@3.6.0)(dayjs@1.11.20)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/overflow': 1.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/resize-observer': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/trigger': 3.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + optionalDependencies: + date-fns: 3.6.0 + dayjs: 1.11.20 + + '@rc-component/portal@2.2.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/progress@1.0.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/qrcode@1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@babel/runtime': 7.29.2 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/rate@1.0.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/resize-observer@1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/segmented@1.3.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@babel/runtime': 7.29.2 + '@rc-component/motion': 1.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/select@1.6.15(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/overflow': 1.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/trigger': 3.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/virtual-list': 1.0.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/slider@1.0.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/steps@1.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/switch@1.0.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/table@1.9.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/context': 2.0.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/resize-observer': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/virtual-list': 1.0.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/tabs@1.7.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/dropdown': 1.0.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/menu': 1.2.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/motion': 1.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/resize-observer': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/textarea@1.1.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/input': 1.1.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/resize-observer': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/tooltip@1.4.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/trigger': 3.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/tour@2.3.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/portal': 2.2.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/trigger': 3.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/tree-select@1.8.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/select': 1.6.15(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/tree': 1.2.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/tree@1.2.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/motion': 1.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/virtual-list': 1.0.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/trigger@3.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/motion': 1.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/portal': 2.2.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/resize-observer': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/upload@1.1.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rc-component/util@1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + is-mobile: 5.0.0 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + react-is: 18.3.1 + + '@rc-component/virtual-list@1.0.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@babel/runtime': 7.29.2 + '@rc-component/resize-observer': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + + '@rolldown/pluginutils@1.0.0-rc.7': {} + + '@sinclair/typebox@0.27.10': {} + + '@standard-schema/spec@1.1.0': {} + + '@swc/core-darwin-arm64@1.15.18': + optional: true + + '@swc/core-darwin-x64@1.15.18': + optional: true + + '@swc/core-linux-arm-gnueabihf@1.15.18': + optional: true + + '@swc/core-linux-arm64-gnu@1.15.18': + optional: true + + '@swc/core-linux-arm64-musl@1.15.18': + optional: true + + '@swc/core-linux-x64-gnu@1.15.18': + optional: true + + '@swc/core-linux-x64-musl@1.15.18': + optional: true + + '@swc/core-win32-arm64-msvc@1.15.18': + optional: true + + '@swc/core-win32-ia32-msvc@1.15.18': + optional: true + + '@swc/core-win32-x64-msvc@1.15.18': + optional: true + + '@swc/core@1.15.18': + dependencies: + '@swc/counter': 0.1.3 + '@swc/types': 0.1.25 + optionalDependencies: + '@swc/core-darwin-arm64': 1.15.18 + '@swc/core-darwin-x64': 1.15.18 + '@swc/core-linux-arm-gnueabihf': 1.15.18 + '@swc/core-linux-arm64-gnu': 1.15.18 + '@swc/core-linux-arm64-musl': 1.15.18 + '@swc/core-linux-x64-gnu': 1.15.18 + '@swc/core-linux-x64-musl': 1.15.18 + '@swc/core-win32-arm64-msvc': 1.15.18 + '@swc/core-win32-ia32-msvc': 1.15.18 + '@swc/core-win32-x64-msvc': 1.15.18 + + '@swc/counter@0.1.3': {} + + '@swc/types@0.1.25': + dependencies: + '@swc/counter': 0.1.3 + + '@tanstack/history@1.161.6': {} + + '@tanstack/query-core@5.90.20': {} + + '@tanstack/react-query@5.90.21(react@19.2.4)': + dependencies: + '@tanstack/query-core': 5.90.20 + react: 19.2.4 + + '@tanstack/react-router@1.167.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@tanstack/history': 1.161.6 + '@tanstack/react-store': 0.9.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@tanstack/router-core': 1.167.4 + isbot: 5.1.36 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + tiny-invariant: 1.3.3 + tiny-warning: 1.0.3 + + '@tanstack/react-store@0.9.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4)': + dependencies: + '@tanstack/store': 0.9.2 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + use-sync-external-store: 1.6.0(react@19.2.4) + + '@tanstack/router-core@1.167.4': + dependencies: + '@tanstack/history': 1.161.6 + '@tanstack/store': 0.9.2 + cookie-es: 2.0.0 + seroval: 1.5.1 + seroval-plugins: 1.5.1(seroval@1.5.1) + tiny-invariant: 1.3.3 + tiny-warning: 1.0.3 + + '@tanstack/router-generator@1.166.12': + dependencies: + '@tanstack/router-core': 1.167.4 + '@tanstack/router-utils': 1.161.6 + '@tanstack/virtual-file-routes': 1.161.7 + prettier: 3.8.1 + recast: 0.23.11 + source-map: 0.7.6 + tsx: 4.21.0 + zod: 3.25.76 + transitivePeerDependencies: + - supports-color + + '@tanstack/router-plugin@1.166.13(@tanstack/react-router@1.167.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(@voidzero-dev/vite-plus-core@0.1.12(@types/node@25.6.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(typescript@5.9.3))': + dependencies: + '@babel/core': 7.29.0 + '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.29.0) + '@babel/plugin-syntax-typescript': 7.28.6(@babel/core@7.29.0) + '@babel/template': 7.28.6 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + '@tanstack/router-core': 1.167.4 + '@tanstack/router-generator': 1.166.12 + '@tanstack/router-utils': 1.161.6 + '@tanstack/virtual-file-routes': 1.161.7 + chokidar: 3.6.0 + unplugin: 2.3.11 + zod: 3.25.76 + optionalDependencies: + '@tanstack/react-router': 1.167.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + vite: '@voidzero-dev/vite-plus-core@0.1.12(@types/node@25.6.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(typescript@5.9.3)' + transitivePeerDependencies: + - supports-color + + '@tanstack/router-utils@1.161.6': + dependencies: + '@babel/core': 7.29.0 + '@babel/generator': 7.29.1 + '@babel/parser': 7.29.2 + '@babel/types': 7.29.0 + ansis: 4.2.0 + babel-dead-code-elimination: 1.0.12 + diff: 8.0.3 + pathe: 2.0.3 + tinyglobby: 0.2.15 + transitivePeerDependencies: + - supports-color + + '@tanstack/store@0.9.2': {} + + '@tanstack/virtual-file-routes@1.161.7': {} + + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + + '@types/deep-eql@4.0.2': {} + + '@types/istanbul-lib-coverage@2.0.6': {} + + '@types/istanbul-lib-report@3.0.3': + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + + '@types/istanbul-reports@3.0.4': + dependencies: + '@types/istanbul-lib-report': 3.0.3 + + '@types/node@25.6.0': + dependencies: + undici-types: 7.19.2 + + '@types/parse-json@4.0.2': + optional: true + + '@types/react-dom@19.2.3(@types/react@19.2.14)': + dependencies: + '@types/react': 19.2.14 + + '@types/react@19.2.14': + dependencies: + csstype: 3.2.3 + + '@types/statuses@2.0.6': {} + + '@types/yargs-parser@21.0.3': {} + + '@types/yargs@17.0.35': + dependencies: + '@types/yargs-parser': 21.0.3 + + '@vitejs/plugin-react-swc@4.3.0(@voidzero-dev/vite-plus-core@0.1.12(@types/node@25.6.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(typescript@5.9.3))': + dependencies: + '@rolldown/pluginutils': 1.0.0-rc.7 + '@swc/core': 1.15.18 + vite: '@voidzero-dev/vite-plus-core@0.1.12(@types/node@25.6.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(typescript@5.9.3)' + transitivePeerDependencies: + - '@swc/helpers' + + '@voidzero-dev/vite-plus-core@0.1.12(@types/node@25.6.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(typescript@5.9.3)': + dependencies: + '@oxc-project/runtime': 0.115.0 + '@oxc-project/types': 0.115.0 + lightningcss: 1.32.0 + postcss: 8.5.8 + optionalDependencies: + '@types/node': 25.6.0 + esbuild: 0.27.4 + fsevents: 2.3.3 + jiti: 2.6.1 + tsx: 4.21.0 + typescript: 5.9.3 + + '@voidzero-dev/vite-plus-darwin-arm64@0.1.12': + optional: true + + '@voidzero-dev/vite-plus-darwin-x64@0.1.12': + optional: true + + '@voidzero-dev/vite-plus-linux-arm64-gnu@0.1.12': + optional: true + + '@voidzero-dev/vite-plus-linux-x64-gnu@0.1.12': + optional: true + + '@voidzero-dev/vite-plus-test@0.1.12(@types/node@25.6.0)(@voidzero-dev/vite-plus-core@0.1.12(@types/node@25.6.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(typescript@5.9.3))(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(typescript@5.9.3)': + dependencies: + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@voidzero-dev/vite-plus-core': 0.1.12(@types/node@25.6.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(typescript@5.9.3) + es-module-lexer: 1.7.0 + obug: 2.1.1 + pixelmatch: 7.1.0 + pngjs: 7.0.0 + sirv: 3.0.2 + std-env: 4.0.0 + tinybench: 2.9.0 + tinyexec: 1.0.4 + tinyglobby: 0.2.15 + vite: '@voidzero-dev/vite-plus-core@0.1.12(@types/node@25.6.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(typescript@5.9.3)' + ws: 8.19.0 + optionalDependencies: + '@types/node': 25.6.0 + transitivePeerDependencies: + - '@arethetypeswrong/core' + - '@tsdown/css' + - '@tsdown/exe' + - '@vitejs/devtools' + - bufferutil + - esbuild + - jiti + - less + - publint + - sass + - sass-embedded + - stylus + - sugarss + - terser + - tsx + - typescript + - unplugin-unused + - utf-8-validate + - yaml + + '@voidzero-dev/vite-plus-win32-arm64-msvc@0.1.12': + optional: true + + '@voidzero-dev/vite-plus-win32-x64-msvc@0.1.12': + optional: true + + acorn@8.16.0: {} + + ansi-regex@5.0.1: {} + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@5.2.0: {} + + ansis@4.2.0: {} + + antd@6.3.3(date-fns@3.6.0)(react-dom@19.2.4(react@19.2.4))(react@19.2.4): + dependencies: + '@ant-design/colors': 8.0.1 + '@ant-design/cssinjs': 2.1.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@ant-design/cssinjs-utils': 2.1.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@ant-design/fast-color': 3.0.1 + '@ant-design/icons': 6.1.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@ant-design/react-slick': 2.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@babel/runtime': 7.29.2 + '@rc-component/cascader': 1.14.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/checkbox': 2.0.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/collapse': 1.2.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/color-picker': 3.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/dialog': 1.8.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/drawer': 1.4.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/dropdown': 1.0.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/form': 1.7.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/image': 1.6.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/input': 1.1.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/input-number': 1.6.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/mentions': 1.6.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/menu': 1.2.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/motion': 1.3.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/mutate-observer': 2.0.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/notification': 1.2.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/pagination': 1.2.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/picker': 1.9.1(date-fns@3.6.0)(dayjs@1.11.20)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/progress': 1.0.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/qrcode': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/rate': 1.0.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/resize-observer': 1.1.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/segmented': 1.3.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/select': 1.6.15(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/slider': 1.0.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/steps': 1.2.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/switch': 1.0.3(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/table': 1.9.1(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/tabs': 1.7.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/textarea': 1.1.2(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/tooltip': 1.4.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/tour': 2.3.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/tree': 1.2.4(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/tree-select': 1.8.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/trigger': 3.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/upload': 1.1.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + '@rc-component/util': 1.9.0(react-dom@19.2.4(react@19.2.4))(react@19.2.4) + clsx: 2.1.1 + dayjs: 1.11.20 + react: 19.2.4 + react-dom: 19.2.4(react@19.2.4) + scroll-into-view-if-needed: 3.1.0 + throttle-debounce: 5.0.2 + transitivePeerDependencies: + - date-fns + - luxon + - moment + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + argparse@2.0.1: {} + + assertion-error@2.0.1: {} + + ast-types@0.16.1: + dependencies: + tslib: 2.8.1 + + babel-dead-code-elimination@1.0.12: + dependencies: + '@babel/core': 7.29.0 + '@babel/parser': 7.29.2 + '@babel/traverse': 7.29.0 + '@babel/types': 7.29.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-macros@3.1.0: + dependencies: + '@babel/runtime': 7.29.2 + cosmiconfig: 7.1.0 + resolve: 1.22.11 + optional: true + + balanced-match@4.0.4: {} + + base64-js@1.5.1: {} + + baseline-browser-mapping@2.10.8: {} + + binary-extensions@2.3.0: {} + + bl@4.1.0: + dependencies: + buffer: 5.7.1 + inherits: 2.0.4 + readable-stream: 3.6.2 + + brace-expansion@5.0.4: + dependencies: + balanced-match: 4.0.4 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browserslist@4.28.1: + dependencies: + baseline-browser-mapping: 2.10.8 + caniuse-lite: 1.0.30001780 + electron-to-chromium: 1.5.313 + node-releases: 2.0.36 + update-browserslist-db: 1.2.3(browserslist@4.28.1) + + buffer@5.7.1: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + cac@6.7.14: {} + + callsites@3.1.0: {} + + camelcase@6.3.0: {} + + caniuse-lite@1.0.30001780: {} + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chokidar@3.5.1: + 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.5.0 + optionalDependencies: + fsevents: 2.3.3 + + 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 + + cli-cursor@3.1.0: + dependencies: + restore-cursor: 3.1.0 + + cli-spinners@2.9.2: {} + + cli-table@0.3.11: + dependencies: + colors: 1.0.3 + + cli-width@4.1.0: {} + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + clone@1.0.4: {} + + clsx@2.1.1: {} + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.4: {} + + colors@1.0.3: {} + + commander@10.0.1: {} + + compute-scroll-into-view@3.1.1: {} + + convert-source-map@2.0.0: {} + + cookie-es@2.0.0: {} + + cookie@1.1.1: {} + + cosmiconfig@7.1.0: + dependencies: + '@types/parse-json': 4.0.2 + import-fresh: 3.3.1 + parse-json: 5.2.0 + path-type: 4.0.0 + yaml: 1.10.2 + optional: true + + cosmiconfig@8.3.6(typescript@5.9.3): + dependencies: + import-fresh: 3.3.1 + js-yaml: 4.1.1 + parse-json: 5.2.0 + path-type: 4.0.0 + optionalDependencies: + typescript: 5.9.3 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + csstype@3.2.3: {} + + date-fns@3.6.0: {} + + dayjs@1.11.20: {} + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + defaults@1.0.4: + dependencies: + clone: 1.0.4 + + detect-libc@2.1.2: {} + + diff@8.0.3: {} + + electron-to-chromium@1.5.313: {} + + emoji-regex@8.0.0: {} + + error-ex@1.3.4: + dependencies: + is-arrayish: 0.2.1 + + es-module-lexer@1.7.0: {} + + esbuild@0.25.12: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.12 + '@esbuild/android-arm': 0.25.12 + '@esbuild/android-arm64': 0.25.12 + '@esbuild/android-x64': 0.25.12 + '@esbuild/darwin-arm64': 0.25.12 + '@esbuild/darwin-x64': 0.25.12 + '@esbuild/freebsd-arm64': 0.25.12 + '@esbuild/freebsd-x64': 0.25.12 + '@esbuild/linux-arm': 0.25.12 + '@esbuild/linux-arm64': 0.25.12 + '@esbuild/linux-ia32': 0.25.12 + '@esbuild/linux-loong64': 0.25.12 + '@esbuild/linux-mips64el': 0.25.12 + '@esbuild/linux-ppc64': 0.25.12 + '@esbuild/linux-riscv64': 0.25.12 + '@esbuild/linux-s390x': 0.25.12 + '@esbuild/linux-x64': 0.25.12 + '@esbuild/netbsd-arm64': 0.25.12 + '@esbuild/netbsd-x64': 0.25.12 + '@esbuild/openbsd-arm64': 0.25.12 + '@esbuild/openbsd-x64': 0.25.12 + '@esbuild/openharmony-arm64': 0.25.12 + '@esbuild/sunos-x64': 0.25.12 + '@esbuild/win32-arm64': 0.25.12 + '@esbuild/win32-ia32': 0.25.12 + '@esbuild/win32-x64': 0.25.12 + + esbuild@0.27.4: + optionalDependencies: + '@esbuild/aix-ppc64': 0.27.4 + '@esbuild/android-arm': 0.27.4 + '@esbuild/android-arm64': 0.27.4 + '@esbuild/android-x64': 0.27.4 + '@esbuild/darwin-arm64': 0.27.4 + '@esbuild/darwin-x64': 0.27.4 + '@esbuild/freebsd-arm64': 0.27.4 + '@esbuild/freebsd-x64': 0.27.4 + '@esbuild/linux-arm': 0.27.4 + '@esbuild/linux-arm64': 0.27.4 + '@esbuild/linux-ia32': 0.27.4 + '@esbuild/linux-loong64': 0.27.4 + '@esbuild/linux-mips64el': 0.27.4 + '@esbuild/linux-ppc64': 0.27.4 + '@esbuild/linux-riscv64': 0.27.4 + '@esbuild/linux-s390x': 0.27.4 + '@esbuild/linux-x64': 0.27.4 + '@esbuild/netbsd-arm64': 0.27.4 + '@esbuild/netbsd-x64': 0.27.4 + '@esbuild/openbsd-arm64': 0.27.4 + '@esbuild/openbsd-x64': 0.27.4 + '@esbuild/openharmony-arm64': 0.27.4 + '@esbuild/sunos-x64': 0.27.4 + '@esbuild/win32-arm64': 0.27.4 + '@esbuild/win32-ia32': 0.27.4 + '@esbuild/win32-x64': 0.27.4 + + escalade@3.2.0: {} + + esm@3.2.25: + optional: true + + esprima@4.0.1: {} + + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + fsevents@2.3.2: + optional: true + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: + optional: true + + gensync@1.0.0-beta.2: {} + + get-caller-file@2.0.5: {} + + get-tsconfig@4.13.6: + dependencies: + resolve-pkg-maps: 1.0.0 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob@11.1.0: + dependencies: + foreground-child: 3.3.1 + jackspeak: 4.2.3 + minimatch: 10.2.4 + minipass: 7.1.3 + package-json-from-dist: 1.0.1 + path-scurry: 2.0.2 + + graphql@16.13.1: {} + + has-flag@4.0.0: {} + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + optional: true + + headers-polyfill@4.0.3: {} + + ieee754@1.2.1: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + inherits@2.0.4: {} + + is-arrayish@0.2.1: {} + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + optional: true + + is-extglob@2.1.1: {} + + is-fullwidth-code-point@3.0.0: {} + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-interactive@1.0.0: {} + + is-mobile@5.0.0: {} + + is-node-process@1.2.0: {} + + is-number@7.0.0: {} + + is-observable@2.1.0: {} + + is-unicode-supported@0.1.0: {} + + isbot@5.1.36: {} + + isexe@2.0.0: {} + + jackspeak@4.2.3: + dependencies: + '@isaacs/cliui': 9.0.0 + + jest-get-type@29.6.3: {} + + jest-validate@29.7.0: + dependencies: + '@jest/types': 29.6.3 + camelcase: 6.3.0 + chalk: 4.1.2 + jest-get-type: 29.6.3 + leven: 3.1.0 + pretty-format: 29.7.0 + + jiti@2.6.1: {} + + js-sha256@0.10.1: {} + + js-tokens@4.0.0: {} + + js-yaml@4.1.1: + dependencies: + argparse: 2.0.1 + + jsesc@3.1.0: {} + + json-parse-even-better-errors@2.3.1: {} + + json2mq@0.2.0: + dependencies: + string-convert: 0.2.1 + + json5@2.2.3: {} + + leven@3.1.0: {} + + lightningcss-android-arm64@1.32.0: + optional: true + + lightningcss-darwin-arm64@1.32.0: + optional: true + + lightningcss-darwin-x64@1.32.0: + optional: true + + lightningcss-freebsd-x64@1.32.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.32.0: + optional: true + + lightningcss-linux-arm64-gnu@1.32.0: + optional: true + + lightningcss-linux-arm64-musl@1.32.0: + optional: true + + lightningcss-linux-x64-gnu@1.32.0: + optional: true + + lightningcss-linux-x64-musl@1.32.0: + optional: true + + lightningcss-win32-arm64-msvc@1.32.0: + optional: true + + lightningcss-win32-x64-msvc@1.32.0: + optional: true + + lightningcss@1.32.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.32.0 + lightningcss-darwin-arm64: 1.32.0 + lightningcss-darwin-x64: 1.32.0 + lightningcss-freebsd-x64: 1.32.0 + lightningcss-linux-arm-gnueabihf: 1.32.0 + lightningcss-linux-arm64-gnu: 1.32.0 + lightningcss-linux-arm64-musl: 1.32.0 + lightningcss-linux-x64-gnu: 1.32.0 + lightningcss-linux-x64-musl: 1.32.0 + lightningcss-win32-arm64-msvc: 1.32.0 + lightningcss-win32-x64-msvc: 1.32.0 + + lines-and-columns@1.2.4: {} + + log-symbols@4.1.0: + dependencies: + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + + lru-cache@11.2.7: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + lucide-react@1.7.0(react@19.2.4): + dependencies: + react: 19.2.4 + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mimic-fn@2.1.0: {} + + minimatch@10.2.4: + dependencies: + brace-expansion: 5.0.4 + + minipass@7.1.3: {} + + moo@0.5.3: {} + + mrmime@2.0.1: {} + + ms@2.1.3: {} + + msw@2.12.12(@types/node@25.6.0)(typescript@5.9.3): + dependencies: + '@inquirer/confirm': 5.1.21(@types/node@25.6.0) + '@mswjs/interceptors': 0.41.3 + '@open-draft/deferred-promise': 2.2.0 + '@types/statuses': 2.0.6 + cookie: 1.1.1 + graphql: 16.13.1 + headers-polyfill: 4.0.3 + is-node-process: 1.2.0 + outvariant: 1.4.3 + path-to-regexp: 6.3.0 + picocolors: 1.1.1 + rettime: 0.10.1 + statuses: 2.0.2 + strict-event-emitter: 0.5.1 + tough-cookie: 6.0.1 + type-fest: 5.4.4 + until-async: 3.0.2 + yargs: 17.7.2 + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - '@types/node' + + mute-stream@2.0.0: {} + + nanoid@3.3.11: {} + + node-releases@2.0.36: {} + + normalize-path@3.0.0: {} + + observable-fns@0.6.1: {} + + obug@2.1.1: {} + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + + ora@5.4.1: + dependencies: + bl: 4.1.0 + chalk: 4.1.2 + cli-cursor: 3.1.0 + cli-spinners: 2.9.2 + is-interactive: 1.0.0 + is-unicode-supported: 0.1.0 + log-symbols: 4.1.0 + strip-ansi: 6.0.1 + wcwidth: 1.0.1 + + outvariant@1.4.3: {} + + oxfmt@0.40.0: + dependencies: + tinypool: 2.1.0 + optionalDependencies: + '@oxfmt/binding-android-arm-eabi': 0.40.0 + '@oxfmt/binding-android-arm64': 0.40.0 + '@oxfmt/binding-darwin-arm64': 0.40.0 + '@oxfmt/binding-darwin-x64': 0.40.0 + '@oxfmt/binding-freebsd-x64': 0.40.0 + '@oxfmt/binding-linux-arm-gnueabihf': 0.40.0 + '@oxfmt/binding-linux-arm-musleabihf': 0.40.0 + '@oxfmt/binding-linux-arm64-gnu': 0.40.0 + '@oxfmt/binding-linux-arm64-musl': 0.40.0 + '@oxfmt/binding-linux-ppc64-gnu': 0.40.0 + '@oxfmt/binding-linux-riscv64-gnu': 0.40.0 + '@oxfmt/binding-linux-riscv64-musl': 0.40.0 + '@oxfmt/binding-linux-s390x-gnu': 0.40.0 + '@oxfmt/binding-linux-x64-gnu': 0.40.0 + '@oxfmt/binding-linux-x64-musl': 0.40.0 + '@oxfmt/binding-openharmony-arm64': 0.40.0 + '@oxfmt/binding-win32-arm64-msvc': 0.40.0 + '@oxfmt/binding-win32-ia32-msvc': 0.40.0 + '@oxfmt/binding-win32-x64-msvc': 0.40.0 + + oxlint-tsgolint@0.17.0: + optionalDependencies: + '@oxlint-tsgolint/darwin-arm64': 0.17.0 + '@oxlint-tsgolint/darwin-x64': 0.17.0 + '@oxlint-tsgolint/linux-arm64': 0.17.0 + '@oxlint-tsgolint/linux-x64': 0.17.0 + '@oxlint-tsgolint/win32-arm64': 0.17.0 + '@oxlint-tsgolint/win32-x64': 0.17.0 + + oxlint@1.55.0(oxlint-tsgolint@0.17.0): + optionalDependencies: + '@oxlint/binding-android-arm-eabi': 1.55.0 + '@oxlint/binding-android-arm64': 1.55.0 + '@oxlint/binding-darwin-arm64': 1.55.0 + '@oxlint/binding-darwin-x64': 1.55.0 + '@oxlint/binding-freebsd-x64': 1.55.0 + '@oxlint/binding-linux-arm-gnueabihf': 1.55.0 + '@oxlint/binding-linux-arm-musleabihf': 1.55.0 + '@oxlint/binding-linux-arm64-gnu': 1.55.0 + '@oxlint/binding-linux-arm64-musl': 1.55.0 + '@oxlint/binding-linux-ppc64-gnu': 1.55.0 + '@oxlint/binding-linux-riscv64-gnu': 1.55.0 + '@oxlint/binding-linux-riscv64-musl': 1.55.0 + '@oxlint/binding-linux-s390x-gnu': 1.55.0 + '@oxlint/binding-linux-x64-gnu': 1.55.0 + '@oxlint/binding-linux-x64-musl': 1.55.0 + '@oxlint/binding-openharmony-arm64': 1.55.0 + '@oxlint/binding-win32-arm64-msvc': 1.55.0 + '@oxlint/binding-win32-ia32-msvc': 1.55.0 + '@oxlint/binding-win32-x64-msvc': 1.55.0 + oxlint-tsgolint: 0.17.0 + + package-json-from-dist@1.0.1: {} + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.29.0 + error-ex: 1.3.4 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + path-key@3.1.1: {} + + path-parse@1.0.7: + optional: true + + path-scurry@2.0.2: + dependencies: + lru-cache: 11.2.7 + minipass: 7.1.3 + + path-to-regexp@6.3.0: {} + + path-type@4.0.0: {} + + pathe@2.0.3: {} + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + picomatch@4.0.3: {} + + pixelmatch@7.1.0: + dependencies: + pngjs: 7.0.0 + + playwright-core@1.58.2: {} + + playwright@1.58.2: + dependencies: + playwright-core: 1.58.2 + optionalDependencies: + fsevents: 2.3.2 + + pngjs@7.0.0: {} + + pofile@1.1.4: {} + + postcss@8.5.8: + dependencies: + nanoid: 3.3.11 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prettier@3.8.1: {} + + pretty-format@29.7.0: + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.3.1 + + pseudolocale@2.2.0: + dependencies: + commander: 10.0.1 + + react-dom@19.2.4(react@19.2.4): + dependencies: + react: 19.2.4 + scheduler: 0.27.0 + + react-is@18.3.1: {} + + react@19.2.4: {} + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readdirp@3.5.0: + dependencies: + picomatch: 2.3.1 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + + 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 + + require-directory@2.1.1: {} + + resolve-from@4.0.0: {} + + resolve-pkg-maps@1.0.0: {} + + resolve@1.22.11: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + optional: true + + restore-cursor@3.1.0: + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + + rettime@0.10.1: {} + + safe-buffer@5.2.1: {} + + scheduler@0.27.0: {} + + scroll-into-view-if-needed@3.1.0: + dependencies: + compute-scroll-into-view: 3.1.1 + + semver@6.3.1: {} + + seroval-plugins@1.5.1(seroval@1.5.1): + dependencies: + seroval: 1.5.1 + + seroval@1.5.1: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + signal-exit@3.0.7: {} + + signal-exit@4.1.0: {} + + sirv@3.0.2: + dependencies: + '@polka/url': 1.0.0-next.29 + mrmime: 2.0.1 + totalist: 3.0.1 + + source-map-js@1.2.1: {} + + source-map@0.6.1: {} + + source-map@0.7.6: {} + + statuses@2.0.2: {} + + std-env@4.0.0: {} + + strict-event-emitter@0.5.1: {} + + string-convert@0.2.1: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + stylis@4.3.6: {} + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-preserve-symlinks-flag@1.0.0: + optional: true + + tagged-tag@1.0.0: {} + + threads@1.7.0: + dependencies: + callsites: 3.1.0 + debug: 4.4.3 + is-observable: 2.1.0 + observable-fns: 0.6.1 + optionalDependencies: + tiny-worker: 2.3.0 + transitivePeerDependencies: + - supports-color + + throttle-debounce@5.0.2: {} + + tiny-invariant@1.3.3: {} + + tiny-warning@1.0.3: {} + + tiny-worker@2.3.0: + dependencies: + esm: 3.2.25 + optional: true + + tinybench@2.9.0: {} + + tinyexec@1.0.4: {} + + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + + tinypool@2.1.0: {} + + tldts-core@7.0.26: {} + + tldts@7.0.26: + dependencies: + tldts-core: 7.0.26 + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + totalist@3.0.1: {} + + tough-cookie@6.0.1: + dependencies: + tldts: 7.0.26 + + tslib@2.8.1: {} + + tsx@4.21.0: + dependencies: + esbuild: 0.27.4 + get-tsconfig: 4.13.6 + optionalDependencies: + fsevents: 2.3.3 + + type-fest@5.4.4: + dependencies: + tagged-tag: 1.0.0 + + typescript@5.9.3: {} + + undici-types@7.19.2: {} + + unplugin@2.3.11: + dependencies: + '@jridgewell/remapping': 2.3.5 + acorn: 8.16.0 + picomatch: 4.0.3 + webpack-virtual-modules: 0.6.2 + + until-async@3.0.2: {} + + update-browserslist-db@1.2.3(browserslist@4.28.1): + dependencies: + browserslist: 4.28.1 + escalade: 3.2.0 + picocolors: 1.1.1 + + use-sync-external-store@1.6.0(react@19.2.4): + dependencies: + react: 19.2.4 + + util-deprecate@1.0.2: {} + + vite-plus@0.1.12(@types/node@25.6.0)(@voidzero-dev/vite-plus-core@0.1.12(@types/node@25.6.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(typescript@5.9.3))(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(typescript@5.9.3): + dependencies: + '@oxc-project/types': 0.115.0 + '@voidzero-dev/vite-plus-core': 0.1.12(@types/node@25.6.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(typescript@5.9.3) + '@voidzero-dev/vite-plus-test': 0.1.12(@types/node@25.6.0)(@voidzero-dev/vite-plus-core@0.1.12(@types/node@25.6.0)(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(typescript@5.9.3))(esbuild@0.27.4)(jiti@2.6.1)(tsx@4.21.0)(typescript@5.9.3) + cac: 6.7.14 + cross-spawn: 7.0.6 + oxfmt: 0.40.0 + oxlint: 1.55.0(oxlint-tsgolint@0.17.0) + oxlint-tsgolint: 0.17.0 + picocolors: 1.1.1 + optionalDependencies: + '@voidzero-dev/vite-plus-darwin-arm64': 0.1.12 + '@voidzero-dev/vite-plus-darwin-x64': 0.1.12 + '@voidzero-dev/vite-plus-linux-arm64-gnu': 0.1.12 + '@voidzero-dev/vite-plus-linux-x64-gnu': 0.1.12 + '@voidzero-dev/vite-plus-win32-arm64-msvc': 0.1.12 + '@voidzero-dev/vite-plus-win32-x64-msvc': 0.1.12 + transitivePeerDependencies: + - '@arethetypeswrong/core' + - '@edge-runtime/vm' + - '@opentelemetry/api' + - '@tsdown/css' + - '@tsdown/exe' + - '@types/node' + - '@vitejs/devtools' + - '@vitest/ui' + - bufferutil + - esbuild + - happy-dom + - jiti + - jsdom + - less + - publint + - sass + - sass-embedded + - stylus + - sugarss + - terser + - tsx + - typescript + - unplugin-unused + - utf-8-validate + - vite + - yaml + + wcwidth@1.0.1: + dependencies: + defaults: 1.0.4 + + webpack-virtual-modules@0.6.2: {} + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + wrap-ansi@6.2.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + ws@8.19.0: {} + + y18n@5.0.8: {} + + yallist@3.1.1: {} + + yaml@1.10.2: + optional: true + + yargs-parser@21.1.1: {} + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + + yoctocolors-cjs@2.1.3: {} + + zod@3.25.76: {} + + zod@4.3.6: {} + + zustand@5.0.12(@types/react@19.2.14)(react@19.2.4)(use-sync-external-store@1.6.0(react@19.2.4)): + optionalDependencies: + '@types/react': 19.2.14 + react: 19.2.4 + use-sync-external-store: 1.6.0(react@19.2.4) diff --git a/apps/with-lingui/public/favicon.svg b/apps/with-lingui/public/favicon.svg new file mode 100644 index 0000000..ce7afe5 --- /dev/null +++ b/apps/with-lingui/public/favicon.svg @@ -0,0 +1,24 @@ + + + + Created with Sketch. + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/with-lingui/public/mockServiceWorker.js b/apps/with-lingui/public/mockServiceWorker.js new file mode 100644 index 0000000..884a801 --- /dev/null +++ b/apps/with-lingui/public/mockServiceWorker.js @@ -0,0 +1,336 @@ +/* eslint-disable */ +/* tslint:disable */ + +/** + * Mock Service Worker. + * @see https://github.com/mswjs/msw + * - Please do NOT modify this file. + */ + +const PACKAGE_VERSION = "2.12.12"; +const INTEGRITY_CHECKSUM = "4db4a41e972cec1b64cc569c66952d82"; +const IS_MOCKED_RESPONSE = Symbol("isMockedResponse"); +const activeClientIds = new Set(); + +addEventListener("install", function () { + self.skipWaiting(); +}); + +addEventListener("activate", function (event) { + event.waitUntil(self.clients.claim()); +}); + +addEventListener("message", async function (event) { + const clientId = Reflect.get(event.source || {}, "id"); + + if (!clientId || !self.clients) { + return; + } + + const client = await self.clients.get(clientId); + + if (!client) { + return; + } + + const allClients = await self.clients.matchAll({ + type: "window", + }); + + switch (event.data) { + case "KEEPALIVE_REQUEST": { + sendToClient(client, { + type: "KEEPALIVE_RESPONSE", + }); + break; + } + + case "INTEGRITY_CHECK_REQUEST": { + sendToClient(client, { + type: "INTEGRITY_CHECK_RESPONSE", + payload: { + packageVersion: PACKAGE_VERSION, + checksum: INTEGRITY_CHECKSUM, + }, + }); + break; + } + + case "MOCK_ACTIVATE": { + activeClientIds.add(clientId); + + sendToClient(client, { + type: "MOCKING_ENABLED", + payload: { + client: { + id: client.id, + frameType: client.frameType, + }, + }, + }); + break; + } + + case "CLIENT_CLOSED": { + activeClientIds.delete(clientId); + + const remainingClients = allClients.filter((client) => { + return client.id !== clientId; + }); + + // Unregister itself when there are no more clients + if (remainingClients.length === 0) { + self.registration.unregister(); + } + + break; + } + } +}); + +addEventListener("fetch", function (event) { + const requestInterceptedAt = Date.now(); + + // Bypass navigation requests. + if (event.request.mode === "navigate") { + return; + } + + // Opening the DevTools triggers the "only-if-cached" request + // that cannot be handled by the worker. Bypass such requests. + if (event.request.cache === "only-if-cached" && event.request.mode !== "same-origin") { + return; + } + + // Bypass all requests when there are no active clients. + // Prevents the self-unregistered worked from handling requests + // after it's been terminated (still remains active until the next reload). + if (activeClientIds.size === 0) { + return; + } + + const requestId = crypto.randomUUID(); + event.respondWith(handleRequest(event, requestId, requestInterceptedAt)); +}); + +/** + * @param {FetchEvent} event + * @param {string} requestId + * @param {number} requestInterceptedAt + */ +async function handleRequest(event, requestId, requestInterceptedAt) { + const client = await resolveMainClient(event); + const requestCloneForEvents = event.request.clone(); + const response = await getResponse(event, client, requestId, requestInterceptedAt); + + // Send back the response clone for the "response:*" life-cycle events. + // Ensure MSW is active and ready to handle the message, otherwise + // this message will pend indefinitely. + if (client && activeClientIds.has(client.id)) { + const serializedRequest = await serializeRequest(requestCloneForEvents); + + // Clone the response so both the client and the library could consume it. + const responseClone = response.clone(); + + sendToClient( + client, + { + type: "RESPONSE", + payload: { + isMockedResponse: IS_MOCKED_RESPONSE in response, + request: { + id: requestId, + ...serializedRequest, + }, + response: { + type: responseClone.type, + status: responseClone.status, + statusText: responseClone.statusText, + headers: Object.fromEntries(responseClone.headers.entries()), + body: responseClone.body, + }, + }, + }, + responseClone.body ? [serializedRequest.body, responseClone.body] : [], + ); + } + + return response; +} + +/** + * Resolve the main client for the given event. + * Client that issues a request doesn't necessarily equal the client + * that registered the worker. It's with the latter the worker should + * communicate with during the response resolving phase. + * @param {FetchEvent} event + * @returns {Promise} + */ +async function resolveMainClient(event) { + const client = await self.clients.get(event.clientId); + + if (activeClientIds.has(event.clientId)) { + return client; + } + + if (client?.frameType === "top-level") { + return client; + } + + const allClients = await self.clients.matchAll({ + type: "window", + }); + + return allClients + .filter((client) => { + // Get only those clients that are currently visible. + return client.visibilityState === "visible"; + }) + .find((client) => { + // Find the client ID that's recorded in the + // set of clients that have registered the worker. + return activeClientIds.has(client.id); + }); +} + +/** + * @param {FetchEvent} event + * @param {Client | undefined} client + * @param {string} requestId + * @param {number} requestInterceptedAt + * @returns {Promise} + */ +async function getResponse(event, client, requestId, requestInterceptedAt) { + // Clone the request because it might've been already used + // (i.e. its body has been read and sent to the client). + const requestClone = event.request.clone(); + + function passthrough() { + // Cast the request headers to a new Headers instance + // so the headers can be manipulated with. + const headers = new Headers(requestClone.headers); + + // Remove the "accept" header value that marked this request as passthrough. + // This prevents request alteration and also keeps it compliant with the + // user-defined CORS policies. + const acceptHeader = headers.get("accept"); + if (acceptHeader) { + const values = acceptHeader.split(",").map((value) => value.trim()); + const filteredValues = values.filter((value) => value !== "msw/passthrough"); + + if (filteredValues.length > 0) { + headers.set("accept", filteredValues.join(", ")); + } else { + headers.delete("accept"); + } + } + + return fetch(requestClone, { headers }); + } + + // Bypass mocking when the client is not active. + if (!client) { + return passthrough(); + } + + // Bypass initial page load requests (i.e. static assets). + // The absence of the immediate/parent client in the map of the active clients + // means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet + // and is not ready to handle requests. + if (!activeClientIds.has(client.id)) { + return passthrough(); + } + + // Notify the client that a request has been intercepted. + const serializedRequest = await serializeRequest(event.request); + const clientMessage = await sendToClient( + client, + { + type: "REQUEST", + payload: { + id: requestId, + interceptedAt: requestInterceptedAt, + ...serializedRequest, + }, + }, + [serializedRequest.body], + ); + + switch (clientMessage.type) { + case "MOCK_RESPONSE": { + return respondWithMock(clientMessage.data); + } + + case "PASSTHROUGH": { + return passthrough(); + } + } + + return passthrough(); +} + +/** + * @param {Client} client + * @param {any} message + * @param {Array} transferrables + * @returns {Promise} + */ +function sendToClient(client, message, transferrables = []) { + return new Promise((resolve, reject) => { + const channel = new MessageChannel(); + + channel.port1.onmessage = (event) => { + if (event.data && event.data.error) { + return reject(event.data.error); + } + + resolve(event.data); + }; + + client.postMessage(message, [channel.port2, ...transferrables.filter(Boolean)]); + }); +} + +/** + * @param {Response} response + * @returns {Response} + */ +function respondWithMock(response) { + // Setting response status code to 0 is a no-op. + // However, when responding with a "Response.error()", the produced Response + // instance will have status code set to 0. Since it's not possible to create + // a Response instance with status code 0, handle that use-case separately. + if (response.status === 0) { + return Response.error(); + } + + const mockedResponse = new Response(response.body, response); + + Reflect.defineProperty(mockedResponse, IS_MOCKED_RESPONSE, { + value: true, + enumerable: true, + }); + + return mockedResponse; +} + +/** + * @param {Request} request + */ +async function serializeRequest(request) { + return { + url: request.url, + mode: request.mode, + method: request.method, + headers: Object.fromEntries(request.headers.entries()), + cache: request.cache, + credentials: request.credentials, + destination: request.destination, + integrity: request.integrity, + redirect: request.redirect, + referrer: request.referrer, + referrerPolicy: request.referrerPolicy, + body: await request.arrayBuffer(), + keepalive: request.keepalive, + }; +} diff --git a/apps/with-lingui/src/api/auth.ts b/apps/with-lingui/src/api/auth.ts new file mode 100644 index 0000000..7afbd41 --- /dev/null +++ b/apps/with-lingui/src/api/auth.ts @@ -0,0 +1,11 @@ +import type { AuthTokens, LoginRequest, User, MenuItem, PermissionsList } from "./schemas"; + +export const AUTH_ENDPOINTS = { + login: "/api/auth/login", + refresh: "/api/auth/refresh", + logout: "/api/auth/logout", + user: "/api/auth/user", + permissions: "/api/auth/permissions", +} as const; + +export type { AuthTokens, LoginRequest, User, MenuItem, PermissionsList }; diff --git a/apps/with-lingui/src/api/schemas.ts b/apps/with-lingui/src/api/schemas.ts new file mode 100644 index 0000000..336b57b --- /dev/null +++ b/apps/with-lingui/src/api/schemas.ts @@ -0,0 +1,131 @@ +import { z } from "zod/v4"; + +export const UserSchema = z.object({ + id: z.string(), + username: z.string(), + avatar: z.string().nullable(), + email: z.string().nullable(), + roles: z.array(z.string()), + permissions: z.array(z.string()), +}); + +export type User = z.infer; + +/** GET `/api/auth/user` body (no `permissions`; load via `/api/auth/permissions`). */ +export const AuthUserResponseSchema = UserSchema.omit({ permissions: true }); +export type AuthUserResponse = z.infer; + +export const AuthTokensSchema = z.object({ + accessToken: z.string().min(1), + refreshToken: z.string().min(1), +}); + +export type AuthTokens = z.infer; + +export const LoginRequestSchema = z.object({ + username: z.string().min(1), + password: z.string().min(1), +}); + +export type LoginRequest = z.infer; + +export const PermissionsListSchema = z.array(z.string()); + +export type PermissionsList = z.infer; + +const BaseMenuNodeSchema = z.object({ + id: z.string(), + name: z.string(), + icon: z.string().nullable(), + permissions: z.array(z.string()).nullable(), + sort: z.int(), + hidden: z.boolean(), +}); + +export type MenuItem = + | (z.infer & { + kind: "item"; + path: string; + children: MenuItem[] | null; + }) + | (z.infer & { + kind: "group"; + path: null; + children: MenuItem[]; + }); + +export const MenuItemSchema: z.ZodType = z.lazy(() => + z.discriminatedUnion("kind", [ + BaseMenuNodeSchema.extend({ + kind: z.literal("item"), + path: z.string(), + children: z.array(MenuItemSchema).nullable(), + }), + BaseMenuNodeSchema.extend({ + kind: z.literal("group"), + path: z.null(), + children: z.array(MenuItemSchema), + }), + ]), +); + +export function ApiResponseSchema(dataSchema: T) { + return z.object({ + code: z.int(), + data: dataSchema, + message: z.string(), + }); +} + +export type ApiResponse = { + code: number; + data: T; + message: string; +}; + +export function PaginatedResponseSchema(itemSchema: T) { + return z.object({ + code: z.int(), + data: z.object({ + list: z.array(itemSchema), + total: z.int(), + }), + message: z.string(), + }); +} + +export type PaginatedData = { + list: T[]; + total: number; +}; + +export const SearchParamsSchema = z.object({ + page: z.number().int().positive().catch(1), + pageSize: z.number().int().positive().catch(10), + sortField: z.string().nullable().catch(null), + sortOrder: z.enum(["ascend", "descend"]).nullable().catch(null), +}); + +export type SearchParams = z.infer; + +/** Ant Design Input submits `""` when empty; treat as null for optional email */ +const createUserEmailSchema = z + .union([z.string(), z.null(), z.undefined()]) + .transform((v) => { + if (v == null) return null; + const t = String(v).trim(); + return t === "" ? null : t; + }) + .pipe(z.union([z.string().email(), z.null()])); + +export const CreateUserRequestSchema = z.object({ + username: z.string().min(1), + email: createUserEmailSchema, + roles: z.array(z.string()).min(1), +}); + +export type CreateUserRequest = z.infer; + +export const UpdateUserRequestSchema = CreateUserRequestSchema.partial(); + +export type UpdateUserRequest = z.infer; diff --git a/apps/with-lingui/src/api/user.ts b/apps/with-lingui/src/api/user.ts new file mode 100644 index 0000000..74a5e93 --- /dev/null +++ b/apps/with-lingui/src/api/user.ts @@ -0,0 +1,10 @@ +import type { CreateUserRequest, UpdateUserRequest, User } from "./schemas"; + +export const USER_ENDPOINTS = { + list: "/api/users", + create: "/api/users", + update: (id: string) => `/api/users/${id}`, + delete: (id: string) => `/api/users/${id}`, +} as const; + +export type { CreateUserRequest, UpdateUserRequest, User }; diff --git a/apps/with-lingui/src/auth/session.ts b/apps/with-lingui/src/auth/session.ts new file mode 100644 index 0000000..45892f5 --- /dev/null +++ b/apps/with-lingui/src/auth/session.ts @@ -0,0 +1,18 @@ +import { httpClient } from "@/utils/http"; +import { AUTH_ENDPOINTS } from "@/api/auth"; +import { AuthUserResponseSchema, PermissionsListSchema, UserSchema } from "@/api/schemas"; +import { APP_MENU_TREE, filterMenuTreeByPermissions } from "@/utils/appMenu"; +import { useAuthStore } from "@/stores/auth"; + +/** Fetches `/api/auth/user` and `/api/auth/permissions`, then updates `user` and sidebar `menus`. */ +export async function fetchSessionAndApplyToStore(): Promise { + const [userBase, permissions] = await Promise.all([ + httpClient.get(AUTH_ENDPOINTS.user).then((d) => AuthUserResponseSchema.parse(d)), + httpClient.get(AUTH_ENDPOINTS.permissions).then((d) => PermissionsListSchema.parse(d)), + ]); + const user = UserSchema.parse({ ...userBase, permissions }); + const menus = filterMenuTreeByPermissions(APP_MENU_TREE, permissions); + const { setUser, setMenus } = useAuthStore.getState(); + setUser(user); + setMenus(menus); +} diff --git a/apps/with-lingui/src/components/Aurora/index.css b/apps/with-lingui/src/components/Aurora/index.css new file mode 100644 index 0000000..325cacc --- /dev/null +++ b/apps/with-lingui/src/components/Aurora/index.css @@ -0,0 +1,88 @@ +.aurora__root { + position: absolute; + inset: 0; + overflow: hidden; + pointer-events: none; + z-index: 0; + --aurora: repeating-linear-gradient( + 100deg, + #3b82f6 10%, + #a5b4fc 15%, + #93c5fd 20%, + #ddd6fe 25%, + #60a5fa 30% + ); + --dark-gradient: repeating-linear-gradient( + 100deg, + #000 0%, + #000 7%, + transparent 10%, + transparent 12%, + #000 16% + ); + --white-gradient: repeating-linear-gradient( + 100deg, + #fff 0%, + #fff 7%, + transparent 10%, + transparent 12%, + #fff 16% + ); +} + +.aurora__glow { + position: absolute; + inset: -10px; + background-image: var(--white-gradient), var(--aurora); + background-size: 300% 200%; + background-position: + 50% 50%, + 50% 50%; + opacity: 0.5; + filter: blur(10px) invert(1); + -webkit-mask-image: radial-gradient(ellipse at 100% 0%, #000 10%, transparent 70%); + mask-image: radial-gradient(ellipse at 100% 0%, #000 10%, transparent 70%); +} + +html[data-theme="dark"] .aurora__glow { + background-image: var(--dark-gradient), var(--aurora); + filter: blur(10px); +} + +.aurora__glow::after { + content: ""; + position: absolute; + inset: 0; + background-image: var(--white-gradient), var(--aurora); + background-size: 200% 100%; + background-position: + 50% 50%, + 50% 50%; + background-attachment: fixed; + mix-blend-mode: difference; +} + +html[data-theme="dark"] .aurora__glow::after { + background-image: var(--dark-gradient), var(--aurora); +} + +@keyframes aurora-keyframes { + 0% { + background-position: 50%, 50%; + } + to { + background-position: 350%, 350%; + } +} + +@media (prefers-reduced-motion: no-preference) { + .aurora__glow::after { + animation: aurora-keyframes 60s linear infinite; + } +} + +@media (prefers-reduced-motion: reduce) { + .aurora__glow::after { + animation: none; + } +} diff --git a/apps/with-lingui/src/components/Aurora/index.tsx b/apps/with-lingui/src/components/Aurora/index.tsx new file mode 100644 index 0000000..f229f70 --- /dev/null +++ b/apps/with-lingui/src/components/Aurora/index.tsx @@ -0,0 +1,14 @@ +import "./index.css"; + +export type AuroraProps = { + className?: string; +}; + +export function Aurora({ className }: AuroraProps) { + const rootClass = className ? `aurora__root ${className}` : "aurora__root"; + return ( +
+
+
+ ); +} diff --git a/apps/with-lingui/src/components/Auth/index.tsx b/apps/with-lingui/src/components/Auth/index.tsx new file mode 100644 index 0000000..23a315b --- /dev/null +++ b/apps/with-lingui/src/components/Auth/index.tsx @@ -0,0 +1,13 @@ +import type { ReactNode } from "react"; +import { usePermission } from "@/hooks/usePermission"; + +interface AuthProps { + permission: string; + children: ReactNode; + fallback?: ReactNode; +} + +export function Auth({ permission, children, fallback = null }: AuthProps) { + const allowed = usePermission(permission); + return allowed ? <>{children} : <>{fallback}; +} diff --git a/apps/with-lingui/src/components/DataTable/DataTableEmpty.tsx b/apps/with-lingui/src/components/DataTable/DataTableEmpty.tsx new file mode 100644 index 0000000..029e2f3 --- /dev/null +++ b/apps/with-lingui/src/components/DataTable/DataTableEmpty.tsx @@ -0,0 +1,64 @@ +import { Flex, theme } from "antd"; +import { useLingui } from "@lingui/react/macro"; +import { BarChart3 } from "lucide-react"; +import type { ReactElement } from "react"; + +/** + * Table empty state: icon in soft tile + bold title + secondary description (dashboard-style). + */ +export function DataTableEmpty(): ReactElement { + const { t } = useLingui(); + const { token } = theme.useToken(); + + return ( + + + + + + + {t`No data`} + + + {t`Nothing to show in this list yet`} + + + + ); +} diff --git a/apps/with-lingui/src/components/DataTable/DataTableSkeleton.tsx b/apps/with-lingui/src/components/DataTable/DataTableSkeleton.tsx new file mode 100644 index 0000000..9554425 --- /dev/null +++ b/apps/with-lingui/src/components/DataTable/DataTableSkeleton.tsx @@ -0,0 +1,298 @@ +import { Skeleton, Table, theme } from "antd"; +import type { TableProps } from "antd"; +import type { ColumnGroupType, ColumnsType, ColumnType } from "antd/es/table"; +import type { GlobalToken } from "antd/es/theme/interface"; +import type { CSSProperties } from "react"; +import { useLayoutEffect, useMemo, useRef, useState } from "react"; + +function rowHeight(size: TableProps["size"]): number { + if (size === "large") return 56; + if (size === "middle") return 48; + return 40; +} + +function numericScrollY(scroll: TableProps["scroll"]): number | undefined { + const y = scroll?.y; + return typeof y === "number" && Number.isFinite(y) && y > 0 ? y : undefined; +} + +function clampRows(bodyHeight: number, rowH: number): number { + return Math.max(3, Math.floor(bodyHeight / rowH)); +} + +function initialRowCount(scroll: TableProps["scroll"], size: TableProps["size"]): number { + const y = numericScrollY(scroll); + return y != null ? clampRows(y, rowHeight(size)) : 10; +} + +export type DataTableSkeletonProps = Pick< + TableProps, + "columns" | "rowSelection" | "pagination" | "size" | "scroll" | "rootClassName" | "style" +> & { + /** + * Fixed skeleton row count. When omitted, rows are derived from `scroll.y` (if numeric) + * or from the table frame height so the body roughly fills the visible area. + */ + rowCount?: number; +}; + +function isActionColumn(col: ColumnType): boolean { + return ( + col.key === "actions" || + col.dataIndex === "actions" || + (typeof col.title === "string" && col.title.toLowerCase() === "actions") + ); +} + +function isIdColumn(col: ColumnType): boolean { + return col.key === "id" || col.dataIndex === "id"; +} + +function isColumnGroup( + col: ColumnType | ColumnGroupType, +): col is ColumnGroupType { + return "children" in col && Array.isArray(col.children) && col.children.length > 0; +} + +/** ~ text icon button, capped small */ +function actionSkeletonDiameter(col: ColumnType): number { + if (typeof col.width === "number") { + return Math.min(24, Math.max(20, col.width - 36)); + } + return 22; +} + +const DATA_CELL_MIN = 48; + +function dataCellMinWidth(col: ColumnType): number { + const cap = typeof col.minWidth === "number" ? col.minWidth : col.width; + if (typeof cap !== "number") return DATA_CELL_MIN; + return Math.max(DATA_CELL_MIN, Math.min(cap, 320)); +} + +function cellJustify(align: ColumnType["align"]): CSSProperties["justifyContent"] { + if (align === "right") return "flex-end"; + if (align === "center") return "center"; + return "flex-start"; +} + +function skeletonInputBarStyle( + token: GlobalToken, + opts: { floor: number; maxWidth: number | string; flex: string }, +): CSSProperties { + return { + width: "100%", + minWidth: opts.floor, + maxWidth: opts.maxWidth, + height: token.controlHeightSM, + borderRadius: token.borderRadiusSM, + flex: opts.flex, + }; +} + +function mapSkeletonColumn( + col: ColumnType | ColumnGroupType, + token: GlobalToken, +): ColumnType | ColumnGroupType { + if (isColumnGroup(col)) { + return { + ...col, + children: (col.children as ColumnsType).map((child) => + mapSkeletonColumn(child, token), + ), + }; + } + + const c = col as ColumnType; + return { + ...c, + sorter: false, + sortOrder: undefined, + render: (_: unknown, __: RecordType) => { + if (isActionColumn(c)) { + const w = actionSkeletonDiameter(c); + return ( + + + + ); + } + + const justify = cellJustify(c.align); + const id = isIdColumn(c); + + if (id) { + const floor = 28; + const maxBar = typeof c.width === "number" ? Math.max(28, Math.min(c.width - 10, 52)) : 40; + return ( + + ); + } + + const floor = dataCellMinWidth(c); + const bar = skeletonInputBarStyle(token, { + floor, + maxWidth: "100%", + flex: "1 1 auto", + }); + + return ( +
+ +
+ ); + }, + }; +} + +export function DataTableSkeleton({ + columns, + rowSelection, + pagination, + size = "small", + scroll, + rootClassName, + style, + rowCount, +}: DataTableSkeletonProps) { + const { token } = theme.useToken(); + const frameRef = useRef(null); + const [measuredRows, setMeasuredRows] = useState(() => initialRowCount(scroll, size)); + + useLayoutEffect(() => { + if (rowCount != null) return; + + const y = numericScrollY(scroll); + if (y != null) { + setMeasuredRows(clampRows(y, rowHeight(size))); + return; + } + + const el = frameRef.current; + if (!el) return; + + const rowH = rowHeight(size); + const measure = () => { + const thead = el.querySelector(".ant-table-thead"); + const pag = pagination === false ? null : el.querySelector(".ant-pagination"); + const theadH = thead?.offsetHeight ?? 39; + const pagH = pag ? pag.offsetHeight + 8 : 0; + const bodyH = Math.max(0, el.clientHeight - theadH - pagH - 2); + setMeasuredRows((prev) => { + const next = clampRows(bodyH, rowH); + return prev === next ? prev : next; + }); + }; + + const ro = new ResizeObserver(() => requestAnimationFrame(measure)); + ro.observe(el); + let raf = requestAnimationFrame(() => { + raf = requestAnimationFrame(measure); + }); + + return () => { + ro.disconnect(); + cancelAnimationFrame(raf); + }; + }, [rowCount, pagination, scroll?.y, size]); + + const effectiveRowCount = rowCount ?? measuredRows; + + const skeletonColumns = useMemo(() => { + if (!columns?.length) return []; + return (columns as ColumnsType).map((col) => mapSkeletonColumn(col, token)); + }, [columns, token]); + + const skeletonData = useMemo( + () => + Array.from({ length: effectiveRowCount }, (_, i) => ({ + __sk: String(i), + })) as unknown as RecordType[], + [effectiveRowCount], + ); + + const skeletonPagination = useMemo((): TableProps["pagination"] => { + if (pagination === false) return false; + if (typeof pagination === "object" && pagination !== null) { + return { + ...pagination, + disabled: true, + onChange: undefined, + onShowSizeChange: undefined, + }; + } + return { + current: 1, + pageSize: 10, + total: 100, + disabled: true, + showSizeChanger: true, + showTotal: () => ( + + ), + }; + }, [pagination, token.fontSize]); + + const selection = + rowSelection != null + ? { ...rowSelection, getCheckboxProps: () => ({ disabled: true }) } + : undefined; + + return ( +
+ + rootClassName={rootClassName} + style={{ flex: 1, minHeight: 0, width: "100%" }} + size={size} + columns={skeletonColumns} + dataSource={skeletonData} + rowKey={(record) => String((record as unknown as { __sk: string }).__sk)} + pagination={skeletonPagination} + rowSelection={selection} + scroll={scroll} + showSorterTooltip={false} + /> +
+ ); +} diff --git a/apps/with-lingui/src/components/DataTable/index.css b/apps/with-lingui/src/components/DataTable/index.css new file mode 100644 index 0000000..61bd4cc --- /dev/null +++ b/apps/with-lingui/src/components/DataTable/index.css @@ -0,0 +1,35 @@ +.data-table__table.ant-table-wrapper { + flex: 1; + min-height: 0; + display: flex; + flex-direction: column; +} + +.data-table__table .ant-spin-nested-loading, +.data-table__table .ant-spin-container { + flex: 1; + min-height: 0; + display: flex; + flex-direction: column; +} + +.data-table__table .ant-table { + flex: 1; + min-height: 0; +} + +.data-table__table .ant-table-container { + flex: 1; + min-height: 0; + display: flex; + flex-direction: column; +} + +/* Empty state: let placeholder row breathe in flex-height tables */ +.data-table__table .ant-table-tbody > tr.ant-table-placeholder > td { + border-bottom: none; +} + +.data-table__table .ant-table-tbody > tr.ant-table-placeholder .ant-table-cell { + padding-block: 0; +} diff --git a/apps/with-lingui/src/components/DataTable/index.tsx b/apps/with-lingui/src/components/DataTable/index.tsx new file mode 100644 index 0000000..a8388bd --- /dev/null +++ b/apps/with-lingui/src/components/DataTable/index.tsx @@ -0,0 +1,125 @@ +import { Flex, Table, theme } from "antd"; +import type { TableProps } from "antd"; +import type { CSSProperties, ReactElement, ReactNode, Ref } from "react"; +import { useMemo } from "react"; +import { DataTableEmpty } from "./DataTableEmpty"; +import { DataTableSkeleton } from "./DataTableSkeleton"; +import "./index.css"; + +/** Merged onto `Table` `rootClassName` with the flex layout class. */ +export const DATA_TABLE_ROOT_CLASS = "data-table__table"; + +export type DataTableProps = { + /** + * When the table uses `scroll.y`, set true so the frame does not shrink in the flex column + * and optional `frameHeight` can pin the outer height. + */ + lockScrollHeight?: boolean; + /** Outer `max-height` (px) */ + maxHeight?: number; + /** When `lockScrollHeight`, optional fixed outer `height` (usually same as max height) */ + frameHeight?: number; + /** Flex column wrapping frame + optional `bottomExtra` */ + layoutRef?: Ref; + /** Bordered box around the table (e.g. for `scrollHeight` vs `clientHeight` checks) */ + frameRef?: Ref; + /** Optional content below the bordered table frame */ + bottomExtra?: ReactNode; +} & TableProps; + +export function DataTable( + props: DataTableProps, +): ReactElement { + const { + lockScrollHeight, + maxHeight, + frameHeight, + layoutRef, + frameRef, + bottomExtra, + rootClassName, + style: tableStyle, + ...tableProps + } = props; + + const { token } = theme.useToken(); + + const { loading, ...restTableProps } = tableProps; + const spinLoading = + loading === true || + (typeof loading === "object" && + loading !== null && + (loading as { spinning?: boolean }).spinning !== false); + + const outerStyle: CSSProperties = { + flexGrow: 0, + flexShrink: lockScrollHeight ? 0 : 1, + flexBasis: "auto", + minHeight: 0, + maxHeight, + ...(lockScrollHeight && frameHeight != null ? { height: frameHeight } : {}), + alignSelf: "stretch", + border: `1px solid ${token.colorBorderSecondary}`, + borderRadius: token.borderRadiusLG, + overflow: "hidden", + display: "flex", + flexDirection: "column", + }; + + const mergedRootClassName = [DATA_TABLE_ROOT_CLASS, rootClassName].filter(Boolean).join(" "); + + const mergedLocale = useMemo( + () => ({ + ...restTableProps.locale, + emptyText: restTableProps.locale?.emptyText ?? , + }), + [restTableProps.locale], + ); + + return ( + +
+
+ {spinLoading ? ( + + columns={restTableProps.columns} + rowSelection={restTableProps.rowSelection} + pagination={restTableProps.pagination} + size={restTableProps.size} + scroll={restTableProps.scroll} + rootClassName={mergedRootClassName} + style={{ flex: 1, minHeight: 0, ...tableStyle }} + /> + ) : ( + + {...restTableProps} + locale={mergedLocale} + loading={loading} + rootClassName={mergedRootClassName} + style={{ flex: 1, minHeight: 0, ...tableStyle }} + /> + )} +
+
+ {bottomExtra} +
+ ); +} diff --git a/apps/with-lingui/src/components/FilterToolbar/index.tsx b/apps/with-lingui/src/components/FilterToolbar/index.tsx new file mode 100644 index 0000000..0d67b72 --- /dev/null +++ b/apps/with-lingui/src/components/FilterToolbar/index.tsx @@ -0,0 +1,168 @@ +import { Button, Flex, Popover, theme, Tooltip } from "antd"; +import { ListFilter } from "lucide-react"; +import { forwardRef, useCallback, useLayoutEffect, useMemo, useRef, useState } from "react"; + +export type FilterToolbarSlot = { + key: string; + /** Used to decide how many filters fit in one row before the rest go into the popover */ + minWidth: number; + children: React.ReactNode; +}; + +export type FilterToolbarProps = { + slots: FilterToolbarSlot[]; + /** Right side: primary actions (not collapsed) */ + actions: React.ReactNode; + /** Reserve width for the “more filters” control when some slots are in the popover */ + collapseTriggerReserve?: number; + /** Accessible label + optional popover title */ + moreFiltersLabel: React.ReactNode; + moreFiltersTitle?: React.ReactNode; +}; + +function maxVisibleSlots( + slotWidths: number[], + availableForLeft: number, + innerGap: number, + triggerReserve: number, +): number { + const n = slotWidths.length; + if (n === 0) return 0; + const sum = (count: number) => { + let s = 0; + for (let i = 0; i < count; i++) s += slotWidths[i] ?? 0; + return s; + }; + const inlineCost = (m: number) => { + if (m <= 0) return 0; + return sum(m) + (m - 1) * innerGap; + }; + const totalLeft = (m: number) => { + if (m <= 0) return n > 0 ? triggerReserve : 0; + const base = inlineCost(m); + if (m >= n) return base; + return base + innerGap + triggerReserve; + }; + for (let m = n; m >= 0; m--) { + if (totalLeft(m) <= availableForLeft) return m; + } + return 0; +} + +export const FilterToolbar = forwardRef(function FilterToolbar( + { slots, actions, collapseTriggerReserve = 40, moreFiltersLabel, moreFiltersTitle }, + ref, +) { + const { token } = theme.useToken(); + const gap = token.marginSM; + const containerRef = useRef(null); + const actionsRef = useRef(null); + const [visibleCount, setVisibleCount] = useState(slots.length); + const [popoverOpen, setPopoverOpen] = useState(false); + + const widths = useMemo(() => slots.map((s) => s.minWidth), [slots]); + + const assignRef = useCallback( + (node: HTMLDivElement | null) => { + containerRef.current = node; + if (typeof ref === "function") ref(node); + else if (ref) ref.current = node; + }, + [ref], + ); + + const remeasure = useCallback(() => { + const root = containerRef.current; + const act = actionsRef.current; + if (!root) return; + const actionsW = act?.offsetWidth ?? 0; + const hasActions = Boolean(act); + const between = hasActions ? gap : 0; + const available = Math.max(0, root.clientWidth - actionsW - between); + const next = maxVisibleSlots(widths, available, gap, collapseTriggerReserve); + setVisibleCount((prev) => (prev === next ? prev : next)); + }, [widths, gap, collapseTriggerReserve]); + + useLayoutEffect(() => { + remeasure(); + const root = containerRef.current; + const act = actionsRef.current; + if (!root) return; + const ro = new ResizeObserver(() => remeasure()); + ro.observe(root); + if (act) ro.observe(act); + return () => ro.disconnect(); + }, [remeasure, slots.length, widths]); + + useLayoutEffect(() => { + setPopoverOpen(false); + }, [visibleCount]); + + const overflowSlots = slots.slice(visibleCount); + const inlineSlots = slots.slice(0, visibleCount); + + const popoverContent = + overflowSlots.length > 0 ? ( + + {overflowSlots.map((slot) => ( +
+ {slot.children} +
+ ))} +
+ ) : null; + + return ( + + + {inlineSlots.map((slot) => ( +
+ {slot.children} +
+ ))} + {overflowSlots.length > 0 ? ( + + + + + + } + /> +
+
+ ); +} diff --git a/apps/with-lingui/src/hooks/usePermission.ts b/apps/with-lingui/src/hooks/usePermission.ts new file mode 100644 index 0000000..b3d3853 --- /dev/null +++ b/apps/with-lingui/src/hooks/usePermission.ts @@ -0,0 +1,10 @@ +import { useAuthStore } from "@/stores/auth"; + +export function hasPermission(point: string): boolean { + return useAuthStore.getState().hasPermission(point); +} + +export function usePermission(point: string): boolean { + const user = useAuthStore((s) => s.user); + return user?.permissions.includes(point) ?? false; +} diff --git a/apps/with-lingui/src/hooks/useResourceCRUD.ts b/apps/with-lingui/src/hooks/useResourceCRUD.ts new file mode 100644 index 0000000..22d92f1 --- /dev/null +++ b/apps/with-lingui/src/hooks/useResourceCRUD.ts @@ -0,0 +1,82 @@ +import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"; + +type MutationLifecycle = { + onMutate?: (values: TValues) => void; + onSuccess?: (values: TValues) => void; + onError?: (values: TValues) => void; +}; + +type UseResourceCRUDOptions = { + queryKey: readonly unknown[]; + invalidateKey: readonly unknown[]; + queryFn: () => Promise; + select: (raw: unknown) => TListData; + createFn: (values: TCreateValues) => Promise; + updateFn: (values: TUpdateValues) => Promise; + deleteFn: (id: string) => Promise; + createLifecycle?: MutationLifecycle; + updateLifecycle?: MutationLifecycle; + deleteLifecycle?: MutationLifecycle; +}; + +export function useResourceCRUD( + options: UseResourceCRUDOptions, +) { + const queryClient = useQueryClient(); + + const query = useQuery({ + queryKey: options.queryKey, + queryFn: options.queryFn, + select: options.select, + }); + + const createMutation = useMutation({ + mutationFn: options.createFn, + onMutate: (values) => { + options.createLifecycle?.onMutate?.(values); + }, + onSuccess: (_data, values) => { + void queryClient.invalidateQueries({ queryKey: options.invalidateKey }); + options.createLifecycle?.onSuccess?.(values); + }, + onError: (_error, values) => { + options.createLifecycle?.onError?.(values); + }, + }); + + const updateMutation = useMutation({ + mutationFn: options.updateFn, + onMutate: (values) => { + options.updateLifecycle?.onMutate?.(values); + }, + onSuccess: (_data, values) => { + void queryClient.invalidateQueries({ queryKey: options.invalidateKey }); + options.updateLifecycle?.onSuccess?.(values); + }, + onError: (_error, values) => { + options.updateLifecycle?.onError?.(values); + }, + }); + + const deleteMutation = useMutation({ + mutationFn: options.deleteFn, + onMutate: (id) => { + options.deleteLifecycle?.onMutate?.(id); + }, + onSuccess: (_data, id) => { + void queryClient.invalidateQueries({ queryKey: options.invalidateKey }); + options.deleteLifecycle?.onSuccess?.(id); + }, + onError: (_error, id) => { + options.deleteLifecycle?.onError?.(id); + }, + }); + + return { + data: query.data, + isLoading: query.isLoading, + createMutation, + updateMutation, + deleteMutation, + }; +} diff --git a/apps/with-lingui/src/index.css b/apps/with-lingui/src/index.css new file mode 100644 index 0000000..7dc5074 --- /dev/null +++ b/apps/with-lingui/src/index.css @@ -0,0 +1,44 @@ +:root { + --app-scrollbar-size: 8px; + --app-scrollbar-track: rgba(0, 0, 0, 0); + --app-scrollbar-thumb: rgba(0, 0, 0, 0.22); + --app-scrollbar-thumb-hover: rgba(0, 0, 0, 0.38); +} + +:root[data-theme="dark"] { + --app-scrollbar-track: rgba(255, 255, 255, 0); + --app-scrollbar-thumb: rgba(255, 255, 255, 0.22); + --app-scrollbar-thumb-hover: rgba(255, 255, 255, 0.38); +} + +/* Firefox */ +* { + scrollbar-width: thin; + scrollbar-color: var(--app-scrollbar-thumb) var(--app-scrollbar-track); +} + +/* Chromium / Safari / Edge */ +*::-webkit-scrollbar { + width: var(--app-scrollbar-size); + height: var(--app-scrollbar-size); +} + +*::-webkit-scrollbar-track { + background: var(--app-scrollbar-track); + border-radius: 9999px; +} + +*::-webkit-scrollbar-thumb { + background: var(--app-scrollbar-thumb); + border-radius: 9999px; + border: 2px solid transparent; + background-clip: content-box; +} + +*::-webkit-scrollbar-thumb:hover { + background-color: var(--app-scrollbar-thumb-hover); +} + +*::-webkit-scrollbar-corner { + background: transparent; +} diff --git a/apps/with-lingui/src/lingui.d.ts b/apps/with-lingui/src/lingui.d.ts new file mode 100644 index 0000000..cbfe464 --- /dev/null +++ b/apps/with-lingui/src/lingui.d.ts @@ -0,0 +1,4 @@ +declare module "*.po" { + import type { Messages } from "@lingui/core"; + export const messages: Messages; +} diff --git a/apps/with-lingui/src/locales/en/messages.po b/apps/with-lingui/src/locales/en/messages.po new file mode 100644 index 0000000..886db19 --- /dev/null +++ b/apps/with-lingui/src/locales/en/messages.po @@ -0,0 +1,317 @@ +msgid "" +msgstr "" +"POT-Creation-Date: 2026-04-07 15:30+0800\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: @lingui/cli\n" +"Language: en\n" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: \n" +"Last-Translator: \n" +"Language-Team: \n" +"Plural-Forms: \n" + +#: src/routes/_auth/users/index.tsx:464 +#~ msgid "{n} rows" +#~ msgstr "{n} rows" + +#: src/routes/_auth/users/index.tsx:386 +msgid "{total} rows" +msgstr "{total} rows" + +#: src/routes/_auth/dashboard/index.tsx:35 +msgid "+180.1% from last month" +msgstr "+180.1% from last month" + +#: src/routes/_auth/dashboard/index.tsx:41 +msgid "+19% from last month" +msgstr "+19% from last month" + +#: src/routes/_auth/dashboard/index.tsx:29 +msgid "+20.1% from last month" +msgstr "+20.1% from last month" + +#: src/routes/_auth/dashboard/index.tsx:47 +msgid "+201 since last hour" +msgstr "+201 since last hour" + +#: src/components/Layout/Header/index.tsx:78 +msgid "403" +msgstr "403" + +#: src/routes/_auth/dashboard/index.tsx:45 +msgid "Active Now" +msgstr "Active Now" + +#: src/routes/_auth/users/-FormModal.tsx:58 +#: src/routes/_auth/users/-Toolbar.tsx:64 +msgid "Admin" +msgstr "Admin" + +#: src/routes/_auth/users/index.tsx:164 +msgid "Are you absolutely sure?" +msgstr "Are you absolutely sure?" + +#: src/routes/login/index.tsx:185 +msgid "Auto login" +msgstr "Auto login" + +#: src/components/NotFound/index.tsx:54 +#: src/routes/_auth/403/index.tsx:40 +msgid "Back to Home" +msgstr "Back to Home" + +#: src/routes/_auth/users/-FormModal.tsx:32 +#: src/routes/_auth/users/index.tsx:168 +msgid "Cancel" +msgstr "Cancel" + +#: src/routes/_auth/dashboard/index.tsx:134 +msgid "Chart Placeholder" +msgstr "Chart Placeholder" + +#: src/routes/_auth/users/index.tsx:106 +msgid "Create failed" +msgstr "Create failed" + +#: src/routes/_auth/users/-Toolbar.tsx:89 +msgid "Create User" +msgstr "Create User" + +#: src/routes/_auth/users/index.tsx:100 +msgid "Created successfully" +msgstr "Created successfully" + +#: src/components/Layout/Header/index.tsx:74 +#: src/components/Layout/Header/index.tsx:87 +#: src/components/Layout/Header/index.tsx:91 +#: src/components/Layout/Sidebar/index.tsx:32 +msgid "Dashboard" +msgstr "Dashboard" + +#: src/routes/_auth/users/index.tsx:166 +#: src/routes/_auth/users/index.tsx:257 +msgid "Delete" +msgstr "Delete" + +#: src/routes/_auth/users/index.tsx:156 +msgid "Delete failed" +msgstr "Delete failed" + +#: src/routes/_auth/users/index.tsx:149 +msgid "Deleted successfully" +msgstr "Deleted successfully" + +#: src/routes/_auth/users/index.tsx:142 +msgid "Deleting…" +msgstr "Deleting…" + +#: src/components/Layout/Sidebar/index.tsx:35 +msgid "Design Engineering" +msgstr "Design Engineering" + +#: src/routes/_auth/users/index.tsx:247 +msgid "Edit" +msgstr "Edit" + +#: src/routes/_auth/users/-FormModal.tsx:29 +msgid "Edit User" +msgstr "Edit User" + +#: src/routes/_auth/users/-FormModal.tsx:59 +#: src/routes/_auth/users/-Toolbar.tsx:65 +msgid "Editor" +msgstr "Editor" + +#: src/routes/_auth/users/-FormModal.tsx:63 +#: src/routes/_auth/users/index.tsx:202 +msgid "Email" +msgstr "Email" + +#: src/routes/_auth/users.tsx:353 +#~ msgid "Filter by role" +#~ msgstr "Filter by role" + +#: src/routes/login/index.tsx:192 +msgid "Forgot password?" +msgstr "Forgot password?" + +#: src/components/NotFound/index.tsx:57 +msgid "Go back" +msgstr "Go back" + +#: src/routes/login/index.tsx:68 +msgid "Login failed" +msgstr "Login failed" + +#: src/routes/login/index.tsx:64 +msgid "Login successful" +msgstr "Login successful" + +#: src/routes/_auth/users/-Toolbar.tsx:92 +#: src/routes/_auth/users/-Toolbar.tsx:93 +msgid "More filters" +msgstr "More filters" + +#: src/routes/_auth/users/-FormModal.tsx:29 +msgid "New User" +msgstr "New User" + +#: src/components/DataTable/DataTableEmpty.tsx:49 +msgid "No data" +msgstr "No data" + +#: src/components/DataTable/DataTableEmpty.tsx:59 +msgid "Nothing to show in this list yet" +msgstr "Nothing to show in this list yet" + +#: src/routes/_auth/users/-FormModal.tsx:31 +msgid "OK" +msgstr "OK" + +#: src/routes/_auth/dashboard/index.tsx:115 +msgid "Overview" +msgstr "Overview" + +#: src/routes/404/index.tsx:87 +#~ msgid "Page not found" +#~ msgstr "Page not found" + +#: src/routes/login/index.tsx:171 +msgid "Password" +msgstr "Password" + +#: src/components/Layout/Sidebar/index.tsx:30 +msgid "Platform" +msgstr "Platform" + +#: src/routes/login/index.tsx:172 +msgid "Please enter password" +msgstr "Please enter password" + +#: src/routes/_auth/users/-FormModal.tsx:46 +#: src/routes/login/index.tsx:164 +msgid "Please enter username" +msgstr "Please enter username" + +#: src/routes/_auth/users/-FormModal.tsx:53 +msgid "Please select roles" +msgstr "Please select roles" + +#: src/components/Layout/AppFooter/index.tsx:36 +msgid "Powered by" +msgstr "Powered by" + +#: src/components/Layout/Sidebar/index.tsx:31 +msgid "Projects" +msgstr "Projects" + +#: src/routes/_auth/dashboard/index.tsx:142 +msgid "Recent Sales" +msgstr "Recent Sales" + +#: src/routes/_auth/users/-Toolbar.tsx:58 +msgid "Role" +msgstr "Role" + +#: src/routes/_auth/users/-FormModal.tsx:52 +#: src/routes/_auth/users/index.tsx:209 +msgid "Roles" +msgstr "Roles" + +#: src/routes/_auth/dashboard/index.tsx:39 +msgid "Sales" +msgstr "Sales" + +#: src/components/Layout/Sidebar/index.tsx:36 +msgid "Sales & Marketing" +msgstr "Sales & Marketing" + +#: src/routes/_auth/users/-Toolbar.tsx:43 +msgid "Search User" +msgstr "Search User" + +#: src/routes/_auth/users.tsx:341 +#~ msgid "Search username or email" +#~ msgstr "Search username or email" + +#: src/routes/login/index.tsx:204 +msgid "Sign In" +msgstr "Sign In" + +#: src/routes/login.tsx:100 +#~ msgid "Sign in with your credentials." +#~ msgstr "Sign in with your credentials." + +#: src/components/Layout/Sidebar/index.tsx:194 +msgid "Sign Out" +msgstr "Sign Out" + +#: src/components/NotFound/index.tsx:50 +msgid "Sorry, the page you visited does not exist." +msgstr "Sorry, the page you visited does not exist." + +#: src/routes/_auth/403/index.tsx:37 +msgid "Sorry, you don't have permission to access this page." +msgstr "Sorry, you don't have permission to access this page." + +#: src/routes/_auth/dashboard/index.tsx:33 +msgid "Subscriptions" +msgstr "Subscriptions" + +#: src/components/Layout/Header/index.tsx:145 +#: src/routes/login/index.tsx:225 +msgid "Switch language" +msgstr "Switch language" + +#: src/routes/_auth/users/index.tsx:165 +msgid "This action cannot be undone. This will permanently delete the user." +msgstr "This action cannot be undone. This will permanently delete the user." + +#: src/components/Layout/Header/index.tsx:133 +#: src/components/Layout/Sidebar/index.tsx:263 +#: src/components/Layout/Sidebar/index.tsx:311 +msgid "Toggle sidebar" +msgstr "Toggle sidebar" + +#: src/components/Layout/Header/index.tsx:151 +#: src/routes/login/index.tsx:232 +msgid "Toggle Theme" +msgstr "Toggle Theme" + +#: src/routes/_auth/dashboard/index.tsx:27 +msgid "Total Revenue" +msgstr "Total Revenue" + +#: src/routes/_auth/users/index.tsx:132 +msgid "Update failed" +msgstr "Update failed" + +#: src/routes/_auth/users/index.tsx:122 +msgid "Updated successfully" +msgstr "Updated successfully" + +#: src/routes/_auth/users/index.tsx:115 +msgid "Updating…" +msgstr "Updating…" + +#: src/components/Layout/Sidebar/index.tsx:34 +msgid "User List" +msgstr "User List" + +#: src/routes/_auth/users/-FormModal.tsx:45 +#: src/routes/_auth/users/index.tsx:182 +#: src/routes/login/index.tsx:163 +msgid "Username" +msgstr "Username" + +#: src/components/Layout/Header/index.tsx:76 +#: src/components/Layout/Sidebar/index.tsx:33 +msgid "Users" +msgstr "Users" + +#: src/routes/login.tsx:101 +#~ msgid "Welcome back" +#~ msgstr "Welcome back" diff --git a/apps/with-lingui/src/locales/zh/messages.po b/apps/with-lingui/src/locales/zh/messages.po new file mode 100644 index 0000000..8b1850f --- /dev/null +++ b/apps/with-lingui/src/locales/zh/messages.po @@ -0,0 +1,317 @@ +msgid "" +msgstr "" +"POT-Creation-Date: 2026-04-07 15:30+0800\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: @lingui/cli\n" +"Language: zh\n" +"Project-Id-Version: \n" +"Report-Msgid-Bugs-To: \n" +"PO-Revision-Date: \n" +"Last-Translator: \n" +"Language-Team: \n" +"Plural-Forms: \n" + +#: src/routes/_auth/users/index.tsx:464 +#~ msgid "{n} rows" +#~ msgstr "{n} 行" + +#: src/routes/_auth/users/index.tsx:386 +msgid "{total} rows" +msgstr "共 {total} 条" + +#: src/routes/_auth/dashboard/index.tsx:35 +msgid "+180.1% from last month" +msgstr "较上月 +180.1%" + +#: src/routes/_auth/dashboard/index.tsx:41 +msgid "+19% from last month" +msgstr "较上月 +19%" + +#: src/routes/_auth/dashboard/index.tsx:29 +msgid "+20.1% from last month" +msgstr "较上月 +20.1%" + +#: src/routes/_auth/dashboard/index.tsx:47 +msgid "+201 since last hour" +msgstr "较上一小时 +201" + +#: src/components/Layout/Header/index.tsx:78 +msgid "403" +msgstr "403" + +#: src/routes/_auth/dashboard/index.tsx:45 +msgid "Active Now" +msgstr "当前在线" + +#: src/routes/_auth/users/-FormModal.tsx:58 +#: src/routes/_auth/users/-Toolbar.tsx:64 +msgid "Admin" +msgstr "管理员" + +#: src/routes/_auth/users/index.tsx:164 +msgid "Are you absolutely sure?" +msgstr "确定要执行此操作吗?" + +#: src/routes/login/index.tsx:185 +msgid "Auto login" +msgstr "自动登录" + +#: src/components/NotFound/index.tsx:54 +#: src/routes/_auth/403/index.tsx:40 +msgid "Back to Home" +msgstr "返回首页" + +#: src/routes/_auth/users/-FormModal.tsx:32 +#: src/routes/_auth/users/index.tsx:168 +msgid "Cancel" +msgstr "取消" + +#: src/routes/_auth/dashboard/index.tsx:134 +msgid "Chart Placeholder" +msgstr "图表占位" + +#: src/routes/_auth/users/index.tsx:106 +msgid "Create failed" +msgstr "创建失败" + +#: src/routes/_auth/users/-Toolbar.tsx:89 +msgid "Create User" +msgstr "创建用户" + +#: src/routes/_auth/users/index.tsx:100 +msgid "Created successfully" +msgstr "创建成功" + +#: src/components/Layout/Header/index.tsx:74 +#: src/components/Layout/Header/index.tsx:87 +#: src/components/Layout/Header/index.tsx:91 +#: src/components/Layout/Sidebar/index.tsx:32 +msgid "Dashboard" +msgstr "仪表盘" + +#: src/routes/_auth/users/index.tsx:166 +#: src/routes/_auth/users/index.tsx:257 +msgid "Delete" +msgstr "删除" + +#: src/routes/_auth/users/index.tsx:156 +msgid "Delete failed" +msgstr "删除失败" + +#: src/routes/_auth/users/index.tsx:149 +msgid "Deleted successfully" +msgstr "删除成功" + +#: src/routes/_auth/users/index.tsx:142 +msgid "Deleting…" +msgstr "正在删除…" + +#: src/components/Layout/Sidebar/index.tsx:35 +msgid "Design Engineering" +msgstr "设计工程" + +#: src/routes/_auth/users/index.tsx:247 +msgid "Edit" +msgstr "编辑" + +#: src/routes/_auth/users/-FormModal.tsx:29 +msgid "Edit User" +msgstr "编辑用户" + +#: src/routes/_auth/users/-FormModal.tsx:59 +#: src/routes/_auth/users/-Toolbar.tsx:65 +msgid "Editor" +msgstr "编辑者" + +#: src/routes/_auth/users/-FormModal.tsx:63 +#: src/routes/_auth/users/index.tsx:202 +msgid "Email" +msgstr "邮箱" + +#: src/routes/_auth/users.tsx:353 +#~ msgid "Filter by role" +#~ msgstr "按角色筛选" + +#: src/routes/login/index.tsx:192 +msgid "Forgot password?" +msgstr "忘记密码?" + +#: src/components/NotFound/index.tsx:57 +msgid "Go back" +msgstr "返回上一页" + +#: src/routes/login/index.tsx:68 +msgid "Login failed" +msgstr "登录失败" + +#: src/routes/login/index.tsx:64 +msgid "Login successful" +msgstr "登录成功" + +#: src/routes/_auth/users/-Toolbar.tsx:92 +#: src/routes/_auth/users/-Toolbar.tsx:93 +msgid "More filters" +msgstr "更多筛选" + +#: src/routes/_auth/users/-FormModal.tsx:29 +msgid "New User" +msgstr "新建用户" + +#: src/components/DataTable/DataTableEmpty.tsx:49 +msgid "No data" +msgstr "暂无数据" + +#: src/components/DataTable/DataTableEmpty.tsx:59 +msgid "Nothing to show in this list yet" +msgstr "当前列表为空,暂无可展示的记录" + +#: src/routes/_auth/users/-FormModal.tsx:31 +msgid "OK" +msgstr "确定" + +#: src/routes/_auth/dashboard/index.tsx:115 +msgid "Overview" +msgstr "概览" + +#: src/routes/404/index.tsx:87 +#~ msgid "Page not found" +#~ msgstr "页面不存在" + +#: src/routes/login/index.tsx:171 +msgid "Password" +msgstr "密码" + +#: src/components/Layout/Sidebar/index.tsx:30 +msgid "Platform" +msgstr "平台" + +#: src/routes/login/index.tsx:172 +msgid "Please enter password" +msgstr "请输入密码" + +#: src/routes/_auth/users/-FormModal.tsx:46 +#: src/routes/login/index.tsx:164 +msgid "Please enter username" +msgstr "请输入用户名" + +#: src/routes/_auth/users/-FormModal.tsx:53 +msgid "Please select roles" +msgstr "请选择角色" + +#: src/components/Layout/AppFooter/index.tsx:36 +msgid "Powered by" +msgstr "由" + +#: src/components/Layout/Sidebar/index.tsx:31 +msgid "Projects" +msgstr "项目" + +#: src/routes/_auth/dashboard/index.tsx:142 +msgid "Recent Sales" +msgstr "近期销售" + +#: src/routes/_auth/users/-Toolbar.tsx:58 +msgid "Role" +msgstr "角色" + +#: src/routes/_auth/users/-FormModal.tsx:52 +#: src/routes/_auth/users/index.tsx:209 +msgid "Roles" +msgstr "角色" + +#: src/routes/_auth/dashboard/index.tsx:39 +msgid "Sales" +msgstr "销售额" + +#: src/components/Layout/Sidebar/index.tsx:36 +msgid "Sales & Marketing" +msgstr "销售与市场" + +#: src/routes/_auth/users/-Toolbar.tsx:43 +msgid "Search User" +msgstr "搜索用户" + +#: src/routes/_auth/users.tsx:341 +#~ msgid "Search username or email" +#~ msgstr "搜索用户名或邮箱" + +#: src/routes/login/index.tsx:204 +msgid "Sign In" +msgstr "登录" + +#: src/routes/login.tsx:100 +#~ msgid "Sign in with your credentials." +#~ msgstr "凭用户名与密码登录" + +#: src/components/Layout/Sidebar/index.tsx:194 +msgid "Sign Out" +msgstr "退出登录" + +#: src/components/NotFound/index.tsx:50 +msgid "Sorry, the page you visited does not exist." +msgstr "抱歉,您访问的页面不存在。" + +#: src/routes/_auth/403/index.tsx:37 +msgid "Sorry, you don't have permission to access this page." +msgstr "抱歉,您没有权限访问此页面。" + +#: src/routes/_auth/dashboard/index.tsx:33 +msgid "Subscriptions" +msgstr "订阅" + +#: src/components/Layout/Header/index.tsx:145 +#: src/routes/login/index.tsx:225 +msgid "Switch language" +msgstr "切换语言" + +#: src/routes/_auth/users/index.tsx:165 +msgid "This action cannot be undone. This will permanently delete the user." +msgstr "此操作无法撤销,将永久删除该用户。" + +#: src/components/Layout/Header/index.tsx:133 +#: src/components/Layout/Sidebar/index.tsx:263 +#: src/components/Layout/Sidebar/index.tsx:311 +msgid "Toggle sidebar" +msgstr "折叠侧栏" + +#: src/components/Layout/Header/index.tsx:151 +#: src/routes/login/index.tsx:232 +msgid "Toggle Theme" +msgstr "切换主题" + +#: src/routes/_auth/dashboard/index.tsx:27 +msgid "Total Revenue" +msgstr "总收入" + +#: src/routes/_auth/users/index.tsx:132 +msgid "Update failed" +msgstr "更新失败" + +#: src/routes/_auth/users/index.tsx:122 +msgid "Updated successfully" +msgstr "更新成功" + +#: src/routes/_auth/users/index.tsx:115 +msgid "Updating…" +msgstr "正在更新…" + +#: src/components/Layout/Sidebar/index.tsx:34 +msgid "User List" +msgstr "用户列表" + +#: src/routes/_auth/users/-FormModal.tsx:45 +#: src/routes/_auth/users/index.tsx:182 +#: src/routes/login/index.tsx:163 +msgid "Username" +msgstr "用户名" + +#: src/components/Layout/Header/index.tsx:76 +#: src/components/Layout/Sidebar/index.tsx:33 +msgid "Users" +msgstr "用户" + +#: src/routes/login.tsx:101 +#~ msgid "Welcome back" +#~ msgstr "欢迎回来" diff --git a/apps/with-lingui/src/main.tsx b/apps/with-lingui/src/main.tsx new file mode 100644 index 0000000..cf27f02 --- /dev/null +++ b/apps/with-lingui/src/main.tsx @@ -0,0 +1,50 @@ +import React from "react"; +import ReactDOM from "react-dom/client"; +import { RouterProvider, createRouter } from "@tanstack/react-router"; +import { routeTree } from "./routeTree.gen"; +import { i18n } from "@lingui/core"; +import { messages as enMessages } from "./locales/en/messages.po"; +import { messages as zhMessages } from "./locales/zh/messages.po"; +import { useSettingsStore } from "./stores/settings"; +import { useAuthStore } from "./stores/auth"; +import { fetchSessionAndApplyToStore } from "./auth/session"; + +i18n.load("en", enMessages); +i18n.load("zh", zhMessages); +i18n.activate(useSettingsStore.getState().locale); + +const router = createRouter({ routeTree }); + +declare module "@tanstack/react-router" { + interface Register { + router: typeof router; + } +} + +async function enableMocking() { + if (!import.meta.env.DEV) return; + const { worker } = await import("./mocks/browser"); + return worker.start({ onUnhandledRequest: "bypass" }); +} + +enableMocking() + .then(async () => { + await useAuthStore.persist.rehydrate(); + const { isAuthenticated, tokens } = useAuthStore.getState(); + if (isAuthenticated && tokens) { + try { + await fetchSessionAndApplyToStore(); + } catch { + useAuthStore.getState().logout(); + } + } + + ReactDOM.createRoot(document.getElementById("root")!).render( + + + , + ); + }) + .catch((err) => { + console.error("Failed to initialize app:", err); + }); diff --git a/apps/with-lingui/src/mocks/browser.ts b/apps/with-lingui/src/mocks/browser.ts new file mode 100644 index 0000000..bcd82e4 --- /dev/null +++ b/apps/with-lingui/src/mocks/browser.ts @@ -0,0 +1,4 @@ +import { setupWorker } from "msw/browser"; +import { handlers } from "./handlers"; + +export const worker = setupWorker(...handlers); diff --git a/apps/with-lingui/src/mocks/createHandler.ts b/apps/with-lingui/src/mocks/createHandler.ts new file mode 100644 index 0000000..76ebc68 --- /dev/null +++ b/apps/with-lingui/src/mocks/createHandler.ts @@ -0,0 +1,57 @@ +import { HttpResponse, delay as mswDelay } from "msw"; + +/** + * Standard API response format + */ +export interface ApiResponse { + code: number; + data: T; + message: string; +} + +/** + * MSW handler factory functions + * Provides consistent response wrapping and error handling + */ + +/** + * Wrap a handler function with standard response format + * Automatically handles delay, error responses, and data wrapping + */ +export async function withDelay(ms: number = 200): Promise { + await mswDelay(ms); +} + +/** + * Create a success response + */ +export function successResponse(data: T, message: string = "ok") { + return HttpResponse.json({ + code: 0, + data, + message, + }); +} + +/** + * Create an error response + */ +export function errorResponse(code: number, message: string, data: unknown = null) { + return HttpResponse.json({ + code, + data, + message, + }); +} + +/** + * Predefined error codes + */ +export const ERROR_CODES = { + INVALID_CREDENTIALS: 1001, + NOT_FOUND: 1002, + UNAUTHORIZED: 1003, + FORBIDDEN: 1004, + BAD_REQUEST: 1005, + INTERNAL_ERROR: 1006, +} as const; diff --git a/apps/with-lingui/src/mocks/data.ts b/apps/with-lingui/src/mocks/data.ts new file mode 100644 index 0000000..ab6639e --- /dev/null +++ b/apps/with-lingui/src/mocks/data.ts @@ -0,0 +1,26 @@ +import type { User } from "@/api/schemas"; +import { vercelAvatarUrl } from "@/utils/avatarUrl"; + +/** Demo logins look like real org accounts (first.last @ northstar.io). Index 0 stays `admin` for mock login. */ +const MOCK_IDENTITIES: ReadonlyArray<[string, string]> = [ + ["admin", "ops.admin@northstar.io"], + ["zhao.ming", "zhao.ming@northstar.io"], + ["sarah.chen", "sarah.chen@northstar.io"], + ["james.park", "james.park@northstar.io"], + ["emma.garcia", "emma.garcia@northstar.io"], + ["ryan.kim", "ryan.kim@northstar.io"], + ["olivia.tanaka", "olivia.tanaka@northstar.io"], + ["liam.patel", "liam.patel@northstar.io"], + ["ava.nguyen", "ava.nguyen@northstar.io"], + ["noah.berg", "noah.berg@northstar.io"], + ["mia.silva", "mia.silva@northstar.io"], +]; + +export const MOCK_USERS: User[] = MOCK_IDENTITIES.map(([username, email], i) => ({ + id: String(i + 1), + username, + avatar: vercelAvatarUrl(username), + email, + roles: i === 0 ? ["admin"] : ["editor"], + permissions: i === 0 ? ["user:view", "user:create", "user:edit", "user:delete"] : ["user:view"], +})); diff --git a/apps/with-lingui/src/mocks/filterUtils.ts b/apps/with-lingui/src/mocks/filterUtils.ts new file mode 100644 index 0000000..23dd35b --- /dev/null +++ b/apps/with-lingui/src/mocks/filterUtils.ts @@ -0,0 +1,47 @@ +/** + * Common filtering utilities for mock user handlers. + */ + +export interface User { + id: string; + username: string; + email?: string | null; + roles: string[]; + [key: string]: any; +} + +export interface FilterOptions { + keyword?: string; + role?: string; +} + +export function filterUsers(users: User[], options: FilterOptions): User[] { + let filtered = [...users]; + + if (options.keyword) { + filtered = filtered.filter( + (u) => + u.username.includes(options.keyword!) || (u.email && u.email.includes(options.keyword!)), + ); + } + + if (options.role) { + filtered = filtered.filter((u) => u.roles.includes(options.role!)); + } + + return filtered; +} + +export function paginateList(items: T[], limit: number, offset: number): T[] { + return items.slice(offset, offset + limit); +} + +export function parsePaginationParams(searchParams: URLSearchParams) { + const limit = Number(searchParams.get("limit") ?? searchParams.get("pageSize") ?? 50); + const offset = Number(searchParams.get("offset") ?? 0); + const page = Number(searchParams.get("page") ?? 1); + + const actualOffset = searchParams.get("offset") !== null ? offset : (page - 1) * limit; + + return { limit, offset: actualOffset }; +} diff --git a/apps/with-lingui/src/mocks/handlers/auth.ts b/apps/with-lingui/src/mocks/handlers/auth.ts new file mode 100644 index 0000000..6af2709 --- /dev/null +++ b/apps/with-lingui/src/mocks/handlers/auth.ts @@ -0,0 +1,37 @@ +import { http } from "msw"; +import { MOCK_USERS } from "../data"; +import { withDelay, successResponse, errorResponse, ERROR_CODES } from "../createHandler"; + +export const authHandlers = [ + http.post("/api/auth/login", async ({ request }) => { + await withDelay(300); + const body = (await request.json()) as { + username: string; + password: string; + }; + if (body.username === "admin" && body.password === "admin") { + return successResponse({ + accessToken: "mock-access-token", + refreshToken: "mock-refresh-token", + }); + } + return errorResponse(ERROR_CODES.INVALID_CREDENTIALS, "Invalid username or password"); + }), + + http.post("/api/auth/refresh", async () => { + await withDelay(100); + return successResponse({ + accessToken: "mock-new-access-token", + refreshToken: "mock-new-refresh-token", + }); + }), + + http.post("/api/auth/logout", () => successResponse(null)), + + http.get("/api/auth/user", () => { + const { permissions: _permissions, ...userWithoutPermissions } = MOCK_USERS[0]!; + return successResponse(userWithoutPermissions); + }), + + http.get("/api/auth/permissions", () => successResponse(MOCK_USERS[0]!.permissions)), +]; diff --git a/apps/with-lingui/src/mocks/handlers/index.ts b/apps/with-lingui/src/mocks/handlers/index.ts new file mode 100644 index 0000000..dbb3817 --- /dev/null +++ b/apps/with-lingui/src/mocks/handlers/index.ts @@ -0,0 +1,4 @@ +import { authHandlers } from "./auth"; +import { userHandlers } from "./user"; + +export const handlers = [...authHandlers, ...userHandlers]; diff --git a/apps/with-lingui/src/mocks/handlers/user.ts b/apps/with-lingui/src/mocks/handlers/user.ts new file mode 100644 index 0000000..b1c232e --- /dev/null +++ b/apps/with-lingui/src/mocks/handlers/user.ts @@ -0,0 +1,53 @@ +import { http } from "msw"; +import { MOCK_USERS } from "../data"; +import { filterUsers, paginateList, parsePaginationParams } from "../filterUtils"; +import { withDelay, successResponse, errorResponse, ERROR_CODES } from "../createHandler"; + +let users = [...MOCK_USERS]; + +export const userHandlers = [ + http.get("/api/users", async ({ request }) => { + await withDelay(200); + const url = new URL(request.url); + const { limit, offset } = parsePaginationParams(url.searchParams); + const keyword = url.searchParams.get("keyword") ?? ""; + const role = url.searchParams.get("role") ?? ""; + + const filtered = filterUsers(users, { keyword, role }); + const list = paginateList(filtered, limit, offset); + + return successResponse({ list, total: filtered.length }); + }), + + http.post("/api/users", async ({ request }) => { + await withDelay(200); + const body = (await request.json()) as Record; + const newUser = { + id: String(users.length + 1), + username: String(body.username), + avatar: null, + email: typeof body.email === "string" ? body.email : null, + roles: (body.roles as string[]) ?? [], + permissions: [], + }; + users.push(newUser); + return successResponse(newUser); + }), + + http.put("/api/users/:id", async ({ params, request }) => { + await withDelay(200); + const body = (await request.json()) as Record; + const idx = users.findIndex((u) => u.id === params.id); + if (idx === -1) { + return errorResponse(ERROR_CODES.NOT_FOUND, "User not found"); + } + users[idx] = { ...users[idx], ...body }; + return successResponse(users[idx]); + }), + + http.delete("/api/users/:id", async ({ params }) => { + await withDelay(200); + users = users.filter((u) => u.id !== params.id); + return successResponse(null); + }), +]; diff --git a/apps/with-lingui/src/routeTree.gen.ts b/apps/with-lingui/src/routeTree.gen.ts new file mode 100644 index 0000000..e3430b5 --- /dev/null +++ b/apps/with-lingui/src/routeTree.gen.ts @@ -0,0 +1,180 @@ +/* eslint-disable */ + +// @ts-nocheck + +// noinspection JSUnusedGlobalSymbols + +// This file was automatically generated by TanStack Router. +// You should NOT make any changes in this file as it will be overwritten. +// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. + +import { Route as rootRouteImport } from './routes/__root' +import { Route as AuthRouteImport } from './routes/_auth' +import { Route as IndexRouteImport } from './routes/index' +import { Route as LoginIndexRouteImport } from './routes/login/index' +import { Route as R404IndexRouteImport } from './routes/404/index' +import { Route as AuthUsersIndexRouteImport } from './routes/_auth/users/index' +import { Route as AuthDashboardIndexRouteImport } from './routes/_auth/dashboard/index' +import { Route as Auth403IndexRouteImport } from './routes/_auth/403/index' + +const AuthRoute = AuthRouteImport.update({ + id: '/_auth', + getParentRoute: () => rootRouteImport, +} as any) +const IndexRoute = IndexRouteImport.update({ + id: '/', + path: '/', + getParentRoute: () => rootRouteImport, +} as any) +const LoginIndexRoute = LoginIndexRouteImport.update({ + id: '/login/', + path: '/login/', + getParentRoute: () => rootRouteImport, +} as any) +const R404IndexRoute = R404IndexRouteImport.update({ + id: '/404/', + path: '/404/', + getParentRoute: () => rootRouteImport, +} as any) +const AuthUsersIndexRoute = AuthUsersIndexRouteImport.update({ + id: '/users/', + path: '/users/', + getParentRoute: () => AuthRoute, +} as any) +const AuthDashboardIndexRoute = AuthDashboardIndexRouteImport.update({ + id: '/dashboard/', + path: '/dashboard/', + getParentRoute: () => AuthRoute, +} as any) +const Auth403IndexRoute = Auth403IndexRouteImport.update({ + id: '/403/', + path: '/403/', + getParentRoute: () => AuthRoute, +} as any) + +export interface FileRoutesByFullPath { + '/': typeof IndexRoute + '/404/': typeof R404IndexRoute + '/login/': typeof LoginIndexRoute + '/403/': typeof Auth403IndexRoute + '/dashboard/': typeof AuthDashboardIndexRoute + '/users/': typeof AuthUsersIndexRoute +} +export interface FileRoutesByTo { + '/': typeof IndexRoute + '/404': typeof R404IndexRoute + '/login': typeof LoginIndexRoute + '/403': typeof Auth403IndexRoute + '/dashboard': typeof AuthDashboardIndexRoute + '/users': typeof AuthUsersIndexRoute +} +export interface FileRoutesById { + __root__: typeof rootRouteImport + '/': typeof IndexRoute + '/_auth': typeof AuthRouteWithChildren + '/404/': typeof R404IndexRoute + '/login/': typeof LoginIndexRoute + '/_auth/403/': typeof Auth403IndexRoute + '/_auth/dashboard/': typeof AuthDashboardIndexRoute + '/_auth/users/': typeof AuthUsersIndexRoute +} +export interface FileRouteTypes { + fileRoutesByFullPath: FileRoutesByFullPath + fullPaths: '/' | '/404/' | '/login/' | '/403/' | '/dashboard/' | '/users/' + fileRoutesByTo: FileRoutesByTo + to: '/' | '/404' | '/login' | '/403' | '/dashboard' | '/users' + id: + | '__root__' + | '/' + | '/_auth' + | '/404/' + | '/login/' + | '/_auth/403/' + | '/_auth/dashboard/' + | '/_auth/users/' + fileRoutesById: FileRoutesById +} +export interface RootRouteChildren { + IndexRoute: typeof IndexRoute + AuthRoute: typeof AuthRouteWithChildren + R404IndexRoute: typeof R404IndexRoute + LoginIndexRoute: typeof LoginIndexRoute +} + +declare module '@tanstack/react-router' { + interface FileRoutesByPath { + '/_auth': { + id: '/_auth' + path: '' + fullPath: '/' + preLoaderRoute: typeof AuthRouteImport + parentRoute: typeof rootRouteImport + } + '/': { + id: '/' + path: '/' + fullPath: '/' + preLoaderRoute: typeof IndexRouteImport + parentRoute: typeof rootRouteImport + } + '/login/': { + id: '/login/' + path: '/login' + fullPath: '/login/' + preLoaderRoute: typeof LoginIndexRouteImport + parentRoute: typeof rootRouteImport + } + '/404/': { + id: '/404/' + path: '/404' + fullPath: '/404/' + preLoaderRoute: typeof R404IndexRouteImport + parentRoute: typeof rootRouteImport + } + '/_auth/users/': { + id: '/_auth/users/' + path: '/users' + fullPath: '/users/' + preLoaderRoute: typeof AuthUsersIndexRouteImport + parentRoute: typeof AuthRoute + } + '/_auth/dashboard/': { + id: '/_auth/dashboard/' + path: '/dashboard' + fullPath: '/dashboard/' + preLoaderRoute: typeof AuthDashboardIndexRouteImport + parentRoute: typeof AuthRoute + } + '/_auth/403/': { + id: '/_auth/403/' + path: '/403' + fullPath: '/403/' + preLoaderRoute: typeof Auth403IndexRouteImport + parentRoute: typeof AuthRoute + } + } +} + +interface AuthRouteChildren { + Auth403IndexRoute: typeof Auth403IndexRoute + AuthDashboardIndexRoute: typeof AuthDashboardIndexRoute + AuthUsersIndexRoute: typeof AuthUsersIndexRoute +} + +const AuthRouteChildren: AuthRouteChildren = { + Auth403IndexRoute: Auth403IndexRoute, + AuthDashboardIndexRoute: AuthDashboardIndexRoute, + AuthUsersIndexRoute: AuthUsersIndexRoute, +} + +const AuthRouteWithChildren = AuthRoute._addFileChildren(AuthRouteChildren) + +const rootRouteChildren: RootRouteChildren = { + IndexRoute: IndexRoute, + AuthRoute: AuthRouteWithChildren, + R404IndexRoute: R404IndexRoute, + LoginIndexRoute: LoginIndexRoute, +} +export const routeTree = rootRouteImport + ._addFileChildren(rootRouteChildren) + ._addFileTypes() diff --git a/apps/with-lingui/src/routes/404/index.tsx b/apps/with-lingui/src/routes/404/index.tsx new file mode 100644 index 0000000..32ae107 --- /dev/null +++ b/apps/with-lingui/src/routes/404/index.tsx @@ -0,0 +1,6 @@ +import { createFileRoute } from "@tanstack/react-router"; +import { NotFound } from "@/components/NotFound"; + +export const Route = createFileRoute("/404/")({ + component: NotFound, +}); diff --git a/apps/with-lingui/src/routes/__root.tsx b/apps/with-lingui/src/routes/__root.tsx new file mode 100644 index 0000000..a9799ef --- /dev/null +++ b/apps/with-lingui/src/routes/__root.tsx @@ -0,0 +1,52 @@ +import { useEffect } from "react"; +import { createRootRoute, Outlet } from "@tanstack/react-router"; +import { ConfigProvider, App } from "antd"; +import enUS from "antd/locale/en_US"; +import zhCN from "antd/locale/zh_CN"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { i18n } from "@lingui/core"; +import { I18nProvider } from "@lingui/react"; +import { useSettingsStore } from "@/stores/settings"; +import { useAppTheme } from "@/theme"; +import { NotFound } from "@/components/NotFound"; +import "@/index.css"; + +const antdLocaleMap = { en: enUS, zh: zhCN } as const; + +const queryClient = new QueryClient({ + defaultOptions: { + queries: { retry: 1, refetchOnWindowFocus: false }, + }, +}); + +function RootComponent() { + const locale = useSettingsStore((s) => s.locale); + const darkMode = useSettingsStore((s) => s.darkMode); + const configProviderProps = useAppTheme(); + + useEffect(() => { + i18n.activate(locale); + document.documentElement.lang = locale === "zh" ? "zh" : "en"; + }, [locale]); + + useEffect(() => { + document.documentElement.setAttribute("data-theme", darkMode ? "dark" : "light"); + }, [darkMode]); + + return ( + + + + + + + + + + ); +} + +export const Route = createRootRoute({ + component: RootComponent, + notFoundComponent: NotFound, +}); diff --git a/apps/with-lingui/src/routes/_auth.tsx b/apps/with-lingui/src/routes/_auth.tsx new file mode 100644 index 0000000..2265dd4 --- /dev/null +++ b/apps/with-lingui/src/routes/_auth.tsx @@ -0,0 +1,21 @@ +import { createFileRoute, redirect } from "@tanstack/react-router"; +import { useAuthStore } from "@/stores/auth"; +import { MainLayout } from "@/components/Layout/MainLayout"; +import { canAccessPath, normalizeAppPath } from "@/utils/appMenu"; + +export const Route = createFileRoute("/_auth")({ + beforeLoad: ({ location }) => { + const { isAuthenticated, user } = useAuthStore.getState(); + if (!isAuthenticated) { + throw redirect({ to: "/login" }); + } + + const path = normalizeAppPath(location.pathname); + if (path === "/403") return; + + if (!canAccessPath(location.pathname, user?.permissions)) { + throw redirect({ to: "/403" }); + } + }, + component: MainLayout, +}); diff --git a/apps/with-lingui/src/routes/_auth/403/index.tsx b/apps/with-lingui/src/routes/_auth/403/index.tsx new file mode 100644 index 0000000..cd988c7 --- /dev/null +++ b/apps/with-lingui/src/routes/_auth/403/index.tsx @@ -0,0 +1,41 @@ +import { createFileRoute, useNavigate } from "@tanstack/react-router"; +import { useLingui } from "@lingui/react/macro"; +import { Home, ShieldAlert } from "lucide-react"; +import { Button, Flex, Result, theme } from "antd"; + +export const Route = createFileRoute("/_auth/403/")({ + component: ForbiddenPage, +}); + +function ForbiddenPage() { + const navigate = useNavigate(); + const { t } = useLingui(); + const { token } = theme.useToken(); + + const goDashboard = () => { + void navigate({ to: "/dashboard" }); + }; + + return ( + + + } + title="403" + subTitle={t`Sorry, you don't have permission to access this page.`} + extra={ + + } + /> + + ); +} diff --git a/apps/with-lingui/src/routes/_auth/dashboard/index.css b/apps/with-lingui/src/routes/_auth/dashboard/index.css new file mode 100644 index 0000000..655beab --- /dev/null +++ b/apps/with-lingui/src/routes/_auth/dashboard/index.css @@ -0,0 +1,42 @@ +.dash-card-interactive.ant-card { + transition: + border-color 0.2s ease, + background-color 0.2s ease; + box-shadow: none; +} + +.dash-card-interactive.ant-card:hover { + background-color: var(--dash-card-hover-bg) !important; + border-color: var(--dash-card-hover-border) !important; + box-shadow: var(--dash-card-hover-shadow); +} + +.dash-recent-row { + cursor: pointer; + transition: background-color 0.2s ease; +} + +.dash-recent-row:hover { + background-color: var(--dash-recent-hover-bg); +} + +.dash-chart-placeholder { + transition: border-color 0.2s ease; +} + +.dash-chart-placeholder:hover { + border-color: var(--dash-chart-hover-border); +} + +.dash-skel-stat .ant-skeleton-input { + min-height: unset !important; +} + +.dash-skel-recent .ant-skeleton-input { + min-height: unset !important; + margin-block: 0 !important; +} + +.dash-skel-recent .ant-skeleton-avatar { + margin-inline-end: 0 !important; +} diff --git a/apps/with-lingui/src/routes/_auth/dashboard/index.tsx b/apps/with-lingui/src/routes/_auth/dashboard/index.tsx new file mode 100644 index 0000000..c535d39 --- /dev/null +++ b/apps/with-lingui/src/routes/_auth/dashboard/index.tsx @@ -0,0 +1,310 @@ +import type { CSSProperties } from "react"; +import { useMemo } from "react"; +import { createFileRoute } from "@tanstack/react-router"; +import { Card, Col, Row, Typography, Avatar, theme, Flex, Skeleton } from "antd"; +import { useQuery } from "@tanstack/react-query"; +import { useLingui } from "@lingui/react/macro"; +import { DollarSign, Users, CreditCard, Activity } from "lucide-react"; +import "./index.css"; + +const { Title, Text } = Typography; + +export const Route = createFileRoute("/_auth/dashboard/")({ + component: DashboardPage, +}); + +async function fetchDashboardShell() { + await new Promise((r) => setTimeout(r, 1000)); + return true; +} + +type AntToken = ReturnType["token"]; + +/** Matches loaded stat card body height: title row, value, description. */ +function StatCardSkeleton({ token }: { token: AntToken }) { + const titleLine = Math.round(token.fontSizeSM * token.lineHeight); + /** Lucide default icon box 24px to align with the first row of real cards. */ + const iconBox = 24; + const titleRowHeight = Math.max(titleLine, iconBox); + const valueLine = Math.round(24 * 1); + const descLine = Math.round(token.fontSizeSM * token.lineHeight); + + return ( + +
+ + + + + + + + +
+
+ ); +} + +function DashboardSkeleton() { + const { token } = theme.useToken(); + const body = { padding: token.paddingLG } as const; + const cardTitleSkel = (w: number) => ( + + ); + + return ( + + + {[0, 1, 2, 3].map((i) => ( + + + + ))} + + + + + +
+ + + + + + + {[0, 1, 2, 3, 4].map((i) => ( + + + + + + + + + + ))} + + + + + + ); +} + +function DashboardPage() { + const { t } = useLingui(); + const { token } = theme.useToken(); + const { isPending } = useQuery({ + queryKey: ["dashboard"], + queryFn: fetchDashboardShell, + staleTime: 60_000, + }); + + /* Hover: emphasize border; keep background matching the card so light theme doesn't gray the whole block */ + const cardHoverStyle = { + ["--dash-card-hover-bg" as string]: token.colorBgContainer, + ["--dash-card-hover-border" as string]: token.colorPrimaryBorderHover, + ["--dash-card-hover-shadow" as string]: "none", + } as CSSProperties; + + const stats = useMemo( + () => [ + { + title: t`Total Revenue`, + value: "$45,231.89", + description: t`+20.1% from last month`, + icon: , + }, + { + title: t`Subscriptions`, + value: "+2350", + description: t`+180.1% from last month`, + icon: , + }, + { + title: t`Sales`, + value: "+12,234", + description: t`+19% from last month`, + icon: , + }, + { + title: t`Active Now`, + value: "+573", + description: t`+201 since last hour`, + icon: , + }, + ], + [t, token.colorTextSecondary], + ); + + const recentSales = useMemo( + () => [ + { + name: "Olivia Martin", + email: "olivia.martin@email.com", + amount: "+$1,999.00", + initials: "OM", + }, + { + name: "Jackson Lee", + email: "jackson.lee@email.com", + amount: "+$39.00", + initials: "JL", + }, + { + name: "Isabella Nguyen", + email: "isabella.nguyen@email.com", + amount: "+$299.00", + initials: "IN", + }, + { + name: "William Kim", + email: "will@email.com", + amount: "+$99.00", + initials: "WK", + }, + { + name: "Sofia Davis", + email: "sofia.davis@email.com", + amount: "+$39.00", + initials: "SD", + }, + ], + [], + ); + + if (isPending) { + return ; + } + + return ( + + + {stats.map((stat) => ( + + + + + {stat.title} + + {stat.icon} + +
{stat.value}
+ + {stat.description} + +
+ + ))} +
+ + + + {t`Overview`}} + > + + + {t`Chart Placeholder`} + + + + + + {t`Recent Sales`}} + > + + {recentSales.map((item) => ( + + + + {item.initials} + + + + {item.name} + + + {item.email} + + + +
{item.amount}
+
+ ))} +
+
+ +
+
+ ); +} diff --git a/apps/with-lingui/src/routes/_auth/users/-FormModal.tsx b/apps/with-lingui/src/routes/_auth/users/-FormModal.tsx new file mode 100644 index 0000000..5d45885 --- /dev/null +++ b/apps/with-lingui/src/routes/_auth/users/-FormModal.tsx @@ -0,0 +1,62 @@ +import { Form, Input, Select } from "antd"; +import type { FormInstance } from "antd/es/form"; +import { useLingui } from "@lingui/react/macro"; +import type { CreateUserRequest, User } from "@/api/schemas"; +import { BaseFormModal } from "@/components/FormModal"; + +export type FormModalProps = { + open: boolean; + editingUser: User | null; + form: FormInstance; + confirmLoading: boolean; + onCancel: () => void; + onFinish: (values: CreateUserRequest) => void; +}; + +export function FormModal({ + open, + editingUser, + form, + confirmLoading, + onCancel, + onFinish, +}: FormModalProps) { + const { t } = useLingui(); + + return ( + + open={open} + title={editingUser ? t`Edit User` : t`New User`} + okText={t`OK`} + cancelText={t`Cancel`} + form={form} + confirmLoading={confirmLoading} + onCancel={onCancel} + onFinish={onFinish} + > + + + + + + + + ); +} diff --git a/apps/with-lingui/src/routes/_auth/users/-Toolbar.tsx b/apps/with-lingui/src/routes/_auth/users/-Toolbar.tsx new file mode 100644 index 0000000..c607325 --- /dev/null +++ b/apps/with-lingui/src/routes/_auth/users/-Toolbar.tsx @@ -0,0 +1,96 @@ +import { Button, Input, Select, theme } from "antd"; +import { useLingui } from "@lingui/react/macro"; +import { Plus, UserRound } from "lucide-react"; +import { forwardRef, useMemo } from "react"; +import { FilterToolbar } from "@/components/FilterToolbar"; + +/** Search + role slot `minWidth` for FilterToolbar collapse math */ +const FILTER_CONTROL_WIDTH = 220; + +export type ToolbarProps = { + keywordInput: string; + onKeywordChange: (value: string) => void; + onSearch: (keyword: string) => void; + onClearSearch: () => void; + roleValue: string | undefined; + onRoleChange: (role: string) => void; + onCreateClick: () => void; +}; + +export const Toolbar = forwardRef(function Toolbar( + { + keywordInput, + onKeywordChange, + onSearch, + onClearSearch, + roleValue, + onRoleChange, + onCreateClick, + }, + ref, +) { + const { t } = useLingui(); + const { token } = theme.useToken(); + + const slots = useMemo( + () => [ + { + key: "keyword", + minWidth: FILTER_CONTROL_WIDTH, + children: ( + onKeywordChange(e.target.value)} + onSearch={(v) => onSearch(v)} + onClear={onClearSearch} + /> + ), + }, + { + key: "role", + minWidth: FILTER_CONTROL_WIDTH, + children: ( + + + + {t`Password`}} + rules={[{ required: true, message: t`Please enter password` }]} + style={{ marginBottom: token.marginLG }} + > + + + + + + {t`Auto login`} + + e.preventDefault()} + style={{ fontSize: token.fontSizeSM }} + > + {t`Forgot password?`} + + + + + + + + + + + + +