diff --git a/client/cms/.gitignore b/client/cms/.gitignore index 668095b..26384d2 100644 --- a/client/cms/.gitignore +++ b/client/cms/.gitignore @@ -24,3 +24,6 @@ dist-ssr *.sw? .direnv + +*storybook.log +storybook-static diff --git a/client/cms/.storybook/main.ts b/client/cms/.storybook/main.ts new file mode 100644 index 0000000..78cf7b3 --- /dev/null +++ b/client/cms/.storybook/main.ts @@ -0,0 +1,17 @@ +import type { StorybookConfig } from '@storybook/react-vite'; + +const config: StorybookConfig = { + "stories": [ + "../src/**/*.mdx", + "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)" + ], + "addons": [ + "@chromatic-com/storybook", + "@storybook/addon-vitest", + "@storybook/addon-a11y", + "@storybook/addon-docs", + "@storybook/addon-onboarding" + ], + "framework": "@storybook/react-vite" +}; +export default config; \ No newline at end of file diff --git a/client/cms/.storybook/preview.tsx b/client/cms/.storybook/preview.tsx new file mode 100644 index 0000000..b9c2ec1 --- /dev/null +++ b/client/cms/.storybook/preview.tsx @@ -0,0 +1,36 @@ +import type { Decorator, Preview } from '@storybook/react-vite'; +import { ThemeProvider } from '../src/components/theme-provider'; +import '../src/index.css'; +import { createRootRoute, createRouter, RouterProvider } from '@tanstack/react-router'; + +const RouterDecorator: Decorator = (Story) => { + const rootRoute = createRootRoute({ component: () => }); + const routeTree = rootRoute; + const router = createRouter({ routeTree }); + return ; +}; + +const ThemeDecorator: Decorator = (Story) => { + return ; +}; + +const preview: Preview = { + decorators: [RouterDecorator, ThemeDecorator], + parameters: { + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/i, + }, + }, + + a11y: { + // 'todo' - show a11y violations in the test UI only + // 'error' - fail CI on a11y violations + // 'off' - skip a11y checks entirely + test: 'todo' + } + }, +}; + +export default preview; diff --git a/client/cms/.storybook/vitest.setup.ts b/client/cms/.storybook/vitest.setup.ts new file mode 100644 index 0000000..44922d5 --- /dev/null +++ b/client/cms/.storybook/vitest.setup.ts @@ -0,0 +1,7 @@ +import * as a11yAddonAnnotations from "@storybook/addon-a11y/preview"; +import { setProjectAnnotations } from '@storybook/react-vite'; +import * as projectAnnotations from './preview'; + +// This is an important step to apply the right configuration when testing your stories. +// More info at: https://storybook.js.org/docs/api/portable-stories/portable-stories-vitest#setprojectannotations +setProjectAnnotations([a11yAddonAnnotations, projectAnnotations]); \ No newline at end of file diff --git a/client/cms/.zed/settings.json b/client/cms/.zed/settings.json new file mode 100644 index 0000000..6424aea --- /dev/null +++ b/client/cms/.zed/settings.json @@ -0,0 +1,18 @@ +{ + "file_scan_exclusions": [ + "src/components/ui", + ".tanstack", + "node_modules", + "dist", + + // default values below + "**/.git", + "**/.svn", + "**/.hg", + "**/CVS", + "**/.DS_Store", + "**/Thumbs.db", + "**/.classpath", + "**/.settings" + ] +} diff --git a/client/cms/eslint.config.js b/client/cms/eslint.config.js index 377f8ce..ec5180d 100644 --- a/client/cms/eslint.config.js +++ b/client/cms/eslint.config.js @@ -1,9 +1,10 @@ +// For more info, see https://github.com/storybookjs/eslint-plugin-storybook#configuration-flat-config-format import antfu from '@antfu/eslint-config'; import pluginQuery from '@tanstack/eslint-plugin-query'; export default antfu({ gitignore: true, - ignores: ['**/node_modules/**', '**/dist/**', 'bun.lock', '**/routeTree.gen.ts', '**/ui/**', 'src/components/editor/**/*', 'src/client/**/*'], + ignores: ['**/node_modules/**', '**/dist/**', 'bun.lock', '**/routeTree.gen.ts', '**/ui/**', 'src/components/editor/**/*', 'src/client/**/*', 'openapi-ts.config.ts', 'vitest.shims.d.ts', '.storybook/**/*'], react: true, stylistic: { semi: true, diff --git a/client/cms/openapi-ts.config.ts b/client/cms/openapi-ts.config.ts index c0d6eef..cb1c382 100644 --- a/client/cms/openapi-ts.config.ts +++ b/client/cms/openapi-ts.config.ts @@ -5,7 +5,11 @@ export default defineConfig({ output: 'src/client', plugins: [ '@hey-api/typescript', - '@tanstack/react-query', + { + name: '@tanstack/react-query', + infiniteQueryOptions: true, + infiniteQueryKeys: true, + }, 'zod', { name: '@hey-api/transformers', diff --git a/client/cms/package.json b/client/cms/package.json index 7350502..64f3e2a 100644 --- a/client/cms/package.json +++ b/client/cms/package.json @@ -9,7 +9,9 @@ "build": "tsc -b && vite build", "lint": "eslint .", "preview": "vite preview", - "gen": "openapi-ts" + "gen": "openapi-ts", + "storybook": "storybook dev -p 6006", + "build-storybook": "storybook build" }, "dependencies": { "@base-ui/react": "^1.1.0", @@ -51,29 +53,41 @@ "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", "culori": "^4.0.2", + "dayjs": "^1.11.19", "immer": "^11.1.0", "lodash-es": "^4.17.22", "lucide-react": "^0.562.0", "next-themes": "^0.4.6", "qrcode": "^1.5.4", + "radix-ui": "^1.4.3", "react": "^19.2.0", "react-dom": "^19.2.0", + "react-error-boundary": "^6.1.0", "react-hook-form": "^7.69.0", "react-markdown": "^10.1.0", + "react-spinners": "^0.17.0", "recharts": "2.15.4", "sonner": "^2.0.7", "tailwind-merge": "^3.4.0", "tailwindcss": "^4.1.18", "utf8": "^3.0.0", "vaul": "^1.1.2", - "zod": "^4.2.1", + "zod": "^3.25.76", "zustand": "^5.0.9" }, "devDependencies": { "@antfu/eslint-config": "^6.7.1", + "@chromatic-com/storybook": "^5.0.0", "@eslint-react/eslint-plugin": "^2.3.13", "@eslint/js": "^9.39.1", "@hey-api/openapi-ts": "0.91.0", + "@redux-devtools/extension": "^3.3.0", + "@storybook/addon-a11y": "^10.2.3", + "@storybook/addon-docs": "^10.2.3", + "@storybook/addon-onboarding": "^10.2.3", + "@storybook/addon-themes": "^10.2.3", + "@storybook/addon-vitest": "^10.2.3", + "@storybook/react-vite": "^10.2.3", "@tailwindcss/typography": "^0.5.19", "@tanstack/eslint-plugin-query": "^5.91.2", "@tanstack/router-plugin": "^1.141.7", @@ -86,18 +100,24 @@ "@types/react-dom": "^19.2.3", "@types/utf8": "^3.0.3", "@vitejs/plugin-react": "^5.1.1", + "@vitest/browser-playwright": "^4.0.18", + "@vitest/coverage-v8": "^4.0.18", "eslint": "^9.39.1", "eslint-plugin-react-hooks": "^7.0.1", "eslint-plugin-react-refresh": "^0.4.26", + "eslint-plugin-storybook": "^10.2.3", "globals": "^16.5.0", "lint-staged": "^16.2.7", + "playwright": "^1.58.0", "simple-git-hooks": "^2.13.1", + "storybook": "^10.2.3", "tw-animate-css": "^1.4.0", "type-fest": "^5.4.1", "typescript": "~5.9.3", "typescript-eslint": "^8.46.4", "vite": "^7.2.4", - "vite-plugin-svgr": "^4.5.0" + "vite-plugin-svgr": "^4.5.0", + "vitest": "^4.0.18" }, "simple-git-hooks": { "pre-commit": "bun run lint-staged" diff --git a/client/cms/pnpm-lock.yaml b/client/cms/pnpm-lock.yaml index 412997d..669b020 100644 --- a/client/cms/pnpm-lock.yaml +++ b/client/cms/pnpm-lock.yaml @@ -100,10 +100,10 @@ importers: version: 8.21.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@tanstack/zod-adapter': specifier: ^1.143.4 - version: 1.153.2(@tanstack/react-router@1.153.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(zod@4.3.5) + version: 1.153.2(@tanstack/react-router@1.153.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(zod@3.25.76) '@tanstack/zod-form-adapter': specifier: ^0.42.1 - version: 0.42.1(zod@4.3.5) + version: 0.42.1(zod@3.25.76) '@uiw/react-md-editor': specifier: ^4.0.11 version: 4.0.11(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -125,6 +125,9 @@ importers: culori: specifier: ^4.0.2 version: 4.0.2 + dayjs: + specifier: ^1.11.19 + version: 1.11.19 immer: specifier: ^11.1.0 version: 11.1.3 @@ -140,18 +143,27 @@ importers: qrcode: specifier: ^1.5.4 version: 1.5.4 + radix-ui: + specifier: ^1.4.3 + version: 1.4.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) react: specifier: ^19.2.0 version: 19.2.3 react-dom: specifier: ^19.2.0 version: 19.2.3(react@19.2.3) + react-error-boundary: + specifier: ^6.1.0 + version: 6.1.0(react@19.2.3) react-hook-form: specifier: ^7.69.0 version: 7.71.1(react@19.2.3) react-markdown: specifier: ^10.1.0 version: 10.1.0(@types/react@19.2.8)(react@19.2.3) + react-spinners: + specifier: ^0.17.0 + version: 0.17.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) recharts: specifier: 2.15.4 version: 2.15.4(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -171,15 +183,18 @@ importers: specifier: ^1.1.2 version: 1.1.2(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) zod: - specifier: ^4.2.1 - version: 4.3.5 + specifier: ^3.25.76 + version: 3.25.76 zustand: specifier: ^5.0.9 version: 5.0.10(@types/react@19.2.8)(immer@11.1.3)(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) devDependencies: '@antfu/eslint-config': specifier: ^6.7.1 - version: 6.7.3(@eslint-react/eslint-plugin@2.7.2(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(@vue/compiler-sfc@3.5.27)(eslint-plugin-react-hooks@7.0.1(eslint@9.39.2(jiti@2.6.1)))(eslint-plugin-react-refresh@0.4.26(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 6.7.3(@eslint-react/eslint-plugin@2.7.2(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(@vue/compiler-sfc@3.5.27)(eslint-plugin-react-hooks@7.0.1(eslint@9.39.2(jiti@2.6.1)))(eslint-plugin-react-refresh@0.4.26(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)(vitest@4.0.18) + '@chromatic-com/storybook': + specifier: ^5.0.0 + version: 5.0.0(storybook@10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)) '@eslint-react/eslint-plugin': specifier: ^2.3.13 version: 2.7.2(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) @@ -188,7 +203,28 @@ importers: version: 9.39.2 '@hey-api/openapi-ts': specifier: 0.91.0 - version: 0.91.0(typescript@5.9.3) + version: 0.91.0(magicast@0.5.1)(typescript@5.9.3) + '@redux-devtools/extension': + specifier: ^3.3.0 + version: 3.3.0(redux@5.0.1) + '@storybook/addon-a11y': + specifier: ^10.2.3 + version: 10.2.3(storybook@10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)) + '@storybook/addon-docs': + specifier: ^10.2.3 + version: 10.2.3(@types/react@19.2.8)(esbuild@0.27.2)(rollup@4.55.2)(storybook@10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)) + '@storybook/addon-onboarding': + specifier: ^10.2.3 + version: 10.2.3(storybook@10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)) + '@storybook/addon-themes': + specifier: ^10.2.3 + version: 10.2.3(storybook@10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)) + '@storybook/addon-vitest': + specifier: ^10.2.3 + version: 10.2.3(@vitest/browser-playwright@4.0.18)(@vitest/browser@4.0.18(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.18))(@vitest/runner@4.0.18)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(storybook@10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vitest@4.0.18) + '@storybook/react-vite': + specifier: ^10.2.3 + version: 10.2.3(esbuild@0.27.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(rollup@4.55.2)(storybook@10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)) '@tailwindcss/typography': specifier: ^0.5.19 version: 0.5.19(tailwindcss@4.1.18) @@ -225,6 +261,12 @@ importers: '@vitejs/plugin-react': specifier: ^5.1.1 version: 5.1.2(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)) + '@vitest/browser-playwright': + specifier: ^4.0.18 + version: 4.0.18(playwright@1.58.0)(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.18) + '@vitest/coverage-v8': + specifier: ^4.0.18 + version: 4.0.18(@vitest/browser@4.0.18(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.18))(vitest@4.0.18) eslint: specifier: ^9.39.1 version: 9.39.2(jiti@2.6.1) @@ -234,15 +276,24 @@ importers: eslint-plugin-react-refresh: specifier: ^0.4.26 version: 0.4.26(eslint@9.39.2(jiti@2.6.1)) + eslint-plugin-storybook: + specifier: ^10.2.3 + version: 10.2.3(eslint@9.39.2(jiti@2.6.1))(storybook@10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@5.9.3) globals: specifier: ^16.5.0 version: 16.5.0 lint-staged: specifier: ^16.2.7 version: 16.2.7 + playwright: + specifier: ^1.58.0 + version: 1.58.0 simple-git-hooks: specifier: ^2.13.1 version: 2.13.1 + storybook: + specifier: ^10.2.3 + version: 10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) tw-animate-css: specifier: ^1.4.0 version: 1.4.0 @@ -261,9 +312,15 @@ importers: vite-plugin-svgr: specifier: ^4.5.0 version: 4.5.0(rollup@4.55.2)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)) + vitest: + specifier: ^4.0.18 + version: 4.0.18(@types/node@25.0.9)(@vitest/browser-playwright@4.0.18)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) packages: + '@adobe/css-tools@4.4.4': + resolution: {integrity: sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==} + '@antfu/eslint-config@6.7.3': resolution: {integrity: sha512-0tYYzY59uLnxWgbP9xpuxpvodTcWDacj439kTAJZB3sn7O0BnPfVxTnRvleGYaKCEALBZkzdC/wCho9FD7ICLw==} hasBin: true @@ -442,6 +499,16 @@ packages: '@types/react': optional: true + '@bcoe/v8-coverage@1.0.2': + resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} + engines: {node: '>=18'} + + '@chromatic-com/storybook@5.0.0': + resolution: {integrity: sha512-8wUsqL8kg6R5ue8XNE7Jv/iD1SuE4+6EXMIGIuE+T2loBITEACLfC3V8W44NJviCLusZRMWbzICddz0nU0bFaw==} + engines: {node: '>=20.0.0', yarn: '>=1.22.18'} + peerDependencies: + storybook: ^0.0.0-0 || ^10.1.0 || ^10.1.0-0 || ^10.2.0-0 || ^10.3.0-0 + '@clack/core@0.5.0': resolution: {integrity: sha512-p3y0FIOwaYRUPRcMO7+dlmLh8PSRcrjuTndsiA0WAFbWES0mLZlrjVoBRZ9DzkPFJZG6KGkJmoEAY0ZcVWTkow==} @@ -996,6 +1063,27 @@ packages: resolution: {integrity: sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==} engines: {node: '>=18.18'} + '@isaacs/balanced-match@4.0.1': + resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} + engines: {node: 20 || >=22} + + '@isaacs/brace-expansion@5.0.0': + resolution: {integrity: sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==} + engines: {node: 20 || >=22} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@joshwooding/vite-plugin-react-docgen-typescript@0.6.3': + resolution: {integrity: sha512-9TGZuAX+liGkNKkwuo3FYJu7gHWT0vkBcf7GkOe7s7fmC19XwH/4u5u7sDIFrMooe558ORcmuBvBz7Ur5PlbHw==} + peerDependencies: + typescript: '>= 4.3.x' + vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + peerDependenciesMeta: + typescript: + optional: true + '@jridgewell/gen-mapping@0.3.13': resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==} @@ -1021,16 +1109,67 @@ packages: react: ^17.0.2 || ^18.0.0 || ^19.0 react-dom: ^17.0.2 || ^18.0.0 || ^19.0 + '@mdx-js/react@3.1.1': + resolution: {integrity: sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==} + peerDependencies: + '@types/react': '>=16' + react: '>=16' + + '@neoconfetti/react@1.0.0': + resolution: {integrity: sha512-klcSooChXXOzIm+SE5IISIAn3bYzYfPjbX7D7HoqZL84oAfgREeSg5vSIaSFH+DaGzzvImTyWe1OyrJ67vik4A==} + '@pkgr/core@0.2.9': resolution: {integrity: sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==} engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + '@polka/url@1.0.0-next.29': + resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} + '@radix-ui/number@1.1.1': resolution: {integrity: sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==} '@radix-ui/primitive@1.1.3': resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==} + '@radix-ui/react-accessible-icon@1.1.7': + resolution: {integrity: sha512-XM+E4WXl0OqUJFovy6GjmxxFyx9opfCAIUku4dlKRd5YEPqt4kALOkQOp0Of6reHuUkJuiPBEc5k0o4z4lTC8A==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-accordion@1.2.12': + resolution: {integrity: sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-alert-dialog@1.1.15': + resolution: {integrity: sha512-oTVLkEw5GpdRe29BqJ0LSDFWI3qu0vR1M0mUkOQWDIUnY/QIkLpgDMWuKxP94c2NAC2LGcgVhG1ImF3jkZ5wXw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-arrow@1.1.7': resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==} peerDependencies: @@ -1044,6 +1183,32 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-aspect-ratio@1.1.7': + resolution: {integrity: sha512-Yq6lvO9HQyPwev1onK1daHCHqXVLzPhSVjmsNjCa2Zcxy2f7uJD2itDtxknv6FzAKCwD1qQkeVDmX/cev13n/g==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-avatar@1.1.10': + resolution: {integrity: sha512-V8piFfWapM5OmNCXTzVQY+E1rDa53zY+MQ4Y7356v4fFz6vqCyUtIz2rUD44ZEdwg78/jKmMJHj07+C/Z/rcog==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-avatar@1.1.11': resolution: {integrity: sha512-0Qk603AHGV28BOBO34p7IgD5m+V5Sg/YovfayABkoDDBM5d3NCx0Mp4gGrjzLGes1jV5eNOE1r3itqOR33VC6Q==} peerDependencies: @@ -1070,6 +1235,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-collapsible@1.1.12': + resolution: {integrity: sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-collection@1.1.7': resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==} peerDependencies: @@ -1092,6 +1270,19 @@ packages: '@types/react': optional: true + '@radix-ui/react-context-menu@2.2.16': + resolution: {integrity: sha512-O8morBEW+HsVG28gYDZPTrT9UUovQUlJue5YO836tiTJhuIWBm/zQHc7j388sHWtdH/xUZurK9olD2+pcqx5ww==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-context@1.1.2': resolution: {integrity: sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==} peerDependencies: @@ -1180,6 +1371,32 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-form@0.1.8': + resolution: {integrity: sha512-QM70k4Zwjttifr5a4sZFts9fn8FzHYvQ5PiB19O2HsYibaHSVt9fH9rzB0XZo/YcM+b7t/p7lYCT/F5eOeF5yQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-hover-card@1.1.15': + resolution: {integrity: sha512-qgTkjNT1CfKMoP0rcasmlH2r1DAiYicWsDsufxl940sT2wHNEWWv6FMWIQXWhVdmC1d/HYfbhQx60KYyAtKxjg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-id@1.1.1': resolution: {integrity: sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==} peerDependencies: @@ -1189,6 +1406,19 @@ packages: '@types/react': optional: true + '@radix-ui/react-label@2.1.7': + resolution: {integrity: sha512-YT1GqPSL8kJn20djelMX7/cTRp/Y9w5IZHvfxQTVHrOqa2yMl7i/UfMqKRU5V7mEyKTrUVgJXhNQPVCG8PBLoQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-label@2.1.8': resolution: {integrity: sha512-FmXs37I6hSBVDlO4y764TNz1rLgKwjJMQ0EGte6F3Cb3f4bIuHB/iLa/8I9VKkmOy+gNHq8rql3j686ACVV21A==} peerDependencies: @@ -1215,6 +1445,71 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-menubar@1.1.16': + resolution: {integrity: sha512-EB1FktTz5xRRi2Er974AUQZWg2yVBb1yjip38/lgwtCVRd3a+maUoGHN/xs9Yv8SY8QwbSEb+YrxGadVWbEutA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-navigation-menu@1.2.14': + resolution: {integrity: sha512-YB9mTFQvCOAQMHU+C/jVl96WmuWeltyUEpRJJky51huhds5W2FQr1J8D/16sQlf0ozxkPK8uF3niQMdUwZPv5w==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-one-time-password-field@0.1.8': + resolution: {integrity: sha512-ycS4rbwURavDPVjCb5iS3aG4lURFDILi6sKI/WITUMZ13gMmn/xGjpLoqBAalhJaDk8I3UbCM5GzKHrnzwHbvg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-password-toggle-field@0.1.3': + resolution: {integrity: sha512-/UuCrDBWravcaMix4TdT+qlNdVwOM1Nck9kWx/vafXsdfj1ChfhOdfi3cy9SGBpWgTXwYCuboT/oYpJy3clqfw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-popover@1.1.15': + resolution: {integrity: sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-popper@1.2.8': resolution: {integrity: sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==} peerDependencies: @@ -1280,6 +1575,32 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-progress@1.1.7': + resolution: {integrity: sha512-vPdg/tF6YC/ynuBIJlk1mm7Le0VgW6ub6J2UWnTQ7/D23KXcPI1qy+0vBkgKgd38RCMJavBXpB83HPNFMTb0Fg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-radio-group@1.3.8': + resolution: {integrity: sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-roving-focus@1.1.11': resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==} peerDependencies: @@ -1293,6 +1614,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-scroll-area@1.2.10': + resolution: {integrity: sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-select@2.2.6': resolution: {integrity: sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ==} peerDependencies: @@ -1306,6 +1640,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-separator@1.1.7': + resolution: {integrity: sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-separator@1.1.8': resolution: {integrity: sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g==} peerDependencies: @@ -1319,6 +1666,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-slider@1.3.6': + resolution: {integrity: sha512-JPYb1GuM1bxfjMRlNLE+BcmBC8onfCi60Blk7OBqi2MLTFdS+8401U4uFjnwkOr49BLmXxLC6JHkvAsx5OJvHw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-slot@1.2.3': resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==} peerDependencies: @@ -1363,6 +1723,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-toast@1.2.15': + resolution: {integrity: sha512-3OSz3TacUWy4WtOXV38DggwxoqJK4+eDkNMl5Z/MJZaoUPaP4/9lf81xXMe1I2ReTAptverZUpbPY4wWwWyL5g==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-toggle-group@1.1.11': resolution: {integrity: sha512-5umnS0T8JQzQT6HbPyO7Hh9dgd82NmS36DQr+X/YJ9ctFNCiiQd6IJAYYZ33LUwm8M+taCz5t2ui29fHZc4Y6Q==} peerDependencies: @@ -1389,6 +1762,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-toolbar@1.1.11': + resolution: {integrity: sha512-4ol06/1bLoFu1nwUqzdD4Y5RZ9oDdKeiHIsntug54Hcr1pgaHiPqHFEaXI1IFP/EsOfROQZ8Mig9VTIRza6Tjg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-tooltip@1.2.8': resolution: {integrity: sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==} peerDependencies: @@ -1499,6 +1885,11 @@ packages: '@radix-ui/rect@1.1.1': resolution: {integrity: sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==} + '@redux-devtools/extension@3.3.0': + resolution: {integrity: sha512-X34S/rC8S/M1BIrkYD1mJ5f8vlH0BDqxXrs96cvxSBo4FhMdbhU+GUGsmNYov1xjSyLMHgo8NYrUG8bNX7525g==} + peerDependencies: + redux: ^3.1.0 || ^4.0.0 || ^5.0.0 + '@rolldown/pluginutils@1.0.0-beta.53': resolution: {integrity: sha512-vENRlFU4YbrwVqNDZ7fLvy+JR1CRkyr01jhSiDpE1u6py3OMzQfztQU2jxykW3ALNxO4kSlqIDeYyD0Y9RcQeQ==} @@ -1640,9 +2031,109 @@ packages: resolution: {integrity: sha512-TeheYy0ILzBEI/CO55CP6zJCSdSWeRtGnHy8U8dWSUH4I68iqTsy7HkMktR4xakThc9jotkPQUXT4ITdbV7cHA==} engines: {node: '>=18'} + '@standard-schema/spec@1.1.0': + resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + '@standard-schema/utils@0.3.0': resolution: {integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==} + '@storybook/addon-a11y@10.2.3': + resolution: {integrity: sha512-EZLTmu/f5uENvbTKzCXlRN9TpaiKVzMfw4JF3qkw4Efae12xTJMIWieehHhl3Clc1x2d6ZtE7vhtMI9mKYQdKw==} + peerDependencies: + storybook: ^10.2.3 + + '@storybook/addon-docs@10.2.3': + resolution: {integrity: sha512-IPprt2qp4HN1uyE1Ki1sH0ZOE5B6z5sKzEMfrKMGokYKYk/AAJVfSiVIKju3q525GrBFlNhRW2+fB4pQfklv2w==} + peerDependencies: + storybook: ^10.2.3 + + '@storybook/addon-onboarding@10.2.3': + resolution: {integrity: sha512-slSExgyykz9lZMVpHu72L8tT3lzPTX6NXpcHYAkof4J+iu5Dl94vdBK320jri61Ox5xKh9h7CTkOK8jSUJP8mA==} + peerDependencies: + storybook: ^10.2.3 + + '@storybook/addon-themes@10.2.3': + resolution: {integrity: sha512-8OVXivm1pDvf2D38RCzzvVqergvFwwG+bNRtevzXW/fjdJ1dG2hMnVlqiONka1Q9w2a2XOxeDBjRxuos0oc3rA==} + peerDependencies: + storybook: ^10.2.3 + + '@storybook/addon-vitest@10.2.3': + resolution: {integrity: sha512-6ucVP+J3taV19/YxCZCUaG2VXku5DFKSK9zzNAd8ba/SNpoU3viy2km7kGvgyEZmSGHEZJpLdefbbPepxJreGg==} + peerDependencies: + '@vitest/browser': ^3.0.0 || ^4.0.0 + '@vitest/browser-playwright': ^4.0.0 + '@vitest/runner': ^3.0.0 || ^4.0.0 + storybook: ^10.2.3 + vitest: ^3.0.0 || ^4.0.0 + peerDependenciesMeta: + '@vitest/browser': + optional: true + '@vitest/browser-playwright': + optional: true + '@vitest/runner': + optional: true + vitest: + optional: true + + '@storybook/builder-vite@10.2.3': + resolution: {integrity: sha512-sKSccERL23gqC+nkTD+4io3ZF8vvNXkNiSi16X6BC29sGsbgWohw3Nv6tIGwVkIlQh0b1z24EQgXYWbdqivHGw==} + peerDependencies: + storybook: ^10.2.3 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0 + + '@storybook/csf-plugin@10.2.3': + resolution: {integrity: sha512-/b/C8C40ukzXs3Xauud2+yOJqwBdOkADfRtJ9O4TzrhftzkEdqsNI03xXZySeh7eXW8eI3Vq4t75Ljuj27Xytw==} + peerDependencies: + esbuild: '*' + rollup: '*' + storybook: ^10.2.3 + vite: '*' + webpack: '*' + peerDependenciesMeta: + esbuild: + optional: true + rollup: + optional: true + vite: + optional: true + webpack: + optional: true + + '@storybook/global@5.0.0': + resolution: {integrity: sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==} + + '@storybook/icons@2.0.1': + resolution: {integrity: sha512-/smVjw88yK3CKsiuR71vNgWQ9+NuY2L+e8X7IMrFjexjm6ZR8ULrV2DRkTA61aV6ryefslzHEGDInGpnNeIocg==} + 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 + + '@storybook/react-dom-shim@10.2.3': + resolution: {integrity: sha512-xMZXvjfQCsmzOTqFCRQ1/gxs//jDGLlnmBCikH4NSGPPogRPaNUkxgdNjOResd6pB+G3ZYAOspJkmGEEbq8dVw==} + 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 + storybook: ^10.2.3 + + '@storybook/react-vite@10.2.3': + resolution: {integrity: sha512-2muczz7r/Mnwscjzliwm8qrcAcJyqkgMA9kpgjDm5jh0EOo2ADHeW4515tRoiYOjeYCa3ixDNs28uhIvz/8BNA==} + 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 + storybook: ^10.2.3 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0 + + '@storybook/react@10.2.3': + resolution: {integrity: sha512-M67G7IY9TcLQQJ/9mHPItIiNvZFyuXf5r/wBY03YGquwCqo4GtLdp9uyGg3uCc2i0dS5VV5OQenisldmdjWFWQ==} + 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 + storybook: ^10.2.3 + typescript: '>= 4.9.x' + peerDependenciesMeta: + typescript: + optional: true + '@stylistic/eslint-plugin@5.7.0': resolution: {integrity: sha512-PsSugIf9ip1H/mWKj4bi/BlEoerxXAda9ByRFsYuwsmr6af9NxJL0AaiNXs8Le7R21QR5KMiD/KdxZZ71LjAxQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1961,6 +2452,23 @@ packages: peerDependencies: zod: ^3.x + '@testing-library/dom@10.4.1': + resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} + engines: {node: '>=18'} + + '@testing-library/jest-dom@6.9.1': + resolution: {integrity: sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==} + engines: {node: '>=14', npm: '>=6', yarn: '>=1'} + + '@testing-library/user-event@14.6.1': + resolution: {integrity: sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==} + engines: {node: '>=12', npm: '>=6'} + peerDependencies: + '@testing-library/dom': '>=7.21.4' + + '@types/aria-query@5.0.4': + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} + '@types/babel__core@7.20.5': resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} @@ -1976,6 +2484,9 @@ packages: '@types/base-64@1.0.2': resolution: {integrity: sha512-uPgKMmM9fmn7I+Zi6YBqctOye4SlJsHKcisjHIMWpb2YKZRc36GpKyNuQ03JcT+oNXg1m7Uv4wU94EVltn8/cw==} + '@types/chai@5.2.3': + resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==} + '@types/culori@4.0.1': resolution: {integrity: sha512-43M51r/22CjhbOXyGT361GZ9vncSVQ39u62x5eJdBQFviI8zWp2X5jzqg7k4M6PVgDQAClpy2bUe2dtwEgEDVQ==} @@ -2009,6 +2520,12 @@ packages: '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + + '@types/doctrine@0.0.9': + resolution: {integrity: sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==} + '@types/estree-jsx@1.0.5': resolution: {integrity: sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==} @@ -2033,6 +2550,9 @@ packages: '@types/mdast@4.0.4': resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + '@types/mdx@2.0.13': + resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==} + '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} @@ -2053,6 +2573,9 @@ packages: '@types/react@19.2.8': resolution: {integrity: sha512-3MbSL37jEchWZz2p2mjntRZtPt837ij10ApxKfgmXCTuHWagYg7iA5bqPw6C8BMPfwidlvfPI/fxOc42HLhcyg==} + '@types/resolve@1.20.6': + resolution: {integrity: sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==} + '@types/unist@2.0.11': resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} @@ -2145,6 +2668,26 @@ packages: peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + '@vitest/browser-playwright@4.0.18': + resolution: {integrity: sha512-gfajTHVCiwpxRj1qh0Sh/5bbGLG4F/ZH/V9xvFVoFddpITfMta9YGow0W6ZpTTORv2vdJuz9TnrNSmjKvpOf4g==} + peerDependencies: + playwright: '*' + vitest: 4.0.18 + + '@vitest/browser@4.0.18': + resolution: {integrity: sha512-gVQqh7paBz3gC+ZdcCmNSWJMk70IUjDeVqi+5m5vYpEHsIwRgw3Y545jljtajhkekIpIp5Gg8oK7bctgY0E2Ng==} + peerDependencies: + vitest: 4.0.18 + + '@vitest/coverage-v8@4.0.18': + resolution: {integrity: sha512-7i+N2i0+ME+2JFZhfuz7Tg/FqKtilHjGyGvoHYQ6iLV0zahbsJ9sljC9OcFcPDbhYKCet+sG8SsVqlyGvPflZg==} + peerDependencies: + '@vitest/browser': 4.0.18 + vitest: 4.0.18 + peerDependenciesMeta: + '@vitest/browser': + optional: true + '@vitest/eslint-plugin@1.6.6': resolution: {integrity: sha512-bwgQxQWRtnTVzsUHK824tBmHzjV0iTx3tZaiQIYDjX3SA7TsQS8CuDVqxXrRY3FaOUMgbGavesCxI9MOfFLm7Q==} engines: {node: '>=18'} @@ -2158,6 +2701,47 @@ packages: vitest: optional: true + '@vitest/expect@3.2.4': + resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==} + + '@vitest/expect@4.0.18': + resolution: {integrity: sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==} + + '@vitest/mocker@4.0.18': + resolution: {integrity: sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==} + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@3.2.4': + resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==} + + '@vitest/pretty-format@4.0.18': + resolution: {integrity: sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==} + + '@vitest/runner@4.0.18': + resolution: {integrity: sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==} + + '@vitest/snapshot@4.0.18': + resolution: {integrity: sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==} + + '@vitest/spy@3.2.4': + resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==} + + '@vitest/spy@4.0.18': + resolution: {integrity: sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==} + + '@vitest/utils@3.2.4': + resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==} + + '@vitest/utils@4.0.18': + resolution: {integrity: sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==} + '@vue/compiler-core@3.5.27': resolution: {integrity: sha512-gnSBQjZA+//qDZen+6a2EdHqJ68Z7uybrMf3SPjEGgG4dicklwDVmMC1AeIHxtLVPT7sn6sH1KOO+tS6gwOUeQ==} @@ -2206,6 +2790,10 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + ansi-styles@6.2.3: resolution: {integrity: sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==} engines: {node: '>=12'} @@ -2229,13 +2817,31 @@ packages: resolution: {integrity: sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==} engines: {node: '>=10'} + aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + + aria-query@5.3.2: + resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} + engines: {node: '>= 0.4'} + + 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'} + ast-v8-to-istanbul@0.3.10: + resolution: {integrity: sha512-p4K7vMz2ZSk3wN8l5o3y2bJAoZXT3VuJI5OLTATY/01CYWumWvwkUw0SqDBnNq6IiTO3qDa1eSQDibAV8g7XOQ==} + asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + axe-core@4.11.1: + resolution: {integrity: sha512-BASOg+YwO2C+346x3LZOeoovTIoTrRqEsqMa6fmfAV0P+U9mFr9NsyOEpiYvFjbc64NMrSswhV50WdXzdb/Z5A==} + engines: {node: '>=4'} + axios@1.13.2: resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==} @@ -2331,6 +2937,14 @@ packages: ccount@2.0.1: resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==} + chai@5.3.3: + resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} + engines: {node: '>=18'} + + chai@6.2.2: + resolution: {integrity: sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==} + engines: {node: '>=18'} + chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -2350,6 +2964,10 @@ packages: character-reference-invalid@2.0.1: resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} + check-error@2.1.3: + resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} + engines: {node: '>= 16'} + chokidar@3.6.0: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} @@ -2358,6 +2976,18 @@ packages: resolution: {integrity: sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==} engines: {node: '>= 20.19.0'} + chromatic@13.3.5: + resolution: {integrity: sha512-MzPhxpl838qJUo0A55osCF2ifwPbjcIPeElr1d4SHcjnHoIcg7l1syJDrAYK/a+PcCBrOGi06jPNpQAln5hWgw==} + hasBin: true + peerDependencies: + '@chromatic-com/cypress': ^0.*.* || ^1.0.0 + '@chromatic-com/playwright': ^0.*.* || ^1.0.0 + peerDependenciesMeta: + '@chromatic-com/cypress': + optional: true + '@chromatic-com/playwright': + optional: true + ci-info@4.3.1: resolution: {integrity: sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==} engines: {node: '>=8'} @@ -2464,6 +3094,9 @@ packages: css-selector-parser@3.3.0: resolution: {integrity: sha512-Y2asgMGFqJKF4fq4xHDSlFYIkeVfRsm69lQC1q9kbEsH5XtnINTMrweLkjYMeaUgiXBy/uvKeO/a1JHTNnmB2g==} + css.escape@1.5.1: + resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} + cssesc@3.0.0: resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} engines: {node: '>=4'} @@ -2520,6 +3153,9 @@ packages: resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==} engines: {node: '>=12'} + dayjs@1.11.19: + resolution: {integrity: sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==} + debug@4.4.3: resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} engines: {node: '>=6.0'} @@ -2539,6 +3175,10 @@ packages: decode-named-character-reference@1.3.0: resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==} + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} + deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} @@ -2593,6 +3233,16 @@ packages: resolution: {integrity: sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA==} hasBin: true + doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + + dom-accessibility-api@0.5.16: + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + + dom-accessibility-api@0.6.3: + resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} + dom-helpers@5.2.1: resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} @@ -2607,6 +3257,9 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + electron-to-chromium@1.5.267: resolution: {integrity: sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==} @@ -2616,6 +3269,9 @@ packages: emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + empathic@2.0.0: resolution: {integrity: sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA==} engines: {node: '>=14'} @@ -2651,6 +3307,9 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} + es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + es-object-atoms@1.1.1: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} @@ -2827,6 +3486,12 @@ packages: peerDependencies: eslint: '>=8.44.0' + eslint-plugin-storybook@10.2.3: + resolution: {integrity: sha512-5wy+OKe6VexZecAedroKv+GR+agciZqK/Su7cdo6b1mICWaWwejU/XjjTLL9zr6wiEjCN/0mhYg7yz70DoaMQQ==} + peerDependencies: + eslint: '>=8' + storybook: ^10.2.3 + eslint-plugin-toml@0.12.0: resolution: {integrity: sha512-+/wVObA9DVhwZB1nG83D2OAQRrcQZXy+drqUnFJKymqnmbnbfg/UPmEMCKrJNcEboUGxUjYrJlgy+/Y930mURQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2935,6 +3600,9 @@ packages: estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} @@ -2945,6 +3613,10 @@ packages: eventemitter3@5.0.4: resolution: {integrity: sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==} + expect-type@1.3.0: + resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} + engines: {node: '>=12.0.0'} + exsolve@1.0.8: resolution: {integrity: sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==} @@ -2980,6 +3652,10 @@ packages: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} + filesize@10.1.6: + resolution: {integrity: sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w==} + engines: {node: '>= 10.4.0'} + fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} @@ -3012,6 +3688,10 @@ packages: debug: optional: true + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + form-data@4.0.5: resolution: {integrity: sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==} engines: {node: '>= 6'} @@ -3020,6 +3700,11 @@ packages: resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==} engines: {node: '>=0.4.x'} + 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} @@ -3070,6 +3755,11 @@ packages: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} + glob@11.1.0: + resolution: {integrity: sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==} + engines: {node: 20 || >=22} + hasBin: true + globals@14.0.0: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} @@ -3173,6 +3863,9 @@ packages: html-entities@2.6.0: resolution: {integrity: sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==} + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + html-url-attributes@3.0.1: resolution: {integrity: sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ==} @@ -3193,6 +3886,9 @@ packages: immer@11.1.3: resolution: {integrity: sha512-6jQTc5z0KJFtr1UgFpIL3N9XSC3saRaI9PwWtzM2pSqkNGtiNkYY2OSwkOGDK2XcTRcLb1pi/aNkKZz0nxVH4Q==} + immutable@4.3.7: + resolution: {integrity: sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==} + import-fresh@3.3.1: resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} engines: {node: '>=6'} @@ -3201,6 +3897,10 @@ packages: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + indent-string@5.0.0: resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==} engines: {node: '>=12'} @@ -3229,6 +3929,10 @@ packages: resolution: {integrity: sha512-f4RqJKBUe5rQkJ2eJEJBXSticB3hGbN9j0yxxMQFqIW89Jp9WYFtzfTcRlstDKVUTRzSOTLKRfO9vIztenwtxA==} engines: {node: '>=18.20'} + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + is-decimal@2.0.1: resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} @@ -3290,6 +3994,22 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + + istanbul-reports@3.2.0: + resolution: {integrity: sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==} + engines: {node: '>=8'} + + jackspeak@4.1.1: + resolution: {integrity: sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==} + engines: {node: 20 || >=22} + jiti@2.6.1: resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} hasBin: true @@ -3297,6 +4017,9 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + js-tokens@9.0.1: + resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} + js-yaml@4.1.1: resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true @@ -3335,6 +4058,9 @@ packages: resolution: {integrity: sha512-1e4qoRgnn448pRuMvKGsFFymUCquZV0mpGgOyIKNgD3JVDTsVJyRBGH/Fm0tBb8WsWGgmB1mDe6/yJMQM37DUA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + jsonfile@6.2.0: + resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} + keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} @@ -3456,9 +4182,16 @@ packages: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true + loupe@3.2.1: + resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} + lower-case@2.0.2: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} + lru-cache@11.2.5: + resolution: {integrity: sha512-vFrFJkWtJvJnD5hg+hJvVE8Lh/TcMzKnTgCWmtBipwI5yLX/iX+5UB2tfuyODF5E7k9xEzMdYgGqaSb1c0c5Yw==} + engines: {node: 20 || >=22} + lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} @@ -3467,9 +4200,20 @@ packages: peerDependencies: react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 + lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + magic-string@0.30.21: resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==} + magicast@0.5.1: + resolution: {integrity: sha512-xrHS24IxaLrvuo613F719wvOIv9xPHFWQHuvGUBmPnCA/3MQxKI3b+r7n1jAoDHmsbC5bRhTZYR77invLAxVnw==} + + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + markdown-table@3.0.4: resolution: {integrity: sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==} @@ -3628,6 +4372,14 @@ packages: resolution: {integrity: sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==} engines: {node: '>=18'} + min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + + minimatch@10.1.1: + resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==} + engines: {node: 20 || >=22} + minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -3635,9 +4387,20 @@ packages: resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + mlly@1.8.0: resolution: {integrity: sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==} + mrmime@2.0.1: + resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} + engines: {node: '>=10'} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -3691,6 +4454,9 @@ packages: object-deep-merge@2.0.0: resolution: {integrity: sha512-3DC3UMpeffLTHiuXSy/UG4NOIYTLlY9u3V82+djSCLYClWobZiS4ivYzpIUWrRY/nfsJ8cWsKyG3QfyLePmhvg==} + obug@2.1.1: + resolution: {integrity: sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==} + ohash@2.0.11: resolution: {integrity: sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==} @@ -3698,6 +4464,10 @@ packages: resolution: {integrity: sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==} engines: {node: '>=18'} + open@10.2.0: + resolution: {integrity: sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==} + engines: {node: '>=18'} + open@11.0.0: resolution: {integrity: sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==} engines: {node: '>=20'} @@ -3726,6 +4496,9 @@ packages: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + package-manager-detector@1.6.0: resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==} @@ -3764,6 +4537,13 @@ packages: 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.1: + resolution: {integrity: sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==} + engines: {node: 20 || >=22} + path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} @@ -3771,6 +4551,10 @@ packages: pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + pathval@2.0.1: + resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} + engines: {node: '>= 14.16'} + perfect-debounce@2.1.0: resolution: {integrity: sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==} @@ -3790,12 +4574,26 @@ packages: engines: {node: '>=0.10'} hasBin: true + pixelmatch@7.1.0: + resolution: {integrity: sha512-1wrVzJ2STrpmONHKBy228LM1b84msXDUoAzVEl0R8Mz4Ce6EPr+IVtxm8+yvrqLYMHswREkjYFaMxnyGnaY3Ng==} + hasBin: true + pkg-types@1.3.1: resolution: {integrity: sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==} pkg-types@2.3.0: resolution: {integrity: sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==} + playwright-core@1.58.0: + resolution: {integrity: sha512-aaoB1RWrdNi3//rOeKuMiS65UCcgOVljU46At6eFcOFPFHWtd2weHRRow6z/n+Lec0Lvu0k9ZPKJSjPugikirw==} + engines: {node: '>=18'} + hasBin: true + + playwright@1.58.0: + resolution: {integrity: sha512-2SVA0sbPktiIY/MCOPX8e86ehA/e+tDNq+e5Y8qjKYti2Z/JG7xnronT/TXTIkKbYGWlCbuucZ6dziEgkoEjQQ==} + engines: {node: '>=18'} + hasBin: true + pluralize@8.0.0: resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} engines: {node: '>=4'} @@ -3804,6 +4602,10 @@ packages: resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==} engines: {node: '>=10.13.0'} + pngjs@7.0.0: + resolution: {integrity: sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==} + engines: {node: '>=14.19.0'} + pnpm-workspace-yaml@1.5.0: resolution: {integrity: sha512-PxdyJuFvq5B0qm3s9PaH/xOtSxrcvpBRr+BblhucpWjs8c79d4b7/cXhyY4AyHOHCnqklCYZTjfl0bT/mFVTRw==} @@ -3832,6 +4634,10 @@ packages: engines: {node: '>=14'} hasBin: true + pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} @@ -3856,14 +4662,41 @@ packages: quansync@0.2.11: resolution: {integrity: sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==} + radix-ui@1.4.3: + resolution: {integrity: sha512-aWizCQiyeAenIdUbqEpXgRA1ya65P13NKn/W8rWkcN0OPkRDxdBVLWnIEDsS2RpwCK2nobI7oMUSmexzTDyAmA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + rc9@2.1.2: resolution: {integrity: sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==} + react-docgen-typescript@2.4.0: + resolution: {integrity: sha512-ZtAp5XTO5HRzQctjPU0ybY0RRCQO19X/8fxn3w7y2VVTUbGHDKULPTL4ky3vB05euSgG5NpALhEhDPvQ56wvXg==} + peerDependencies: + typescript: '>= 4.3.x' + + react-docgen@8.0.2: + resolution: {integrity: sha512-+NRMYs2DyTP4/tqWz371Oo50JqmWltR1h2gcdgUMAWZJIAvrd0/SqlCfx7tpzpl/s36rzw6qH2MjoNrxtRNYhA==} + engines: {node: ^20.9.0 || >=22} + react-dom@19.2.3: resolution: {integrity: sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==} peerDependencies: react: ^19.2.3 + react-error-boundary@6.1.0: + resolution: {integrity: sha512-02k9WQ/mUhdbXir0tC1NiMesGzRPaCsJEWU/4bcFrbY1YMZOtHShtZP6zw0SJrBWA/31H0KT9/FgdL8+sPKgHA==} + peerDependencies: + react: ^18.0.0 || ^19.0.0 + react-hook-form@7.71.1: resolution: {integrity: sha512-9SUJKCGKo8HUSsCO+y0CtqkqI5nNuaDqTxyqPsZPqIwudpj4rCrAz/jZV+jn57bx5gtZKOh3neQu94DXMc+w5w==} engines: {node: '>=18.0.0'} @@ -3873,6 +4706,9 @@ packages: react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} @@ -3918,6 +4754,12 @@ packages: 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 + react-spinners@0.17.0: + resolution: {integrity: sha512-L/8HTylaBmIWwQzIjMq+0vyaRXuoAevzWoD35wKpNTxxtYXWZp+xtgkfD7Y4WItuX0YvdxMPU79+7VhhmbmuTQ==} + peerDependencies: + react: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-style-singleton@2.2.3: resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} engines: {node: '>=10'} @@ -3960,6 +4802,13 @@ packages: react: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + redent@3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + + redux@5.0.1: + resolution: {integrity: sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==} + refa@0.12.1: resolution: {integrity: sha512-J8rn6v4DBb2nnFqkqwy6/NnTYMcgLA+sLr0iIO41qpv0n+ngb7ksag2tMRl0inb1bbO/esUwzW1vbJi7K0sI0g==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} @@ -4052,6 +4901,11 @@ packages: 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@5.1.0: resolution: {integrity: sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==} engines: {node: '>=18'} @@ -4105,6 +4959,9 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} @@ -4113,6 +4970,10 @@ packages: resolution: {integrity: sha512-WszCLXwT4h2k1ufIXAgsbiTOazqqevFCIncOuUBZJ91DdvWcC5+OFkluWRQPrcuSYd8fjq+o2y1QfWqYMoAToQ==} hasBin: true + sirv@3.0.2: + resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==} + engines: {node: '>=18'} + sisteransi@1.0.5: resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} @@ -4153,6 +5014,21 @@ packages: spdx-license-ids@3.0.22: resolution: {integrity: sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==} + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + std-env@3.10.0: + resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==} + + storybook@10.2.3: + resolution: {integrity: sha512-kjsJ0hctkTO0ipHiyv1MY39wP4tAyVM7rPQGyVMU1iQ7NYHxthiiCHhFB/szmVjXdJa58fu3ZH5cwENMn8Y5eA==} + hasBin: true + peerDependencies: + prettier: ^2 || ^3 + peerDependenciesMeta: + prettier: + optional: true + string-argv@0.3.2: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} engines: {node: '>=0.6.19'} @@ -4164,6 +5040,10 @@ packages: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + string-width@7.2.0: resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==} engines: {node: '>=18'} @@ -4183,6 +5063,14 @@ packages: resolution: {integrity: sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==} engines: {node: '>=12'} + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + strip-indent@4.1.1: resolution: {integrity: sha512-SlyRoSkdh1dYP0PzclLE7r0M9sgbFKKMFXpFRUMNuKhQSbC6VQIGzq3E0qsfvGJaUFJPGv6Ws1NZ/haTAjfbMA==} engines: {node: '>=12'} @@ -4201,6 +5089,10 @@ packages: 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'} + svg-parser@2.0.4: resolution: {integrity: sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==} @@ -4231,6 +5123,9 @@ packages: tiny-warning@1.0.3: resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==} + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + tinyexec@1.0.2: resolution: {integrity: sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==} engines: {node: '>=18'} @@ -4239,6 +5134,18 @@ packages: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} + tinyrainbow@2.0.0: + resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} + engines: {node: '>=14.0.0'} + + tinyrainbow@3.0.3: + resolution: {integrity: sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==} + engines: {node: '>=14.0.0'} + + tinyspy@4.0.4: + resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} + engines: {node: '>=14.0.0'} + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -4251,6 +5158,10 @@ packages: resolution: {integrity: sha512-9mjy3frhioGIVGcwamlVlUyJ9x+WHw/TXiz9R4YOlmsIuBN43r9Dp8HZ35SF9EKjHrn3BUZj04CF+YqZ2oJ+7w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} + trim-lines@3.0.1: resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} @@ -4268,9 +5179,17 @@ packages: peerDependencies: typescript: '>=4.0.0' + ts-dedent@2.2.0: + resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} + engines: {node: '>=6.10'} + ts-pattern@5.9.0: resolution: {integrity: sha512-6s5V71mX8qBUmlgbrfL33xDUwO0fq48rxAu2LBE11WBeGdpCPOsXksQbZJHvHwhrd3QjUusd3mAOM5Gg0mFBLg==} + tsconfig-paths@4.2.0: + resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} + engines: {node: '>=6'} + tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} @@ -4329,6 +5248,10 @@ packages: unist-util-visit@5.0.0: resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + unplugin@2.3.11: resolution: {integrity: sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==} engines: {node: '>=18.12.0'} @@ -4436,6 +5359,40 @@ packages: yaml: optional: true + vitest@4.0.18: + resolution: {integrity: sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==} + engines: {node: ^20.0.0 || ^22.0.0 || >=24.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@opentelemetry/api': ^1.9.0 + '@types/node': ^20.0.0 || ^22.0.0 || >=24.0.0 + '@vitest/browser-playwright': 4.0.18 + '@vitest/browser-preview': 4.0.18 + '@vitest/browser-webdriverio': 4.0.18 + '@vitest/ui': 4.0.18 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@opentelemetry/api': + optional: true + '@types/node': + optional: true + '@vitest/browser-playwright': + optional: true + '@vitest/browser-preview': + optional: true + '@vitest/browser-webdriverio': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + vue-eslint-parser@10.2.0: resolution: {integrity: sha512-CydUvFOQKD928UzZhTp4pr2vWz1L+H99t7Pkln2QSPdvmURT0MoC4wUccfCnuEaihNsu9aYYyk+bep8rlfkUXw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4456,6 +5413,11 @@ packages: engines: {node: '>= 8'} hasBin: true + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} @@ -4464,10 +5426,34 @@ packages: 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'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + wrap-ansi@9.0.2: resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} engines: {node: '>=18'} + 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 + + wsl-utils@0.1.0: + resolution: {integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==} + engines: {node: '>=18'} + wsl-utils@0.3.1: resolution: {integrity: sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==} engines: {node: '>=20'} @@ -4542,7 +5528,9 @@ packages: snapshots: - '@antfu/eslint-config@6.7.3(@eslint-react/eslint-plugin@2.7.2(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(@vue/compiler-sfc@3.5.27)(eslint-plugin-react-hooks@7.0.1(eslint@9.39.2(jiti@2.6.1)))(eslint-plugin-react-refresh@0.4.26(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': + '@adobe/css-tools@4.4.4': {} + + '@antfu/eslint-config@6.7.3(@eslint-react/eslint-plugin@2.7.2(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(@vue/compiler-sfc@3.5.27)(eslint-plugin-react-hooks@7.0.1(eslint@9.39.2(jiti@2.6.1)))(eslint-plugin-react-refresh@0.4.26(eslint@9.39.2(jiti@2.6.1)))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)(vitest@4.0.18)': dependencies: '@antfu/install-pkg': 1.1.0 '@clack/prompts': 0.11.0 @@ -4551,7 +5539,7 @@ snapshots: '@stylistic/eslint-plugin': 5.7.0(eslint@9.39.2(jiti@2.6.1)) '@typescript-eslint/eslint-plugin': 8.53.1(@typescript-eslint/parser@8.53.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/parser': 8.53.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) - '@vitest/eslint-plugin': 1.6.6(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + '@vitest/eslint-plugin': 1.6.6(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)(vitest@4.0.18) ansis: 4.2.0 cac: 6.7.14 eslint: 9.39.2(jiti@2.6.1) @@ -4746,6 +5734,20 @@ snapshots: optionalDependencies: '@types/react': 19.2.8 + '@bcoe/v8-coverage@1.0.2': {} + + '@chromatic-com/storybook@5.0.0(storybook@10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))': + dependencies: + '@neoconfetti/react': 1.0.0 + chromatic: 13.3.5 + filesize: 10.1.6 + jsonfile: 6.2.0 + storybook: 10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + strip-ansi: 7.1.2 + transitivePeerDependencies: + - '@chromatic-com/cypress' + - '@chromatic-com/playwright' + '@clack/core@0.5.0': dependencies: picocolors: 1.1.1 @@ -5202,11 +6204,11 @@ snapshots: '@floating-ui/utils@0.2.10': {} - '@hey-api/codegen-core@0.6.0(typescript@5.9.3)': + '@hey-api/codegen-core@0.6.0(magicast@0.5.1)(typescript@5.9.3)': dependencies: '@hey-api/types': 0.1.3(typescript@5.9.3) ansi-colors: 4.1.3 - c12: 3.3.3 + c12: 3.3.3(magicast@0.5.1) color-support: 1.1.3 typescript: 5.9.3 transitivePeerDependencies: @@ -5219,11 +6221,11 @@ snapshots: js-yaml: 4.1.1 lodash: 4.17.21 - '@hey-api/openapi-ts@0.91.0(typescript@5.9.3)': + '@hey-api/openapi-ts@0.91.0(magicast@0.5.1)(typescript@5.9.3)': dependencies: - '@hey-api/codegen-core': 0.6.0(typescript@5.9.3) + '@hey-api/codegen-core': 0.6.0(magicast@0.5.1)(typescript@5.9.3) '@hey-api/json-schema-ref-parser': 1.2.3 - '@hey-api/shared': 0.1.0(typescript@5.9.3) + '@hey-api/shared': 0.1.0(magicast@0.5.1)(typescript@5.9.3) '@hey-api/types': 0.1.3(typescript@5.9.3) ansi-colors: 4.1.3 color-support: 1.1.3 @@ -5232,9 +6234,9 @@ snapshots: transitivePeerDependencies: - magicast - '@hey-api/shared@0.1.0(typescript@5.9.3)': + '@hey-api/shared@0.1.0(magicast@0.5.1)(typescript@5.9.3)': dependencies: - '@hey-api/codegen-core': 0.6.0(typescript@5.9.3) + '@hey-api/codegen-core': 0.6.0(magicast@0.5.1)(typescript@5.9.3) '@hey-api/json-schema-ref-parser': 1.2.3 '@hey-api/types': 0.1.3(typescript@5.9.3) ansi-colors: 4.1.3 @@ -5265,6 +6267,29 @@ snapshots: '@humanwhocodes/retry@0.4.3': {} + '@isaacs/balanced-match@4.0.1': {} + + '@isaacs/brace-expansion@5.0.0': + dependencies: + '@isaacs/balanced-match': 4.0.1 + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.2 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@joshwooding/vite-plugin-react-docgen-typescript@0.6.3(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))': + dependencies: + glob: 11.1.0 + react-docgen-typescript: 2.4.0(typescript@5.9.3) + vite: 7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + optionalDependencies: + typescript: 5.9.3 + '@jridgewell/gen-mapping@0.3.13': dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -5291,12 +6316,62 @@ snapshots: react: 19.2.3 react-dom: 19.2.3(react@19.2.3) + '@mdx-js/react@3.1.1(@types/react@19.2.8)(react@19.2.3)': + dependencies: + '@types/mdx': 2.0.13 + '@types/react': 19.2.8 + react: 19.2.3 + + '@neoconfetti/react@1.0.0': {} + '@pkgr/core@0.2.9': {} + '@polka/url@1.0.0-next.29': {} + '@radix-ui/number@1.1.1': {} '@radix-ui/primitive@1.1.3': {} + '@radix-ui/react-accessible-icon@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.8 + '@types/react-dom': 19.2.3(@types/react@19.2.8) + + '@radix-ui/react-accordion@1.2.12(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collapsible': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.8)(react@19.2.3) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.8 + '@types/react-dom': 19.2.3(@types/react@19.2.8) + + '@radix-ui/react-alert-dialog@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.8)(react@19.2.3) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.8 + '@types/react-dom': 19.2.3(@types/react@19.2.8) + '@radix-ui/react-arrow@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -5306,6 +6381,28 @@ snapshots: '@types/react': 19.2.8 '@types/react-dom': 19.2.3(@types/react@19.2.8) + '@radix-ui/react-aspect-ratio@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.8 + '@types/react-dom': 19.2.3(@types/react@19.2.8) + + '@radix-ui/react-avatar@1.1.10(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.8)(react@19.2.3) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.8 + '@types/react-dom': 19.2.3(@types/react@19.2.8) + '@radix-ui/react-avatar@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: '@radix-ui/react-context': 1.1.3(@types/react@19.2.8)(react@19.2.3) @@ -5335,6 +6432,22 @@ snapshots: '@types/react': 19.2.8 '@types/react-dom': 19.2.3(@types/react@19.2.8) + '@radix-ui/react-collapsible@1.1.12(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.8)(react@19.2.3) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.8 + '@types/react-dom': 19.2.3(@types/react@19.2.8) + '@radix-ui/react-collection@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3) @@ -5353,6 +6466,20 @@ snapshots: optionalDependencies: '@types/react': 19.2.8 + '@radix-ui/react-context-menu@2.2.16(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.8)(react@19.2.3) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.8 + '@types/react-dom': 19.2.3(@types/react@19.2.8) + '@radix-ui/react-context@1.1.2(@types/react@19.2.8)(react@19.2.3)': dependencies: react: 19.2.3 @@ -5438,6 +6565,37 @@ snapshots: '@types/react': 19.2.8 '@types/react-dom': 19.2.3(@types/react@19.2.8) + '@radix-ui/react-form@0.1.8(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-label': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.8 + '@types/react-dom': 19.2.3(@types/react@19.2.8) + + '@radix-ui/react-hover-card@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.8)(react@19.2.3) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.8 + '@types/react-dom': 19.2.3(@types/react@19.2.8) + '@radix-ui/react-id@1.1.1(@types/react@19.2.8)(react@19.2.3)': dependencies: '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.8)(react@19.2.3) @@ -5445,6 +6603,15 @@ snapshots: optionalDependencies: '@types/react': 19.2.8 + '@radix-ui/react-label@2.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.8 + '@types/react-dom': 19.2.3(@types/react@19.2.8) + '@radix-ui/react-label@2.1.8(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: '@radix-ui/react-primitive': 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -5480,6 +6647,105 @@ snapshots: '@types/react': 19.2.8 '@types/react-dom': 19.2.3(@types/react@19.2.8) + '@radix-ui/react-menubar@1.1.16(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.8)(react@19.2.3) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.8 + '@types/react-dom': 19.2.3(@types/react@19.2.8) + + '@radix-ui/react-navigation-menu@1.2.14(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.8 + '@types/react-dom': 19.2.3(@types/react@19.2.8) + + '@radix-ui/react-one-time-password-field@0.1.8(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@radix-ui/number': 1.1.1 + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.8)(react@19.2.3) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.8 + '@types/react-dom': 19.2.3(@types/react@19.2.8) + + '@radix-ui/react-password-toggle-field@0.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@19.2.8)(react@19.2.3) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.8 + '@types/react-dom': 19.2.3(@types/react@19.2.8) + + '@radix-ui/react-popover@1.1.15(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-id': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.8)(react@19.2.3) + aria-hidden: 1.2.6 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + react-remove-scroll: 2.7.2(@types/react@19.2.8)(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.8 + '@types/react-dom': 19.2.3(@types/react@19.2.8) + '@radix-ui/react-popper@1.2.8(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: '@floating-ui/react-dom': 2.1.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -5536,6 +6802,34 @@ snapshots: '@types/react': 19.2.8 '@types/react-dom': 19.2.3(@types/react@19.2.8) + '@radix-ui/react-progress@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.8 + '@types/react-dom': 19.2.3(@types/react@19.2.8) + + '@radix-ui/react-radio-group@1.3.8(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.8)(react@19.2.3) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.8 + '@types/react-dom': 19.2.3(@types/react@19.2.8) + '@radix-ui/react-roving-focus@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: '@radix-ui/primitive': 1.1.3 @@ -5553,6 +6847,23 @@ snapshots: '@types/react': 19.2.8 '@types/react-dom': 19.2.3(@types/react@19.2.8) + '@radix-ui/react-scroll-area@1.2.10(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@radix-ui/number': 1.1.1 + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.8)(react@19.2.3) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.8 + '@types/react-dom': 19.2.3(@types/react@19.2.8) + '@radix-ui/react-select@2.2.6(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: '@radix-ui/number': 1.1.1 @@ -5582,6 +6893,15 @@ snapshots: '@types/react': 19.2.8 '@types/react-dom': 19.2.3(@types/react@19.2.8) + '@radix-ui/react-separator@1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.8 + '@types/react-dom': 19.2.3(@types/react@19.2.8) + '@radix-ui/react-separator@1.1.8(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: '@radix-ui/react-primitive': 2.1.4(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -5591,6 +6911,25 @@ snapshots: '@types/react': 19.2.8 '@types/react-dom': 19.2.3(@types/react@19.2.8) + '@radix-ui/react-slider@1.3.6(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@radix-ui/number': 1.1.1 + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.8)(react@19.2.3) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.8 + '@types/react-dom': 19.2.3(@types/react@19.2.8) + '@radix-ui/react-slot@1.2.3(@types/react@19.2.8)(react@19.2.3)': dependencies: '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3) @@ -5636,6 +6975,26 @@ snapshots: '@types/react': 19.2.8 '@types/react-dom': 19.2.3(@types/react@19.2.8) + '@radix-ui/react-toast@1.2.15(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.8 + '@types/react-dom': 19.2.3(@types/react@19.2.8) + '@radix-ui/react-toggle-group@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: '@radix-ui/primitive': 1.1.3 @@ -5662,6 +7021,21 @@ snapshots: '@types/react': 19.2.8 '@types/react-dom': 19.2.3(@types/react@19.2.8) + '@radix-ui/react-toolbar@1.1.11(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-separator': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-toggle-group': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.8 + '@types/react-dom': 19.2.3(@types/react@19.2.8) + '@radix-ui/react-tooltip@1.2.8(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: '@radix-ui/primitive': 1.1.3 @@ -5754,6 +7128,12 @@ snapshots: '@radix-ui/rect@1.1.1': {} + '@redux-devtools/extension@3.3.0(redux@5.0.1)': + dependencies: + '@babel/runtime': 7.28.6 + immutable: 4.3.7 + redux: 5.0.1 + '@rolldown/pluginutils@1.0.0-beta.53': {} '@rollup/pluginutils@5.3.0(rollup@4.55.2)': @@ -5841,8 +7221,124 @@ snapshots: '@sindresorhus/base62@1.0.0': {} + '@standard-schema/spec@1.1.0': {} + '@standard-schema/utils@0.3.0': {} + '@storybook/addon-a11y@10.2.3(storybook@10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))': + dependencies: + '@storybook/global': 5.0.0 + axe-core: 4.11.1 + storybook: 10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + + '@storybook/addon-docs@10.2.3(@types/react@19.2.8)(esbuild@0.27.2)(rollup@4.55.2)(storybook@10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))': + dependencies: + '@mdx-js/react': 3.1.1(@types/react@19.2.8)(react@19.2.3) + '@storybook/csf-plugin': 10.2.3(esbuild@0.27.2)(rollup@4.55.2)(storybook@10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)) + '@storybook/icons': 2.0.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@storybook/react-dom-shim': 10.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(storybook@10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + storybook: 10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + ts-dedent: 2.2.0 + transitivePeerDependencies: + - '@types/react' + - esbuild + - rollup + - vite + - webpack + + '@storybook/addon-onboarding@10.2.3(storybook@10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))': + dependencies: + storybook: 10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + + '@storybook/addon-themes@10.2.3(storybook@10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))': + dependencies: + storybook: 10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + ts-dedent: 2.2.0 + + '@storybook/addon-vitest@10.2.3(@vitest/browser-playwright@4.0.18)(@vitest/browser@4.0.18(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.18))(@vitest/runner@4.0.18)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(storybook@10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vitest@4.0.18)': + dependencies: + '@storybook/global': 5.0.0 + '@storybook/icons': 2.0.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + storybook: 10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + optionalDependencies: + '@vitest/browser': 4.0.18(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.18) + '@vitest/browser-playwright': 4.0.18(playwright@1.58.0)(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.18) + '@vitest/runner': 4.0.18 + vitest: 4.0.18(@types/node@25.0.9)(@vitest/browser-playwright@4.0.18)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + transitivePeerDependencies: + - react + - react-dom + + '@storybook/builder-vite@10.2.3(esbuild@0.27.2)(rollup@4.55.2)(storybook@10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))': + dependencies: + '@storybook/csf-plugin': 10.2.3(esbuild@0.27.2)(rollup@4.55.2)(storybook@10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)) + storybook: 10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + ts-dedent: 2.2.0 + vite: 7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + transitivePeerDependencies: + - esbuild + - rollup + - webpack + + '@storybook/csf-plugin@10.2.3(esbuild@0.27.2)(rollup@4.55.2)(storybook@10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))': + dependencies: + storybook: 10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + unplugin: 2.3.11 + optionalDependencies: + esbuild: 0.27.2 + rollup: 4.55.2 + vite: 7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + + '@storybook/global@5.0.0': {} + + '@storybook/icons@2.0.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + + '@storybook/react-dom-shim@10.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(storybook@10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))': + dependencies: + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + storybook: 10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + + '@storybook/react-vite@10.2.3(esbuild@0.27.2)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(rollup@4.55.2)(storybook@10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))': + dependencies: + '@joshwooding/vite-plugin-react-docgen-typescript': 0.6.3(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)) + '@rollup/pluginutils': 5.3.0(rollup@4.55.2) + '@storybook/builder-vite': 10.2.3(esbuild@0.27.2)(rollup@4.55.2)(storybook@10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)) + '@storybook/react': 10.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(storybook@10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@5.9.3) + empathic: 2.0.0 + magic-string: 0.30.21 + react: 19.2.3 + react-docgen: 8.0.2 + react-dom: 19.2.3(react@19.2.3) + resolve: 1.22.11 + storybook: 10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + tsconfig-paths: 4.2.0 + vite: 7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + transitivePeerDependencies: + - esbuild + - rollup + - supports-color + - typescript + - webpack + + '@storybook/react@10.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(storybook@10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@5.9.3)': + dependencies: + '@storybook/global': 5.0.0 + '@storybook/react-dom-shim': 10.2.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(storybook@10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)) + react: 19.2.3 + react-docgen: 8.0.2 + react-dom: 19.2.3(react@19.2.3) + storybook: 10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + optionalDependencies: + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + '@stylistic/eslint-plugin@5.7.0(eslint@9.39.2(jiti@2.6.1))': dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) @@ -6151,15 +7647,41 @@ snapshots: '@tanstack/virtual-file-routes@1.145.4': {} - '@tanstack/zod-adapter@1.153.2(@tanstack/react-router@1.153.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(zod@4.3.5)': + '@tanstack/zod-adapter@1.153.2(@tanstack/react-router@1.153.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(zod@3.25.76)': dependencies: '@tanstack/react-router': 1.153.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - zod: 4.3.5 + zod: 3.25.76 - '@tanstack/zod-form-adapter@0.42.1(zod@4.3.5)': + '@tanstack/zod-form-adapter@0.42.1(zod@3.25.76)': dependencies: '@tanstack/form-core': 0.42.1 - zod: 4.3.5 + zod: 3.25.76 + + '@testing-library/dom@10.4.1': + dependencies: + '@babel/code-frame': 7.28.6 + '@babel/runtime': 7.28.6 + '@types/aria-query': 5.0.4 + aria-query: 5.3.0 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + picocolors: 1.1.1 + pretty-format: 27.5.1 + + '@testing-library/jest-dom@6.9.1': + dependencies: + '@adobe/css-tools': 4.4.4 + aria-query: 5.3.2 + css.escape: 1.5.1 + dom-accessibility-api: 0.6.3 + picocolors: 1.1.1 + redent: 3.0.0 + + '@testing-library/user-event@14.6.1(@testing-library/dom@10.4.1)': + dependencies: + '@testing-library/dom': 10.4.1 + + '@types/aria-query@5.0.4': {} '@types/babel__core@7.20.5': dependencies: @@ -6184,6 +7706,11 @@ snapshots: '@types/base-64@1.0.2': {} + '@types/chai@5.2.3': + dependencies: + '@types/deep-eql': 4.0.2 + assertion-error: 2.0.1 + '@types/culori@4.0.1': {} '@types/d3-array@3.2.2': {} @@ -6214,6 +7741,10 @@ snapshots: dependencies: '@types/ms': 2.1.0 + '@types/deep-eql@4.0.2': {} + + '@types/doctrine@0.0.9': {} + '@types/estree-jsx@1.0.5': dependencies: '@types/estree': 1.0.8 @@ -6240,6 +7771,8 @@ snapshots: dependencies: '@types/unist': 3.0.3 + '@types/mdx@2.0.13': {} + '@types/ms@2.1.0': {} '@types/node@25.0.9': @@ -6260,6 +7793,8 @@ snapshots: dependencies: csstype: 3.2.3 + '@types/resolve@1.20.6': {} + '@types/unist@2.0.11': {} '@types/unist@3.0.3': {} @@ -6406,16 +7941,124 @@ snapshots: transitivePeerDependencies: - supports-color - '@vitest/eslint-plugin@1.6.6(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': + '@vitest/browser-playwright@4.0.18(playwright@1.58.0)(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.18)': + dependencies: + '@vitest/browser': 4.0.18(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.18) + '@vitest/mocker': 4.0.18(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)) + playwright: 1.58.0 + tinyrainbow: 3.0.3 + vitest: 4.0.18(@types/node@25.0.9)(@vitest/browser-playwright@4.0.18)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + + '@vitest/browser@4.0.18(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.18)': + dependencies: + '@vitest/mocker': 4.0.18(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)) + '@vitest/utils': 4.0.18 + magic-string: 0.30.21 + pixelmatch: 7.1.0 + pngjs: 7.0.0 + sirv: 3.0.2 + tinyrainbow: 3.0.3 + vitest: 4.0.18(@types/node@25.0.9)(@vitest/browser-playwright@4.0.18)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + ws: 8.19.0 + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + + '@vitest/coverage-v8@4.0.18(@vitest/browser@4.0.18(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.18))(vitest@4.0.18)': + dependencies: + '@bcoe/v8-coverage': 1.0.2 + '@vitest/utils': 4.0.18 + ast-v8-to-istanbul: 0.3.10 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-reports: 3.2.0 + magicast: 0.5.1 + obug: 2.1.1 + std-env: 3.10.0 + tinyrainbow: 3.0.3 + vitest: 4.0.18(@types/node@25.0.9)(@vitest/browser-playwright@4.0.18)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + optionalDependencies: + '@vitest/browser': 4.0.18(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.18) + + '@vitest/eslint-plugin@1.6.6(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)(vitest@4.0.18)': dependencies: '@typescript-eslint/scope-manager': 8.53.1 '@typescript-eslint/utils': 8.53.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) eslint: 9.39.2(jiti@2.6.1) optionalDependencies: typescript: 5.9.3 + vitest: 4.0.18(@types/node@25.0.9)(@vitest/browser-playwright@4.0.18)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) transitivePeerDependencies: - supports-color + '@vitest/expect@3.2.4': + dependencies: + '@types/chai': 5.2.3 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 + chai: 5.3.3 + tinyrainbow: 2.0.0 + + '@vitest/expect@4.0.18': + dependencies: + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@vitest/spy': 4.0.18 + '@vitest/utils': 4.0.18 + chai: 6.2.2 + tinyrainbow: 3.0.3 + + '@vitest/mocker@4.0.18(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))': + dependencies: + '@vitest/spy': 4.0.18 + estree-walker: 3.0.3 + magic-string: 0.30.21 + optionalDependencies: + vite: 7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + + '@vitest/pretty-format@3.2.4': + dependencies: + tinyrainbow: 2.0.0 + + '@vitest/pretty-format@4.0.18': + dependencies: + tinyrainbow: 3.0.3 + + '@vitest/runner@4.0.18': + dependencies: + '@vitest/utils': 4.0.18 + pathe: 2.0.3 + + '@vitest/snapshot@4.0.18': + dependencies: + '@vitest/pretty-format': 4.0.18 + magic-string: 0.30.21 + pathe: 2.0.3 + + '@vitest/spy@3.2.4': + dependencies: + tinyspy: 4.0.4 + + '@vitest/spy@4.0.18': {} + + '@vitest/utils@3.2.4': + dependencies: + '@vitest/pretty-format': 3.2.4 + loupe: 3.2.1 + tinyrainbow: 2.0.0 + + '@vitest/utils@4.0.18': + dependencies: + '@vitest/pretty-format': 4.0.18 + tinyrainbow: 3.0.3 + '@vue/compiler-core@3.5.27': dependencies: '@babel/parser': 7.28.6 @@ -6475,6 +8118,8 @@ snapshots: dependencies: color-convert: 2.0.1 + ansi-styles@5.2.0: {} + ansi-styles@6.2.3: {} ansis@4.2.0: {} @@ -6492,12 +8137,28 @@ snapshots: dependencies: tslib: 2.8.1 + aria-query@5.3.0: + dependencies: + dequal: 2.0.3 + + aria-query@5.3.2: {} + + assertion-error@2.0.1: {} + ast-types@0.16.1: dependencies: tslib: 2.8.1 + ast-v8-to-istanbul@0.3.10: + dependencies: + '@jridgewell/trace-mapping': 0.3.31 + estree-walker: 3.0.3 + js-tokens: 9.0.1 + asynckit@0.4.0: {} + axe-core@4.11.1: {} + axios@1.13.2: dependencies: follow-redirects: 1.15.11 @@ -6565,7 +8226,7 @@ snapshots: dependencies: run-applescript: 7.1.0 - c12@3.3.3: + c12@3.3.3(magicast@0.5.1): dependencies: chokidar: 5.0.0 confbox: 0.2.2 @@ -6579,6 +8240,8 @@ snapshots: perfect-debounce: 2.1.0 pkg-types: 2.3.0 rc9: 2.1.2 + optionalDependencies: + magicast: 0.5.1 cac@6.7.14: {} @@ -6597,6 +8260,16 @@ snapshots: ccount@2.0.1: {} + chai@5.3.3: + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.3 + deep-eql: 5.0.2 + loupe: 3.2.1 + pathval: 2.0.1 + + chai@6.2.2: {} + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 @@ -6612,6 +8285,8 @@ snapshots: character-reference-invalid@2.0.1: {} + check-error@2.1.3: {} + chokidar@3.6.0: dependencies: anymatch: 3.1.3 @@ -6628,6 +8303,8 @@ snapshots: dependencies: readdirp: 5.0.0 + chromatic@13.3.5: {} + ci-info@4.3.1: {} citty@0.1.6: @@ -6718,6 +8395,8 @@ snapshots: css-selector-parser@3.3.0: {} + css.escape@1.5.1: {} + cssesc@3.0.0: {} csstype@3.2.3: {} @@ -6762,6 +8441,8 @@ snapshots: d3-timer@3.0.1: {} + dayjs@1.11.19: {} + debug@4.4.3: dependencies: ms: 2.1.3 @@ -6774,6 +8455,8 @@ snapshots: dependencies: character-entities: 2.0.2 + deep-eql@5.0.2: {} + deep-is@0.1.4: {} default-browser-id@5.0.1: {} @@ -6809,6 +8492,14 @@ snapshots: direction@2.0.1: {} + doctrine@3.0.0: + dependencies: + esutils: 2.0.3 + + dom-accessibility-api@0.5.16: {} + + dom-accessibility-api@0.6.3: {} + dom-helpers@5.2.1: dependencies: '@babel/runtime': 7.28.6 @@ -6827,12 +8518,16 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 + eastasianwidth@0.2.0: {} + electron-to-chromium@1.5.267: {} emoji-regex@10.6.0: {} emoji-regex@8.0.0: {} + emoji-regex@9.2.2: {} + empathic@2.0.0: {} enhanced-resolve@5.18.4: @@ -6856,6 +8551,8 @@ snapshots: es-errors@1.3.0: {} + es-module-lexer@1.7.0: {} + es-object-atoms@1.1.1: dependencies: es-errors: 1.3.0 @@ -7147,6 +8844,15 @@ snapshots: regexp-ast-analysis: 0.7.1 scslre: 0.3.0 + eslint-plugin-storybook@10.2.3(eslint@9.39.2(jiti@2.6.1))(storybook@10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@5.9.3): + dependencies: + '@typescript-eslint/utils': 8.53.1(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + eslint: 9.39.2(jiti@2.6.1) + storybook: 10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + transitivePeerDependencies: + - supports-color + - typescript + eslint-plugin-toml@0.12.0(eslint@9.39.2(jiti@2.6.1)): dependencies: debug: 4.4.3 @@ -7302,12 +9008,18 @@ snapshots: estree-walker@2.0.2: {} + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.8 + esutils@2.0.3: {} eventemitter3@4.0.7: {} eventemitter3@5.0.4: {} + expect-type@1.3.0: {} + exsolve@1.0.8: {} extend@3.0.2: {} @@ -7332,6 +9044,8 @@ snapshots: dependencies: flat-cache: 4.0.1 + filesize@10.1.6: {} + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 @@ -7357,6 +9071,11 @@ snapshots: follow-redirects@1.15.11: {} + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + form-data@4.0.5: dependencies: asynckit: 0.4.0 @@ -7367,6 +9086,9 @@ snapshots: format@0.2.2: {} + fsevents@2.3.2: + optional: true + fsevents@2.3.3: optional: true @@ -7421,6 +9143,15 @@ snapshots: dependencies: is-glob: 4.0.3 + glob@11.1.0: + dependencies: + foreground-child: 3.3.1 + jackspeak: 4.1.1 + minimatch: 10.1.1 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 2.0.1 + globals@14.0.0: {} globals@15.15.0: {} @@ -7601,6 +9332,8 @@ snapshots: html-entities@2.6.0: {} + html-escaper@2.0.2: {} + html-url-attributes@3.0.1: {} html-void-elements@3.0.0: {} @@ -7613,6 +9346,8 @@ snapshots: immer@11.1.3: {} + immutable@4.3.7: {} + import-fresh@3.3.1: dependencies: parent-module: 1.0.1 @@ -7620,6 +9355,8 @@ snapshots: imurmurhash@0.1.4: {} + indent-string@4.0.0: {} + indent-string@5.0.0: {} inline-style-parser@0.2.7: {} @@ -7643,6 +9380,10 @@ snapshots: dependencies: builtin-modules: 5.0.0 + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + is-decimal@2.0.1: {} is-docker@3.0.0: {} @@ -7689,10 +9430,29 @@ snapshots: isexe@2.0.0: {} + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-reports@3.2.0: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + + jackspeak@4.1.1: + dependencies: + '@isaacs/cliui': 8.0.2 + jiti@2.6.1: {} js-tokens@4.0.0: {} + js-tokens@9.0.1: {} + js-yaml@4.1.1: dependencies: argparse: 2.0.1 @@ -7720,6 +9480,12 @@ snapshots: espree: 9.6.1 semver: 7.7.3 + jsonfile@6.2.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + keyv@4.5.4: dependencies: json-buffer: 3.0.1 @@ -7833,10 +9599,14 @@ snapshots: dependencies: js-tokens: 4.0.0 + loupe@3.2.1: {} + lower-case@2.0.2: dependencies: tslib: 2.8.1 + lru-cache@11.2.5: {} + lru-cache@5.1.1: dependencies: yallist: 3.1.1 @@ -7845,10 +9615,22 @@ snapshots: dependencies: react: 19.2.3 + lz-string@1.5.0: {} + magic-string@0.30.21: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 + magicast@0.5.1: + dependencies: + '@babel/parser': 7.28.6 + '@babel/types': 7.28.6 + source-map-js: 1.2.1 + + make-dir@4.0.0: + dependencies: + semver: 7.7.3 + markdown-table@3.0.4: {} math-intrinsics@1.1.0: {} @@ -8228,6 +10010,12 @@ snapshots: mimic-function@5.0.1: {} + min-indent@1.0.1: {} + + minimatch@10.1.1: + dependencies: + '@isaacs/brace-expansion': 5.0.0 + minimatch@3.1.2: dependencies: brace-expansion: 1.1.12 @@ -8236,6 +10024,10 @@ snapshots: dependencies: brace-expansion: 2.0.2 + minimist@1.2.8: {} + + minipass@7.1.2: {} + mlly@1.8.0: dependencies: acorn: 8.15.0 @@ -8243,6 +10035,8 @@ snapshots: pkg-types: 1.3.1 ufo: 1.6.3 + mrmime@2.0.1: {} + ms@2.1.3: {} nano-spawn@2.0.0: {} @@ -8283,12 +10077,21 @@ snapshots: object-deep-merge@2.0.0: {} + obug@2.1.1: {} + ohash@2.0.11: {} onetime@7.0.0: dependencies: mimic-function: 5.0.1 + open@10.2.0: + dependencies: + default-browser: 5.4.0 + define-lazy-prop: 3.0.0 + is-inside-container: 1.0.0 + wsl-utils: 0.1.0 + open@11.0.0: dependencies: default-browser: 5.4.0 @@ -8325,6 +10128,8 @@ snapshots: p-try@2.2.0: {} + package-json-from-dist@1.0.1: {} + package-manager-detector@1.6.0: {} parent-module@1.0.1: @@ -8366,10 +10171,19 @@ snapshots: path-key@3.1.1: {} + path-parse@1.0.7: {} + + path-scurry@2.0.1: + dependencies: + lru-cache: 11.2.5 + minipass: 7.1.2 + path-type@4.0.0: {} pathe@2.0.3: {} + pathval@2.0.1: {} + perfect-debounce@2.1.0: {} picocolors@1.1.1: {} @@ -8380,6 +10194,10 @@ snapshots: pidtree@0.6.0: {} + pixelmatch@7.1.0: + dependencies: + pngjs: 7.0.0 + pkg-types@1.3.1: dependencies: confbox: 0.1.8 @@ -8392,10 +10210,20 @@ snapshots: exsolve: 1.0.8 pathe: 2.0.3 + playwright-core@1.58.0: {} + + playwright@1.58.0: + dependencies: + playwright-core: 1.58.0 + optionalDependencies: + fsevents: 2.3.2 + pluralize@8.0.0: {} pngjs@5.0.0: {} + pngjs@7.0.0: {} + pnpm-workspace-yaml@1.5.0: dependencies: yaml: 2.8.2 @@ -8422,6 +10250,12 @@ snapshots: prettier@3.8.0: {} + pretty-format@27.5.1: + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + prop-types@15.8.1: dependencies: loose-envify: 1.4.0 @@ -8444,22 +10278,110 @@ snapshots: quansync@0.2.11: {} + radix-ui@1.4.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3): + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-accessible-icon': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-accordion': 1.2.12(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-alert-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-arrow': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-aspect-ratio': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-avatar': 1.1.10(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-checkbox': 1.3.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-collapsible': 1.1.12(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-collection': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-context-menu': 2.2.16(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-dialog': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-direction': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-dropdown-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-form': 0.1.8(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-hover-card': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-label': 2.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-menu': 2.1.16(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-menubar': 1.1.16(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-navigation-menu': 1.2.14(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-one-time-password-field': 0.1.8(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-password-toggle-field': 0.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-popover': 1.1.15(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-progress': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-radio-group': 1.3.8(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-scroll-area': 1.2.10(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-select': 2.2.6(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-separator': 1.1.7(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-slider': 1.3.6(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-slot': 1.2.3(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-switch': 1.2.6(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-tabs': 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-toast': 1.2.15(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-toggle': 1.1.10(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-toggle-group': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-toolbar': 1.1.11(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-tooltip': 1.2.8(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-use-effect-event': 0.0.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-use-is-hydrated': 0.1.0(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.8 + '@types/react-dom': 19.2.3(@types/react@19.2.8) + rc9@2.1.2: dependencies: defu: 6.1.4 destr: 2.0.5 + react-docgen-typescript@2.4.0(typescript@5.9.3): + dependencies: + typescript: 5.9.3 + + react-docgen@8.0.2: + dependencies: + '@babel/core': 7.28.6 + '@babel/traverse': 7.28.6 + '@babel/types': 7.28.6 + '@types/babel__core': 7.20.5 + '@types/babel__traverse': 7.28.0 + '@types/doctrine': 0.0.9 + '@types/resolve': 1.20.6 + doctrine: 3.0.0 + resolve: 1.22.11 + strip-indent: 4.1.1 + transitivePeerDependencies: + - supports-color + react-dom@19.2.3(react@19.2.3): dependencies: react: 19.2.3 scheduler: 0.27.0 + react-error-boundary@6.1.0(react@19.2.3): + dependencies: + react: 19.2.3 + react-hook-form@7.71.1(react@19.2.3): dependencies: react: 19.2.3 react-is@16.13.1: {} + react-is@17.0.2: {} + react-is@18.3.1: {} react-markdown@10.1.0(@types/react@19.2.8)(react@19.2.3): @@ -8526,6 +10448,11 @@ snapshots: react-dom: 19.2.3(react@19.2.3) react-transition-group: 4.4.5(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + react-spinners@0.17.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3): + dependencies: + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + react-style-singleton@2.2.3(@types/react@19.2.8)(react@19.2.3): dependencies: get-nonce: 1.0.1 @@ -8576,6 +10503,13 @@ snapshots: tiny-invariant: 1.3.3 victory-vendor: 36.9.2 + redent@3.0.0: + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + + redux@5.0.1: {} + refa@0.12.1: dependencies: '@eslint-community/regexpp': 4.12.2 @@ -8725,6 +10659,12 @@ snapshots: 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 + restore-cursor@5.1.0: dependencies: onetime: 7.0.0 @@ -8791,10 +10731,18 @@ snapshots: shebang-regex@3.0.0: {} + siginfo@2.0.0: {} + signal-exit@4.1.0: {} simple-git-hooks@2.13.1: {} + sirv@3.0.2: + dependencies: + '@polka/url': 1.0.0-next.29 + mrmime: 2.0.1 + totalist: 3.0.1 + sisteransi@1.0.5: {} slice-ansi@7.1.2: @@ -8829,6 +10777,33 @@ snapshots: spdx-license-ids@3.0.22: {} + stackback@0.0.2: {} + + std-env@3.10.0: {} + + storybook@10.2.3(@testing-library/dom@10.4.1)(prettier@3.8.0)(react-dom@19.2.3(react@19.2.3))(react@19.2.3): + dependencies: + '@storybook/global': 5.0.0 + '@storybook/icons': 2.0.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@testing-library/jest-dom': 6.9.1 + '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.1) + '@vitest/expect': 3.2.4 + '@vitest/spy': 3.2.4 + esbuild: 0.27.2 + open: 10.2.0 + recast: 0.23.11 + semver: 7.7.3 + use-sync-external-store: 1.6.0(react@19.2.3) + ws: 8.19.0 + optionalDependencies: + prettier: 3.8.0 + transitivePeerDependencies: + - '@testing-library/dom' + - bufferutil + - react + - react-dom + - utf-8-validate + string-argv@0.3.2: {} string-ts@2.3.1: {} @@ -8839,6 +10814,12 @@ snapshots: is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.2 + string-width@7.2.0: dependencies: emoji-regex: 10.6.0 @@ -8863,6 +10844,12 @@ snapshots: dependencies: ansi-regex: 6.2.2 + strip-bom@3.0.0: {} + + strip-indent@3.0.0: + dependencies: + min-indent: 1.0.1 + strip-indent@4.1.1: {} strip-json-comments@3.1.1: {} @@ -8879,6 +10866,8 @@ snapshots: dependencies: has-flag: 4.0.0 + supports-preserve-symlinks-flag@1.0.0: {} + svg-parser@2.0.4: {} synckit@0.11.12: @@ -8899,6 +10888,8 @@ snapshots: tiny-warning@1.0.3: {} + tinybench@2.9.0: {} + tinyexec@1.0.2: {} tinyglobby@0.2.15: @@ -8906,6 +10897,12 @@ snapshots: fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 + tinyrainbow@2.0.0: {} + + tinyrainbow@3.0.3: {} + + tinyspy@4.0.4: {} + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -8919,6 +10916,8 @@ snapshots: dependencies: eslint-visitor-keys: 3.4.3 + totalist@3.0.1: {} + trim-lines@3.0.1: {} trough@2.2.0: {} @@ -8932,8 +10931,16 @@ snapshots: picomatch: 4.0.3 typescript: 5.9.3 + ts-dedent@2.2.0: {} + ts-pattern@5.9.0: {} + tsconfig-paths@4.2.0: + dependencies: + json5: 2.2.3 + minimist: 1.2.8 + strip-bom: 3.0.0 + tslib@2.8.1: {} tsx@4.21.0: @@ -9009,6 +11016,8 @@ snapshots: unist-util-is: 6.0.1 unist-util-visit-parents: 6.0.2 + universalify@2.0.1: {} + unplugin@2.3.11: dependencies: '@jridgewell/remapping': 2.3.5 @@ -9117,6 +11126,44 @@ snapshots: tsx: 4.21.0 yaml: 2.8.2 + vitest@4.0.18(@types/node@25.0.9)(@vitest/browser-playwright@4.0.18)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2): + dependencies: + '@vitest/expect': 4.0.18 + '@vitest/mocker': 4.0.18(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2)) + '@vitest/pretty-format': 4.0.18 + '@vitest/runner': 4.0.18 + '@vitest/snapshot': 4.0.18 + '@vitest/spy': 4.0.18 + '@vitest/utils': 4.0.18 + es-module-lexer: 1.7.0 + expect-type: 1.3.0 + magic-string: 0.30.21 + obug: 2.1.1 + pathe: 2.0.3 + picomatch: 4.0.3 + std-env: 3.10.0 + tinybench: 2.9.0 + tinyexec: 1.0.2 + tinyglobby: 0.2.15 + tinyrainbow: 3.0.3 + vite: 7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 25.0.9 + '@vitest/browser-playwright': 4.0.18(playwright@1.58.0)(vite@7.3.1(@types/node@25.0.9)(jiti@2.6.1)(lightningcss@1.30.2)(tsx@4.21.0)(yaml@2.8.2))(vitest@4.0.18) + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - terser + - tsx + - yaml + vue-eslint-parser@10.2.0(eslint@9.39.2(jiti@2.6.1)): dependencies: debug: 4.4.3 @@ -9139,6 +11186,11 @@ snapshots: dependencies: isexe: 2.0.0 + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + word-wrap@1.2.5: {} wrap-ansi@6.2.0: @@ -9147,12 +11199,30 @@ snapshots: 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 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.3 + string-width: 5.1.2 + strip-ansi: 7.1.2 + wrap-ansi@9.0.2: dependencies: ansi-styles: 6.2.3 string-width: 7.2.0 strip-ansi: 7.1.2 + ws@8.19.0: {} + + wsl-utils@0.1.0: + dependencies: + is-wsl: 3.1.0 + wsl-utils@0.3.1: dependencies: is-wsl: 3.1.0 diff --git a/client/cms/src/assets/event-placeholder.png b/client/cms/src/assets/event-placeholder.png new file mode 100644 index 0000000..dc2c293 Binary files /dev/null and b/client/cms/src/assets/event-placeholder.png differ diff --git a/client/cms/src/client/@tanstack/react-query.gen.ts b/client/cms/src/client/@tanstack/react-query.gen.ts index 6c77868..89fcd78 100644 --- a/client/cms/src/client/@tanstack/react-query.gen.ts +++ b/client/cms/src/client/@tanstack/react-query.gen.ts @@ -3,8 +3,8 @@ import { type InfiniteData, infiniteQueryOptions, queryOptions, type UseMutationOptions } from '@tanstack/react-query'; import { client } from '../client.gen'; -import { getAuthRedirect, getEventCheckin, getEventCheckinQuery, getEventInfo, getUserFull, getUserInfo, getUserList, type Options, patchUserUpdate, postAuthExchange, postAuthMagic, postAuthRefresh, postAuthToken, postEventCheckinSubmit } from '../sdk.gen'; -import type { GetAuthRedirectData, GetAuthRedirectError, GetEventCheckinData, GetEventCheckinError, GetEventCheckinQueryData, GetEventCheckinQueryError, GetEventCheckinQueryResponse, GetEventCheckinResponse, GetEventInfoData, GetEventInfoError, GetEventInfoResponse, GetUserFullData, GetUserFullError, GetUserFullResponse, GetUserInfoData, GetUserInfoError, GetUserInfoResponse, GetUserListData, GetUserListError, GetUserListResponse, PatchUserUpdateData, PatchUserUpdateError, PatchUserUpdateResponse, PostAuthExchangeData, PostAuthExchangeError, PostAuthExchangeResponse, PostAuthMagicData, PostAuthMagicError, PostAuthMagicResponse, PostAuthRefreshData, PostAuthRefreshError, PostAuthRefreshResponse, PostAuthTokenData, PostAuthTokenError, PostAuthTokenResponse, PostEventCheckinSubmitData, PostEventCheckinSubmitError, PostEventCheckinSubmitResponse } from '../types.gen'; +import { getAuthRedirect, getEventAttendance, getEventCheckin, getEventCheckinQuery, getEventInfo, getEventList, getUserInfo, getUserInfoByUserId, getUserList, type Options, patchUserUpdate, postAuthExchange, postAuthMagic, postAuthRefresh, postAuthToken, postEventCheckinSubmit, postEventJoin, postKycQuery, postKycSession } from '../sdk.gen'; +import type { GetAuthRedirectData, GetAuthRedirectError, GetEventAttendanceData, GetEventAttendanceError, GetEventAttendanceResponse, GetEventCheckinData, GetEventCheckinError, GetEventCheckinQueryData, GetEventCheckinQueryError, GetEventCheckinQueryResponse, GetEventCheckinResponse, GetEventInfoData, GetEventInfoError, GetEventInfoResponse, GetEventListData, GetEventListError, GetEventListResponse, GetUserInfoByUserIdData, GetUserInfoByUserIdError, GetUserInfoByUserIdResponse, GetUserInfoData, GetUserInfoError, GetUserInfoResponse, GetUserListData, GetUserListError, GetUserListResponse, PatchUserUpdateData, PatchUserUpdateError, PatchUserUpdateResponse, PostAuthExchangeData, PostAuthExchangeError, PostAuthExchangeResponse, PostAuthMagicData, PostAuthMagicError, PostAuthMagicResponse, PostAuthRefreshData, PostAuthRefreshError, PostAuthRefreshResponse, PostAuthTokenData, PostAuthTokenError, PostAuthTokenResponse, PostEventCheckinSubmitData, PostEventCheckinSubmitError, PostEventCheckinSubmitResponse, PostEventJoinData, PostEventJoinError, PostEventJoinResponse, PostKycQueryData, PostKycQueryError, PostKycQueryResponse, PostKycSessionData, PostKycSessionError, PostKycSessionResponse } from '../types.gen'; /** * Exchange Auth Code @@ -135,6 +135,26 @@ export const postAuthTokenMutation = (options?: Partial) => createQueryKey('getEventAttendance', options); + +/** + * Get Attendance List + * + * Retrieves the list of attendees, including user info and decrypted KYC data for a specified event. + */ +export const getEventAttendanceOptions = (options: Options) => queryOptions>({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await getEventAttendance({ + ...options, + ...queryKey[0], + signal, + throwOnError: true + }); + return data; + }, + queryKey: getEventAttendanceQueryKey(options) +}); + export const getEventCheckinQueryKey = (options: Options) => createQueryKey('getEventCheckin', options); /** @@ -214,16 +234,35 @@ export const getEventInfoOptions = (options: Options) => query queryKey: getEventInfoQueryKey(options) }); -export const getUserFullQueryKey = (options?: Options) => createQueryKey('getUserFull', options); +/** + * Join an Event + * + * Allows an authenticated user to join an event by providing the event ID. The user's role and state are initialized by the service. + */ +export const postEventJoinMutation = (options?: Partial>): UseMutationOptions> => { + const mutationOptions: UseMutationOptions> = { + mutationFn: async (fnOptions) => { + const { data } = await postEventJoin({ + ...options, + ...fnOptions, + throwOnError: true + }); + return data; + } + }; + return mutationOptions; +}; + +export const getEventListQueryKey = (options: Options) => createQueryKey('getEventList', options); /** - * Get Full User Table + * List Events * - * Fetches all user records without pagination. This is typically used for administrative overview or data export. + * Fetches a list of events with support for pagination via limit and offset. Data is retrieved directly from the database for consistency. */ -export const getUserFullOptions = (options?: Options) => queryOptions>({ +export const getEventListOptions = (options: Options) => queryOptions>({ queryFn: async ({ queryKey, signal }) => { - const { data } = await getUserFull({ + const { data } = await getEventList({ ...options, ...queryKey[0], signal, @@ -231,47 +270,7 @@ export const getUserFullOptions = (options?: Options) => queryO }); return data; }, - queryKey: getUserFullQueryKey(options) -}); - -export const getUserInfoQueryKey = (options?: Options) => createQueryKey('getUserInfo', options); - -/** - * Get My User Information - * - * Fetches the complete profile data for the user associated with the provided session/token. - */ -export const getUserInfoOptions = (options?: Options) => queryOptions>({ - queryFn: async ({ queryKey, signal }) => { - const { data } = await getUserInfo({ - ...options, - ...queryKey[0], - signal, - throwOnError: true - }); - return data; - }, - queryKey: getUserInfoQueryKey(options) -}); - -export const getUserListQueryKey = (options: Options) => createQueryKey('getUserList', options); - -/** - * List Users - * - * Fetches a list of users with support for pagination via limit and offset. Data is sourced from the search engine for high performance. - */ -export const getUserListOptions = (options: Options) => queryOptions>({ - queryFn: async ({ queryKey, signal }) => { - const { data } = await getUserList({ - ...options, - ...queryKey[0], - signal, - throwOnError: true - }); - return data; - }, - queryKey: getUserListQueryKey(options) + queryKey: getEventListQueryKey(options) }); const createInfiniteParams = [0], 'body' | 'headers' | 'path' | 'query'>>(queryKey: QueryKey, page: K) => { @@ -303,6 +302,133 @@ const createInfiniteParams = [0], 'body' | 'hea return params as unknown as typeof page; }; +export const getEventListInfiniteQueryKey = (options: Options): QueryKey> => createQueryKey('getEventList', options, true); + +/** + * List Events + * + * Fetches a list of events with support for pagination via limit and offset. Data is retrieved directly from the database for consistency. + */ +export const getEventListInfiniteOptions = (options: Options) => infiniteQueryOptions, QueryKey>, number | Pick>[0], 'body' | 'headers' | 'path' | 'query'>>( +// @ts-ignore +{ + queryFn: async ({ pageParam, queryKey, signal }) => { + // @ts-ignore + const page: Pick>[0], 'body' | 'headers' | 'path' | 'query'> = typeof pageParam === 'object' ? pageParam : { + query: { + offset: pageParam + } + }; + const params = createInfiniteParams(queryKey, page); + const { data } = await getEventList({ + ...options, + ...params, + signal, + throwOnError: true + }); + return data; + }, + queryKey: getEventListInfiniteQueryKey(options) +}); + +/** + * Query KYC Status + * + * Checks the current state of a KYC session and updates local database if approved. + */ +export const postKycQueryMutation = (options?: Partial>): UseMutationOptions> => { + const mutationOptions: UseMutationOptions> = { + mutationFn: async (fnOptions) => { + const { data } = await postKycQuery({ + ...options, + ...fnOptions, + throwOnError: true + }); + return data; + } + }; + return mutationOptions; +}; + +/** + * Create KYC Session + * + * Initializes a KYC process (CNRid or Passport) and returns the status or redirect URI. + */ +export const postKycSessionMutation = (options?: Partial>): UseMutationOptions> => { + const mutationOptions: UseMutationOptions> = { + mutationFn: async (fnOptions) => { + const { data } = await postKycSession({ + ...options, + ...fnOptions, + throwOnError: true + }); + return data; + } + }; + return mutationOptions; +}; + +export const getUserInfoQueryKey = (options: Options) => createQueryKey('getUserInfo', options); + +/** + * Get My User Information + * + * Fetches the complete profile data for the user associated with the provided session/token. + */ +export const getUserInfoOptions = (options: Options) => queryOptions>({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await getUserInfo({ + ...options, + ...queryKey[0], + signal, + throwOnError: true + }); + return data; + }, + queryKey: getUserInfoQueryKey(options) +}); + +export const getUserInfoByUserIdQueryKey = (options: Options) => createQueryKey('getUserInfoByUserId', options); + +/** + * Get Other User Information + * + * Fetches the complete profile data for the user associated with the provided session/token. + */ +export const getUserInfoByUserIdOptions = (options: Options) => queryOptions>({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await getUserInfoByUserId({ + ...options, + ...queryKey[0], + signal, + throwOnError: true + }); + return data; + }, + queryKey: getUserInfoByUserIdQueryKey(options) +}); + +export const getUserListQueryKey = (options: Options) => createQueryKey('getUserList', options); + +/** + * List Users + * + * Fetches a list of users with support for pagination via limit and offset. Data is sourced from the search engine for high performance. + */ +export const getUserListOptions = (options: Options) => queryOptions>({ + queryFn: async ({ queryKey, signal }) => { + const { data } = await getUserList({ + ...options, + ...queryKey[0], + signal, + throwOnError: true + }); + return data; + }, + queryKey: getUserListQueryKey(options) +}); + export const getUserListInfiniteQueryKey = (options: Options): QueryKey> => createQueryKey('getUserList', options, true); /** diff --git a/client/cms/src/client/index.ts b/client/cms/src/client/index.ts index e4e494e..0b14418 100644 --- a/client/cms/src/client/index.ts +++ b/client/cms/src/client/index.ts @@ -1,4 +1,4 @@ // This file is auto-generated by @hey-api/openapi-ts -export { getAuthRedirect, getEventCheckin, getEventCheckinQuery, getEventInfo, getUserFull, getUserInfo, getUserList, type Options, patchUserUpdate, postAuthExchange, postAuthMagic, postAuthRefresh, postAuthToken, postEventCheckinSubmit } from './sdk.gen'; -export type { ClientOptions, DataUser, DataUserSearchDoc, GetAuthRedirectData, GetAuthRedirectError, GetAuthRedirectErrors, GetEventCheckinData, GetEventCheckinError, GetEventCheckinErrors, GetEventCheckinQueryData, GetEventCheckinQueryError, GetEventCheckinQueryErrors, GetEventCheckinQueryResponse, GetEventCheckinQueryResponses, GetEventCheckinResponse, GetEventCheckinResponses, GetEventInfoData, GetEventInfoError, GetEventInfoErrors, GetEventInfoResponse, GetEventInfoResponses, GetUserFullData, GetUserFullError, GetUserFullErrors, GetUserFullResponse, GetUserFullResponses, GetUserInfoData, GetUserInfoError, GetUserInfoErrors, GetUserInfoResponse, GetUserInfoResponses, GetUserListData, GetUserListError, GetUserListErrors, GetUserListResponse, GetUserListResponses, PatchUserUpdateData, PatchUserUpdateError, PatchUserUpdateErrors, PatchUserUpdateResponse, PatchUserUpdateResponses, PostAuthExchangeData, PostAuthExchangeError, PostAuthExchangeErrors, PostAuthExchangeResponse, PostAuthExchangeResponses, PostAuthMagicData, PostAuthMagicError, PostAuthMagicErrors, PostAuthMagicResponse, PostAuthMagicResponses, PostAuthRefreshData, PostAuthRefreshError, PostAuthRefreshErrors, PostAuthRefreshResponse, PostAuthRefreshResponses, PostAuthTokenData, PostAuthTokenError, PostAuthTokenErrors, PostAuthTokenResponse, PostAuthTokenResponses, PostEventCheckinSubmitData, PostEventCheckinSubmitError, PostEventCheckinSubmitErrors, PostEventCheckinSubmitResponse, PostEventCheckinSubmitResponses, ServiceAuthExchangeData, ServiceAuthExchangeResponse, ServiceAuthMagicData, ServiceAuthMagicResponse, ServiceAuthRefreshData, ServiceAuthTokenData, ServiceAuthTokenResponse, ServiceEventCheckinQueryResponse, ServiceEventCheckinResponse, ServiceEventCheckinSubmitData, ServiceEventInfoResponse, ServiceUserUserInfoData, ServiceUserUserTableResponse, UtilsRespStatus } from './types.gen'; +export { getAuthRedirect, getEventAttendance, getEventCheckin, getEventCheckinQuery, getEventInfo, getEventList, getUserInfo, getUserInfoByUserId, getUserList, type Options, patchUserUpdate, postAuthExchange, postAuthMagic, postAuthRefresh, postAuthToken, postEventCheckinSubmit, postEventJoin, postKycQuery, postKycSession } from './sdk.gen'; +export type { ClientOptions, DataEventIndexDoc, DataUserIndexDoc, GetAuthRedirectData, GetAuthRedirectError, GetAuthRedirectErrors, GetEventAttendanceData, GetEventAttendanceError, GetEventAttendanceErrors, GetEventAttendanceResponse, GetEventAttendanceResponses, GetEventCheckinData, GetEventCheckinError, GetEventCheckinErrors, GetEventCheckinQueryData, GetEventCheckinQueryError, GetEventCheckinQueryErrors, GetEventCheckinQueryResponse, GetEventCheckinQueryResponses, GetEventCheckinResponse, GetEventCheckinResponses, GetEventInfoData, GetEventInfoError, GetEventInfoErrors, GetEventInfoResponse, GetEventInfoResponses, GetEventListData, GetEventListError, GetEventListErrors, GetEventListResponse, GetEventListResponses, GetUserInfoByUserIdData, GetUserInfoByUserIdError, GetUserInfoByUserIdErrors, GetUserInfoByUserIdResponse, GetUserInfoByUserIdResponses, GetUserInfoData, GetUserInfoError, GetUserInfoErrors, GetUserInfoResponse, GetUserInfoResponses, GetUserListData, GetUserListError, GetUserListErrors, GetUserListResponse, GetUserListResponses, PatchUserUpdateData, PatchUserUpdateError, PatchUserUpdateErrors, PatchUserUpdateResponse, PatchUserUpdateResponses, PostAuthExchangeData, PostAuthExchangeError, PostAuthExchangeErrors, PostAuthExchangeResponse, PostAuthExchangeResponses, PostAuthMagicData, PostAuthMagicError, PostAuthMagicErrors, PostAuthMagicResponse, PostAuthMagicResponses, PostAuthRefreshData, PostAuthRefreshError, PostAuthRefreshErrors, PostAuthRefreshResponse, PostAuthRefreshResponses, PostAuthTokenData, PostAuthTokenError, PostAuthTokenErrors, PostAuthTokenResponse, PostAuthTokenResponses, PostEventCheckinSubmitData, PostEventCheckinSubmitError, PostEventCheckinSubmitErrors, PostEventCheckinSubmitResponse, PostEventCheckinSubmitResponses, PostEventJoinData, PostEventJoinError, PostEventJoinErrors, PostEventJoinResponse, PostEventJoinResponses, PostKycQueryData, PostKycQueryError, PostKycQueryErrors, PostKycQueryResponse, PostKycQueryResponses, PostKycSessionData, PostKycSessionError, PostKycSessionErrors, PostKycSessionResponse, PostKycSessionResponses, ServiceAuthExchangeData, ServiceAuthExchangeResponse, ServiceAuthMagicData, ServiceAuthMagicResponse, ServiceAuthRefreshData, ServiceAuthTokenData, ServiceAuthTokenResponse, ServiceEventAttendanceListResponse, ServiceEventCheckinQueryResponse, ServiceEventCheckinResponse, ServiceEventCheckinSubmitData, ServiceEventEventJoinData, ServiceKycKycQueryData, ServiceKycKycQueryResponse, ServiceKycKycSessionData, ServiceKycKycSessionResponse, ServiceUserUserInfoData, UtilsRespStatus } from './types.gen'; diff --git a/client/cms/src/client/sdk.gen.ts b/client/cms/src/client/sdk.gen.ts index d9d3e85..ae9f15d 100644 --- a/client/cms/src/client/sdk.gen.ts +++ b/client/cms/src/client/sdk.gen.ts @@ -2,7 +2,7 @@ import type { Client, Options as Options2, TDataShape } from './client'; import { client } from './client.gen'; -import type { GetAuthRedirectData, GetAuthRedirectErrors, GetEventCheckinData, GetEventCheckinErrors, GetEventCheckinQueryData, GetEventCheckinQueryErrors, GetEventCheckinQueryResponses, GetEventCheckinResponses, GetEventInfoData, GetEventInfoErrors, GetEventInfoResponses, GetUserFullData, GetUserFullErrors, GetUserFullResponses, GetUserInfoData, GetUserInfoErrors, GetUserInfoResponses, GetUserListData, GetUserListErrors, GetUserListResponses, PatchUserUpdateData, PatchUserUpdateErrors, PatchUserUpdateResponses, PostAuthExchangeData, PostAuthExchangeErrors, PostAuthExchangeResponses, PostAuthMagicData, PostAuthMagicErrors, PostAuthMagicResponses, PostAuthRefreshData, PostAuthRefreshErrors, PostAuthRefreshResponses, PostAuthTokenData, PostAuthTokenErrors, PostAuthTokenResponses, PostEventCheckinSubmitData, PostEventCheckinSubmitErrors, PostEventCheckinSubmitResponses } from './types.gen'; +import type { GetAuthRedirectData, GetAuthRedirectErrors, GetEventAttendanceData, GetEventAttendanceErrors, GetEventAttendanceResponses, GetEventCheckinData, GetEventCheckinErrors, GetEventCheckinQueryData, GetEventCheckinQueryErrors, GetEventCheckinQueryResponses, GetEventCheckinResponses, GetEventInfoData, GetEventInfoErrors, GetEventInfoResponses, GetEventListData, GetEventListErrors, GetEventListResponses, GetUserInfoByUserIdData, GetUserInfoByUserIdErrors, GetUserInfoByUserIdResponses, GetUserInfoData, GetUserInfoErrors, GetUserInfoResponses, GetUserListData, GetUserListErrors, GetUserListResponses, PatchUserUpdateData, PatchUserUpdateErrors, PatchUserUpdateResponses, PostAuthExchangeData, PostAuthExchangeErrors, PostAuthExchangeResponses, PostAuthMagicData, PostAuthMagicErrors, PostAuthMagicResponses, PostAuthRefreshData, PostAuthRefreshErrors, PostAuthRefreshResponses, PostAuthTokenData, PostAuthTokenErrors, PostAuthTokenResponses, PostEventCheckinSubmitData, PostEventCheckinSubmitErrors, PostEventCheckinSubmitResponses, PostEventJoinData, PostEventJoinErrors, PostEventJoinResponses, PostKycQueryData, PostKycQueryErrors, PostKycQueryResponses, PostKycSessionData, PostKycSessionErrors, PostKycSessionResponses } from './types.gen'; export type Options = Options2 & { /** @@ -81,6 +81,13 @@ export const postAuthToken = (options: Opt } }); +/** + * Get Attendance List + * + * Retrieves the list of attendees, including user info and decrypted KYC data for a specified event. + */ +export const getEventAttendance = (options: Options) => (options.client ?? client).get({ url: '/event/attendance', ...options }); + /** * Generate Check-in Code * @@ -117,18 +124,67 @@ export const postEventCheckinSubmit = (opt export const getEventInfo = (options: Options) => (options.client ?? client).get({ url: '/event/info', ...options }); /** - * Get Full User Table + * Join an Event * - * Fetches all user records without pagination. This is typically used for administrative overview or data export. + * Allows an authenticated user to join an event by providing the event ID. The user's role and state are initialized by the service. */ -export const getUserFull = (options?: Options) => (options?.client ?? client).get({ url: '/user/full', ...options }); +export const postEventJoin = (options: Options) => (options.client ?? client).post({ + url: '/event/join', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } +}); + +/** + * List Events + * + * Fetches a list of events with support for pagination via limit and offset. Data is retrieved directly from the database for consistency. + */ +export const getEventList = (options: Options) => (options.client ?? client).get({ url: '/event/list', ...options }); + +/** + * Query KYC Status + * + * Checks the current state of a KYC session and updates local database if approved. + */ +export const postKycQuery = (options: Options) => (options.client ?? client).post({ + url: '/kyc/query', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } +}); + +/** + * Create KYC Session + * + * Initializes a KYC process (CNRid or Passport) and returns the status or redirect URI. + */ +export const postKycSession = (options: Options) => (options.client ?? client).post({ + url: '/kyc/session', + ...options, + headers: { + 'Content-Type': 'application/json', + ...options.headers + } +}); /** * Get My User Information * * Fetches the complete profile data for the user associated with the provided session/token. */ -export const getUserInfo = (options?: Options) => (options?.client ?? client).get({ url: '/user/info', ...options }); +export const getUserInfo = (options: Options) => (options.client ?? client).get({ url: '/user/info', ...options }); + +/** + * Get Other User Information + * + * Fetches the complete profile data for the user associated with the provided session/token. + */ +export const getUserInfoByUserId = (options: Options) => (options.client ?? client).get({ url: '/user/info/{user_id}', ...options }); /** * List Users diff --git a/client/cms/src/client/types.gen.ts b/client/cms/src/client/types.gen.ts index 4e66492..379bdc7 100644 --- a/client/cms/src/client/types.gen.ts +++ b/client/cms/src/client/types.gen.ts @@ -4,21 +4,21 @@ export type ClientOptions = { baseUrl: 'http://localhost:8000/api/v1' | 'https://localhost:8000/api/v1' | (string & {}); }; -export type DataUser = { - allow_public?: boolean; - avatar?: string; - bio?: string; - email?: string; - id?: number; - nickname?: string; - permission_level?: number; - subtitle?: string; - user_id?: string; - username?: string; - uuid?: string; +export type DataEventIndexDoc = { + checkin_count?: number; + description?: string; + enable_kyc?: boolean; + end_time?: string; + event_id?: string; + is_joined?: boolean; + join_count?: number; + name?: string; + start_time?: string; + thumbnail?: string; + type?: string; }; -export type DataUserSearchDoc = { +export type DataUserIndexDoc = { avatar?: string; email?: string; nickname?: string; @@ -64,6 +64,13 @@ export type ServiceAuthTokenResponse = { refresh_token?: string; }; +export type ServiceEventAttendanceListResponse = { + attendance_id?: string; + kyc_info?: unknown; + kyc_type?: string; + user_info?: ServiceUserUserInfoData; +}; + export type ServiceEventCheckinQueryResponse = { checkin_at?: string; }; @@ -76,10 +83,40 @@ export type ServiceEventCheckinSubmitData = { checkin_code?: string; }; -export type ServiceEventInfoResponse = { - end_time?: string; - name?: string; - start_time?: string; +export type ServiceEventEventJoinData = { + event_id?: string; + kyc_id?: string; +}; + +export type ServiceKycKycQueryData = { + kyc_id?: string; +}; + +export type ServiceKycKycQueryResponse = { + /** + * success | pending | failed + */ + status?: string; +}; + +export type ServiceKycKycSessionData = { + /** + * base64 json + */ + identity?: string; + /** + * cnrid | passport + */ + type?: string; +}; + +export type ServiceKycKycSessionResponse = { + kyc_id?: string; + redirect_uri?: string; + /** + * success | processing + */ + status?: string; }; export type ServiceUserUserInfoData = { @@ -94,10 +131,6 @@ export type ServiceUserUserInfoData = { username?: string; }; -export type ServiceUserUserTableResponse = { - user_table?: Array; -}; - export type UtilsRespStatus = { code?: number; data?: unknown; @@ -110,6 +143,12 @@ export type PostAuthExchangeData = { * Exchange Request Credentials */ body: ServiceAuthExchangeData; + headers: { + /** + * latest + */ + 'X-Api-Version': string; + }; path?: never; query?: never; url: '/auth/exchange'; @@ -160,6 +199,12 @@ export type PostAuthMagicData = { * Magic Link Request Data */ body: ServiceAuthMagicData; + headers: { + /** + * latest + */ + 'X-Api-Version': string; + }; path?: never; query?: never; url: '/auth/magic'; @@ -263,6 +308,12 @@ export type PostAuthRefreshData = { * Refresh Token Body */ body: ServiceAuthRefreshData; + headers: { + /** + * latest + */ + 'X-Api-Version': string; + }; path?: never; query?: never; url: '/auth/refresh'; @@ -313,6 +364,12 @@ export type PostAuthTokenData = { * Token Request Body */ body: ServiceAuthTokenData; + headers: { + /** + * latest + */ + 'X-Api-Version': string; + }; path?: never; query?: never; url: '/auth/token'; @@ -358,8 +415,72 @@ export type PostAuthTokenResponses = { export type PostAuthTokenResponse = PostAuthTokenResponses[keyof PostAuthTokenResponses]; +export type GetEventAttendanceData = { + body?: never; + headers: { + /** + * latest + */ + 'X-Api-Version': string; + }; + path?: never; + query: { + /** + * Event UUID + */ + event_id: string; + }; + url: '/event/attendance'; +}; + +export type GetEventAttendanceErrors = { + /** + * Invalid Input + */ + 400: UtilsRespStatus & { + data?: { + [key: string]: unknown; + }; + }; + /** + * Unauthorized + */ + 401: UtilsRespStatus & { + data?: { + [key: string]: unknown; + }; + }; + /** + * Internal Server Error + */ + 500: UtilsRespStatus & { + data?: { + [key: string]: unknown; + }; + }; +}; + +export type GetEventAttendanceError = GetEventAttendanceErrors[keyof GetEventAttendanceErrors]; + +export type GetEventAttendanceResponses = { + /** + * Successful retrieval + */ + 200: UtilsRespStatus & { + data?: Array; + }; +}; + +export type GetEventAttendanceResponse = GetEventAttendanceResponses[keyof GetEventAttendanceResponses]; + export type GetEventCheckinData = { body?: never; + headers: { + /** + * latest + */ + 'X-Api-Version': string; + }; path?: never; query: { /** @@ -379,6 +500,14 @@ export type GetEventCheckinErrors = { [key: string]: unknown; }; }; + /** + * Missing User ID / Unauthorized + */ + 401: UtilsRespStatus & { + data?: { + [key: string]: unknown; + }; + }; /** * Internal Server Error */ @@ -484,6 +613,12 @@ export type PostEventCheckinSubmitResponse = PostEventCheckinSubmitResponses[key export type GetEventInfoData = { body?: never; + headers: { + /** + * latest + */ + 'X-Api-Version': string; + }; path?: never; query: { /** @@ -503,6 +638,14 @@ export type GetEventInfoErrors = { [key: string]: unknown; }; }; + /** + * Missing User ID / Unauthorized + */ + 401: UtilsRespStatus & { + data?: { + [key: string]: unknown; + }; + }; /** * Event Not Found */ @@ -528,22 +671,55 @@ export type GetEventInfoResponses = { * Successful retrieval */ 200: UtilsRespStatus & { - data?: ServiceEventInfoResponse; + data?: DataEventIndexDoc; }; }; export type GetEventInfoResponse = GetEventInfoResponses[keyof GetEventInfoResponses]; -export type GetUserFullData = { - body?: never; +export type PostEventJoinData = { + /** + * Event Join Details (UserId and EventId are required) + */ + body: ServiceEventEventJoinData; + headers: { + /** + * latest + */ + 'X-Api-Version': string; + }; path?: never; query?: never; - url: '/user/full'; + url: '/event/join'; }; -export type GetUserFullErrors = { +export type PostEventJoinErrors = { /** - * Internal Server Error (Database Error) + * Invalid Input or UUID Parse Failed + */ + 400: UtilsRespStatus & { + data?: { + [key: string]: unknown; + }; + }; + /** + * Missing User ID / Unauthorized + */ + 401: UtilsRespStatus & { + data?: { + [key: string]: unknown; + }; + }; + /** + * Unauthorized / Missing User ID / Event Limit Exceeded + */ + 403: UtilsRespStatus & { + data?: { + [key: string]: unknown; + }; + }; + /** + * Internal Server Error / Database Error */ 500: UtilsRespStatus & { data?: { @@ -552,21 +728,203 @@ export type GetUserFullErrors = { }; }; -export type GetUserFullError = GetUserFullErrors[keyof GetUserFullErrors]; +export type PostEventJoinError = PostEventJoinErrors[keyof PostEventJoinErrors]; -export type GetUserFullResponses = { +export type PostEventJoinResponses = { /** - * Successful retrieval of full user table + * Successfully joined the event */ 200: UtilsRespStatus & { - data?: ServiceUserUserTableResponse; + data?: { + [key: string]: unknown; + }; }; }; -export type GetUserFullResponse = GetUserFullResponses[keyof GetUserFullResponses]; +export type PostEventJoinResponse = PostEventJoinResponses[keyof PostEventJoinResponses]; + +export type GetEventListData = { + body?: never; + headers: { + /** + * latest + */ + 'X-Api-Version': string; + }; + path?: never; + query?: { + /** + * Maximum number of events to return (default 20) + */ + limit?: number; + /** + * Number of events to skip + */ + offset?: number; + }; + url: '/event/list'; +}; + +export type GetEventListErrors = { + /** + * Invalid Input (Missing offset or malformed parameters) + */ + 400: UtilsRespStatus & { + data?: { + [key: string]: unknown; + }; + }; + /** + * Missing User ID / Unauthorized + */ + 401: UtilsRespStatus & { + data?: { + [key: string]: unknown; + }; + }; + /** + * Internal Server Error (Database query failed) + */ + 500: UtilsRespStatus & { + data?: { + [key: string]: unknown; + }; + }; +}; + +export type GetEventListError = GetEventListErrors[keyof GetEventListErrors]; + +export type GetEventListResponses = { + /** + * Successful paginated list retrieval + */ + 200: UtilsRespStatus & { + data?: Array; + }; +}; + +export type GetEventListResponse = GetEventListResponses[keyof GetEventListResponses]; + +export type PostKycQueryData = { + /** + * KYC query data (KycId) + */ + body: ServiceKycKycQueryData; + headers: { + /** + * latest + */ + 'X-Api-Version': string; + }; + path?: never; + query?: never; + url: '/kyc/query'; +}; + +export type PostKycQueryErrors = { + /** + * Invalid UUID or input + */ + 400: UtilsRespStatus & { + data?: { + [key: string]: unknown; + }; + }; + /** + * Unauthorized + */ + 403: UtilsRespStatus & { + data?: { + [key: string]: unknown; + }; + }; + /** + * Internal Server Error + */ + 500: UtilsRespStatus & { + data?: { + [key: string]: unknown; + }; + }; +}; + +export type PostKycQueryError = PostKycQueryErrors[keyof PostKycQueryErrors]; + +export type PostKycQueryResponses = { + /** + * Query processed (success/pending/failed) + */ + 200: UtilsRespStatus & { + data?: ServiceKycKycQueryResponse; + }; +}; + +export type PostKycQueryResponse = PostKycQueryResponses[keyof PostKycQueryResponses]; + +export type PostKycSessionData = { + /** + * KYC session data (Type and Base64 Identity) + */ + body: ServiceKycKycSessionData; + headers: { + /** + * latest + */ + 'X-Api-Version': string; + }; + path?: never; + query?: never; + url: '/kyc/session'; +}; + +export type PostKycSessionErrors = { + /** + * Invalid input or decode failed + */ + 400: UtilsRespStatus & { + data?: { + [key: string]: unknown; + }; + }; + /** + * Missing User ID + */ + 403: UtilsRespStatus & { + data?: { + [key: string]: unknown; + }; + }; + /** + * Internal Server Error / KYC Service Error + */ + 500: UtilsRespStatus & { + data?: { + [key: string]: unknown; + }; + }; +}; + +export type PostKycSessionError = PostKycSessionErrors[keyof PostKycSessionErrors]; + +export type PostKycSessionResponses = { + /** + * Session created successfully + */ + 200: UtilsRespStatus & { + data?: ServiceKycKycSessionResponse; + }; +}; + +export type PostKycSessionResponse = PostKycSessionResponses[keyof PostKycSessionResponses]; export type GetUserInfoData = { body?: never; + headers: { + /** + * latest + */ + 'X-Api-Version': string; + }; path?: never; query?: never; url: '/user/info'; @@ -576,7 +934,7 @@ export type GetUserInfoErrors = { /** * Missing User ID / Unauthorized */ - 403: UtilsRespStatus & { + 401: UtilsRespStatus & { data?: { [key: string]: unknown; }; @@ -612,8 +970,80 @@ export type GetUserInfoResponses = { export type GetUserInfoResponse = GetUserInfoResponses[keyof GetUserInfoResponses]; +export type GetUserInfoByUserIdData = { + body?: never; + headers: { + /** + * latest + */ + 'X-Api-Version': string; + }; + path: { + /** + * Other user id + */ + user_id: string; + }; + query?: never; + url: '/user/info/{user_id}'; +}; + +export type GetUserInfoByUserIdErrors = { + /** + * Missing User ID / Unauthorized + */ + 401: UtilsRespStatus & { + data?: { + [key: string]: unknown; + }; + }; + /** + * User Not Public + */ + 403: UtilsRespStatus & { + data?: { + [key: string]: unknown; + }; + }; + /** + * User Not Found + */ + 404: UtilsRespStatus & { + data?: { + [key: string]: unknown; + }; + }; + /** + * Internal Server Error (UUID Parse Failed) + */ + 500: UtilsRespStatus & { + data?: { + [key: string]: unknown; + }; + }; +}; + +export type GetUserInfoByUserIdError = GetUserInfoByUserIdErrors[keyof GetUserInfoByUserIdErrors]; + +export type GetUserInfoByUserIdResponses = { + /** + * Successful profile retrieval + */ + 200: UtilsRespStatus & { + data?: ServiceUserUserInfoData; + }; +}; + +export type GetUserInfoByUserIdResponse = GetUserInfoByUserIdResponses[keyof GetUserInfoByUserIdResponses]; + export type GetUserListData = { body?: never; + headers: { + /** + * latest + */ + 'X-Api-Version': string; + }; path?: never; query: { /** @@ -637,6 +1067,14 @@ export type GetUserListErrors = { [key: string]: unknown; }; }; + /** + * Missing User ID / Unauthorized + */ + 401: UtilsRespStatus & { + data?: { + [key: string]: unknown; + }; + }; /** * Internal Server Error (Search Engine or Missing Offset) */ @@ -654,7 +1092,7 @@ export type GetUserListResponses = { * Successful paginated list retrieval */ 200: UtilsRespStatus & { - data?: Array; + data?: Array; }; }; @@ -665,6 +1103,12 @@ export type PatchUserUpdateData = { * Updated User Profile Data */ body: ServiceUserUserInfoData; + headers: { + /** + * latest + */ + 'X-Api-Version': string; + }; path?: never; query?: never; url: '/user/update'; @@ -682,7 +1126,7 @@ export type PatchUserUpdateErrors = { /** * Missing User ID / Unauthorized */ - 403: UtilsRespStatus & { + 401: UtilsRespStatus & { data?: { [key: string]: unknown; }; diff --git a/client/cms/src/client/zod.gen.ts b/client/cms/src/client/zod.gen.ts index efd557b..3303d44 100644 --- a/client/cms/src/client/zod.gen.ts +++ b/client/cms/src/client/zod.gen.ts @@ -2,175 +2,229 @@ import { z } from 'zod'; -export const zDataUser = z.object({ - allow_public: z.optional(z.boolean()), - avatar: z.optional(z.string()), - bio: z.optional(z.string()), - email: z.optional(z.string()), - id: z.optional(z.int()), - nickname: z.optional(z.string()), - permission_level: z.optional(z.int()), - subtitle: z.optional(z.string()), - user_id: z.optional(z.string()), - username: z.optional(z.string()), - uuid: z.optional(z.string()) +export const zDataEventIndexDoc = z.object({ + checkin_count: z.number().int().optional(), + description: z.string().optional(), + enable_kyc: z.boolean().optional(), + end_time: z.string().optional(), + event_id: z.string().optional(), + is_joined: z.boolean().optional(), + join_count: z.number().int().optional(), + name: z.string().optional(), + start_time: z.string().optional(), + thumbnail: z.string().optional(), + type: z.string().optional() }); -export const zDataUserSearchDoc = z.object({ - avatar: z.optional(z.string()), - email: z.optional(z.string()), - nickname: z.optional(z.string()), - subtitle: z.optional(z.string()), - type: z.optional(z.string()), - user_id: z.optional(z.string()), - username: z.optional(z.string()) +export const zDataUserIndexDoc = z.object({ + avatar: z.string().optional(), + email: z.string().optional(), + nickname: z.string().optional(), + subtitle: z.string().optional(), + type: z.string().optional(), + user_id: z.string().optional(), + username: z.string().optional() }); export const zServiceAuthExchangeData = z.object({ - client_id: z.optional(z.string()), - redirect_uri: z.optional(z.string()), - state: z.optional(z.string()) + client_id: z.string().optional(), + redirect_uri: z.string().optional(), + state: z.string().optional() }); export const zServiceAuthExchangeResponse = z.object({ - redirect_uri: z.optional(z.string()) + redirect_uri: z.string().optional() }); export const zServiceAuthMagicData = z.object({ - client_id: z.optional(z.string()), - client_ip: z.optional(z.string()), - email: z.optional(z.string()), - redirect_uri: z.optional(z.string()), - state: z.optional(z.string()), - turnstile_token: z.optional(z.string()) + client_id: z.string().optional(), + client_ip: z.string().optional(), + email: z.string().optional(), + redirect_uri: z.string().optional(), + state: z.string().optional(), + turnstile_token: z.string().optional() }); export const zServiceAuthMagicResponse = z.object({ - uri: z.optional(z.string()) + uri: z.string().optional() }); export const zServiceAuthRefreshData = z.object({ - refresh_token: z.optional(z.string()) + refresh_token: z.string().optional() }); export const zServiceAuthTokenData = z.object({ - code: z.optional(z.string()) + code: z.string().optional() }); export const zServiceAuthTokenResponse = z.object({ - access_token: z.optional(z.string()), - refresh_token: z.optional(z.string()) + access_token: z.string().optional(), + refresh_token: z.string().optional() }); export const zServiceEventCheckinQueryResponse = z.object({ - checkin_at: z.optional(z.string()) + checkin_at: z.string().optional() }); export const zServiceEventCheckinResponse = z.object({ - checkin_code: z.optional(z.string()) + checkin_code: z.string().optional() }); export const zServiceEventCheckinSubmitData = z.object({ - checkin_code: z.optional(z.string()) + checkin_code: z.string().optional() }); -export const zServiceEventInfoResponse = z.object({ - end_time: z.optional(z.string()), - name: z.optional(z.string()), - start_time: z.optional(z.string()) +export const zServiceEventEventJoinData = z.object({ + event_id: z.string().optional(), + kyc_id: z.string().optional() +}); + +export const zServiceKycKycQueryData = z.object({ + kyc_id: z.string().optional() +}); + +export const zServiceKycKycQueryResponse = z.object({ + status: z.string().optional() +}); + +export const zServiceKycKycSessionData = z.object({ + identity: z.string().optional(), + type: z.string().optional() +}); + +export const zServiceKycKycSessionResponse = z.object({ + kyc_id: z.string().optional(), + redirect_uri: z.string().optional(), + status: z.string().optional() }); export const zServiceUserUserInfoData = z.object({ - allow_public: z.optional(z.boolean()), - avatar: z.optional(z.string()), - bio: z.optional(z.string()), - email: z.optional(z.string()), - nickname: z.optional(z.string()), - permission_level: z.optional(z.int()), - subtitle: z.optional(z.string()), - user_id: z.optional(z.string()), - username: z.optional(z.string()) + allow_public: z.boolean().optional(), + avatar: z.string().optional(), + bio: z.string().optional(), + email: z.string().optional(), + nickname: z.string().optional(), + permission_level: z.number().int().optional(), + subtitle: z.string().optional(), + user_id: z.string().optional(), + username: z.string().optional() }); -export const zServiceUserUserTableResponse = z.object({ - user_table: z.optional(z.array(zDataUser)) +export const zServiceEventAttendanceListResponse = z.object({ + attendance_id: z.string().optional(), + kyc_info: z.unknown().optional(), + kyc_type: z.string().optional(), + user_info: zServiceUserUserInfoData.optional() }); export const zUtilsRespStatus = z.object({ - code: z.optional(z.int()), - data: z.optional(z.unknown()), - error_id: z.optional(z.string()), - status: z.optional(z.string()) + code: z.number().int().optional(), + data: z.unknown().optional(), + error_id: z.string().optional(), + status: z.string().optional() }); export const zPostAuthExchangeData = z.object({ body: zServiceAuthExchangeData, - path: z.optional(z.never()), - query: z.optional(z.never()) + path: z.never().optional(), + query: z.never().optional(), + headers: z.object({ + 'X-Api-Version': z.string() + }) }); /** * Successful exchange */ export const zPostAuthExchangeResponse = zUtilsRespStatus.and(z.object({ - data: z.optional(zServiceAuthExchangeResponse) + data: zServiceAuthExchangeResponse.optional() })); export const zPostAuthMagicData = z.object({ body: zServiceAuthMagicData, - path: z.optional(z.never()), - query: z.optional(z.never()) + path: z.never().optional(), + query: z.never().optional(), + headers: z.object({ + 'X-Api-Version': z.string() + }) }); /** * Successful request */ export const zPostAuthMagicResponse = zUtilsRespStatus.and(z.object({ - data: z.optional(zServiceAuthMagicResponse) + data: zServiceAuthMagicResponse.optional() })); export const zGetAuthRedirectData = z.object({ - body: z.optional(z.never()), - path: z.optional(z.never()), + body: z.never().optional(), + path: z.never().optional(), query: z.object({ client_id: z.string(), redirect_uri: z.string(), code: z.string(), - state: z.optional(z.string()) + state: z.string().optional() }) }); export const zPostAuthRefreshData = z.object({ body: zServiceAuthRefreshData, - path: z.optional(z.never()), - query: z.optional(z.never()) + path: z.never().optional(), + query: z.never().optional(), + headers: z.object({ + 'X-Api-Version': z.string() + }) }); /** * Successful rotation */ export const zPostAuthRefreshResponse = zUtilsRespStatus.and(z.object({ - data: z.optional(zServiceAuthTokenResponse) + data: zServiceAuthTokenResponse.optional() })); export const zPostAuthTokenData = z.object({ body: zServiceAuthTokenData, - path: z.optional(z.never()), - query: z.optional(z.never()) + path: z.never().optional(), + query: z.never().optional(), + headers: z.object({ + 'X-Api-Version': z.string() + }) }); /** * Successful token issuance */ export const zPostAuthTokenResponse = zUtilsRespStatus.and(z.object({ - data: z.optional(zServiceAuthTokenResponse) + data: zServiceAuthTokenResponse.optional() +})); + +export const zGetEventAttendanceData = z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: z.object({ + event_id: z.string() + }), + headers: z.object({ + 'X-Api-Version': z.string() + }) +}); + +/** + * Successful retrieval + */ +export const zGetEventAttendanceResponse = zUtilsRespStatus.and(z.object({ + data: z.array(zServiceEventAttendanceListResponse).optional() })); export const zGetEventCheckinData = z.object({ - body: z.optional(z.never()), - path: z.optional(z.never()), + body: z.never().optional(), + path: z.never().optional(), query: z.object({ event_id: z.string() + }), + headers: z.object({ + 'X-Api-Version': z.string() }) }); @@ -178,12 +232,12 @@ export const zGetEventCheckinData = z.object({ * Successfully generated code */ export const zGetEventCheckinResponse = zUtilsRespStatus.and(z.object({ - data: z.optional(zServiceEventCheckinResponse) + data: zServiceEventCheckinResponse.optional() })); export const zGetEventCheckinQueryData = z.object({ - body: z.optional(z.never()), - path: z.optional(z.never()), + body: z.never().optional(), + path: z.never().optional(), query: z.object({ event_id: z.string() }) @@ -193,27 +247,30 @@ export const zGetEventCheckinQueryData = z.object({ * Current attendance status */ export const zGetEventCheckinQueryResponse = zUtilsRespStatus.and(z.object({ - data: z.optional(zServiceEventCheckinQueryResponse) + data: zServiceEventCheckinQueryResponse.optional() })); export const zPostEventCheckinSubmitData = z.object({ body: zServiceEventCheckinSubmitData, - path: z.optional(z.never()), - query: z.optional(z.never()) + path: z.never().optional(), + query: z.never().optional() }); /** * Attendance marked successfully */ export const zPostEventCheckinSubmitResponse = zUtilsRespStatus.and(z.object({ - data: z.optional(z.record(z.string(), z.unknown())) + data: z.record(z.unknown()).optional() })); export const zGetEventInfoData = z.object({ - body: z.optional(z.never()), - path: z.optional(z.never()), + body: z.never().optional(), + path: z.never().optional(), query: z.object({ event_id: z.string() + }), + headers: z.object({ + 'X-Api-Version': z.string() }) }); @@ -221,41 +278,119 @@ export const zGetEventInfoData = z.object({ * Successful retrieval */ export const zGetEventInfoResponse = zUtilsRespStatus.and(z.object({ - data: z.optional(zServiceEventInfoResponse) + data: zDataEventIndexDoc.optional() })); -export const zGetUserFullData = z.object({ - body: z.optional(z.never()), - path: z.optional(z.never()), - query: z.optional(z.never()) +export const zPostEventJoinData = z.object({ + body: zServiceEventEventJoinData, + path: z.never().optional(), + query: z.never().optional(), + headers: z.object({ + 'X-Api-Version': z.string() + }) }); /** - * Successful retrieval of full user table + * Successfully joined the event */ -export const zGetUserFullResponse = zUtilsRespStatus.and(z.object({ - data: z.optional(zServiceUserUserTableResponse) +export const zPostEventJoinResponse = zUtilsRespStatus.and(z.object({ + data: z.record(z.unknown()).optional() +})); + +export const zGetEventListData = z.object({ + body: z.never().optional(), + path: z.never().optional(), + query: z.object({ + limit: z.number().int().optional(), + offset: z.number().int().optional() + }).optional(), + headers: z.object({ + 'X-Api-Version': z.string() + }) +}); + +/** + * Successful paginated list retrieval + */ +export const zGetEventListResponse = zUtilsRespStatus.and(z.object({ + data: z.array(zDataEventIndexDoc).optional() +})); + +export const zPostKycQueryData = z.object({ + body: zServiceKycKycQueryData, + path: z.never().optional(), + query: z.never().optional(), + headers: z.object({ + 'X-Api-Version': z.string() + }) +}); + +/** + * Query processed (success/pending/failed) + */ +export const zPostKycQueryResponse = zUtilsRespStatus.and(z.object({ + data: zServiceKycKycQueryResponse.optional() +})); + +export const zPostKycSessionData = z.object({ + body: zServiceKycKycSessionData, + path: z.never().optional(), + query: z.never().optional(), + headers: z.object({ + 'X-Api-Version': z.string() + }) +}); + +/** + * Session created successfully + */ +export const zPostKycSessionResponse = zUtilsRespStatus.and(z.object({ + data: zServiceKycKycSessionResponse.optional() })); export const zGetUserInfoData = z.object({ - body: z.optional(z.never()), - path: z.optional(z.never()), - query: z.optional(z.never()) + body: z.never().optional(), + path: z.never().optional(), + query: z.never().optional(), + headers: z.object({ + 'X-Api-Version': z.string() + }) }); /** * Successful profile retrieval */ export const zGetUserInfoResponse = zUtilsRespStatus.and(z.object({ - data: z.optional(zServiceUserUserInfoData) + data: zServiceUserUserInfoData.optional() +})); + +export const zGetUserInfoByUserIdData = z.object({ + body: z.never().optional(), + path: z.object({ + user_id: z.string() + }), + query: z.never().optional(), + headers: z.object({ + 'X-Api-Version': z.string() + }) +}); + +/** + * Successful profile retrieval + */ +export const zGetUserInfoByUserIdResponse = zUtilsRespStatus.and(z.object({ + data: zServiceUserUserInfoData.optional() })); export const zGetUserListData = z.object({ - body: z.optional(z.never()), - path: z.optional(z.never()), + body: z.never().optional(), + path: z.never().optional(), query: z.object({ - limit: z.optional(z.string()), + limit: z.string().optional(), offset: z.string() + }), + headers: z.object({ + 'X-Api-Version': z.string() }) }); @@ -263,18 +398,21 @@ export const zGetUserListData = z.object({ * Successful paginated list retrieval */ export const zGetUserListResponse = zUtilsRespStatus.and(z.object({ - data: z.optional(z.array(zDataUserSearchDoc)) + data: z.array(zDataUserIndexDoc).optional() })); export const zPatchUserUpdateData = z.object({ body: zServiceUserUserInfoData, - path: z.optional(z.never()), - query: z.optional(z.never()) + path: z.never().optional(), + query: z.never().optional(), + headers: z.object({ + 'X-Api-Version': z.string() + }) }); /** * Successful profile update */ export const zPatchUserUpdateResponse = zUtilsRespStatus.and(z.object({ - data: z.optional(z.record(z.string(), z.unknown())) + data: z.record(z.unknown()).optional() })); diff --git a/client/cms/src/components/events/event-card.skeleton.tsx b/client/cms/src/components/events/event-card.skeleton.tsx new file mode 100644 index 0000000..0a874c0 --- /dev/null +++ b/client/cms/src/components/events/event-card.skeleton.tsx @@ -0,0 +1,40 @@ +import { Calendar } from 'lucide-react'; +import { + Card, + CardAction, + CardDescription, + CardFooter, + CardHeader, + CardTitle, +} from '@/components/ui/card'; +import { Badge } from '../ui/badge'; +import { Skeleton } from '../ui/skeleton'; + +export function EventCardSkeleton() { + return ( + +
+ + + + Official + + + + + + + + + + + + + + + + + ); +} diff --git a/client/cms/src/components/events/event-card.view.tsx b/client/cms/src/components/events/event-card.view.tsx new file mode 100644 index 0000000..a065653 --- /dev/null +++ b/client/cms/src/components/events/event-card.view.tsx @@ -0,0 +1,48 @@ +import type { EventInfo } from './types'; +import dayjs from 'dayjs'; +import { Calendar } from 'lucide-react'; +import { Badge } from '@/components/ui/badge'; +import { + Card, + CardAction, + CardDescription, + CardFooter, + CardHeader, + CardTitle, +} from '@/components/ui/card'; +import { Skeleton } from '../ui/skeleton'; + +export function EventCardView({ eventInfo, actionFooter }: { eventInfo: EventInfo; actionFooter: React.ReactNode }) { + const { type, coverImage, eventName, description, startTime, endTime } = eventInfo; + const startDayJs = dayjs(startTime); + const endDayJs = dayjs(endTime); + return ( + +
+ Event cover + + + + {type === 'official' ? Official : Party} + + {eventName} + + + {`${startDayJs.format('YYYY/MM/DD')} - ${endDayJs.format('YYYY/MM/DD')}`} + + + {description} + + + + {actionFooter} + + + ); +} diff --git a/client/cms/src/components/events/event-grid.container.tsx b/client/cms/src/components/events/event-grid.container.tsx new file mode 100644 index 0000000..d442978 --- /dev/null +++ b/client/cms/src/components/events/event-grid.container.tsx @@ -0,0 +1,40 @@ +import type { EventInfo } from './types'; +import PlaceholderImage from '@/assets/event-placeholder.png'; +import { useGetEvents } from '@/hooks/data/useGetEvents'; +import { Button } from '../ui/button'; +import { DialogTrigger } from '../ui/dialog'; +import { EventGridView } from './event-grid.view'; +import { KycDialogContainer } from './kyc/kyc.dialog.container'; + +export function EventGridContainer() { + const { data, isLoading } = useGetEvents(); + const allEvents: EventInfo[] = isLoading + ? [] + : data.pages.flatMap(page => page.data!).map(it => ({ + type: it.type! as EventInfo['type'], + eventId: it.event_id!, + isJoined: it.is_joined!, + requireKyc: it.enable_kyc!, + coverImage: it.thumbnail! || PlaceholderImage, + eventName: it.name!, + description: it.description!, + startTime: new Date(it.start_time!), + endTime: new Date(it.end_time!), + } satisfies EventInfo)); + + return ( + (eventInfo.isJoined + ? + : ( + + + + + + ) + )} + /> + ); +} diff --git a/client/cms/src/components/events/event-grid.skeleton.tsx b/client/cms/src/components/events/event-grid.skeleton.tsx new file mode 100644 index 0000000..7c0046a --- /dev/null +++ b/client/cms/src/components/events/event-grid.skeleton.tsx @@ -0,0 +1,12 @@ +import { EventCardSkeleton } from './event-card.skeleton'; + +export function EventGridSkeleton() { + return ( +
+ {Array.from({ length: 8 }).map((_, i) => ( + // eslint-disable-next-line react/no-array-index-key + + ))} +
+ ); +} diff --git a/client/cms/src/components/events/event-grid.view.tsx b/client/cms/src/components/events/event-grid.view.tsx new file mode 100644 index 0000000..e5186bd --- /dev/null +++ b/client/cms/src/components/events/event-grid.view.tsx @@ -0,0 +1,12 @@ +import type { EventInfo } from './types'; +import { EventCardView } from './event-card.view'; + +export function EventGridView({ events, assembleFooter }: { events: EventInfo[]; assembleFooter: (event: EventInfo) => React.ReactNode }) { + return ( +
+ {events.map(event => ( + + ))} +
+ ); +} diff --git a/client/cms/src/components/events/kyc/kyc-failed.dialog.view.tsx b/client/cms/src/components/events/kyc/kyc-failed.dialog.view.tsx new file mode 100644 index 0000000..768ee0e --- /dev/null +++ b/client/cms/src/components/events/kyc/kyc-failed.dialog.view.tsx @@ -0,0 +1,18 @@ +import { X } from 'lucide-react'; +import { DialogContent, DialogDescription, DialogHeader, DialogTitle } from '../../ui/dialog'; + +export function KycFailedDialogView() { + return ( + + + 失败 + +

提交身份认证失败,请重试。

+
+ +
+
+
+
+ ); +} diff --git a/client/cms/src/components/events/kyc/kyc-method-selection.dialog.view.tsx b/client/cms/src/components/events/kyc/kyc-method-selection.dialog.view.tsx new file mode 100644 index 0000000..238f666 --- /dev/null +++ b/client/cms/src/components/events/kyc/kyc-method-selection.dialog.view.tsx @@ -0,0 +1,177 @@ +import type { KycSubmission } from './kyc.types'; +import { useForm } from '@tanstack/react-form'; +import { useState } from 'react'; +import { toast } from 'sonner'; +import z from 'zod'; +import { + Field, + FieldError, + FieldLabel, +} from '@/components/ui/field'; +import { Input } from '@/components/ui/input'; +import { Label } from '@/components/ui/label'; +import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; +import { Button } from '../../ui/button'; +import { DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '../../ui/dialog'; + +const CnridSchema = z.object({ + cnrid: z.string().min(18, '身份证号应为18位').max(18, '身份证号应为18位'), + name: z.string().min(2, '姓名应至少2个字符').max(10, '姓名应不超过10个字符'), +}); + +function CnridForm({ onSubmit }: { onSubmit: OnSubmit }) { + const form = useForm({ + defaultValues: { + cnrid: '', + name: '', + }, + validators: { + onSubmit: CnridSchema, + }, + onSubmit: async (values) => { + await onSubmit({ + method: 'cnrid', + ...values.value, + }).catch(() => { + toast('认证失败,请稍后再试'); + }); + }, + }); + return ( +
{ + e.preventDefault(); + e.stopPropagation(); + void form.handleSubmit(); + }} + className="flex flex-col gap-4" + > + + {field => ( + + 姓名 + field.handleChange(e.target.value)} + /> + + + )} + + + {field => ( + + 身份证号 + field.handleChange(e.target.value)} + /> + + + )} + + + [state.canSubmit, state.isPristine, state.isSubmitting]} + children={([canSubmit, isPristine, isSubmitting]) => ( + + )} + /> + +
+ ); +} + +const PassportSchema = z.object({ + passportId: z.string().min(9, '护照号应为9个字符').max(9, '护照号应为9个字符'), +}); + +function PassportForm({ onSubmit }: { onSubmit: OnSubmit }) { + const form = useForm({ + defaultValues: { + passportId: '', + }, + validators: { + onSubmit: PassportSchema, + }, + onSubmit: async (values) => { + await onSubmit({ + method: 'passport', + ...values.value, + }).catch(() => { + toast('认证失败,请稍后再试'); + }); + }, + }); + return ( +
{ + e.preventDefault(); + e.stopPropagation(); + void form.handleSubmit(); + }} + className="flex flex-col gap-4" + > + + {field => ( + + 护照号 + field.handleChange(e.target.value)} + /> + + + )} + + + [state.canSubmit, state.isPristine, state.isSubmitting]} + children={([canSubmit, isPristine, isSubmitting]) => ( + + )} + /> + +
+ ); +} + +type OnSubmit = (submission: KycSubmission) => Promise; + +export function KycMethodSelectionDialogView({ onSubmit }: { onSubmit: OnSubmit }) { + const [kycMethod, setKycMethod] = useState(null); + + return ( + + + 选择身份认证模式 + +

我们支持身份证和护照认证。

+
+
+ + + {kycMethod === 'cnrid' && } + {kycMethod === 'passport' && } +
+ ); +} diff --git a/client/cms/src/components/events/kyc/kyc-pending.dialog.view.tsx b/client/cms/src/components/events/kyc/kyc-pending.dialog.view.tsx new file mode 100644 index 0000000..5de1c35 --- /dev/null +++ b/client/cms/src/components/events/kyc/kyc-pending.dialog.view.tsx @@ -0,0 +1,18 @@ +import { HashLoader } from 'react-spinners/esm'; +import { DialogContent, DialogDescription, DialogHeader, DialogTitle } from '../../ui/dialog'; + +export function KycPendingDialogView() { + return ( + + + 等待身份认证结果 + +

认证页面已打开。正在等待认证服务器回传数据...

+
+ +
+
+
+
+ ); +} diff --git a/client/cms/src/components/events/kyc/kyc-prompt.dialog.view.tsx b/client/cms/src/components/events/kyc/kyc-prompt.dialog.view.tsx new file mode 100644 index 0000000..ff604c0 --- /dev/null +++ b/client/cms/src/components/events/kyc/kyc-prompt.dialog.view.tsx @@ -0,0 +1,24 @@ +import { Button } from '../../ui/button'; +import { DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '../../ui/dialog'; + +export function KycPromptDialogView({ next }: { next: () => void }) { + return ( + + + 需要身份认证 + +

为了确保会议的安全性及合规性,我们需要对参会者进行实名认证。

+

您的个人隐私对我们至关重要:

+
    +
  • 数据加密:您的所有个人敏感信息均会通过 AES-256 标准进行强加密存储。
  • +
  • 用途限制:收集的信息仅用于本次活动的身份核实,不会用于任何商业用途。
  • +
  • 按时销毁:所有身份证明文件及关联的敏感原始数据将在活动完成后最多 30 天内从服务器中彻底删除。
  • +
+
+
+ + + +
+ ); +} diff --git a/client/cms/src/components/events/kyc/kyc-success.dialog.view.tsx b/client/cms/src/components/events/kyc/kyc-success.dialog.view.tsx new file mode 100644 index 0000000..867b20a --- /dev/null +++ b/client/cms/src/components/events/kyc/kyc-success.dialog.view.tsx @@ -0,0 +1,18 @@ +import { Check } from 'lucide-react'; +import { DialogContent, DialogDescription, DialogHeader, DialogTitle } from '../../ui/dialog'; + +export function KycSuccessDialogView() { + return ( + + + 成功 + +

已完成身份认证。

+
+ +
+
+
+
+ ); +} diff --git a/client/cms/src/components/events/kyc/kyc.dialog.container.tsx b/client/cms/src/components/events/kyc/kyc.dialog.container.tsx new file mode 100644 index 0000000..ad7953c --- /dev/null +++ b/client/cms/src/components/events/kyc/kyc.dialog.container.tsx @@ -0,0 +1,129 @@ +import type { KycSubmission } from './kyc.types'; +import { Dialog } from '@radix-ui/react-dialog'; +import { useQueryClient } from '@tanstack/react-query'; +import { useCallback, useEffect, useState } from 'react'; +import { useStore } from 'zustand'; +import { postEventJoin, postKycQuery } from '@/client'; +import { getEventListInfiniteQueryKey } from '@/client/@tanstack/react-query.gen'; +import { useCreateKycSession } from '@/hooks/data/useCreateKycSession'; +import { ver } from '@/lib/apiVersion'; +import { KycFailedDialogView } from './kyc-failed.dialog.view'; +import { KycMethodSelectionDialogView } from './kyc-method-selection.dialog.view'; +import { KycPendingDialogView } from './kyc-pending.dialog.view'; +import { KycPromptDialogView } from './kyc-prompt.dialog.view'; +import { KycSuccessDialogView } from './kyc-success.dialog.view'; +import { createKycStore } from './kyc.state'; + +export function KycDialogContainer({ eventIdToJoin, children }: { eventIdToJoin: string; children: React.ReactNode }) { + const [store] = useState(() => createKycStore(eventIdToJoin)); + const isDialogOpen = useStore(store, s => s.isDialogOpen); + const setIsDialogOpen = useStore(store, s => s.setIsDialogOpen); + const stage = useStore(store, s => s.stage); + const setStage = useStore(store, s => s.setStage); + const setKycId = useStore(store, s => s.setKycId); + + const { mutateAsync } = useCreateKycSession(); + const queryClient = useQueryClient(); + + const joinEvent = useCallback(async (eventId: string, kycId: string, abortSignal?: AbortSignal) => { + try { + await postEventJoin({ + signal: abortSignal, + body: { event_id: eventId, kyc_id: kycId }, + headers: ver('20260205'), + }); + setStage('success'); + } + catch (e) { + console.error('Error joining event:', e); + setStage('failed'); + } + }, [setStage]); + + const onKycSessionCreate = useCallback(async (submission: KycSubmission) => { + try { + const { data } = await mutateAsync(submission); + setKycId(data!.kyc_id!); + if (data!.status === 'success') { + await joinEvent(eventIdToJoin, data!.kyc_id!, undefined); + } + else if (data!.status === 'processing') { + window.open(data!.redirect_uri, '_blank'); + setStage('pending'); + } + } + catch (e) { + console.error(e); + setStage('failed'); + } + }, [eventIdToJoin, joinEvent, mutateAsync, setKycId, setStage]); + + useEffect(() => { + if (stage !== 'pending' || !isDialogOpen) { + return; + } + + const controller = new AbortController(); + let timer: NodeJS.Timeout; + + const poll = async () => { + try { + const { data } = await postKycQuery({ + signal: controller.signal, + body: { kyc_id: store.getState().kycId! }, + headers: ver('20260205'), + }); + + const status = data?.data?.status; + + if (status === 'success') { + void joinEvent(eventIdToJoin, store.getState().kycId!, controller.signal); + } + else if (status === 'failed') { + setStage('failed'); + } + else if (status === 'pending') { + timer = setTimeout(() => void poll(), 1000); + } + else { + // What the fuck? + setStage('failed'); + } + } + catch (e) { + if ((e as Error).name === 'AbortError') + return; + console.error('Error fetching KYC status:', e); + setStage('failed'); + } + }; + + void poll(); + + return () => { + controller.abort(); + clearTimeout(timer); + }; + }, [stage, store, setStage, isDialogOpen, joinEvent, eventIdToJoin]); + + return ( + { + if (!open) { + void queryClient.invalidateQueries({ + queryKey: getEventListInfiniteQueryKey({ query: {}, headers: ver('20260205') }), + }); + } + setIsDialogOpen(open); + }} + > + {children} + {stage === 'prompt' && setStage('methodSelection')} />} + {stage === 'methodSelection' && } + {stage === 'pending' && } + {stage === 'success' && } + {stage === 'failed' && } + + ); +} diff --git a/client/cms/src/components/events/kyc/kyc.state.ts b/client/cms/src/components/events/kyc/kyc.state.ts new file mode 100644 index 0000000..34fc1bb --- /dev/null +++ b/client/cms/src/components/events/kyc/kyc.state.ts @@ -0,0 +1,34 @@ +import { createStore } from 'zustand'; +import { devtools } from 'zustand/middleware'; + +interface KycState { + isDialogOpen: boolean; + eventIdToJoin: string; + kycId: string | null; + stage: 'prompt' | 'methodSelection' | 'pending' | 'success' | 'failed'; + + setIsDialogOpen: (open: boolean) => void; + setStage: (stage: KycState['stage']) => void; + setKycId: (kycId: string) => void; +} + +export function createKycStore(eventIdToJoin: string) { + const initialState = { + isDialogOpen: false, + eventIdToJoin, + kycId: null, + stage: 'prompt' as const, + }; + return createStore()(devtools(set => ({ + ...initialState, + setIsDialogOpen: (open: boolean) => set(() => + open + ? { ...initialState, isDialogOpen: true } + : { ...initialState, isDialogOpen: false }, + ), + setStage: (stage: KycState['stage']) => set(() => ({ stage })), + setKycId: (kycId: string) => set(() => ({ kycId })), + }))); +} + +export type KycStore = ReturnType; diff --git a/client/cms/src/components/events/kyc/kyc.types.ts b/client/cms/src/components/events/kyc/kyc.types.ts new file mode 100644 index 0000000..4a9f0a1 --- /dev/null +++ b/client/cms/src/components/events/kyc/kyc.types.ts @@ -0,0 +1,8 @@ +export type KycSubmission = { + method: 'cnrid'; + cnrid: string; + name: string; +} | { + method: 'passport'; + passportId: string; +}; diff --git a/client/cms/src/components/events/types.ts b/client/cms/src/components/events/types.ts new file mode 100644 index 0000000..6564ba3 --- /dev/null +++ b/client/cms/src/components/events/types.ts @@ -0,0 +1,11 @@ +export interface EventInfo { + type: 'official' | 'party'; + eventId: string; + isJoined: boolean; + requireKyc: boolean; + coverImage: string; + eventName: string; + description: string; + startTime: Date; + endTime: Date; +} diff --git a/client/cms/src/components/hoc/with-fallback.tsx b/client/cms/src/components/hoc/with-fallback.tsx deleted file mode 100644 index 5d4c0e6..0000000 --- a/client/cms/src/components/hoc/with-fallback.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import type { ReactNode } from 'react'; -import React, { Suspense } from 'react'; - -export function withFallback

( - Component: React.ComponentType

, - fallback: ReactNode, -) { - const Wrapped: React.FC

= (props) => { - return ( - - - - ); - }; - - Wrapped.displayName = `withFallback(${Component.displayName! || Component.name || 'Component' - })`; - - return Wrapped; -} diff --git a/client/cms/src/components/login-form.tsx b/client/cms/src/components/login-form.tsx index 5447440..68afe8e 100644 --- a/client/cms/src/components/login-form.tsx +++ b/client/cms/src/components/login-form.tsx @@ -13,6 +13,7 @@ import { } from '@/components/ui/field'; import { Input } from '@/components/ui/input'; import { useGetMagicLink } from '@/hooks/data/useGetMagicLink'; +import { ver } from '@/lib/apiVersion'; import { cn } from '@/lib/utils'; export function LoginForm({ @@ -32,7 +33,7 @@ export function LoginForm({ event.preventDefault(); const formData = new FormData(formRef.current!); const email = formData.get('email')! as string; - mutateAsync({ body: { email, turnstile_token: token!, ...oauthParams } }).then(() => { + mutateAsync({ body: { email, turnstile_token: token!, ...oauthParams }, headers: ver('20260205') }).then(() => { void navigate({ to: '/magicLinkSent', search: { email } }); }).catch((error) => { console.error(error); diff --git a/client/cms/src/components/profile/edit-profile.dialog.container.tsx b/client/cms/src/components/profile/edit-profile.dialog.container.tsx new file mode 100644 index 0000000..d8ade1b --- /dev/null +++ b/client/cms/src/components/profile/edit-profile.dialog.container.tsx @@ -0,0 +1,16 @@ +import type { ServiceUserUserInfoData } from '@/client'; +import { useUpdateUser } from '@/hooks/data/useUpdateUser'; +import { ver } from '@/lib/apiVersion'; +import { EditProfileDialogView } from './edit-profile.dialog.view'; + +export function EditProfileDialogContainer({ data }: { data: ServiceUserUserInfoData }) { + const { mutateAsync } = useUpdateUser(); + return ( + { + await mutateAsync({ body: data, headers: ver('20260205') }); + }} + /> + ); +} diff --git a/client/cms/src/components/profile/edit-profile-dialog.tsx b/client/cms/src/components/profile/edit-profile.dialog.view.tsx similarity index 89% rename from client/cms/src/components/profile/edit-profile-dialog.tsx rename to client/cms/src/components/profile/edit-profile.dialog.view.tsx index 47be953..ed4f5dd 100644 --- a/client/cms/src/components/profile/edit-profile-dialog.tsx +++ b/client/cms/src/components/profile/edit-profile.dialog.view.tsx @@ -1,5 +1,9 @@ +import type { ServiceUserUserInfoData } from '@/client'; import { useForm } from '@tanstack/react-form'; -import { useState } from 'react'; +import { + useEffect, + useState, +} from 'react'; import { toast } from 'sonner'; import z from 'zod'; import { Button } from '@/components/ui/button'; @@ -20,22 +24,16 @@ import { import { Input, } from '@/components/ui/input'; -import { useUpdateUser } from '@/hooks/data/useUpdateUser'; -import { useUserInfo } from '@/hooks/data/useUserInfo'; import { Switch } from '../ui/switch'; const formSchema = z.object({ username: z.string().min(5), nickname: z.string(), subtitle: z.string(), - avatar: z.url().or(z.literal('')), + avatar: z.string().url().or(z.literal('')), allow_public: z.boolean(), }); -export function EditProfileDialog() { - const { data } = useUserInfo(); - const user = data.data!; - const { mutateAsync } = useUpdateUser(); - +export function EditProfileDialogView({ user, updateProfile }: { user: ServiceUserUserInfoData; updateProfile: (data: ServiceUserUserInfoData) => Promise }) { const form = useForm({ defaultValues: { avatar: user.avatar, @@ -51,7 +49,7 @@ export function EditProfileDialog() { value, }) => { try { - await mutateAsync({ body: value }); + await updateProfile(value); toast.success('个人资料更新成功'); } catch (error) { @@ -63,11 +61,14 @@ export function EditProfileDialog() { const [open, setOpen] = useState(false); - if (!open) { - setTimeout(() => { - form.reset(); - }, 200); - } + useEffect(() => { + if (!open) { + const id = setTimeout(() => { + form.reset(); + }, 200); + return () => clearTimeout(id); + } + }, [open, form]); return (

@@ -79,7 +80,7 @@ export function EditProfileDialog() { onSubmit={(e) => { e.preventDefault(); e.stopPropagation(); - form.handleSubmit().then(() => setOpen(false)); + void form.handleSubmit().then(() => setOpen(false)); }} className="grid gap-4" > diff --git a/client/cms/src/components/profile/profile.container.tsx b/client/cms/src/components/profile/profile.container.tsx new file mode 100644 index 0000000..38afb2d --- /dev/null +++ b/client/cms/src/components/profile/profile.container.tsx @@ -0,0 +1,18 @@ +import { useUpdateUser } from '@/hooks/data/useUpdateUser'; +import { useOtherUserInfo } from '@/hooks/data/useUserInfo'; +import { ver } from '@/lib/apiVersion'; +import { utf8ToBase64 } from '@/lib/utils'; +import { ProfileView } from './profile.view'; + +export function ProfileContainer({ userId }: { userId: string }) { + const { data } = useOtherUserInfo(userId); + const { mutateAsync } = useUpdateUser(); + return ( + { + await mutateAsync({ body: { bio: utf8ToBase64(bio) }, headers: ver('20260205') }); + }} + /> + ); +} diff --git a/client/cms/src/components/profile/profile.error.tsx b/client/cms/src/components/profile/profile.error.tsx new file mode 100644 index 0000000..2f6f42a --- /dev/null +++ b/client/cms/src/components/profile/profile.error.tsx @@ -0,0 +1,30 @@ +import { Mail } from 'lucide-react'; +import { Skeleton } from '../ui/skeleton'; + +export function ProfileError({ reason }: { reason: string }) { + return ( +
+
+
+
+
+ +
+ + +
+
+
+ + +
+
+ +
+
+ + {reason} + +
+ ); +} diff --git a/client/cms/src/components/profile/profile.skeleton.tsx b/client/cms/src/components/profile/profile.skeleton.tsx new file mode 100644 index 0000000..42a95af --- /dev/null +++ b/client/cms/src/components/profile/profile.skeleton.tsx @@ -0,0 +1,29 @@ +import { Mail } from 'lucide-react'; +import { Skeleton } from '../ui/skeleton'; + +export function ProfileSkeleton() { + return ( +
+
+
+
+
+ +
+ + +
+
+
+ + +
+
+ +
+
+ + +
+ ); +} diff --git a/client/cms/src/components/profile/main-profile.tsx b/client/cms/src/components/profile/profile.view.tsx similarity index 83% rename from client/cms/src/components/profile/main-profile.tsx rename to client/cms/src/components/profile/profile.view.tsx index 28d4adf..5981f0b 100644 --- a/client/cms/src/components/profile/main-profile.tsx +++ b/client/cms/src/components/profile/profile.view.tsx @@ -1,24 +1,23 @@ +import type { ServiceUserUserInfoData } from '@/client'; import { identicon } from '@dicebear/collection'; import { createAvatar } from '@dicebear/core'; import MDEditor from '@uiw/react-md-editor'; -import { isNil } from 'lodash-es'; +import { + isEmpty, + isNil, +} from 'lodash-es'; import { Mail, Pencil } from 'lucide-react'; import { useMemo, useState } from 'react'; import Markdown from 'react-markdown'; import { toast } from 'sonner'; import { Avatar, AvatarImage } from '@/components/ui/avatar'; -import { useUpdateUser } from '@/hooks/data/useUpdateUser'; -import { useUserInfo } from '@/hooks/data/useUserInfo'; -import { base64ToUtf8, utf8ToBase64 } from '@/lib/utils'; +import { base64ToUtf8 } from '@/lib/utils'; import { Button } from '../ui/button'; -import { EditProfileDialog } from './edit-profile-dialog'; +import { EditProfileDialogContainer } from './edit-profile.dialog.container'; -export function MainProfile() { - const { data } = useUserInfo(); - const user = data.data!; +export function ProfileView({ user, onSaveBio }: { user: ServiceUserUserInfoData; onSaveBio: (bio: string) => Promise }) { const [bio, setBio] = useState(() => base64ToUtf8(user.bio ?? '')); const [enableBioEdit, setEnableBioEdit] = useState(false); - const { mutateAsync } = useUpdateUser(); const IdentIcon = useMemo(() => { const avatar = createAvatar(identicon, { @@ -35,7 +34,7 @@ export function MainProfile() {
- {user.avatar ? : IdentIcon} + {!isEmpty(user.avatar) ? : IdentIcon}
@@ -47,7 +46,7 @@ export function MainProfile() { {user.email}
- +
@@ -71,7 +70,7 @@ export function MainProfile() { else { if (!isNil(bio)) { try { - await mutateAsync({ body: { bio: utf8ToBase64(bio) } }); + await onSaveBio(bio); setEnableBioEdit(false); } catch (error) { diff --git a/client/cms/src/components/sidebar/app-sidebar.tsx b/client/cms/src/components/sidebar/app-sidebar.view.tsx similarity index 78% rename from client/cms/src/components/sidebar/app-sidebar.tsx rename to client/cms/src/components/sidebar/app-sidebar.view.tsx index 0d1a945..f6f1017 100644 --- a/client/cms/src/components/sidebar/app-sidebar.tsx +++ b/client/cms/src/components/sidebar/app-sidebar.view.tsx @@ -1,7 +1,8 @@ +import type { NavData } from '@/lib/navData'; import * as React from 'react'; import NixOSLogo from '@/assets/nixos.svg?react'; -import { NavMain } from '@/components/sidebar/nav-main'; -import { NavSecondary } from '@/components/sidebar/nav-secondary'; +import { NavMain } from '@/components/sidebar/nav-main.view'; +import { NavSecondary } from '@/components/sidebar/nav-secondary.view'; import { Sidebar, SidebarContent, @@ -11,10 +12,8 @@ import { SidebarMenuButton, SidebarMenuItem, } from '@/components/ui/sidebar'; -import { navData } from '@/lib/navData'; -import { NavUser } from './nav-user'; -export function AppSidebar({ ...props }: React.ComponentProps) { +export function AppSidebar({ navData, footerWidget, ...props }: React.ComponentProps & { navData: NavData; footerWidget: React.ReactNode }) { return ( @@ -37,7 +36,7 @@ export function AppSidebar({ ...props }: React.ComponentProps) { - + {footerWidget} ); diff --git a/client/cms/src/components/sidebar/nav-main.tsx b/client/cms/src/components/sidebar/nav-main.view.tsx similarity index 100% rename from client/cms/src/components/sidebar/nav-main.tsx rename to client/cms/src/components/sidebar/nav-main.view.tsx diff --git a/client/cms/src/components/sidebar/nav-secondary.tsx b/client/cms/src/components/sidebar/nav-secondary.view.tsx similarity index 100% rename from client/cms/src/components/sidebar/nav-secondary.tsx rename to client/cms/src/components/sidebar/nav-secondary.view.tsx diff --git a/client/cms/src/components/sidebar/nav-user.container.tsx b/client/cms/src/components/sidebar/nav-user.container.tsx new file mode 100644 index 0000000..3e65113 --- /dev/null +++ b/client/cms/src/components/sidebar/nav-user.container.tsx @@ -0,0 +1,11 @@ +import { useUserInfo } from '@/hooks/data/useUserInfo'; +import { NavUserView } from './nav-user.view'; + +export function NavUserContainer() { + const { data } = useUserInfo(); + return ( + + ); +} diff --git a/client/cms/src/components/sidebar/nav-user.skeletion.tsx b/client/cms/src/components/sidebar/nav-user.skeletion.tsx new file mode 100644 index 0000000..de9d3c7 --- /dev/null +++ b/client/cms/src/components/sidebar/nav-user.skeletion.tsx @@ -0,0 +1,18 @@ +import { IconDotsVertical } from '@tabler/icons-react'; +import { SidebarMenuButton } from '../ui/sidebar'; +import { Skeleton } from '../ui/skeleton'; + +export function NavUserSkeleton() { + return ( + + +
+ + +
+ +
+ ); +} diff --git a/client/cms/src/components/sidebar/nav-user.tsx b/client/cms/src/components/sidebar/nav-user.view.tsx similarity index 72% rename from client/cms/src/components/sidebar/nav-user.tsx rename to client/cms/src/components/sidebar/nav-user.view.tsx index 5ac0f2c..6ba97ff 100644 --- a/client/cms/src/components/sidebar/nav-user.tsx +++ b/client/cms/src/components/sidebar/nav-user.view.tsx @@ -1,10 +1,12 @@ -import { identicon } from '@dicebear/collection'; +import type { ServiceUserUserInfoData } from '@/client'; +import { identicon } from '@dicebear/collection'; import { createAvatar } from '@dicebear/core'; import { IconDotsVertical, IconLogout, } from '@tabler/icons-react'; +import { isEmpty } from 'lodash-es'; import { useMemo } from 'react'; import { Avatar, @@ -24,16 +26,10 @@ import { SidebarMenuItem, useSidebar, } from '@/components/ui/sidebar'; -import { useUserInfo } from '@/hooks/data/useUserInfo'; -import { useLogout } from '@/hooks/useLogout'; -import { withFallback } from '../hoc/with-fallback'; -import { Skeleton } from '../ui/skeleton'; +import { logout } from '@/lib/token'; -function NavUser_() { +export function NavUserView({ user }: { user: ServiceUserUserInfoData }) { const { isMobile } = useSidebar(); - const { data } = useUserInfo(); - const user = data.data!; - const { logout } = useLogout(); const IdentIcon = useMemo(() => { const avatar = createAvatar(identicon, { @@ -53,7 +49,7 @@ function NavUser_() { className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground" > - {user.avatar ? : IdentIcon} + {!isEmpty(user.avatar) ? : IdentIcon}
{user.nickname} @@ -73,7 +69,7 @@ function NavUser_() {
- {user.avatar ? : IdentIcon} + {!isEmpty(user.avatar) ? : IdentIcon}
{user.nickname} @@ -84,7 +80,7 @@ function NavUser_() {
- + logout()}> 登出 @@ -94,20 +90,3 @@ function NavUser_() { ); } - -function NavUserSkeleton() { - return ( - - -
- - -
- -
- ); -} - -export const NavUser = withFallback(NavUser_, ); diff --git a/client/cms/src/components/site-header.tsx b/client/cms/src/components/site-header.tsx index 9ecc44b..4eb3e5c 100644 --- a/client/cms/src/components/site-header.tsx +++ b/client/cms/src/components/site-header.tsx @@ -1,18 +1,7 @@ -import { useRouterState } from '@tanstack/react-router'; import { Separator } from '@/components/ui/separator'; import { SidebarTrigger } from '@/components/ui/sidebar'; -import { navData } from '@/lib/navData'; - -export function SiteHeader() { - const pathname = useRouterState({ select: state => state.location.pathname }); - const allNavItems = [...navData.navMain, ...navData.navSecondary]; - const currentTitle - = allNavItems.find(item => - item.url === '/' - ? pathname === '/' - : pathname.startsWith(item.url), - )?.title ?? '工作台'; +export function SiteHeader({ title }: { title: string }) { return (
@@ -21,7 +10,7 @@ export function SiteHeader() { orientation="vertical" className="mx-2 data-[orientation=vertical]:h-4" /> -

{currentTitle}

+

{title}

); diff --git a/client/cms/src/components/workbenchCards/card-skeleton.tsx b/client/cms/src/components/workbenchCards/card-skeleton.tsx deleted file mode 100644 index 007b499..0000000 --- a/client/cms/src/components/workbenchCards/card-skeleton.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { Skeleton } from '../ui/skeleton'; - -export function CardSkeleton() { - return ( - - ); -} diff --git a/client/cms/src/hooks/data/useCreateKycSession.ts b/client/cms/src/hooks/data/useCreateKycSession.ts new file mode 100644 index 0000000..4f0c342 --- /dev/null +++ b/client/cms/src/hooks/data/useCreateKycSession.ts @@ -0,0 +1,45 @@ +import type { KycSubmission } from '@/components/events/kyc/kyc.types'; +import { useMutation } from '@tanstack/react-query'; +import { postKycSessionMutation } from '@/client/@tanstack/react-query.gen'; +import { ver } from '@/lib/apiVersion'; +import { utf8ToBase64 } from '@/lib/utils'; + +type CreateKycSessionBase64Payload = { + // Cnrid + legal_name: string; + resident_id: string; +} | { + // Passport + id: string; +}; + +export function useCreateKycSession() { + const mutation = useMutation({ + ...postKycSessionMutation(), + }); + + return { + ...mutation, + mutate: null, // Don't ever use this + mutateAsync: async (data: KycSubmission) => { + const payload = utf8ToBase64(JSON.stringify( + data.method === 'cnrid' + ? { + legal_name: data.name, + resident_id: data.cnrid, + } satisfies CreateKycSessionBase64Payload + : { + id: data.passportId, + } satisfies CreateKycSessionBase64Payload, + )); + const response = await mutation.mutateAsync({ + body: { + identity: payload, + type: data.method, + }, + headers: ver('20260205'), + }); + return response; + }, + }; +} diff --git a/client/cms/src/hooks/data/useExchangeToken.ts b/client/cms/src/hooks/data/useExchangeToken.ts index 92f153d..d146c21 100644 --- a/client/cms/src/hooks/data/useExchangeToken.ts +++ b/client/cms/src/hooks/data/useExchangeToken.ts @@ -6,7 +6,7 @@ export function useExchangeToken() { return useMutation({ ...postAuthExchangeMutation(), onSuccess: (data) => { - window.location.href = data.data?.redirect_uri!; + window.location.href = data.data!.redirect_uri!; }, onError: (error) => { console.error(error); diff --git a/client/cms/src/hooks/data/useGetEvents.ts b/client/cms/src/hooks/data/useGetEvents.ts new file mode 100644 index 0000000..854969a --- /dev/null +++ b/client/cms/src/hooks/data/useGetEvents.ts @@ -0,0 +1,21 @@ +import { useInfiniteQuery } from '@tanstack/react-query'; +import { isNil } from 'lodash-es'; +import { getEventListInfiniteOptions } from '@/client/@tanstack/react-query.gen'; +import { ver } from '@/lib/apiVersion'; + +export function useGetEvents() { + return useInfiniteQuery({ + ...getEventListInfiniteOptions({ + query: {}, + headers: ver('20260205'), + }), + initialPageParam: 0, + getNextPageParam: (lastPage, allPages) => { + const currentData = lastPage?.data; + if (!isNil(currentData) && currentData.length === 20) { + return allPages.length * 20; + } + return undefined; + }, + }); +} diff --git a/client/cms/src/hooks/data/useUpdateUser.ts b/client/cms/src/hooks/data/useUpdateUser.ts index 9fe2efe..c3940ea 100644 --- a/client/cms/src/hooks/data/useUpdateUser.ts +++ b/client/cms/src/hooks/data/useUpdateUser.ts @@ -1,12 +1,18 @@ +import type { ServiceUserUserInfoData } from '@/client'; import { useMutation, useQueryClient } from '@tanstack/react-query'; -import { getUserInfoQueryKey, patchUserUpdateMutation } from '@/client/@tanstack/react-query.gen'; +import { getUserInfoByUserIdQueryKey, getUserInfoQueryKey, patchUserUpdateMutation } from '@/client/@tanstack/react-query.gen'; +import { ver } from '@/lib/apiVersion'; export function useUpdateUser() { const queryClient = useQueryClient(); + const data: { data: ServiceUserUserInfoData | undefined } | undefined = queryClient.getQueryData(getUserInfoQueryKey({ headers: ver('20260205') })); return useMutation({ ...patchUserUpdateMutation(), onSuccess: async () => { - await queryClient.invalidateQueries({ queryKey: getUserInfoQueryKey() }); + await queryClient.invalidateQueries({ queryKey: getUserInfoQueryKey({ headers: ver('20260205') }) }); + if ((data?.data?.user_id) != null) { + await queryClient.invalidateQueries({ queryKey: getUserInfoByUserIdQueryKey({ path: { user_id: data.data.user_id }, headers: ver('20260205') }) }); + } }, }); } diff --git a/client/cms/src/hooks/data/useUserInfo.ts b/client/cms/src/hooks/data/useUserInfo.ts index db64bd6..b1b9d81 100644 --- a/client/cms/src/hooks/data/useUserInfo.ts +++ b/client/cms/src/hooks/data/useUserInfo.ts @@ -1,9 +1,21 @@ import { useSuspenseQuery } from '@tanstack/react-query'; -import { getUserInfoOptions } from '@/client/@tanstack/react-query.gen'; +import { + getUserInfoByUserIdOptions, + getUserInfoOptions, +} from '@/client/@tanstack/react-query.gen'; +import { ver } from '@/lib/apiVersion'; export function useUserInfo() { return useSuspenseQuery({ - ...getUserInfoOptions(), + ...getUserInfoOptions({ headers: ver('20260205') }), staleTime: 10 * 60 * 1000, }); } + +export function useOtherUserInfo(userId: string) { + return useSuspenseQuery({ + ...getUserInfoByUserIdOptions({ path: { user_id: userId }, headers: ver('20260205') }), + staleTime: 10 * 60 * 1000, + retry: (_failureCount, error) => error.code !== 403, + }); +} diff --git a/client/cms/src/hooks/use-mobile.ts b/client/cms/src/hooks/use-mobile.ts index ba553c6..adf8be1 100644 --- a/client/cms/src/hooks/use-mobile.ts +++ b/client/cms/src/hooks/use-mobile.ts @@ -11,6 +11,7 @@ export function useIsMobile() { setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); }; mql.addEventListener('change', onChange); + // eslint-disable-next-line react-hooks-extra/no-direct-set-state-in-use-effect setIsMobile(window.innerWidth < MOBILE_BREAKPOINT); return () => mql.removeEventListener('change', onChange); }, []); diff --git a/client/cms/src/hooks/useLogout.ts b/client/cms/src/hooks/useLogout.ts deleted file mode 100644 index e8f731c..0000000 --- a/client/cms/src/hooks/useLogout.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { useNavigate } from '@tanstack/react-router'; -import { useCallback } from 'react'; -import { clearTokens } from '@/lib/token'; - -export function useLogout() { - const navigate = useNavigate(); - - const logout = useCallback(() => { - clearTokens(); - void navigate({ to: '/authorize' }); - }, [navigate]); - - return { logout }; -} diff --git a/client/cms/src/lib/apiVersion.ts b/client/cms/src/lib/apiVersion.ts new file mode 100644 index 0000000..0c757ea --- /dev/null +++ b/client/cms/src/lib/apiVersion.ts @@ -0,0 +1,5 @@ +export function ver(version: string) { + return { + 'X-Api-Version': version, + }; +} diff --git a/client/cms/src/lib/client.ts b/client/cms/src/lib/client.ts index 452fb0d..c061f8f 100644 --- a/client/cms/src/lib/client.ts +++ b/client/cms/src/lib/client.ts @@ -1,13 +1,12 @@ import { isEmpty, isNil } from 'lodash-es'; import { client } from '@/client/client.gen'; -import { router } from './router'; import { - clearTokens, doRefreshToken, + getAccessToken, getRefreshToken, - getToken, + logout, + setAccessToken, setRefreshToken, - setToken, } from './token'; export function configInternalApiClient() { @@ -19,8 +18,8 @@ export function configInternalApiClient() { }); client.interceptors.request.use((request) => { - const token = getToken(); - if (token) { + const token = getAccessToken(); + if (!isNil(token) && !isEmpty(token)) { request.headers.set('Authorization', `Bearer ${token}`); } return request; @@ -28,14 +27,21 @@ export function configInternalApiClient() { client.interceptors.response.use(async (response, request, options) => { if (response.status === 401) { - const refreshToken = getRefreshToken(); // Avoid infinite loop if the refresh token request itself fails - if (!request.url.includes('/auth/refresh') && !isNil(refreshToken)) { - try { - const refreshResponse = await doRefreshToken(); + if (request.url.includes('/auth/refresh')) { + // Refresh token failed, clear tokens and redirect to login page + logout('会话已过期'); + } + else { + const refreshToken = getRefreshToken(); + if (isNil(refreshToken) || isEmpty(refreshToken)) { + logout('未登录'); + } + else { + const refreshResponse = await doRefreshToken(refreshToken); if (!isEmpty(refreshResponse)) { const { access_token, refresh_token } = refreshResponse; - setToken(access_token!); + setAccessToken(access_token!); setRefreshToken(refresh_token!); const fetchFn = options.fetch ?? globalThis.fetch; @@ -50,11 +56,6 @@ export function configInternalApiClient() { }); } } - catch (e) { - clearTokens(); - await router.navigate({ to: '/authorize' }); - return response; - } } } return response; diff --git a/client/cms/src/lib/navData.ts b/client/cms/src/lib/navData.ts index 7266d47..f5f24ad 100644 --- a/client/cms/src/lib/navData.ts +++ b/client/cms/src/lib/navData.ts @@ -1,4 +1,5 @@ import { + IconCalendarEvent, IconDashboard, IconUser, } from '@tabler/icons-react'; @@ -10,6 +11,11 @@ export const navData = { url: '/', icon: IconDashboard, }, + { + title: '活动列表', + url: '/events', + icon: IconCalendarEvent, + }, ], navSecondary: [ { @@ -19,3 +25,4 @@ export const navData = { }, ], }; +export type NavData = typeof navData; diff --git a/client/cms/src/lib/token.ts b/client/cms/src/lib/token.ts index 469a54e..6354075 100644 --- a/client/cms/src/lib/token.ts +++ b/client/cms/src/lib/token.ts @@ -1,40 +1,54 @@ import type { ServiceAuthTokenResponse } from '@/client'; +import { toast } from 'sonner'; import { postAuthRefresh } from '@/client'; +import { ver } from './apiVersion'; +import { router } from './router'; -export function setToken(token: string) { - localStorage.setItem('token', token); +const ACCESS_TOKEN_LOCALSTORAGE_KEY = 'token'; +const REFRESH_TOKEN_LOCALSTORAGE_KEY = 'refreshToken'; + +export function setAccessToken(token: string) { + localStorage.setItem(ACCESS_TOKEN_LOCALSTORAGE_KEY, token); } -export function getToken() { - return localStorage.getItem('token'); +export function getAccessToken() { + return localStorage.getItem(ACCESS_TOKEN_LOCALSTORAGE_KEY); } -export function removeToken() { - localStorage.removeItem('token'); -} - -export function hasToken() { - return getToken() !== null; +export function removeAccessToken() { + localStorage.removeItem(ACCESS_TOKEN_LOCALSTORAGE_KEY); } export function setRefreshToken(refreshToken: string) { - localStorage.setItem('refreshToken', refreshToken); + localStorage.setItem(REFRESH_TOKEN_LOCALSTORAGE_KEY, refreshToken); } export function getRefreshToken() { - return localStorage.getItem('refreshToken'); + return localStorage.getItem(REFRESH_TOKEN_LOCALSTORAGE_KEY); +} + +export function removeRefreshToken() { + localStorage.removeItem(REFRESH_TOKEN_LOCALSTORAGE_KEY); } export function clearTokens() { - removeToken(); - setRefreshToken(''); + removeAccessToken(); + removeRefreshToken(); } -export async function doRefreshToken(): Promise { +export async function doRefreshToken(refreshToken: string): Promise { const { data } = await postAuthRefresh({ body: { - refresh_token: getRefreshToken()!, + refresh_token: refreshToken, }, + headers: ver('20260205'), }); return data?.data; } + +export function logout(message: string = '已登出') { + clearTokens(); + void router.navigate({ to: '/authorize' }).then(() => { + toast.info(message); + }); +} diff --git a/client/cms/src/lib/utils.ts b/client/cms/src/lib/utils.ts index 4306642..9c08cf1 100644 --- a/client/cms/src/lib/utils.ts +++ b/client/cms/src/lib/utils.ts @@ -1,3 +1,4 @@ +import type { Query } from '@tanstack/react-query'; import type { ClassValue } from 'clsx'; // eslint-disable-next-line unicorn/prefer-node-protocol import { Buffer } from 'buffer'; @@ -17,3 +18,12 @@ export function base64ToUtf8(base64: string): string { export function utf8ToBase64(utf8: string): string { return Buffer.from(utf8, 'utf-8').toString('base64'); } + +export function invalidateBlurry(id: string) { + return { + predicate: (query: Query) => { + const key = query.queryKey[0] as { _id: string }; + return key?._id === id; + }, + }; +} diff --git a/client/cms/src/routeTree.gen.ts b/client/cms/src/routeTree.gen.ts index 7d1304c..26aa039 100644 --- a/client/cms/src/routeTree.gen.ts +++ b/client/cms/src/routeTree.gen.ts @@ -12,9 +12,11 @@ import { Route as rootRouteImport } from './routes/__root' import { Route as TokenRouteImport } from './routes/token' import { Route as MagicLinkSentRouteImport } from './routes/magicLinkSent' import { Route as AuthorizeRouteImport } from './routes/authorize' -import { Route as SidebarLayoutRouteImport } from './routes/_sidebarLayout' -import { Route as SidebarLayoutIndexRouteImport } from './routes/_sidebarLayout/index' -import { Route as SidebarLayoutProfileRouteImport } from './routes/_sidebarLayout/profile' +import { Route as WorkbenchLayoutRouteImport } from './routes/_workbenchLayout' +import { Route as WorkbenchLayoutIndexRouteImport } from './routes/_workbenchLayout/index' +import { Route as WorkbenchLayoutEventsRouteImport } from './routes/_workbenchLayout/events' +import { Route as WorkbenchLayoutProfileIndexRouteImport } from './routes/_workbenchLayout/profile.index' +import { Route as WorkbenchLayoutProfileUserIdRouteImport } from './routes/_workbenchLayout/profile.$userId' const TokenRoute = TokenRouteImport.update({ id: '/token', @@ -31,61 +33,95 @@ const AuthorizeRoute = AuthorizeRouteImport.update({ path: '/authorize', getParentRoute: () => rootRouteImport, } as any) -const SidebarLayoutRoute = SidebarLayoutRouteImport.update({ - id: '/_sidebarLayout', +const WorkbenchLayoutRoute = WorkbenchLayoutRouteImport.update({ + id: '/_workbenchLayout', getParentRoute: () => rootRouteImport, } as any) -const SidebarLayoutIndexRoute = SidebarLayoutIndexRouteImport.update({ +const WorkbenchLayoutIndexRoute = WorkbenchLayoutIndexRouteImport.update({ id: '/', path: '/', - getParentRoute: () => SidebarLayoutRoute, + getParentRoute: () => WorkbenchLayoutRoute, } as any) -const SidebarLayoutProfileRoute = SidebarLayoutProfileRouteImport.update({ - id: '/profile', - path: '/profile', - getParentRoute: () => SidebarLayoutRoute, +const WorkbenchLayoutEventsRoute = WorkbenchLayoutEventsRouteImport.update({ + id: '/events', + path: '/events', + getParentRoute: () => WorkbenchLayoutRoute, } as any) +const WorkbenchLayoutProfileIndexRoute = + WorkbenchLayoutProfileIndexRouteImport.update({ + id: '/profile/', + path: '/profile/', + getParentRoute: () => WorkbenchLayoutRoute, + } as any) +const WorkbenchLayoutProfileUserIdRoute = + WorkbenchLayoutProfileUserIdRouteImport.update({ + id: '/profile/$userId', + path: '/profile/$userId', + getParentRoute: () => WorkbenchLayoutRoute, + } as any) export interface FileRoutesByFullPath { - '/': typeof SidebarLayoutIndexRoute + '/': typeof WorkbenchLayoutIndexRoute '/authorize': typeof AuthorizeRoute '/magicLinkSent': typeof MagicLinkSentRoute '/token': typeof TokenRoute - '/profile': typeof SidebarLayoutProfileRoute + '/events': typeof WorkbenchLayoutEventsRoute + '/profile/$userId': typeof WorkbenchLayoutProfileUserIdRoute + '/profile/': typeof WorkbenchLayoutProfileIndexRoute } export interface FileRoutesByTo { '/authorize': typeof AuthorizeRoute '/magicLinkSent': typeof MagicLinkSentRoute '/token': typeof TokenRoute - '/profile': typeof SidebarLayoutProfileRoute - '/': typeof SidebarLayoutIndexRoute + '/events': typeof WorkbenchLayoutEventsRoute + '/': typeof WorkbenchLayoutIndexRoute + '/profile/$userId': typeof WorkbenchLayoutProfileUserIdRoute + '/profile': typeof WorkbenchLayoutProfileIndexRoute } export interface FileRoutesById { __root__: typeof rootRouteImport - '/_sidebarLayout': typeof SidebarLayoutRouteWithChildren + '/_workbenchLayout': typeof WorkbenchLayoutRouteWithChildren '/authorize': typeof AuthorizeRoute '/magicLinkSent': typeof MagicLinkSentRoute '/token': typeof TokenRoute - '/_sidebarLayout/profile': typeof SidebarLayoutProfileRoute - '/_sidebarLayout/': typeof SidebarLayoutIndexRoute + '/_workbenchLayout/events': typeof WorkbenchLayoutEventsRoute + '/_workbenchLayout/': typeof WorkbenchLayoutIndexRoute + '/_workbenchLayout/profile/$userId': typeof WorkbenchLayoutProfileUserIdRoute + '/_workbenchLayout/profile/': typeof WorkbenchLayoutProfileIndexRoute } export interface FileRouteTypes { fileRoutesByFullPath: FileRoutesByFullPath - fullPaths: '/' | '/authorize' | '/magicLinkSent' | '/token' | '/profile' - fileRoutesByTo: FileRoutesByTo - to: '/authorize' | '/magicLinkSent' | '/token' | '/profile' | '/' - id: - | '__root__' - | '/_sidebarLayout' + fullPaths: + | '/' | '/authorize' | '/magicLinkSent' | '/token' - | '/_sidebarLayout/profile' - | '/_sidebarLayout/' + | '/events' + | '/profile/$userId' + | '/profile/' + fileRoutesByTo: FileRoutesByTo + to: + | '/authorize' + | '/magicLinkSent' + | '/token' + | '/events' + | '/' + | '/profile/$userId' + | '/profile' + id: + | '__root__' + | '/_workbenchLayout' + | '/authorize' + | '/magicLinkSent' + | '/token' + | '/_workbenchLayout/events' + | '/_workbenchLayout/' + | '/_workbenchLayout/profile/$userId' + | '/_workbenchLayout/profile/' fileRoutesById: FileRoutesById } export interface RootRouteChildren { - SidebarLayoutRoute: typeof SidebarLayoutRouteWithChildren + WorkbenchLayoutRoute: typeof WorkbenchLayoutRouteWithChildren AuthorizeRoute: typeof AuthorizeRoute MagicLinkSentRoute: typeof MagicLinkSentRoute TokenRoute: typeof TokenRoute @@ -114,46 +150,64 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof AuthorizeRouteImport parentRoute: typeof rootRouteImport } - '/_sidebarLayout': { - id: '/_sidebarLayout' + '/_workbenchLayout': { + id: '/_workbenchLayout' path: '' fullPath: '/' - preLoaderRoute: typeof SidebarLayoutRouteImport + preLoaderRoute: typeof WorkbenchLayoutRouteImport parentRoute: typeof rootRouteImport } - '/_sidebarLayout/': { - id: '/_sidebarLayout/' + '/_workbenchLayout/': { + id: '/_workbenchLayout/' path: '/' fullPath: '/' - preLoaderRoute: typeof SidebarLayoutIndexRouteImport - parentRoute: typeof SidebarLayoutRoute + preLoaderRoute: typeof WorkbenchLayoutIndexRouteImport + parentRoute: typeof WorkbenchLayoutRoute } - '/_sidebarLayout/profile': { - id: '/_sidebarLayout/profile' + '/_workbenchLayout/events': { + id: '/_workbenchLayout/events' + path: '/events' + fullPath: '/events' + preLoaderRoute: typeof WorkbenchLayoutEventsRouteImport + parentRoute: typeof WorkbenchLayoutRoute + } + '/_workbenchLayout/profile/': { + id: '/_workbenchLayout/profile/' path: '/profile' - fullPath: '/profile' - preLoaderRoute: typeof SidebarLayoutProfileRouteImport - parentRoute: typeof SidebarLayoutRoute + fullPath: '/profile/' + preLoaderRoute: typeof WorkbenchLayoutProfileIndexRouteImport + parentRoute: typeof WorkbenchLayoutRoute + } + '/_workbenchLayout/profile/$userId': { + id: '/_workbenchLayout/profile/$userId' + path: '/profile/$userId' + fullPath: '/profile/$userId' + preLoaderRoute: typeof WorkbenchLayoutProfileUserIdRouteImport + parentRoute: typeof WorkbenchLayoutRoute } } } -interface SidebarLayoutRouteChildren { - SidebarLayoutProfileRoute: typeof SidebarLayoutProfileRoute - SidebarLayoutIndexRoute: typeof SidebarLayoutIndexRoute +interface WorkbenchLayoutRouteChildren { + WorkbenchLayoutEventsRoute: typeof WorkbenchLayoutEventsRoute + WorkbenchLayoutIndexRoute: typeof WorkbenchLayoutIndexRoute + WorkbenchLayoutProfileUserIdRoute: typeof WorkbenchLayoutProfileUserIdRoute + WorkbenchLayoutProfileIndexRoute: typeof WorkbenchLayoutProfileIndexRoute } -const SidebarLayoutRouteChildren: SidebarLayoutRouteChildren = { - SidebarLayoutProfileRoute: SidebarLayoutProfileRoute, - SidebarLayoutIndexRoute: SidebarLayoutIndexRoute, +const WorkbenchLayoutRouteChildren: WorkbenchLayoutRouteChildren = { + WorkbenchLayoutEventsRoute: WorkbenchLayoutEventsRoute, + WorkbenchLayoutIndexRoute: WorkbenchLayoutIndexRoute, + WorkbenchLayoutProfileUserIdRoute: WorkbenchLayoutProfileUserIdRoute, + WorkbenchLayoutProfileIndexRoute: WorkbenchLayoutProfileIndexRoute, } -const SidebarLayoutRouteWithChildren = SidebarLayoutRoute._addFileChildren( - SidebarLayoutRouteChildren, +const WorkbenchLayoutRouteWithChildren = WorkbenchLayoutRoute._addFileChildren( + WorkbenchLayoutRouteChildren, ) const rootRouteChildren: RootRouteChildren = { - SidebarLayoutRoute: SidebarLayoutRouteWithChildren, + WorkbenchLayoutRoute: WorkbenchLayoutRouteWithChildren, AuthorizeRoute: AuthorizeRoute, MagicLinkSentRoute: MagicLinkSentRoute, TokenRoute: TokenRoute, diff --git a/client/cms/src/routes/__root.tsx b/client/cms/src/routes/__root.tsx index faf535a..1f0df9e 100644 --- a/client/cms/src/routes/__root.tsx +++ b/client/cms/src/routes/__root.tsx @@ -12,11 +12,9 @@ const queryClient = new QueryClient({ const status // eslint-disable-next-line ts/no-unsafe-member-access = error?.response?.status ?? error?.status; - if (status >= 400 && status < 500) { return false; } - return failureCount < 3; }, }, diff --git a/client/cms/src/routes/_sidebarLayout.tsx b/client/cms/src/routes/_sidebarLayout.tsx deleted file mode 100644 index e282a5e..0000000 --- a/client/cms/src/routes/_sidebarLayout.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { createFileRoute, Outlet } from '@tanstack/react-router'; -import { AppSidebar } from '@/components/sidebar/app-sidebar'; -import { SiteHeader } from '@/components/site-header'; -import { SidebarInset, SidebarProvider } from '@/components/ui/sidebar'; - -export const Route = createFileRoute('/_sidebarLayout')({ - component: RouteComponent, -}); - -function RouteComponent() { - return ( - - - - -
-
- -
-
-
-
- ); -} diff --git a/client/cms/src/routes/_sidebarLayout/profile.tsx b/client/cms/src/routes/_sidebarLayout/profile.tsx deleted file mode 100644 index 7dfcf31..0000000 --- a/client/cms/src/routes/_sidebarLayout/profile.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import { createFileRoute } from '@tanstack/react-router'; -import { MainProfile } from '@/components/profile/main-profile'; - -export const Route = createFileRoute('/_sidebarLayout/profile')({ - component: RouteComponent, -}); - -function RouteComponent() { - return ( -
- -
- ); -} diff --git a/client/cms/src/routes/_workbenchLayout.tsx b/client/cms/src/routes/_workbenchLayout.tsx new file mode 100644 index 0000000..65a366f --- /dev/null +++ b/client/cms/src/routes/_workbenchLayout.tsx @@ -0,0 +1,52 @@ +import { createFileRoute, Outlet, useRouterState } from '@tanstack/react-router'; +import { Suspense } from 'react'; +import { AppSidebar } from '@/components/sidebar/app-sidebar.view'; +import { NavUserContainer } from '@/components/sidebar/nav-user.container'; +import { NavUserSkeleton } from '@/components/sidebar/nav-user.skeletion'; +import { SiteHeader } from '@/components/site-header'; +import { SidebarInset, SidebarProvider } from '@/components/ui/sidebar'; +import { navData } from '@/lib/navData'; + +export const Route = createFileRoute('/_workbenchLayout')({ + component: RouteComponent, +}); + +function RouteComponent() { + const pathname = useRouterState({ select: state => state.location.pathname }); + const allNavItems = [...navData.navMain, ...navData.navSecondary]; + const title + = allNavItems.find(item => + item.url === '/' + ? pathname === '/' + : pathname.startsWith(item.url), + )?.title ?? '工作台'; + + return ( + + }> + + + )} + variant="inset" + /> + + +
+
+ +
+
+
+
+ ); +} diff --git a/client/cms/src/routes/_workbenchLayout/events.tsx b/client/cms/src/routes/_workbenchLayout/events.tsx new file mode 100644 index 0000000..79e31d1 --- /dev/null +++ b/client/cms/src/routes/_workbenchLayout/events.tsx @@ -0,0 +1,14 @@ +import { createFileRoute } from '@tanstack/react-router'; +import { EventGridContainer } from '@/components/events/event-grid.container'; + +export const Route = createFileRoute('/_workbenchLayout/events')({ + component: RouteComponent, +}); + +function RouteComponent() { + return ( +
+ +
+ ); +} diff --git a/client/cms/src/routes/_sidebarLayout/index.tsx b/client/cms/src/routes/_workbenchLayout/index.tsx similarity index 64% rename from client/cms/src/routes/_sidebarLayout/index.tsx rename to client/cms/src/routes/_workbenchLayout/index.tsx index 0b42a00..c16b887 100644 --- a/client/cms/src/routes/_sidebarLayout/index.tsx +++ b/client/cms/src/routes/_workbenchLayout/index.tsx @@ -1,15 +1,7 @@ -import { createFileRoute, redirect } from '@tanstack/react-router'; -import { hasToken } from '@/lib/token'; +import { createFileRoute } from '@tanstack/react-router'; -export const Route = createFileRoute('/_sidebarLayout/')({ +export const Route = createFileRoute('/_workbenchLayout/')({ component: Index, - loader: async () => { - if (!hasToken()) { - throw redirect({ - to: '/authorize', - }); - } - }, }); function Index() { diff --git a/client/cms/src/routes/_workbenchLayout/profile.$userId.tsx b/client/cms/src/routes/_workbenchLayout/profile.$userId.tsx new file mode 100644 index 0000000..f502805 --- /dev/null +++ b/client/cms/src/routes/_workbenchLayout/profile.$userId.tsx @@ -0,0 +1,28 @@ +import { createFileRoute } from '@tanstack/react-router'; +import { Suspense } from 'react'; +import { ErrorBoundary } from 'react-error-boundary'; +import { ProfileContainer } from '@/components/profile/profile.container'; +import { ProfileError } from '@/components/profile/profile.error'; +import { ProfileSkeleton } from '@/components/profile/profile.skeleton'; + +export const Route = createFileRoute('/_workbenchLayout/profile/$userId')({ + component: RouteComponent, +}); + +function RouteComponent() { + const { userId } = Route.useParams(); + return ( +
+ { + if ((error.error as { code: number }).code === 403) + return ; + else return ; + }} + > + }> + + + +
+ ); +} diff --git a/client/cms/src/routes/_workbenchLayout/profile.index.tsx b/client/cms/src/routes/_workbenchLayout/profile.index.tsx new file mode 100644 index 0000000..c4add66 --- /dev/null +++ b/client/cms/src/routes/_workbenchLayout/profile.index.tsx @@ -0,0 +1,21 @@ +import { createFileRoute, Navigate } from '@tanstack/react-router'; +import { Suspense } from 'react'; +import { ErrorBoundary } from 'react-error-boundary'; +import { ProfileError } from '@/components/profile/profile.error'; +import { ProfileSkeleton } from '@/components/profile/profile.skeleton'; +import { useUserInfo } from '@/hooks/data/useUserInfo'; + +export const Route = createFileRoute('/_workbenchLayout/profile/')({ + component: RouteComponent, +}); + +function RouteComponent() { + const { data } = useUserInfo(); + return ( + }> + }> + + + + ); +} diff --git a/client/cms/src/routes/authorize.tsx b/client/cms/src/routes/authorize.tsx index f8ed2ed..c426bb1 100644 --- a/client/cms/src/routes/authorize.tsx +++ b/client/cms/src/routes/authorize.tsx @@ -5,8 +5,9 @@ import { useEffect } from 'react'; import z from 'zod'; import { LoginForm } from '@/components/login-form'; import { useExchangeToken } from '@/hooks/data/useExchangeToken'; +import { ver } from '@/lib/apiVersion'; import { generateOAuthState } from '@/lib/random'; -import { getToken } from '@/lib/token'; +import { getAccessToken } from '@/lib/token'; const baseUrl = import.meta.env.VITE_APP_BASE_URL; @@ -25,7 +26,7 @@ export const Route = createFileRoute('/authorize')({ }); function RouteComponent() { - const token = getToken(); + const token = getAccessToken(); const oauthParams = Route.useSearch(); const mutation = useExchangeToken(); /** @@ -39,9 +40,10 @@ function RouteComponent() { redirect_uri: oauthParams.redirect_uri, state: oauthParams.state, }, + headers: ver('20260205'), }); } - }, [token, mutation.isIdle]); + }, [token, mutation.isIdle, mutation, oauthParams.client_id, oauthParams.redirect_uri, oauthParams.state]); return (
diff --git a/client/cms/src/routes/token.tsx b/client/cms/src/routes/token.tsx index b2c26dd..9849693 100644 --- a/client/cms/src/routes/token.tsx +++ b/client/cms/src/routes/token.tsx @@ -6,7 +6,8 @@ import { } from 'react'; import z from 'zod'; import { postAuthTokenMutation } from '@/client/@tanstack/react-query.gen'; -import { setRefreshToken, setToken } from '@/lib/token'; +import { ver } from '@/lib/apiVersion'; +import { setAccessToken, setRefreshToken } from '@/lib/token'; const tokenCodeSchema = z.object({ code: z.string().nonempty(), @@ -25,8 +26,8 @@ function RouteComponent() { const mutation = useMutation({ ...postAuthTokenMutation(), onSuccess: (data) => { - setToken(data.data?.access_token!); - setRefreshToken(data.data?.refresh_token!); + setAccessToken(data.data!.access_token!); + setRefreshToken(data.data!.refresh_token!); void navigate({ to: '/' }); }, onError: () => { @@ -36,8 +37,9 @@ function RouteComponent() { useEffect(() => { if (mutation.isIdle) { - mutation.mutate({ body: { code } }); + mutation.mutate({ body: { code }, headers: ver('20260205') }); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return
{status}
; diff --git a/client/cms/src/stories/events/event-card.stories.tsx b/client/cms/src/stories/events/event-card.stories.tsx new file mode 100644 index 0000000..b07b120 --- /dev/null +++ b/client/cms/src/stories/events/event-card.stories.tsx @@ -0,0 +1,47 @@ +import type { Meta, StoryObj } from '@storybook/react-vite'; +import { EventCardSkeleton } from '@/components/events/event-card.skeleton'; +import { EventCardView } from '@/components/events/event-card.view'; +import { Button } from '@/components/ui/button'; + +const meta = { + title: 'Events/EventCard', + component: EventCardView, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Primary: Story = { + args: { + eventInfo: { + eventId: '1', + type: 'official', + requireKyc: true, + isJoined: false, + coverImage: 'https://github.com/NixOS/nixos-artwork/blob/master/wallpapers/nix-wallpaper-watersplash.png?raw=true', + eventName: 'Nix CN Conference 26.05', + description: 'Event Description', + startTime: new Date('2026-06-13T04:00:00.000Z'), + endTime: new Date('2026-06-14T04:00:00.000Z'), + }, + actionFooter: , + }, +}; + +export const Loading: Story = { + render: () => , + args: { + eventInfo: { + eventId: '1', + type: 'official', + requireKyc: true, + coverImage: '', + isJoined: false, + eventName: '', + description: '', + startTime: new Date(0), + endTime: new Date(0), + }, + actionFooter: , + }, +}; diff --git a/client/cms/src/stories/events/event-grid.stories.tsx b/client/cms/src/stories/events/event-grid.stories.tsx new file mode 100644 index 0000000..055ed05 --- /dev/null +++ b/client/cms/src/stories/events/event-grid.stories.tsx @@ -0,0 +1,73 @@ +import type { Meta, StoryObj } from '@storybook/react-vite'; +import { EventGridSkeleton } from '@/components/events/event-grid.skeleton'; +import { EventGridView } from '@/components/events/event-grid.view'; +import { Button } from '@/components/ui/button'; +import { Skeleton as UiSkeleton } from '@/components/ui/skeleton'; + +const meta = { + title: 'Events/EventGrid', + component: EventGridView, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Primary: Story = { + args: { + events: [ + { + eventId: '1', + requireKyc: true, + isJoined: false, + type: 'official', + coverImage: 'https://github.com/NixOS/nixos-artwork/blob/master/wallpapers/nix-wallpaper-watersplash.png?raw=true', + eventName: 'Nix CN Conference 26.05', + description: 'Event Description', + startTime: new Date('2026-06-13T04:00:00.000Z'), + endTime: new Date('2026-06-14T04:00:00.000Z'), + }, + { + eventId: '2', + requireKyc: true, + isJoined: false, + type: 'official', + coverImage: 'https://github.com/NixOS/nixos-artwork/blob/master/wallpapers/nix-wallpaper-moonscape.png?raw=true', + eventName: 'Nix CN Conference 26.05', + description: 'Event Description', + startTime: new Date('2026-06-13T04:00:00.000Z'), + endTime: new Date('2026-06-14T04:00:00.000Z'), + }, + { + eventId: '3', + requireKyc: true, + isJoined: false, + type: 'official', + coverImage: 'https://github.com/NixOS/nixos-artwork/blob/master/wallpapers/nix-wallpaper-nineish-catppuccin-latte.png?raw=true', + eventName: 'Nix CN Conference 26.05', + description: 'Event Description', + startTime: new Date('2026-06-13T04:00:00.000Z'), + endTime: new Date('2026-06-14T04:00:00.000Z'), + }, + { + eventId: '4', + requireKyc: true, + isJoined: false, + type: 'official', + coverImage: 'https://github.com/NixOS/nixos-artwork/blob/master/wallpapers/nixos-wallpaper-catppuccin-macchiato.png?raw=true', + eventName: 'Nix CN Conference 26.05', + description: 'Event Description', + startTime: new Date('2026-06-13T04:00:00.000Z'), + endTime: new Date('2026-06-14T04:00:00.000Z'), + }, + ], + assembleFooter: () => , + }, +}; + +export const Skeleton: Story = { + render: () => , + args: { + events: [], + assembleFooter: () => , + }, +}; diff --git a/client/cms/src/stories/events/kyc-dialog.stories.tsx b/client/cms/src/stories/events/kyc-dialog.stories.tsx new file mode 100644 index 0000000..6314dbe --- /dev/null +++ b/client/cms/src/stories/events/kyc-dialog.stories.tsx @@ -0,0 +1,56 @@ +import type { Meta, StoryObj } from '@storybook/react-vite'; +import { KycFailedDialogView } from '@/components/events/kyc/kyc-failed.dialog.view'; +import { KycMethodSelectionDialogView } from '@/components/events/kyc/kyc-method-selection.dialog.view'; +import { KycPendingDialogView } from '@/components/events/kyc/kyc-pending.dialog.view'; +import { KycPromptDialogView } from '@/components/events/kyc/kyc-prompt.dialog.view'; +import { KycSuccessDialogView } from '@/components/events/kyc/kyc-success.dialog.view'; +import { Dialog } from '@/components/ui/dialog'; + +const meta = { + title: 'Events/KycDialog', + component: KycPromptDialogView, + decorators: [ + Story => ( + + + + ), + ], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Prompt: Story = { + args: { + next: () => { }, + }, +}; + +export const MethodSelection: Story = { + render: () => Promise.resolve()} />, + args: { + next: () => { }, + }, +}; + +export const Pending: Story = { + render: () => , + args: { + next: () => { }, + }, +}; + +export const Success: Story = { + render: () => , + args: { + next: () => { }, + }, +}; + +export const Failed: Story = { + render: () => , + args: { + next: () => { }, + }, +}; diff --git a/client/cms/src/stories/exampleUser.ts b/client/cms/src/stories/exampleUser.ts new file mode 100644 index 0000000..40800ff --- /dev/null +++ b/client/cms/src/stories/exampleUser.ts @@ -0,0 +1,8 @@ +export const user = { + username: 'nvirellia', + nickname: 'Noa Virellia', + subtitle: '天生骄傲', + email: 'noa@requiem.garden', + bio: '', + avatar: 'https://avatars.githubusercontent.com/u/54884471?v=4', +}; diff --git a/client/cms/src/stories/layout/sidebar.stories.tsx b/client/cms/src/stories/layout/sidebar.stories.tsx new file mode 100644 index 0000000..ac2aeac --- /dev/null +++ b/client/cms/src/stories/layout/sidebar.stories.tsx @@ -0,0 +1,46 @@ +import type { Meta, StoryObj } from '@storybook/react-vite'; +import { AppSidebar } from '@/components/sidebar/app-sidebar.view'; +import { NavUserSkeleton } from '@/components/sidebar/nav-user.skeletion'; +import { NavUserView } from '@/components/sidebar/nav-user.view'; +import { SidebarProvider } from '@/components/ui/sidebar'; +import { navData } from '@/lib/navData'; +import { user } from '../exampleUser'; + +const meta = { + title: 'Layout/Sidebar', + component: AppSidebar, + decorators: [ + Story => ( + + + + ), + ], + parameters: { + layout: 'fullscreen', + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Primary: Story = { + args: { + navData, + footerWidget: , + }, +}; + +export const Loading: Story = { + args: { + navData, + footerWidget: , + }, +}; diff --git a/client/cms/src/stories/profile/edit-profile.dialog.stories.tsx b/client/cms/src/stories/profile/edit-profile.dialog.stories.tsx new file mode 100644 index 0000000..e67e929 --- /dev/null +++ b/client/cms/src/stories/profile/edit-profile.dialog.stories.tsx @@ -0,0 +1,37 @@ +import type { Meta, StoryObj } from '@storybook/react-vite'; +import { EditProfileDialogView } from '@/components/profile/edit-profile.dialog.view'; +import { user } from '../exampleUser'; + +const meta = { + title: 'Profile/EditDialog', + component: EditProfileDialogView, + decorators: [ + Story => ( +
+ +
+ ), + ], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Primary: Story = { + args: { + user, + updateProfile: async () => { }, + }, + parameters: { + layout: 'fullscreen', + }, +}; diff --git a/client/cms/src/stories/profile/profile.stories.tsx b/client/cms/src/stories/profile/profile.stories.tsx new file mode 100644 index 0000000..7590c49 --- /dev/null +++ b/client/cms/src/stories/profile/profile.stories.tsx @@ -0,0 +1,48 @@ +import type { Meta, StoryObj } from '@storybook/react-vite'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { ProfileError } from '@/components/profile/profile.error'; +import { ProfileSkeleton } from '@/components/profile/profile.skeleton'; +import { ProfileView } from '@/components/profile/profile.view'; +import { user } from '../exampleUser'; + +const queryClient = new QueryClient(); + +const meta = { + title: 'Profile/View', + component: ProfileView, + decorators: [ + Story => ( + + + + ), + ], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Primary: Story = { + args: { + user, + onSaveBio: async () => Promise.resolve(), + }, +}; + +export const Loading: Story = { + render: () => , + args: { + user: {}, + onSaveBio: async () => Promise.resolve(), + }, +}; + +export const Error: Story = { + render: () => , + args: { + user: { + allow_public: false, + }, + onSaveBio: async () => Promise.resolve(), + }, +}; diff --git a/client/cms/vite.config.ts b/client/cms/vite.config.ts index 06cd972..32346a7 100644 --- a/client/cms/vite.config.ts +++ b/client/cms/vite.config.ts @@ -1,21 +1,24 @@ +/// import path from 'node:path'; +// https://vite.dev/config/ +import { fileURLToPath } from 'node:url'; +import { storybookTest } from '@storybook/addon-vitest/vitest-plugin'; import tailwindcss from '@tailwindcss/vite'; import { tanstackRouter } from '@tanstack/router-plugin/vite'; import react from '@vitejs/plugin-react'; + +import { playwright } from '@vitest/browser-playwright'; import { defineConfig } from 'vite'; import svgr from 'vite-plugin-svgr'; -// https://vite.dev/config/ +const dirname = typeof __dirname !== 'undefined' ? __dirname : path.dirname(fileURLToPath(import.meta.url)); + +// More info at: https://storybook.js.org/docs/next/writing-tests/integrations/vitest-addon export default defineConfig({ - plugins: [ - tanstackRouter({ - target: 'react', - autoCodeSplitting: true, - }), - react(), - tailwindcss(), - svgr(), - ], + plugins: [tanstackRouter({ + target: 'react', + autoCodeSplitting: true, + }), react(), tailwindcss(), svgr()], resolve: { alias: { '@': path.resolve(__dirname, './src'), @@ -29,4 +32,28 @@ export default defineConfig({ port: 5173, allowedHosts: ['nix.org.cn', 'nixos.party'], }, + test: { + projects: [{ + extends: true, + plugins: [ + // The plugin will run tests for the stories defined in your Storybook config + // See options at: https://storybook.js.org/docs/next/writing-tests/integrations/vitest-addon#storybooktest + storybookTest({ + configDir: path.join(dirname, '.storybook'), + }), + ], + test: { + name: 'storybook', + browser: { + enabled: true, + headless: true, + provider: playwright({}), + instances: [{ + browser: 'chromium', + }], + }, + setupFiles: ['.storybook/vitest.setup.ts'], + }, + }], + }, }); diff --git a/client/cms/vitest.shims.d.ts b/client/cms/vitest.shims.d.ts new file mode 100644 index 0000000..7782f28 --- /dev/null +++ b/client/cms/vitest.shims.d.ts @@ -0,0 +1 @@ +/// \ No newline at end of file