From 481402e09fe760634b826b09e302e2e1bfec88b1 Mon Sep 17 00:00:00 2001 From: shu Date: Mon, 7 Sep 2026 15:48:36 +0800 Subject: feat: initialize React Spectrum template with layouts and showcases --- .gitignore | 24 + .oxlintrc.json | 8 + README.md | 98 ++ index.html | 12 + package.json | 29 + pnpm-lock.yaml | 1279 ++++++++++++++++++++ pnpm-workspace.yaml | 2 + src/App.tsx | 38 + src/components/collapsed-navigation.tsx | 54 + src/components/form-examples/color-file-fields.tsx | 69 ++ .../form-examples/date-number-fields.tsx | 45 + src/components/form-examples/field-grid.tsx | 10 + .../form-examples/form-examples.module.css | 136 +++ src/components/form-examples/form-examples.tsx | 91 ++ src/components/form-examples/selection-fields.tsx | 68 ++ src/components/form-examples/text-fields.tsx | 28 + src/components/global-settings.module.css | 15 + src/components/global-settings.tsx | 41 + src/components/layout-basic.module.css | 156 +++ src/components/layout-basic.tsx | 67 + src/components/menu-icon.module.css | 6 + src/components/mobile-navigation.module.css | 53 + src/components/mobile-navigation.tsx | 64 + src/components/sidebar-menu.tsx | 35 + src/components/ui-kit/actions-feedback.tsx | 101 ++ src/components/ui-kit/navigation-data.tsx | 75 ++ src/components/ui-kit/ui-kit.module.css | 80 ++ src/components/ui-kit/ui-kit.tsx | 6 + src/index.css | 74 ++ src/main.tsx | 12 + src/page-about.tsx | 16 + src/page-form.module.css | 23 + src/page-form.tsx | 18 + src/page-home.tsx | 11 + src/page-not-found.tsx | 14 + src/page-ui-kit.module.css | 23 + src/page-ui-kit.tsx | 13 + src/page.module.css | 9 + src/route-config.ts | 82 ++ src/router.tsx | 11 + src/theme.ts | 25 + tsconfig.app.json | 26 + tsconfig.json | 7 + tsconfig.node.json | 23 + vite.config.ts | 33 + 45 files changed, 3110 insertions(+) create mode 100644 .gitignore create mode 100644 .oxlintrc.json create mode 100644 README.md create mode 100644 index.html create mode 100644 package.json create mode 100644 pnpm-lock.yaml create mode 100644 pnpm-workspace.yaml create mode 100644 src/App.tsx create mode 100644 src/components/collapsed-navigation.tsx create mode 100644 src/components/form-examples/color-file-fields.tsx create mode 100644 src/components/form-examples/date-number-fields.tsx create mode 100644 src/components/form-examples/field-grid.tsx create mode 100644 src/components/form-examples/form-examples.module.css create mode 100644 src/components/form-examples/form-examples.tsx create mode 100644 src/components/form-examples/selection-fields.tsx create mode 100644 src/components/form-examples/text-fields.tsx create mode 100644 src/components/global-settings.module.css create mode 100644 src/components/global-settings.tsx create mode 100644 src/components/layout-basic.module.css create mode 100644 src/components/layout-basic.tsx create mode 100644 src/components/menu-icon.module.css create mode 100644 src/components/mobile-navigation.module.css create mode 100644 src/components/mobile-navigation.tsx create mode 100644 src/components/sidebar-menu.tsx create mode 100644 src/components/ui-kit/actions-feedback.tsx create mode 100644 src/components/ui-kit/navigation-data.tsx create mode 100644 src/components/ui-kit/ui-kit.module.css create mode 100644 src/components/ui-kit/ui-kit.tsx create mode 100644 src/index.css create mode 100644 src/main.tsx create mode 100644 src/page-about.tsx create mode 100644 src/page-form.module.css create mode 100644 src/page-form.tsx create mode 100644 src/page-home.tsx create mode 100644 src/page-not-found.tsx create mode 100644 src/page-ui-kit.module.css create mode 100644 src/page-ui-kit.tsx create mode 100644 src/page.module.css create mode 100644 src/route-config.ts create mode 100644 src/router.tsx create mode 100644 src/theme.ts create mode 100644 tsconfig.app.json create mode 100644 tsconfig.json create mode 100644 tsconfig.node.json create mode 100644 vite.config.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/.oxlintrc.json b/.oxlintrc.json new file mode 100644 index 0000000..6fa991d --- /dev/null +++ b/.oxlintrc.json @@ -0,0 +1,8 @@ +{ + "$schema": "./node_modules/oxlint/configuration_schema.json", + "plugins": ["react", "typescript", "oxc"], + "rules": { + "react/rules-of-hooks": "error", + "react/only-export-components": ["warn", { "allowConstantExport": true }] + } +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..9299ae6 --- /dev/null +++ b/README.md @@ -0,0 +1,98 @@ +# React + TypeScript + Vite + +This template provides a minimal setup to get React working in Vite with HMR and some Oxlint rules. + +## Routing + +Routing uses [React Router Data Mode](https://reactrouter.com/start/data/installation). +`src/route-config.ts` is the single source for page paths, components, titles, +icons, menu groups, and default expanded groups. It generates the page routes and +menu data. `src/router.tsx` creates the router with `createBrowserRouter`, and +`src/main.tsx` renders it with `RouterProvider`. `src/App.tsx` configures the +Spectrum Provider and renders the route `Outlet` inside `BasicLayout`. +`src/components/layout-basic.tsx` owns the sidebar, top bar, collapse state, and content area, +with styles in `src/components/layout-basic.module.css`. It accepts page content through `children`. +`src/components/sidebar-menu.tsx` provides the shared menu list, and +`src/components/collapsed-navigation.tsx` renders the same data in icon mode. +The top bar reads the title from the matched route's metadata. On screens up to +640px wide, `src/components/mobile-navigation.tsx` opens it in a full-screen modal +from the top bar. Selecting a page or closing the modal returns to the content. + +- `/`: the homepage in `src/page-home.tsx`. +- `/about`: the about page in `src/page-about.tsx`. +- `/form`: the Spectrum form showcase in `src/page-form.tsx`. +- `/ui-kit`: the Spectrum component showcase in `src/page-ui-kit.tsx`. +- Unmatched paths: the 404 page in `src/page-not-found.tsx`. + +Place page components directly in `src/` and name their files `page-*.tsx`. +Place shared components and their styles in `src/components/`. +Use colocated `*.module.css` files for page and component styles. Keep global +theme variables, document styles, and resets in `src/index.css`. Shared menu icon +styles live in `src/components/menu-icon.module.css`, and the basic page spacing +is shared through `src/page.module.css`. + +The top-right settings button opens `src/components/global-settings.tsx` with +light and dark appearance options. `src/theme.ts` provides the shared theme +context; `App` synchronizes it with Spectrum's Provider and the document theme. +The initial theme uses the saved preference, or the system preference on first +visit. Selections persist in local storage when it is available. + +## UI Kit + +`src/components/ui-kit/` contains lazily loaded examples of buttons, badges, +status lights, alerts, progress indicators, dialogs, popovers, tooltips, toasts, +breadcrumbs, tabs, accordions, removable tags, cards, and a sortable table with +row selection. Examples respond to the global light/dark appearance setting. + +## Form showcase + +`src/components/form-examples/` contains lazily loaded examples of text, password, +email, URL, telephone, search, multiline, number, checkbox, radio, switch, picker, +combo box, select box, segmented control, toggle buttons, slider, range slider, +date/time fields, date pickers, calendars, color controls, file selection, and drag +and drop. Layout controls demonstrate sizes, label positions, and disabled states. +Each field has its own named label/input grid. Side labels automatically fall +back to top labels when the form container is narrower than 560px, and restore +when sufficient space is available. + +Submission uses native validation plus a custom username rule. The username +`admin` demonstrates a local business validation error. A successful submission +shows a data preview with the password masked; no data or files are uploaded. +Reset remounts the examples to clear both native inputs and controlled widget state. + +Add pages to `routeConfig` in `src/route-config.ts` with a unique `id`, `title`, +absolute `path`, `Component`, and optional `Icon`. Use `children` for menu groups +and `defaultExpanded` to control their initial expansion. Menu groups do not +change page URLs. Set `hidden: true` to keep a route out of navigation, as with +the 404 page. Desktop, collapsed, and mobile menus all use this configuration. +When deploying, configure your host to serve `index.html` for application URLs +so direct visits and refreshes on nested routes work. + +Currently, two official plugins are available: + +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs) +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) + +## React Compiler + +The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation). + +## Expanding the Oxlint configuration + +If you are developing a production application, we recommend enabling type-aware lint rules by installing `oxlint-tsgolint` and editing `.oxlintrc.json`: + +```json +{ + "$schema": "./node_modules/oxlint/configuration_schema.json", + "plugins": ["react", "typescript", "oxc"], + "options": { + "typeAware": true + }, + "rules": { + "react/rules-of-hooks": "error", + "react/only-export-components": ["warn", { "allowConstantExport": true }] + } +} +``` + +See the [Oxlint rules documentation](https://oxc.rs/docs/guide/usage/linter/rules) for the full list of rules and categories. diff --git a/index.html b/index.html new file mode 100644 index 0000000..c812ecd --- /dev/null +++ b/index.html @@ -0,0 +1,12 @@ + + + + + + template-react-spectrum + + +
+ + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..9bacee5 --- /dev/null +++ b/package.json @@ -0,0 +1,29 @@ +{ + "name": "template-react-spectrum", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "lint": "oxlint", + "preview": "vite preview" + }, + "dependencies": { + "@react-aria/optimize-locales-plugin": "^2.0.2", + "@react-spectrum/s2": "^1.7.1", + "react": "^19.2.8", + "react-dom": "^19.2.8", + "react-router": "^8.3.1" + }, + "devDependencies": { + "@types/node": "^24.13.3", + "@types/react": "^19.2.18", + "@types/react-dom": "^19.2.4", + "@vitejs/plugin-react": "^6.1.0", + "oxlint": "^1.79.0", + "typescript": "~6.0.2", + "unplugin-parcel-macros": "^0.2.0", + "vite": "^8.2.2" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..72fdc7f --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,1279 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@react-aria/optimize-locales-plugin': + specifier: ^2.0.2 + version: 2.0.2 + '@react-spectrum/s2': + specifier: ^1.7.1 + version: 1.7.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + react: + specifier: ^19.2.8 + version: 19.2.8 + react-dom: + specifier: ^19.2.8 + version: 19.2.8(react@19.2.8) + react-router: + specifier: ^8.3.1 + version: 8.3.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + devDependencies: + '@types/node': + specifier: ^24.13.3 + version: 24.13.3 + '@types/react': + specifier: ^19.2.18 + version: 19.2.18 + '@types/react-dom': + specifier: ^19.2.4 + version: 19.2.7(@types/react@19.2.18) + '@vitejs/plugin-react': + specifier: ^6.1.0 + version: 6.1.1(vite@8.2.2(@types/node@24.13.3)) + oxlint: + specifier: ^1.79.0 + version: 1.81.0 + typescript: + specifier: ~6.0.2 + version: 6.0.3 + unplugin-parcel-macros: + specifier: ^0.2.0 + version: 0.2.0(@swc/helpers@0.5.23) + vite: + specifier: ^8.2.2 + version: 8.2.2(@types/node@24.13.3) + +packages: + + '@internationalized/date@3.12.4': + resolution: {integrity: sha512-M1dEn4c1U1HsSlaVR8upZtSqvXrTkHDfv18H01uCSJyjVLDxnBR38v/fMxecmlwXKR4i9HeZcmgQAPE6A+aGJQ==} + + '@internationalized/number@3.6.8': + resolution: {integrity: sha512-8UmMFia46DUt+k97zKd9fKWXcWHR+k8ae3eYzILETuT2KbIvLyOfac7zesw+sJdRAAZ7Q9pM1Mk22aXp2LD0Ig==} + + '@internationalized/string@3.2.10': + resolution: {integrity: sha512-PDx6//vHSpRnHfxqMqto11zQvhsaU74O3mKv2F/0eicGZcl9NLjQmGlbHz/LsJh5tLKp4A4L7ZVTzN1/MmMTvA==} + + '@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.6.0': + resolution: {integrity: sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==} + + '@jridgewell/trace-mapping@0.3.31': + resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + + '@oxc-project/types@0.148.0': + resolution: {integrity: sha512-Nm4s/jB+4FpFsPhWGEC4h7rzksesmtnMXomo6rCMcg/b8zLQuOziRgkCS1fxDCXOlJB/6Q8oABOZ/OP6RIPj9A==} + + '@oxlint/binding-android-arm-eabi@1.81.0': + resolution: {integrity: sha512-IcCRsXiedJoJopY6mpZUBEeVFsUrutmrG7dZ87zMuKJlhg70Ora9bBl1WcCxZQtyI10YpnVdEso5oCg7YcfSHw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@oxlint/binding-android-arm64@1.81.0': + resolution: {integrity: sha512-GRrIPyTGVhx3L3h+0T5xT2A0jFAcdPv4+IfuXpGDLIdl6XeYhgg/zw72A5ILZoUgRqZuM8F1y+V/gfDriXSxzQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@oxlint/binding-darwin-arm64@1.81.0': + resolution: {integrity: sha512-qNQ9tXRgLuKbqSV1S2h9h4KPHjbovO7RRR2/enUOtHzTkFZ7B9X5zqqHJua8dRyc7dBy7Aoyq5pqTSLFVcAzGQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@oxlint/binding-darwin-x64@1.81.0': + resolution: {integrity: sha512-q0QTm32jWga2Gv4j7IaVZN0jYMi9UV73sWVgFtDA4iIfqwMCLLZ3ve+9KwfYtsaKZSgQhmPaogeZWqDZpcY1Pw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@oxlint/binding-freebsd-x64@1.81.0': + resolution: {integrity: sha512-/+8wVWDXEC7wHVAhOc59Fw/SkMc1arLkFD8iQCaSsmzenK1X4doFqquL9H1wrtGUzaiycVqkf/sSpcILK6W1UA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@oxlint/binding-linux-arm-gnueabihf@1.81.0': + resolution: {integrity: sha512-4xt422FEgioRq9hAL4Tq7fujGUWnc8z1BJ+Oi8RN8vB8axaP+sdK6a2xdlcQCCYnJg9QMuMFS0AucuIFx/EacA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxlint/binding-linux-arm-musleabihf@1.81.0': + resolution: {integrity: sha512-u3vna8KdGplH4DRCW9K54D68fcMo7IxVrkCJWwXnIhwtBdnDnYrmzOUA/XjmBlPpcLsgw9Z5BNdY4za9+Dj+MQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxlint/binding-linux-arm64-gnu@1.81.0': + resolution: {integrity: sha512-3j9k+gsYsE7nv71GWotXsqsa2l9/aJenD7dVHNt/CBvsb0SgRjSMnHFeP59IXUAl1wvVFhqGl2wJNMwWU3UBlA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-arm64-musl@1.81.0': + resolution: {integrity: sha512-k5iAp3dNxW0/uDCBY+WSm8jKB2szu7SkEQZdgRRpDXvuDd69vvDcqhB3A/pWCfCwXyenjNjFn9Td1fVoyAc+Yg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@oxlint/binding-linux-ppc64-gnu@1.81.0': + resolution: {integrity: sha512-TFqLja3uYmVSte6nof9GWrex9Z8WgdZrNiLC6Te5rXGDqXB2y4j/26iFhwosXiAFqDhE9JJVuuCkDKLwptTn1g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-riscv64-gnu@1.81.0': + resolution: {integrity: sha512-UEcySvGS0NOVo7h7n7CYyJL9+6gFAh7Zc/ToDXVScFvzHSTIxtzkMVU30rmQ6+nQ1LF+UdiRDdJajpDu+OylLg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-riscv64-musl@1.81.0': + resolution: {integrity: sha512-H+diDbhD00+wI1IRP8Kz88x/lat+DgtoBJzoTthS16xkTJGNaEkfb8gzmd1rzc/2uDQQMl7GNl+JFUacVeWxIA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@oxlint/binding-linux-s390x-gnu@1.81.0': + resolution: {integrity: sha512-8znJ/5TekjOKg1j1Acho4PJMdiAHLtlcXuWEiipOhAMV6rQcXdmDdXCbheyDczN6TjBwiNfjcP81k4AthrKRzw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-x64-gnu@1.81.0': + resolution: {integrity: sha512-Q2Wj70yFsvn5QjlmifFzbj4H+kJy53bwqc41o1fzoM7MpLV1NIbhg/LpWXRfC6KOkSAdUx1Wd8VJsdPmhp/HRA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@oxlint/binding-linux-x64-musl@1.81.0': + resolution: {integrity: sha512-cPInHp/ddEe5qkyK2IiyQ8Q3Mp2oLLEhhsGgTK2oZx4L6+llGam1H1yBvJZ7qHfOXj8N3hxBS8sj4tO+gtFlIg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@oxlint/binding-openharmony-arm64@1.81.0': + resolution: {integrity: sha512-0CQxSX4ajqm07AHBf5U33qQzXKdd7wtq/oTL/7vpY6RNNuxrRi8W4bqUV1Jyu/vj+9KmxQyDhxfeVX1nQL6kfg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@oxlint/binding-win32-arm64-msvc@1.81.0': + resolution: {integrity: sha512-l0hbeISm9673hVrrQU8j/p2M7YH9Ouoj7p7E/QM55NTrKVLP+P3PF8hLu+OY+x0VtGRW+ggiQKZqmdYps9H+TA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@oxlint/binding-win32-ia32-msvc@1.81.0': + resolution: {integrity: sha512-ksqPP5jbFXcYreEQ7zdJh06rJQBymCTyGRCdaXjfcf2aG4f8KxUWY5wcgYHmaTK+FJ4bPG5sUAdOX+6trnH1JA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + + '@oxlint/binding-win32-x64-msvc@1.81.0': + resolution: {integrity: sha512-IZuUCwGw9emG5JtCp+fYGB+Z4OWEoeEcM8R5BA1pYw63/ieYFVdcU2ylxTpHbVHSenZnsYE+ZZ20uHAJszQ4cA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@parcel/macros@2.16.4': + resolution: {integrity: sha512-Uijt2AYhsMtxnRlwxQwYgZ7TTZVgi0mfk0EKh83NoCEJjrwArJRLNBv/xP6e/5KuTEDSNr/vqqcPk0BgmBvTKw==} + engines: {node: '>= 16.0.0', parcel: ^2.16.4} + + '@parcel/source-map@2.1.1': + resolution: {integrity: sha512-Ejx1P/mj+kMjQb8/y5XxDUn4reGdr+WyKYloBljpppUy8gs42T+BNoEOuRYqDVdgPc6NxduzIDoJS9pOFfV5Ew==} + engines: {node: ^12.18.3 || >=14} + + '@react-aria/optimize-locales-plugin@2.0.2': + resolution: {integrity: sha512-YxRwGC76G/aOozUEzl93irjhGuLsC63clF5abOX+lNAlg7EGns7250Ud8Ice6dy5oLv9mSXQx8LEf0b+56Cclg==} + + '@react-spectrum/s2@1.7.1': + resolution: {integrity: sha512-MMuEtebNabzzglLiGGSyXkg/yEig1cLqmq/JSKlYS+9cKzQoxwUIWtbdZLFFE9Ju0MPH9zNfpHXma1q9+hC+Yg==} + peerDependencies: + react: ^19.0.0-rc.1 + react-dom: ^19.0.0-rc.1 + + '@react-types/shared@3.36.1': + resolution: {integrity: sha512-AzsuD9OfxTOZMMvTRhlN3oHBwOmFN7tDh27LzqmHt4+uOgPhJT7ZM7/kVs/8/o0WxayMUIk3hBmCFRHv1FUoag==} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + + '@rolldown/binding-android-arm-eabi@1.2.7': + resolution: {integrity: sha512-EypzgnYCwyVY4NDHKzGmNJT5b+XaQEBniHxsMdeIQLB/tcCzZnhqrzHpZFbX9iaxx+5RiB8caATBtfvZP7zVxQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@rolldown/binding-android-arm64@1.2.7': + resolution: {integrity: sha512-l17HE9EweWaqJZhuUuNBN/FzM62xw+DECVnJyvMsxn8vJFAGLy5QfLDoYAcronkAN8VxKZHezDpulHDPx95vFw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@rolldown/binding-darwin-arm64@1.2.7': + resolution: {integrity: sha512-8ED8ELFvHXc6OCETIn4gXObPiaR6bckM/ipXtbzlPVDRMBfEGjCKgO90F9YtfdpDatVx/ZQw7aZ1vUMf/+T3Mw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@rolldown/binding-darwin-x64@1.2.7': + resolution: {integrity: sha512-/WPripjtiAIZ2tWY7ddijORT0Ujg87wxWW/qcoFVCKAWVDPhtY0xr7Dj0M3GyNGz60jGwTElhro/mkF9dT7dDQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@rolldown/binding-freebsd-x64@1.2.7': + resolution: {integrity: sha512-14DI4NcqpvbICxSnGLx3PmtDaWqRP/KGSGb6C+JLLVPeZRl6dKdHba3pGsqT3vpdTqhEYIPG0MMQ8c0xYqoJxA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@rolldown/binding-linux-arm-gnueabihf@1.2.7': + resolution: {integrity: sha512-bxrWIRvHWQvbJwi+VIie/kDJmQxcNE6xxWwZdqF/ExVAigtHkv54WTLQPb+QsZdnFy18fg7JPfWGL0RH6vwIlQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@rolldown/binding-linux-arm64-gnu@1.2.7': + resolution: {integrity: sha512-toOY2BChBZyuxU7OYX6Tn389di4IzAqPTycVcci0O7FSfBqzRB3RZn+K5Is6ANf4tmgRd/K1yZTsNTXbkXsnLg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-arm64-musl@1.2.7': + resolution: {integrity: sha512-lAIXTH/aiLRLxsTgQvfhjo4K1ydWIp00+V0voOr9beb/9ZmkUFrSIb03dXNFRgMNvkE6oGsF10ioQ6UsI+vS5Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rolldown/binding-linux-ppc64-gnu@1.2.7': + resolution: {integrity: sha512-kdnwS28Pkenp/mZMRwjXXXwxQ7pIsm+bF919LUK93BOyhcLsrVKdP2p9fxpiPNPAbNuch8ypQt0pm2P2LYCAGg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-s390x-gnu@1.2.7': + resolution: {integrity: sha512-516OdsyLdr5E65paF3yBF55t8mfm9+gmtCsK3xI7XKXIT7EfRlHhxL8K/NR6Hu8BWSgF5+1w74lTL0+nxcc8Qw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-gnu@1.2.7': + resolution: {integrity: sha512-r8/z8n7GFaYRln3xmP1Cxy0HH/HLM0uBUPkEuSVEfKGDA89M0FsZRZJRSwe/tJjRx+fpH/gjorfhB8tmEbSFLA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@rolldown/binding-linux-x64-musl@1.2.7': + resolution: {integrity: sha512-pAsE8iiDxUg1xBqdhrTfg45AVDVpirjz00sblEYClGNNcMnDb+e8beQgqIAw6LvauX/APvgxUnwrgun/YYGBhw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@rolldown/binding-openharmony-arm64@1.2.7': + resolution: {integrity: sha512-lTcIYmmnQQA8Or/2DatS6oSqcdLHvendjS+zLu+FwgToynWMRSmQdpM65fTANJgIS4mjbMOo5KT2lnT9SAb96w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@rolldown/binding-win32-arm64-msvc@1.2.7': + resolution: {integrity: sha512-e3Gu3WxbNk/UqQhxqU7YIYO+9ZBvWNz3U+h/qRFosscMFzdRPbXYSaSWgSnklv2fz1TgzBTcti2z35c/7irsHw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@rolldown/binding-win32-x64-msvc@1.2.7': + resolution: {integrity: sha512-W/jg5qoRSqjsEv0+dZi4e687mcHqmVuU0P4fK6qS/xjetW2Gmc1W8j//z5nAeNcC8Ttm0hV46IjcYeuVwYhuiw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@rolldown/pluginutils@1.0.1': + resolution: {integrity: sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==} + + '@swc/core-darwin-arm64@1.16.2': + resolution: {integrity: sha512-i/j0HNbnn79qnTVPicvay92Nark8fW8NQqn1e2mGERjUXNpBV0+SwQxlRpk2zBhn6laJ8PDI6Kn1nHZhnz3LCA==} + engines: {node: '>=10'} + cpu: [arm64] + os: [darwin] + + '@swc/core-darwin-x64@1.16.2': + resolution: {integrity: sha512-HrwqHyEyHVXO3qTk8EkNK7/b6sOZSEoNh+pot6RdE5x0LbNqfo8LtJUvi3UTXr+5ja/o5HbJdW80eCXo+NjbiA==} + engines: {node: '>=10'} + cpu: [x64] + os: [darwin] + + '@swc/core-linux-arm-gnueabihf@1.16.2': + resolution: {integrity: sha512-MdXi83Z/gGp1LIrg+h7HKxiul/z/Bty/ZJSvYAFqDl9zteC1XLSAZdScquKtXPp50rdyXqritTDCqQBhwVfZKA==} + engines: {node: '>=10'} + cpu: [arm] + os: [linux] + + '@swc/core-linux-arm64-gnu@1.16.2': + resolution: {integrity: sha512-/jcTmK6Ktz3owM3YtiKvjofV6p3VpHnYzTIrOGwDIOsDigRAAVuZ8east33wYO/7UTdKYFlyHNnJNT0WJqOA3Q==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@swc/core-linux-arm64-musl@1.16.2': + resolution: {integrity: sha512-4gFarKaFnlJTSlJYKmMhV4u+3YE4uYfiydpBoYjmgQhCf9lAieOq+WilZaK9vVSHeqLuQpTEiGULZqAdsRX5Dw==} + engines: {node: '>=10'} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@swc/core-linux-ppc64-gnu@1.16.2': + resolution: {integrity: sha512-syqSLGd6KlZ1PciNzs6bIUlhOuFztZufebOHaERjc4N4SqNZxyqYd4I+jj/EfOYnpe0kNjccn9HJLN1p5dz3+w==} + engines: {node: '>=10'} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@swc/core-linux-s390x-gnu@1.16.2': + resolution: {integrity: sha512-ZBBLK+ewGyXLzWeMS7wbKtWBdnif6etn7xvPY/iOfbdsjX/+bgkp1pQt2lWF2wlu2hXYZuhJ/tHZE/QR8/apzg==} + engines: {node: '>=10'} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@swc/core-linux-x64-gnu@1.16.2': + resolution: {integrity: sha512-LyHJgxCA4Tje0ysBMbEb0tt/ie8kgUKoFE3JAKFhpevmTmhYEoC0H9s47WuDsqiFckF1ITUguZIXJG6K5e0dvg==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@swc/core-linux-x64-musl@1.16.2': + resolution: {integrity: sha512-PghXJlVM1cgtLfNUR1vxFo1z+PDRAe8cWAJlZZ7spmeiN7BospGXg/MHUg7oNSgwSX7Zo//YKv9P5yD9apsFJQ==} + engines: {node: '>=10'} + cpu: [x64] + os: [linux] + libc: [musl] + + '@swc/core-win32-arm64-msvc@1.16.2': + resolution: {integrity: sha512-StTOSefYBxemvNYYUI3UmO1a8y+hSPjjfHogC2TEHL+Z1PlEBim/XtLas5rS04jAzT9RrNmbtX911SZ42H9jSQ==} + engines: {node: '>=10'} + cpu: [arm64] + os: [win32] + + '@swc/core-win32-ia32-msvc@1.16.2': + resolution: {integrity: sha512-fycER209DYIzsibpTMC+chND05OfOjgztWL9U8OE6/uUlsOUZH3eh98isBLEnOymYUhlJLEt5++W1+KL/FOh5Q==} + engines: {node: '>=10'} + cpu: [ia32] + os: [win32] + + '@swc/core-win32-x64-msvc@1.16.2': + resolution: {integrity: sha512-cSd1z6ivSrJPVr+moVwOHWjeKy6TpO4/Shwcv5KCrKYXCccxwh4pRy1C3fDioNx2PF1jPZWHKZjtXt+Be9VbaQ==} + engines: {node: '>=10'} + cpu: [x64] + os: [win32] + + '@swc/core@1.16.2': + resolution: {integrity: sha512-95I4kiSMeveI/Mhi+tE4fiWcWLUMfzfKrk0jtr8LRMqHgOgq+xHS+zExkDqoO4b5OeeuXHMWVdD5MeP3X6sULw==} + 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/helpers@0.5.23': + resolution: {integrity: sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==} + + '@swc/types@0.1.28': + resolution: {integrity: sha512-V6Mnml8v09QALx6K0elJ7o9K/MkVDtW3t6L+7Ou/JcWtb3xwId2AH4FeOceySd2JaO87IMw4+6vSZxLm34LPbw==} + + '@types/node@24.13.3': + resolution: {integrity: sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==} + + '@types/react-dom@19.2.7': + resolution: {integrity: sha512-I8bPpDLcHBv1qiIiXDCy71Rt8eQDKJP0sMSWJphDdAcdqiJ1sGpZamavoEIRZmYzjia9LuEb2HlYdDpmoENpvQ==} + peerDependencies: + '@types/react': ^19.2.0 + + '@types/react@19.2.18': + resolution: {integrity: sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w==} + + '@vitejs/plugin-react@6.1.1': + resolution: {integrity: sha512-yxLaQV9gkhS8ezJqCM6+ndU7mDY6gqAg75NQ+0IjwEI8IYOmQCgkRwHKVSfWXW076DsqMo0Dk+0FK1U+M5RgFw==} + engines: {node: ^20.19.0 || >=22.12.0} + peerDependencies: + '@rolldown/plugin-babel': ^0.1.7 || ^0.2.0 + babel-plugin-react-compiler: ^1.0.0 + oxc-transform-react: ^0.145.0 + vite: ^8.0.0 + peerDependenciesMeta: + '@rolldown/plugin-babel': + optional: true + babel-plugin-react-compiler: + optional: true + oxc-transform-react: + optional: true + + acorn@8.18.0: + resolution: {integrity: sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==} + engines: {node: '>=0.4.0'} + hasBin: true + + aria-hidden@1.2.6: + resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} + engines: {node: '>=10'} + + client-only@0.0.1: + resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} + + clsx@2.1.1: + resolution: {integrity: sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==} + engines: {node: '>=6'} + + cookie-es@3.1.1: + resolution: {integrity: sha512-UaXxwISYJPTr9hwQxMFYZ7kNhSXboMXP+Z3TRX6f1/NyaGPfuNUZOWP1pUEb75B2HjfklIYLVRfWiFZJyC6Npg==} + + csstype@3.2.3: + resolution: {integrity: sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==} + + detect-libc@1.0.3: + resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==} + engines: {node: '>=0.10'} + hasBin: true + + detect-libc@2.1.2: + resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} + engines: {node: '>=8'} + + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + lightningcss-android-arm64@1.33.0: + resolution: {integrity: sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [android] + + lightningcss-darwin-arm64@1.33.0: + resolution: {integrity: sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [darwin] + + lightningcss-darwin-x64@1.33.0: + resolution: {integrity: sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [darwin] + + lightningcss-freebsd-x64@1.33.0: + resolution: {integrity: sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [freebsd] + + lightningcss-linux-arm-gnueabihf@1.33.0: + resolution: {integrity: sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm] + os: [linux] + + lightningcss-linux-arm64-gnu@1.33.0: + resolution: {integrity: sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + lightningcss-linux-arm64-musl@1.33.0: + resolution: {integrity: sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [linux] + libc: [musl] + + lightningcss-linux-x64-gnu@1.33.0: + resolution: {integrity: sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [glibc] + + lightningcss-linux-x64-musl@1.33.0: + resolution: {integrity: sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [linux] + libc: [musl] + + lightningcss-win32-arm64-msvc@1.33.0: + resolution: {integrity: sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==} + engines: {node: '>= 12.0.0'} + cpu: [arm64] + os: [win32] + + lightningcss-win32-x64-msvc@1.33.0: + resolution: {integrity: sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==} + engines: {node: '>= 12.0.0'} + cpu: [x64] + os: [win32] + + lightningcss@1.33.0: + resolution: {integrity: sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==} + engines: {node: '>= 12.0.0'} + + nanoid@3.3.18: + resolution: {integrity: sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + napi-wasm@1.1.3: + resolution: {integrity: sha512-h/4nMGsHjZDCYmQVNODIrYACVJ+I9KItbG+0si6W/jSjdA9JbWDoU4LLeMXVcEQGHjttI2tuXqDrbGF7qkUHHg==} + + oxlint@1.81.0: + resolution: {integrity: sha512-HyrJYqeoOCL0iqaLEzGewGT48ZX99P3hxYh8udAF9RGGIghSamkXE4ClUyBpEDNqasamThgmlPbuMOe7SAZmHg==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + oxlint-tsgolint: '>=7.0.2001' + vite-plus: '*' + peerDependenciesMeta: + oxlint-tsgolint: + optional: true + vite-plus: + optional: true + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@4.0.7: + resolution: {integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==} + engines: {node: '>=12'} + + postcss@8.5.28: + resolution: {integrity: sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==} + engines: {node: ^10 || ^12 || >=14} + + react-aria-components@1.21.1: + resolution: {integrity: sha512-J88WflYY0z+EhLX0ce+GjFlQ3ag3ubIgfUTjpKSrBQBu92Xtl4Ub9o118HItUddtbk1Ido0jzyPy94/klZy1hg==} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + + react-aria@3.52.1: + resolution: {integrity: sha512-fdZZruC9/x/joCg0mhKGs5aHpwrXLCSZ4GOJmhhYyiE0ffyEsk9MLFt9LCOCF9tn8ErTD+UDQP4oDUSlZkmpCg==} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + react-dom: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + + react-dom@19.2.8: + resolution: {integrity: sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==} + peerDependencies: + react: ^19.2.8 + + react-router@8.3.1: + resolution: {integrity: sha512-TEOpiO2g0TJHEOJeRVv4amUFun9v1npCKszvcquNvzETUtJ8udV86ah5eFoHT7g26bsBvT6EiIhqulR8eDF++A==} + engines: {node: '>=22.22.0'} + peerDependencies: + react: '>=19.2.7' + react-dom: '>=19.2.7' + peerDependenciesMeta: + react-dom: + optional: true + + react-stately@3.50.0: + resolution: {integrity: sha512-TnckvpDQGU0672wEaLZqdzvhuSeXWjgW6vijMWxiKOxc8CosQUfPGISdcZyfHqjX3XMjEtRxj4w9HumvX4h4mw==} + peerDependencies: + react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1 + + react@19.2.8: + resolution: {integrity: sha512-PWaYA1L/q9u2u7xYQi+Y3L3Yfnie7XyLeaJICV1MGD6LprsBxcAqGjYyr0eY3p+QdsA+x/Irkt4Qif8D63+Sbw==} + engines: {node: '>=0.10.0'} + + rolldown@1.2.7: + resolution: {integrity: sha512-g0EtLvBjTUB7jhyV0S/TCup3v/XSVl45vUIGbOGU4QPiyjTenCe4mKuFvW9fEgYmS2Fo42AUssRmNuMziXdrig==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + + scheduler@0.27.0: + resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + tinyglobby@0.2.17: + resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} + engines: {node: '>=12.0.0'} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + typescript@6.0.3: + resolution: {integrity: sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==} + engines: {node: '>=14.17'} + hasBin: true + + undici-types@7.18.2: + resolution: {integrity: sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==} + + unplugin-parcel-macros-darwin-arm64@0.2.0: + resolution: {integrity: sha512-gwCMdklmYmUHlF+TLa76R/Z/HBfklE2GIVtljMgTdJhNGseigbz+jWLWNKX+D95XHa7J2JPVfCUeiAQ0qYSvfw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [darwin] + + unplugin-parcel-macros-darwin-x64@0.2.0: + resolution: {integrity: sha512-4YW0YH7rhthQIWiOapCLvVQdTIRQSBX/mWZ+TeLjgRPZbxCq38FSiyVehG6uTFKK/9tRG9yR8hOcFulv1EOP7g==} + engines: {node: '>= 10'} + cpu: [x64] + os: [darwin] + + unplugin-parcel-macros-linux-arm64-gnu@0.2.0: + resolution: {integrity: sha512-X8X8gjxOdX5b60gVUaU7t2HoDt1aOXNcG9aiQmPQF+BZVv2AiEf9XjaiMFwCTG9A6dVJLAVSxCNv8D14mm4W2w==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [glibc] + + unplugin-parcel-macros-linux-arm64-musl@0.2.0: + resolution: {integrity: sha512-d21oC4k248xuRObcqHelB9Rh9gTnr+1bCpPwG88cREj/jOT+RnsMj/ht1N5a0KZI8OF0dGCiLaIa9Qo9QT+Liw==} + engines: {node: '>= 10'} + cpu: [arm64] + os: [linux] + libc: [musl] + + unplugin-parcel-macros-linux-x64-gnu@0.2.0: + resolution: {integrity: sha512-ziGoLVVidgnHAYfcbt99xKmA+nSuglxuj1nleecH9U3S7gZ6i/41rtTLi8wn2klyWlbnGozL6/leWnMSJe+PVA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [glibc] + + unplugin-parcel-macros-linux-x64-musl@0.2.0: + resolution: {integrity: sha512-miRdxxNIFtlyCYfy/pyCjdgju2T/j/IpsNKcjnP0rw3zYXKVnA8sZy5XtlU4xxC7SpDeIbOhwLYXrrABLlobAA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [linux] + libc: [musl] + + unplugin-parcel-macros-win32-x64-msvc@0.2.0: + resolution: {integrity: sha512-rWEKltnOpqb64UQg9Os4atU8ogaaCEsI5SDFn+/x4nLXK8RhPR66yfGoEwitjfFpwxMdQ/h0EmztBMJxCWEXCA==} + engines: {node: '>= 10'} + cpu: [x64] + os: [win32] + + unplugin-parcel-macros@0.2.0: + resolution: {integrity: sha512-Cwb3C9UMRcXYQYSkxh9BJ0swGrZgEShX7nar3qKAaYHmiwUzLbOUyMCQV4oyCbIO2aE6Sip0i2L1Ch5opXp/gw==} + engines: {node: '>= 18'} + + unplugin@1.16.1: + resolution: {integrity: sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w==} + engines: {node: '>=14.0.0'} + + unplugin@2.3.11: + resolution: {integrity: sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==} + engines: {node: '>=18.12.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 + + vite@8.2.2: + resolution: {integrity: sha512-cFKLV/PRgAUlIRm5WjMjJ86jrftzpqcgH+Us+DS8mI3CDNiH30Whrz8uHL3+MOLPAgqbMBAqWdAHAphOAM+z/Q==} + engines: {node: ^20.19.0 || >=22.12.0} + hasBin: true + peerDependencies: + '@types/node': ^20.19.0 || >=22.12.0 + '@vitejs/devtools': ^0.4.0 || ^0.5.0 + esbuild: ^0.27.0 || ^0.28.0 + jiti: '>=1.21.0' + less: ^4.0.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: '>=0.54.8' + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + '@vitejs/devtools': + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + webpack-virtual-modules@0.6.2: + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + +snapshots: + + '@internationalized/date@3.12.4': + dependencies: + '@swc/helpers': 0.5.23 + + '@internationalized/number@3.6.8': + dependencies: + '@swc/helpers': 0.5.23 + + '@internationalized/string@3.2.10': + dependencies: + '@swc/helpers': 0.5.23 + + '@jridgewell/gen-mapping@0.3.13': + dependencies: + '@jridgewell/sourcemap-codec': 1.6.0 + '@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.6.0': {} + + '@jridgewell/trace-mapping@0.3.31': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.6.0 + + '@oxc-project/types@0.148.0': {} + + '@oxlint/binding-android-arm-eabi@1.81.0': + optional: true + + '@oxlint/binding-android-arm64@1.81.0': + optional: true + + '@oxlint/binding-darwin-arm64@1.81.0': + optional: true + + '@oxlint/binding-darwin-x64@1.81.0': + optional: true + + '@oxlint/binding-freebsd-x64@1.81.0': + optional: true + + '@oxlint/binding-linux-arm-gnueabihf@1.81.0': + optional: true + + '@oxlint/binding-linux-arm-musleabihf@1.81.0': + optional: true + + '@oxlint/binding-linux-arm64-gnu@1.81.0': + optional: true + + '@oxlint/binding-linux-arm64-musl@1.81.0': + optional: true + + '@oxlint/binding-linux-ppc64-gnu@1.81.0': + optional: true + + '@oxlint/binding-linux-riscv64-gnu@1.81.0': + optional: true + + '@oxlint/binding-linux-riscv64-musl@1.81.0': + optional: true + + '@oxlint/binding-linux-s390x-gnu@1.81.0': + optional: true + + '@oxlint/binding-linux-x64-gnu@1.81.0': + optional: true + + '@oxlint/binding-linux-x64-musl@1.81.0': + optional: true + + '@oxlint/binding-openharmony-arm64@1.81.0': + optional: true + + '@oxlint/binding-win32-arm64-msvc@1.81.0': + optional: true + + '@oxlint/binding-win32-ia32-msvc@1.81.0': + optional: true + + '@oxlint/binding-win32-x64-msvc@1.81.0': + optional: true + + '@parcel/macros@2.16.4': {} + + '@parcel/source-map@2.1.1': + dependencies: + detect-libc: 1.0.3 + + '@react-aria/optimize-locales-plugin@2.0.2': + dependencies: + unplugin: 2.3.11 + + '@react-spectrum/s2@1.7.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8)': + dependencies: + '@internationalized/date': 3.12.4 + '@internationalized/number': 3.6.8 + '@parcel/macros': 2.16.4 + '@react-types/shared': 3.36.1(react@19.2.8) + react: 19.2.8 + react-aria: 3.52.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + react-aria-components: 1.21.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + react-dom: 19.2.8(react@19.2.8) + react-stately: 3.50.0(react@19.2.8) + + '@react-types/shared@3.36.1(react@19.2.8)': + dependencies: + react: 19.2.8 + + '@rolldown/binding-android-arm-eabi@1.2.7': + optional: true + + '@rolldown/binding-android-arm64@1.2.7': + optional: true + + '@rolldown/binding-darwin-arm64@1.2.7': + optional: true + + '@rolldown/binding-darwin-x64@1.2.7': + optional: true + + '@rolldown/binding-freebsd-x64@1.2.7': + optional: true + + '@rolldown/binding-linux-arm-gnueabihf@1.2.7': + optional: true + + '@rolldown/binding-linux-arm64-gnu@1.2.7': + optional: true + + '@rolldown/binding-linux-arm64-musl@1.2.7': + optional: true + + '@rolldown/binding-linux-ppc64-gnu@1.2.7': + optional: true + + '@rolldown/binding-linux-s390x-gnu@1.2.7': + optional: true + + '@rolldown/binding-linux-x64-gnu@1.2.7': + optional: true + + '@rolldown/binding-linux-x64-musl@1.2.7': + optional: true + + '@rolldown/binding-openharmony-arm64@1.2.7': + optional: true + + '@rolldown/binding-win32-arm64-msvc@1.2.7': + optional: true + + '@rolldown/binding-win32-x64-msvc@1.2.7': + optional: true + + '@rolldown/pluginutils@1.0.1': {} + + '@swc/core-darwin-arm64@1.16.2': + optional: true + + '@swc/core-darwin-x64@1.16.2': + optional: true + + '@swc/core-linux-arm-gnueabihf@1.16.2': + optional: true + + '@swc/core-linux-arm64-gnu@1.16.2': + optional: true + + '@swc/core-linux-arm64-musl@1.16.2': + optional: true + + '@swc/core-linux-ppc64-gnu@1.16.2': + optional: true + + '@swc/core-linux-s390x-gnu@1.16.2': + optional: true + + '@swc/core-linux-x64-gnu@1.16.2': + optional: true + + '@swc/core-linux-x64-musl@1.16.2': + optional: true + + '@swc/core-win32-arm64-msvc@1.16.2': + optional: true + + '@swc/core-win32-ia32-msvc@1.16.2': + optional: true + + '@swc/core-win32-x64-msvc@1.16.2': + optional: true + + '@swc/core@1.16.2(@swc/helpers@0.5.23)': + dependencies: + '@swc/counter': 0.1.3 + '@swc/types': 0.1.28 + optionalDependencies: + '@swc/core-darwin-arm64': 1.16.2 + '@swc/core-darwin-x64': 1.16.2 + '@swc/core-linux-arm-gnueabihf': 1.16.2 + '@swc/core-linux-arm64-gnu': 1.16.2 + '@swc/core-linux-arm64-musl': 1.16.2 + '@swc/core-linux-ppc64-gnu': 1.16.2 + '@swc/core-linux-s390x-gnu': 1.16.2 + '@swc/core-linux-x64-gnu': 1.16.2 + '@swc/core-linux-x64-musl': 1.16.2 + '@swc/core-win32-arm64-msvc': 1.16.2 + '@swc/core-win32-ia32-msvc': 1.16.2 + '@swc/core-win32-x64-msvc': 1.16.2 + '@swc/helpers': 0.5.23 + + '@swc/counter@0.1.3': {} + + '@swc/helpers@0.5.23': + dependencies: + tslib: 2.8.1 + + '@swc/types@0.1.28': + dependencies: + '@swc/counter': 0.1.3 + + '@types/node@24.13.3': + dependencies: + undici-types: 7.18.2 + + '@types/react-dom@19.2.7(@types/react@19.2.18)': + dependencies: + '@types/react': 19.2.18 + + '@types/react@19.2.18': + dependencies: + csstype: 3.2.3 + + '@vitejs/plugin-react@6.1.1(vite@8.2.2(@types/node@24.13.3))': + dependencies: + '@rolldown/pluginutils': 1.0.1 + vite: 8.2.2(@types/node@24.13.3) + + acorn@8.18.0: {} + + aria-hidden@1.2.6: + dependencies: + tslib: 2.8.1 + + client-only@0.0.1: {} + + clsx@2.1.1: {} + + cookie-es@3.1.1: {} + + csstype@3.2.3: {} + + detect-libc@1.0.3: {} + + detect-libc@2.1.2: {} + + fdir@6.5.0(picomatch@4.0.7): + optionalDependencies: + picomatch: 4.0.7 + + fsevents@2.3.3: + optional: true + + lightningcss-android-arm64@1.33.0: + optional: true + + lightningcss-darwin-arm64@1.33.0: + optional: true + + lightningcss-darwin-x64@1.33.0: + optional: true + + lightningcss-freebsd-x64@1.33.0: + optional: true + + lightningcss-linux-arm-gnueabihf@1.33.0: + optional: true + + lightningcss-linux-arm64-gnu@1.33.0: + optional: true + + lightningcss-linux-arm64-musl@1.33.0: + optional: true + + lightningcss-linux-x64-gnu@1.33.0: + optional: true + + lightningcss-linux-x64-musl@1.33.0: + optional: true + + lightningcss-win32-arm64-msvc@1.33.0: + optional: true + + lightningcss-win32-x64-msvc@1.33.0: + optional: true + + lightningcss@1.33.0: + dependencies: + detect-libc: 2.1.2 + optionalDependencies: + lightningcss-android-arm64: 1.33.0 + lightningcss-darwin-arm64: 1.33.0 + lightningcss-darwin-x64: 1.33.0 + lightningcss-freebsd-x64: 1.33.0 + lightningcss-linux-arm-gnueabihf: 1.33.0 + lightningcss-linux-arm64-gnu: 1.33.0 + lightningcss-linux-arm64-musl: 1.33.0 + lightningcss-linux-x64-gnu: 1.33.0 + lightningcss-linux-x64-musl: 1.33.0 + lightningcss-win32-arm64-msvc: 1.33.0 + lightningcss-win32-x64-msvc: 1.33.0 + + nanoid@3.3.18: {} + + napi-wasm@1.1.3: {} + + oxlint@1.81.0: + optionalDependencies: + '@oxlint/binding-android-arm-eabi': 1.81.0 + '@oxlint/binding-android-arm64': 1.81.0 + '@oxlint/binding-darwin-arm64': 1.81.0 + '@oxlint/binding-darwin-x64': 1.81.0 + '@oxlint/binding-freebsd-x64': 1.81.0 + '@oxlint/binding-linux-arm-gnueabihf': 1.81.0 + '@oxlint/binding-linux-arm-musleabihf': 1.81.0 + '@oxlint/binding-linux-arm64-gnu': 1.81.0 + '@oxlint/binding-linux-arm64-musl': 1.81.0 + '@oxlint/binding-linux-ppc64-gnu': 1.81.0 + '@oxlint/binding-linux-riscv64-gnu': 1.81.0 + '@oxlint/binding-linux-riscv64-musl': 1.81.0 + '@oxlint/binding-linux-s390x-gnu': 1.81.0 + '@oxlint/binding-linux-x64-gnu': 1.81.0 + '@oxlint/binding-linux-x64-musl': 1.81.0 + '@oxlint/binding-openharmony-arm64': 1.81.0 + '@oxlint/binding-win32-arm64-msvc': 1.81.0 + '@oxlint/binding-win32-ia32-msvc': 1.81.0 + '@oxlint/binding-win32-x64-msvc': 1.81.0 + + picocolors@1.1.1: {} + + picomatch@4.0.7: {} + + postcss@8.5.28: + dependencies: + nanoid: 3.3.18 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + react-aria-components@1.21.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8): + dependencies: + '@internationalized/date': 3.12.4 + '@internationalized/string': 3.2.10 + '@react-types/shared': 3.36.1(react@19.2.8) + '@swc/helpers': 0.5.23 + client-only: 0.0.1 + react: 19.2.8 + react-aria: 3.52.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8) + react-dom: 19.2.8(react@19.2.8) + react-stately: 3.50.0(react@19.2.8) + + react-aria@3.52.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8): + dependencies: + '@internationalized/date': 3.12.4 + '@internationalized/number': 3.6.8 + '@internationalized/string': 3.2.10 + '@react-types/shared': 3.36.1(react@19.2.8) + '@swc/helpers': 0.5.23 + aria-hidden: 1.2.6 + clsx: 2.1.1 + react: 19.2.8 + react-dom: 19.2.8(react@19.2.8) + react-stately: 3.50.0(react@19.2.8) + use-sync-external-store: 1.6.0(react@19.2.8) + + react-dom@19.2.8(react@19.2.8): + dependencies: + react: 19.2.8 + scheduler: 0.27.0 + + react-router@8.3.1(react-dom@19.2.8(react@19.2.8))(react@19.2.8): + dependencies: + cookie-es: 3.1.1 + react: 19.2.8 + optionalDependencies: + react-dom: 19.2.8(react@19.2.8) + + react-stately@3.50.0(react@19.2.8): + dependencies: + '@internationalized/date': 3.12.4 + '@internationalized/number': 3.6.8 + '@internationalized/string': 3.2.10 + '@react-types/shared': 3.36.1(react@19.2.8) + '@swc/helpers': 0.5.23 + react: 19.2.8 + use-sync-external-store: 1.6.0(react@19.2.8) + + react@19.2.8: {} + + rolldown@1.2.7: + dependencies: + '@oxc-project/types': 0.148.0 + '@rolldown/pluginutils': 1.0.1 + optionalDependencies: + '@rolldown/binding-android-arm-eabi': 1.2.7 + '@rolldown/binding-android-arm64': 1.2.7 + '@rolldown/binding-darwin-arm64': 1.2.7 + '@rolldown/binding-darwin-x64': 1.2.7 + '@rolldown/binding-freebsd-x64': 1.2.7 + '@rolldown/binding-linux-arm-gnueabihf': 1.2.7 + '@rolldown/binding-linux-arm64-gnu': 1.2.7 + '@rolldown/binding-linux-arm64-musl': 1.2.7 + '@rolldown/binding-linux-ppc64-gnu': 1.2.7 + '@rolldown/binding-linux-s390x-gnu': 1.2.7 + '@rolldown/binding-linux-x64-gnu': 1.2.7 + '@rolldown/binding-linux-x64-musl': 1.2.7 + '@rolldown/binding-openharmony-arm64': 1.2.7 + '@rolldown/binding-win32-arm64-msvc': 1.2.7 + '@rolldown/binding-win32-x64-msvc': 1.2.7 + + scheduler@0.27.0: {} + + source-map-js@1.2.1: {} + + tinyglobby@0.2.17: + dependencies: + fdir: 6.5.0(picomatch@4.0.7) + picomatch: 4.0.7 + + tslib@2.8.1: {} + + typescript@6.0.3: {} + + undici-types@7.18.2: {} + + unplugin-parcel-macros-darwin-arm64@0.2.0: + optional: true + + unplugin-parcel-macros-darwin-x64@0.2.0: + optional: true + + unplugin-parcel-macros-linux-arm64-gnu@0.2.0: + optional: true + + unplugin-parcel-macros-linux-arm64-musl@0.2.0: + optional: true + + unplugin-parcel-macros-linux-x64-gnu@0.2.0: + optional: true + + unplugin-parcel-macros-linux-x64-musl@0.2.0: + optional: true + + unplugin-parcel-macros-win32-x64-msvc@0.2.0: + optional: true + + unplugin-parcel-macros@0.2.0(@swc/helpers@0.5.23): + dependencies: + '@parcel/source-map': 2.1.1 + '@swc/core': 1.16.2(@swc/helpers@0.5.23) + napi-wasm: 1.1.3 + unplugin: 1.16.1 + optionalDependencies: + unplugin-parcel-macros-darwin-arm64: 0.2.0 + unplugin-parcel-macros-darwin-x64: 0.2.0 + unplugin-parcel-macros-linux-arm64-gnu: 0.2.0 + unplugin-parcel-macros-linux-arm64-musl: 0.2.0 + unplugin-parcel-macros-linux-x64-gnu: 0.2.0 + unplugin-parcel-macros-linux-x64-musl: 0.2.0 + unplugin-parcel-macros-win32-x64-msvc: 0.2.0 + transitivePeerDependencies: + - '@swc/helpers' + + unplugin@1.16.1: + dependencies: + acorn: 8.18.0 + webpack-virtual-modules: 0.6.2 + + unplugin@2.3.11: + dependencies: + '@jridgewell/remapping': 2.3.5 + acorn: 8.18.0 + picomatch: 4.0.7 + webpack-virtual-modules: 0.6.2 + + use-sync-external-store@1.6.0(react@19.2.8): + dependencies: + react: 19.2.8 + + vite@8.2.2(@types/node@24.13.3): + dependencies: + lightningcss: 1.33.0 + picomatch: 4.0.7 + postcss: 8.5.28 + rolldown: 1.2.7 + tinyglobby: 0.2.17 + optionalDependencies: + '@types/node': 24.13.3 + fsevents: 2.3.3 + + webpack-virtual-modules@0.6.2: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml new file mode 100644 index 0000000..91ac346 --- /dev/null +++ b/pnpm-workspace.yaml @@ -0,0 +1,2 @@ +allowBuilds: + '@swc/core': true diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 0000000..716d5ad --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,38 @@ +import { useLayoutEffect, useState } from 'react' +import { Outlet, useHref, useNavigate, type NavigateOptions } from 'react-router' +import { Provider } from '@react-spectrum/s2/Provider' +import BasicLayout from './components/layout-basic' +import { getInitialColorScheme, ThemeContext, themeStorageKey } from './theme' + +// Configure the type of the `routerOptions` prop on all React Spectrum components. +declare module '@react-spectrum/s2/Provider' { + interface RouterConfig { + routerOptions: NavigateOptions + } +} + +function App() { + const navigate = useNavigate() + const [colorScheme, setColorScheme] = useState(getInitialColorScheme) + + useLayoutEffect(() => { + document.documentElement.dataset.theme = colorScheme + try { + localStorage.setItem(themeStorageKey, colorScheme) + } catch { + // Keep applying the theme even when browser storage is unavailable. + } + }, [colorScheme]) + + return ( + + + + + + + + ) +} + +export default App diff --git a/src/components/collapsed-navigation.tsx b/src/components/collapsed-navigation.tsx new file mode 100644 index 0000000..1748317 --- /dev/null +++ b/src/components/collapsed-navigation.tsx @@ -0,0 +1,54 @@ +import { NavLink } from 'react-router' +import { ActionButton } from '@react-spectrum/s2/ActionButton' +import { Menu, MenuItem, MenuTrigger, SubmenuTrigger, Text } from '@react-spectrum/s2/Menu' +import { Tooltip, TooltipTrigger } from '@react-spectrum/s2/Tooltip' +import { menuItems, type NavigationItem } from '../route-config' +import iconStyles from './menu-icon.module.css' +import styles from './layout-basic.module.css' + +function containsPage(item: NavigationItem, pageId?: string): boolean { + return item.id === pageId || !!item.children?.some((child) => containsPage(child, pageId)) +} + +function renderMenuItem(item: NavigationItem) { + const Icon = item.Icon + const content = <>{Icon && }{item.title} + + return item.children ? ( + + {content} + {item.children.map(renderMenuItem)} + + ) : ( + {content} + ) +} + +function CollapsedNavigation({ activePageId }: { activePageId?: string }) { + return ( +
+ {menuItems.map((item) => { + const Icon = item.Icon + const icon = Icon ? : item.title.slice(0, 1) + + return item.children ? ( +
+ + + {icon} + {item.title} + + {item.children.map(renderMenuItem)} + +
+ ) : ( + + {icon} + + ) + })} +
+ ) +} + +export default CollapsedNavigation diff --git a/src/components/form-examples/color-file-fields.tsx b/src/components/form-examples/color-file-fields.tsx new file mode 100644 index 0000000..e9d0e74 --- /dev/null +++ b/src/components/form-examples/color-file-fields.tsx @@ -0,0 +1,69 @@ +import FieldGrid from './field-grid' +import { useState } from 'react' +import { ColorArea, parseColor } from '@react-spectrum/s2/ColorArea' +import { ColorField } from '@react-spectrum/s2/ColorField' +import { ColorSlider } from '@react-spectrum/s2/ColorSlider' +import { ColorWheel } from '@react-spectrum/s2/ColorWheel' +import { ColorSwatch, ColorSwatchPicker } from '@react-spectrum/s2/ColorSwatchPicker' +import { DropZone } from '@react-spectrum/s2/DropZone' +import { FileTrigger } from '@react-spectrum/s2/FileTrigger' +import { Button } from '@react-spectrum/s2/Button' +import styles from './form-examples.module.css' + +export default function ColorFileFields({ disabled }: { disabled: boolean }) { + const [color, setColor] = useState(() => parseColor('hsl(265, 75%, 60%)')) + const [files, setFiles] = useState([]) + const [fileError, setFileError] = useState('') + return ( + <> +
+

颜色选择

+

输入框、色板、色轮和滑块共享同一个颜色值。

+ + { if (next) setColor(next) }} /> + + +
+ 预设色板 + + + +
+
+
+
二维颜色面板
+
色轮
+
+ + {color.toString('hexa')} +
+
+

文件选择与拖放

+ !disabled && types.has('Files') ? 'copy' : 'cancel'} + onDrop={async (event) => { + try { + const next = await Promise.all(event.items.filter((item) => item.kind === 'file').map((item) => item.getFile())) + setFiles(next) + setFileError('') + } catch { + setFileError('无法读取文件,请重新选择。') + } + }}> +
+

将文件拖放到这里,或从设备中选择。

+ { if (selected) { setFiles(Array.from(selected)); setFileError('') } }}> + + +

仅在本页预览文件信息,不上传。

+
+
+ {fileError &&

{fileError}

} +
+ {files.length ?
    {files.map((file, index) =>
  • {file.name} · {Math.ceil(file.size / 1024)} KB
  • )}
:

尚未选择文件。

} +
+ {files.length > 0 && } + ({ name, size, type })))} /> +
+ + ) +} diff --git a/src/components/form-examples/date-number-fields.tsx b/src/components/form-examples/date-number-fields.tsx new file mode 100644 index 0000000..f2c489f --- /dev/null +++ b/src/components/form-examples/date-number-fields.tsx @@ -0,0 +1,45 @@ +import FieldGrid from './field-grid' +import { useState } from 'react' +import { NumberField } from '@react-spectrum/s2/NumberField' +import { Slider } from '@react-spectrum/s2/Slider' +import { RangeSlider } from '@react-spectrum/s2/RangeSlider' +import { DateField } from '@react-spectrum/s2/DateField' +import { TimeField } from '@react-spectrum/s2/TimeField' +import { DatePicker } from '@react-spectrum/s2/DatePicker' +import { DateRangePicker } from '@react-spectrum/s2/DateRangePicker' +import { Calendar } from '@react-spectrum/s2/Calendar' +import { RangeCalendar, type DateRange } from '@react-spectrum/s2/RangeCalendar' +import styles from './form-examples.module.css' + +export default function DateNumberFields({ disabled }: { disabled: boolean }) { + const [day, setDay] = useState('') + const [range, setRange] = useState(null) + return ( + <> +
+

数字与滑块

+ + + + + + + +
+
+

日期与时间

+ + + + + + + +
+
独立日历 setDay(value?.toString() ?? '')} />
+
独立范围日历
+
+
+ + ) +} diff --git a/src/components/form-examples/field-grid.tsx b/src/components/form-examples/field-grid.tsx new file mode 100644 index 0000000..7dbb83d --- /dev/null +++ b/src/components/form-examples/field-grid.tsx @@ -0,0 +1,10 @@ +import { Children, type ReactNode } from 'react' +import styles from './form-examples.module.css' + +export default function FieldGrid({ children }: { children: ReactNode }) { + return ( +
+ {Children.map(children, (child) =>
{child}
)} +
+ ) +} diff --git a/src/components/form-examples/form-examples.module.css b/src/components/form-examples/form-examples.module.css new file mode 100644 index 0000000..d63db91 --- /dev/null +++ b/src/components/form-examples/form-examples.module.css @@ -0,0 +1,136 @@ +.controls { + display: flex; + flex-wrap: wrap; + align-items: end; + gap: 20px; + padding: 20px; + border: 1px solid var(--border); + border-radius: 12px; + margin-bottom: 24px; +} + +.form.form { + display: block; +} + +.fields { + min-width: 0; + margin: 0; + padding: 0; + border: 0; +} + +.section, +.result { + display: grid; + gap: 24px; + min-width: 0; + padding: 24px; + margin-bottom: 24px; + border: 1px solid var(--border); + border-radius: 12px; +} + +.section h2, +.result h2 { + font-size: 20px; + margin: 0; +} + +.section p, +.result p { + font-size: 14px; + line-height: 1.6; +} + +.grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr)); + align-items: start; + gap: 28px; + min-width: 0; +} + +.field { + display: grid; + grid-template-columns: [field] minmax(0, 1fr); + align-content: start; + min-width: 0; +} + +.grid .field > * { + grid-column: 1 / -1; + min-width: 0; +} + +.sideLabels .grid { + grid-template-columns: repeat(auto-fit, minmax(min(100%, 480px), 1fr)); +} + +.sideLabels .field { + grid-template-columns: [label] minmax(0, 10rem) [field] minmax(0, 1fr); + column-gap: 16px; +} + +.layoutHint { + margin-bottom: 20px; + font-size: 14px; +} + +.fields:disabled { + opacity: 0.6; +} + +.stack { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 12px; + min-width: 0; + font-size: 14px; +} + +.calendars { + display: flex; + flex-wrap: wrap; + gap: 32px; + min-width: 0; + overflow-x: auto; +} + +.dropContent { + padding: 24px; + display: flex; + flex-direction: column; + align-items: center; + gap: 16px; + text-align: center; +} + +.output, +.result pre { + margin: 0; + padding: 16px; + border-radius: 8px; + background: var(--social-bg); + font-family: monospace; + font-size: 13px; + overflow: auto; +} + +.srOnly { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + overflow: hidden; + clip-path: inset(50%); + white-space: nowrap; +} + +@media (max-width: 640px) { + .section, + .result { + padding: 16px; + } +} diff --git a/src/components/form-examples/form-examples.tsx b/src/components/form-examples/form-examples.tsx new file mode 100644 index 0000000..e1dd6c8 --- /dev/null +++ b/src/components/form-examples/form-examples.tsx @@ -0,0 +1,91 @@ +import { useLayoutEffect, useRef, useState } from 'react' +import { Form } from '@react-spectrum/s2/Form' +import { Button, ButtonGroup } from '@react-spectrum/s2/ButtonGroup' +import { Picker, PickerItem } from '@react-spectrum/s2/Picker' +import { Switch } from '@react-spectrum/s2/Switch' +import { Checkbox } from '@react-spectrum/s2/Checkbox' +import TextFields from './text-fields' +import SelectionFields from './selection-fields' +import DateNumberFields from './date-number-fields' +import ColorFileFields from './color-file-fields' +import styles from './form-examples.module.css' + +function DemoForm({ onReset }: { onReset: () => void }) { + const containerRef = useRef(null) + const [isCompact, setIsCompact] = useState(false) + const [size, setSize] = useState<'S' | 'M' | 'L' | 'XL'>('M') + const [sideLabels, setSideLabels] = useState(false) + const [disabled, setDisabled] = useState(false) + const [errors, setErrors] = useState>({}) + const [result, setResult] = useState | null>(null) + + useLayoutEffect(() => { + const container = containerRef.current + if (!container) return + const update = () => setIsCompact(container.clientWidth < 560) + update() + const observer = new ResizeObserver(update) + observer.observe(container) + return () => observer.disconnect() + }, []) + + const useSideLabels = sideLabels && !isCompact + + return ( +
+
+ { if (key === 'S' || key === 'M' || key === 'L' || key === 'XL') setSize(key) }}> + SMLXL + + 标签放在侧边 + 禁用表单 +
+ {sideLabels && isCompact &&

当前宽度较窄,已自动使用顶部标签。

} +
{ event.preventDefault(); onReset() }} + onSubmit={(event) => { + event.preventDefault() + const data = new FormData(event.currentTarget) + if (data.get('username') === 'admin') { + setErrors({ username: '该用户名已被占用,请换一个。(本地模拟业务校验)' }) + setResult(null) + return + } + setErrors({}) + const entries = [...new Set(data.keys())].map((key) => { + const values = data.getAll(key).map((value) => typeof value === 'string' ? value : value.name) + return [key, key === 'password' && values[0] ? '••••••••' : values.length === 1 ? values[0] : values] + }) + setResult(Object.fromEntries(entries)) + }}> +
+ Spectrum 表单示例 + + + + +
+

校验与提交

+

用户名和邮箱为必填项。可以直接提交,体验错误提示和焦点定位。

+ 我已了解这是本地表单示例 + + + + +
+
+
+
+

提交结果

+

{result ? '校验通过,以下为本次提交的数据。' : '填写表单并提交后,在这里查看结果。'}

+ {result &&
{JSON.stringify(result, null, 2)}
} +
+
+ ) +} + +export default function FormExamples() { + const [version, setVersion] = useState(0) + return setVersion((value) => value + 1)} /> +} diff --git a/src/components/form-examples/selection-fields.tsx b/src/components/form-examples/selection-fields.tsx new file mode 100644 index 0000000..84e1ec1 --- /dev/null +++ b/src/components/form-examples/selection-fields.tsx @@ -0,0 +1,68 @@ +import FieldGrid from './field-grid' +import { useState } from 'react' +import { Checkbox, CheckboxGroup } from '@react-spectrum/s2/CheckboxGroup' +import { Radio, RadioGroup } from '@react-spectrum/s2/RadioGroup' +import { Switch } from '@react-spectrum/s2/Switch' +import { Picker, PickerItem } from '@react-spectrum/s2/Picker' +import { ComboBox, ComboBoxItem } from '@react-spectrum/s2/ComboBox' +import { SelectBox, SelectBoxGroup, Text, type Selection } from '@react-spectrum/s2/SelectBoxGroup' +import { SegmentedControl, SegmentedControlItem, type Key } from '@react-spectrum/s2/SegmentedControl' +import { ToggleButton, ToggleButtonGroup } from '@react-spectrum/s2/ToggleButtonGroup' +import styles from './form-examples.module.css' + +export default function SelectionFields({ disabled }: { disabled: boolean }) { + const [plan, setPlan] = useState(new Set(['personal'])) + const [view, setView] = useState('list') + const [format, setFormat] = useState(new Set()) + const [favorite, setFavorite] = useState(false) + const [partial, setPartial] = useState(true) + const [partialSelected, setPartialSelected] = useState(false) + return ( +
+

选择控件

+ + + 上海北京深圳 + + + {(item) => {item.name}} + + + 邮件电话 + + + 设计开发研究 + +
+ 订阅邮件 + { setPartial(false); setPartialSelected(value) }}>部分选中状态 + 开启通知 +
+
+ 分段选择 + + 列表网格 + + +
+
+ 切换按钮组 + + 粗体斜体 + + + 收藏 + +
+
+
+ 卡片选择 + + 个人版个人工作空间 + 团队版多人协作空间 + + +
+
+ ) +} diff --git a/src/components/form-examples/text-fields.tsx b/src/components/form-examples/text-fields.tsx new file mode 100644 index 0000000..59cdd28 --- /dev/null +++ b/src/components/form-examples/text-fields.tsx @@ -0,0 +1,28 @@ +import FieldGrid from './field-grid' +import { TextField } from '@react-spectrum/s2/TextField' +import { TextArea } from '@react-spectrum/s2/TextArea' +import { SearchField } from '@react-spectrum/s2/SearchField' +import { ContextualHelp, Heading, Content } from '@react-spectrum/s2/ContextualHelp' +import styles from './form-examples.module.css' + +export default function TextFields() { + return ( +
+

文本输入

+ + 用户名可使用字母、数字和下划线。} + validate={(value) => value && !/^[a-zA-Z0-9_]+$/.test(value) ? '只能包含字母、数字和下划线。' : null} /> + + + + + +