From 145472acf3b355d3f147ec5db3380fb974c9bb37 Mon Sep 17 00:00:00 2001
From: Corbin Crutchley
Date: Tue, 1 Sep 2026 16:24:47 -0700
Subject: [PATCH 1/6] chore: initial storybook scaffolding
---
.gitignore | 3 +
.storybook/main.ts | 9 +
.storybook/preview.tsx | 14 +
eslint.config.mjs | 4 +
package.json | 10 +-
pnpm-lock.yaml | 1831 +++++++++++++++++++++++++++++++------
stories/Button.stories.ts | 54 ++
stories/Button.tsx | 43 +
stories/button.css | 30 +
vitest.config.mts | 23 +-
vitest.shims.d.ts | 1 +
11 files changed, 1736 insertions(+), 286 deletions(-)
create mode 100644 .storybook/main.ts
create mode 100644 .storybook/preview.tsx
create mode 100644 stories/Button.stories.ts
create mode 100644 stories/Button.tsx
create mode 100644 stories/button.css
create mode 100644 vitest.shims.d.ts
diff --git a/.gitignore b/.gitignore
index f5e550b..453e44a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -45,3 +45,6 @@ next-env.d.ts
# IDEs
.vscode/
.idea/
+
+*storybook.log
+storybook-static
diff --git a/.storybook/main.ts b/.storybook/main.ts
new file mode 100644
index 0000000..2617af8
--- /dev/null
+++ b/.storybook/main.ts
@@ -0,0 +1,9 @@
+import type { StorybookConfig } from "@storybook/nextjs-vite";
+
+const config: StorybookConfig = {
+ stories: ["../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
+ addons: ["@storybook/addon-mcp"],
+ framework: "@storybook/nextjs-vite",
+ staticDirs: ["../public"],
+};
+export default config;
diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx
new file mode 100644
index 0000000..c0adadc
--- /dev/null
+++ b/.storybook/preview.tsx
@@ -0,0 +1,14 @@
+import type { Preview } from "@storybook/nextjs-vite";
+
+const preview: Preview = {
+ parameters: {
+ controls: {
+ matchers: {
+ color: /(background|color)$/i,
+ date: /Date$/i,
+ },
+ },
+ },
+};
+
+export default preview;
diff --git a/eslint.config.mjs b/eslint.config.mjs
index eedcf90..ce98339 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -1,3 +1,6 @@
+// For more info, see https://github.com/storybookjs/eslint-plugin-storybook#configuration-flat-config-format
+import storybook from "eslint-plugin-storybook";
+
import { defineConfig, globalIgnores } from "eslint/config";
import eslintConfigPrettier from "eslint-config-prettier/flat";
import nextVitals from "eslint-config-next/core-web-vitals";
@@ -14,4 +17,5 @@ export default defineConfig([
"next-env.d.ts",
]),
eslintConfigPrettier,
+ ...storybook.configs["flat/recommended"],
]);
diff --git a/package.json b/package.json
index 6f76ed4..ffdc44a 100644
--- a/package.json
+++ b/package.json
@@ -23,7 +23,9 @@
"db:migrate": "netlify database migrations apply",
"db:status": "netlify database status",
"auth:generate": "BETTER_AUTH_SCHEMA_GENERATION=1 auth generate --config ./lib/auth-config.ts --output ./db/auth-schema.ts --yes",
- "auth:create-admin": "auth create-admin --config ./lib/auth-config.ts"
+ "auth:create-admin": "auth create-admin --config ./lib/auth-config.ts",
+ "storybook": "storybook dev -p 6006",
+ "build-storybook": "storybook build"
},
"dependencies": {
"@better-auth/drizzle-adapter": "1.7.1",
@@ -73,6 +75,10 @@
"prettier": "3.9.6",
"typescript": "^6.0.3",
"vite": "^8.2.1",
- "vitest": "5.0.0-beta.7"
+ "vitest": "5.0.0-beta.7",
+ "storybook": "^10.5.10",
+ "@storybook/nextjs-vite": "^10.5.10",
+ "@storybook/addon-mcp": "^0.7.0",
+ "eslint-plugin-storybook": "^10.5.10"
}
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index eaefde6..2b286a2 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -5,9 +5,7 @@ settings:
excludeLinksFromLockfile: false
patchedDependencies:
- drizzle-orm@1.0.0-rc.4:
- hash: 4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867
- path: patches/drizzle-orm@1.0.0-rc.4.patch
+ drizzle-orm@1.0.0-rc.4: 4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867
importers:
@@ -15,7 +13,7 @@ importers:
dependencies:
'@better-auth/drizzle-adapter':
specifier: 1.7.1
- version: 1.7.1(@better-auth/core@1.7.1(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.1))(@better-auth/utils@0.4.2)(drizzle-orm@1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(zod@4.4.3))
+ version: 1.7.1(@better-auth/core@1.7.1(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.1))(@better-auth/utils@0.4.2)(drizzle-orm@1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(valibot@1.2.0(typescript@6.0.3))(zod@4.4.3))
'@lexical/code':
specifier: 0.49.0
version: 0.49.0(typescript@6.0.3)
@@ -48,19 +46,19 @@ importers:
version: 2.1.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
better-auth:
specifier: 1.7.1
- version: 1.7.1(@opentelemetry/api@1.9.1)(drizzle-kit@1.0.0-rc.4)(drizzle-orm@1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(zod@4.4.3))(next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(pg@8.23.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@5.0.0-beta.7)
+ version: 1.7.1(@opentelemetry/api@1.9.1)(drizzle-kit@1.0.0-rc.4)(drizzle-orm@1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(valibot@1.2.0(typescript@6.0.3))(zod@4.4.3))(next@16.3.1(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(pg@8.23.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@5.0.0-beta.7)
dayjs:
specifier: ^1.11.23
version: 1.11.23
drizzle-orm:
specifier: 1.0.0-rc.4
- version: 1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(zod@4.4.3)
+ version: 1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(valibot@1.2.0(typescript@6.0.3))(zod@4.4.3)
lexical:
specifier: 0.49.0
version: 0.49.0(typescript@6.0.3)
next:
specifier: ^16.3.1
- version: 16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
+ version: 16.3.1(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
react:
specifier: ^19.1.0
version: 19.2.8
@@ -69,13 +67,13 @@ importers:
version: 19.2.8(react@19.2.8)
react-email:
specifier: ^6.9.2
- version: 6.9.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
+ version: 6.9.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(supports-color@10.2.2)
react-markdown:
specifier: 10.1.0
- version: 10.1.0(@types/react@19.2.18)(react@19.2.8)
+ version: 10.1.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2)
remark-gfm:
specifier: 4.0.1
- version: 4.0.1
+ version: 4.0.1(supports-color@10.2.2)
resend:
specifier: ^6.20.0
version: 6.20.0(@react-email/render@2.1.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8))
@@ -91,7 +89,13 @@ importers:
version: 1.0.0
'@react-email/ui':
specifier: 6.9.2
- version: 6.9.2(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
+ version: 6.9.2(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
+ '@storybook/addon-mcp':
+ specifier: ^0.7.0
+ version: 0.7.0(@storybook/addon-vitest@10.5.10(@vitest/browser-playwright@5.0.0-beta.7)(@vitest/browser@5.0.0-beta.7(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-beta.7))(react@19.2.8)(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(vitest@5.0.0-beta.7))(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(typescript@6.0.3)
+ '@storybook/nextjs-vite':
+ specifier: ^10.5.10
+ version: 10.5.10(@babel/core@7.29.7(supports-color@10.2.2))(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(esbuild@0.28.1)(next@16.3.1(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(supports-color@10.2.2)(typescript@6.0.3)(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
'@testing-library/dom':
specifier: ^10.4.1
version: 10.4.1
@@ -121,28 +125,34 @@ importers:
version: 5.0.0-beta.7(playwright@1.62.1)(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-beta.7)
auth:
specifier: ^1.7.1
- version: 1.7.1(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(chokidar@5.0.0)(drizzle-kit@1.0.0-rc.4)(drizzle-orm@1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.1)(next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(pg@8.23.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@5.0.0-beta.7)
+ version: 1.7.1(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(chokidar@5.0.0)(drizzle-kit@1.0.0-rc.4)(drizzle-orm@1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(valibot@1.2.0(typescript@6.0.3))(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.1)(next@16.3.1(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(pg@8.23.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(supports-color@10.2.2)(vitest@5.0.0-beta.7)
drizzle-kit:
specifier: 1.0.0-rc.4
version: 1.0.0-rc.4
eslint:
specifier: ^9.31.0
- version: 9.39.5(jiti@2.7.0)
+ version: 9.39.5(jiti@2.7.0)(supports-color@10.2.2)
eslint-config-next:
specifier: ^16.3.1
- version: 16.3.1(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3)
+ version: 16.3.1(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
eslint-config-prettier:
specifier: 10.1.8
- version: 10.1.8(eslint@9.39.5(jiti@2.7.0))
+ version: 10.1.8(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))
+ eslint-plugin-storybook:
+ specifier: ^10.5.10
+ version: 10.5.10(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
netlify-cli:
specifier: ^27.1.2
- version: 27.1.2(@types/node@24.13.3)(picomatch@4.0.5)
+ version: 27.1.2(@types/node@24.13.3)(picomatch@4.0.5)(supports-color@10.2.2)
playwright:
specifier: 1.62.1
version: 1.62.1
prettier:
specifier: 3.9.6
version: 3.9.6
+ storybook:
+ specifier: ^10.5.10
+ version: 10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8)
typescript:
specifier: ^6.0.3
version: 6.0.3
@@ -528,15 +538,30 @@ packages:
'@emnapi/core@1.10.0':
resolution: {integrity: sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==}
+ '@emnapi/core@1.11.0':
+ resolution: {integrity: sha512-l9Oo58x0HOP5znGzVhYW9U3e5wVuA4LAZU2AGezTmkhO1CgQRFDhDg4nneHsu/t3WniXg9QrG2nIXL/ZS8ln8Q==}
+
+ '@emnapi/core@1.9.2':
+ resolution: {integrity: sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==}
+
'@emnapi/runtime@1.10.0':
resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==}
+ '@emnapi/runtime@1.11.0':
+ resolution: {integrity: sha512-55coeOFKHv1ywEcUXJtWU5f+Jr/W5tZDvZig8DLKSwUN1JpROQ4rk/SNOQiFWmaR/VKF4zuFyW1B8JduOSv6Pg==}
+
'@emnapi/runtime@1.11.3':
resolution: {integrity: sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==}
+ '@emnapi/runtime@1.9.2':
+ resolution: {integrity: sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==}
+
'@emnapi/wasi-threads@1.2.1':
resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==}
+ '@emnapi/wasi-threads@1.2.2':
+ resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==}
+
'@envelop/instrumentation@1.0.0':
resolution: {integrity: sha512-cxgkB66RQB95H3X27jlnxCRNTmPuSTgmBAq6/4n2Dtv4hsk4yz8FadA1ggmd0uZzvKqWD6CR+WFgTjhDqg7eyw==}
engines: {node: '>=18.0.0'}
@@ -1312,6 +1337,15 @@ packages:
resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==}
engines: {node: '>=18.0.0'}
+ '@joshwooding/vite-plugin-react-docgen-typescript@0.7.0':
+ resolution: {integrity: sha512-qvsTEwEFefhdirGOPnu9Wp6ChfIwy2dBCRuETU3uE+4cC+PFoxMSiiEhxk4lOluA34eARHA0OxqsEUYDqRMgeQ==}
+ peerDependencies:
+ typescript: '>= 4.3.x'
+ vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
'@jridgewell/gen-mapping@0.3.13':
resolution: {integrity: sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==}
@@ -1819,6 +1853,9 @@ packages:
'@next/env@16.3.0':
resolution: {integrity: sha512-o9r1S0BNiNreHP9Vs+Qnqd9kviDkJh8xIACY7UFZSmiGbbQRzPBBosvHzAU4TULHOIuOj/18RSsyz2qrREmIFw==}
+ '@next/env@16.3.0-preview.5':
+ resolution: {integrity: sha512-XqdVR0utAWMsVc1OIyO48D32vrdmC4/uAgI3Ds088YlOO4vfGKXXVyvkGFkOZkOK0xg7bNYNfJAarX4A0tYqGg==}
+
'@next/env@16.3.1':
resolution: {integrity: sha512-35G3xwkQUb2oETSDjFXGrVugknoayLFBh7vSE+yAcl9IP2zT9wyGwq7297AYHR11kJld807t5f8AJBs6WBzXsQ==}
@@ -2075,9 +2112,242 @@ packages:
resolution: {integrity: sha512-eSYWTm620tTk45EKSedaUL8MFYI8hW164hIXsgIHyxu3VobUB3fFCu5t0hQby6OoWRPsG1KkKUG2M5UadiLiVg==}
engines: {node: '>=14'}
+ '@oxc-parser/binding-android-arm-eabi@0.127.0':
+ resolution: {integrity: sha512-0LC7ye4hvqbIKxAzThzvswgHLFu2AURKzYLeSVvLdu2TBOYWQDmHnTqPLeA597BcUCxiLqLsS4CJ5uoI5WYWCQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm]
+ os: [android]
+
+ '@oxc-parser/binding-android-arm64@0.127.0':
+ resolution: {integrity: sha512-b5jtVTH6AU5CJXHNdj7Jj9IEiR9yVjjnwHzPJhGyHGPdcsZSzBCkS9GBbV33niRMvKthDwQRFRJfI4a+k4PvYg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [android]
+
+ '@oxc-parser/binding-darwin-arm64@0.127.0':
+ resolution: {integrity: sha512-obCE8B7ISKkJidjlhv9xRGJPOSDG2Yu6PRga9Ruaz35uintHxbp1Ki/Yc71wx4rj3Edrm0a1kzG1TAwit0wFpg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@oxc-parser/binding-darwin-x64@0.127.0':
+ resolution: {integrity: sha512-JL6Xb5IwPQT8rUzlpsX7E+AgfcdNklXNPFp8pjCQQ5MQOQo5rtEB2ui+3Hgg9Sn7Y9Egj6YOLLiHhLpdAe12Aw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [darwin]
+
+ '@oxc-parser/binding-freebsd-x64@0.127.0':
+ resolution: {integrity: sha512-SDQ/3MQFw58fqQz3Z1PhSKFF3JoCF4gmlNjziDm8X02tTahCw0qJbd7FGPDKw1i4VTBZene9JPyC3mHtSvi+wA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@oxc-parser/binding-linux-arm-gnueabihf@0.127.0':
+ resolution: {integrity: sha512-Av+D1MIqzV0YMGPT9we2SIZaMKD7Cxs4CvXSx/yxaWHewZjYEjScpOf5igc8IILASViw4WTnjlwUdI1KzVtDHQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm]
+ os: [linux]
+
+ '@oxc-parser/binding-linux-arm-musleabihf@0.127.0':
+ resolution: {integrity: sha512-Cs2fdJ8cPpFdeebj6p4dag8A4+56hPvZ0AhQQzlaLswGz1tz7bXt1nETLeorrM9+AMcWFFkqxcXwDGfTVidY8g==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm]
+ os: [linux]
+
+ '@oxc-parser/binding-linux-arm64-gnu@0.127.0':
+ resolution: {integrity: sha512-qdOfTcT6SY8gsJrrV92uyEUyjqMGPpIB5JZUG6QN5dukYd+7/j0kX6MwK1DgQj39jtUYixxPiaRUiEN1+0CXgQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [linux]
+ libc: [glibc]
+
+ '@oxc-parser/binding-linux-arm64-musl@0.127.0':
+ resolution: {integrity: sha512-EoTCZneNFU/P2qrpEM+RHmQwt+CvDkyGESG6qhr7KaegXLZwePfbrkCDfAk8/rhxbDUVGsZILX+2tqPzFtoFWA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [linux]
+ libc: [musl]
+
+ '@oxc-parser/binding-linux-ppc64-gnu@0.127.0':
+ resolution: {integrity: sha512-zALjmZYgxFLHjXeudcDF0xFGNydTAtkAeXAr2EuC17ywCyFxcmQra4w0BMde0Yi/re4Bi4iwEoEXtYN7l6eBLQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [ppc64]
+ os: [linux]
+ libc: [glibc]
+
+ '@oxc-parser/binding-linux-riscv64-gnu@0.127.0':
+ resolution: {integrity: sha512-fPP8M6zQLS7Jz7o9d5ArUSuAuSK3e+WCYVrCpdzeCOejidtZExJ9tjhDrAd3HEPqARBCPmdpqxESPFqy44vkBQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [riscv64]
+ os: [linux]
+ libc: [glibc]
+
+ '@oxc-parser/binding-linux-riscv64-musl@0.127.0':
+ resolution: {integrity: sha512-7IcC4Ao02oGpfnjt+X/oF4U2mllo2qoSkw5xxiXNKL9MCTsTiAC6616beOuehdxGcnz1bRoPC1RQ2f1GQDdN+g==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [riscv64]
+ os: [linux]
+ libc: [musl]
+
+ '@oxc-parser/binding-linux-s390x-gnu@0.127.0':
+ resolution: {integrity: sha512-pbXIhiNFHoqWeqDNLiJ9JkpHz1IM9k4DXa66x+1GTWMG7iLxtkXgE53iiuKSXwmk3zIYmaPVfBvgcAhS583K4Q==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [s390x]
+ os: [linux]
+ libc: [glibc]
+
+ '@oxc-parser/binding-linux-x64-gnu@0.127.0':
+ resolution: {integrity: sha512-MYCguB9RvBvlSd6gbuNI7QwiLoCCAlGnlRJFPrzLI6U1/9wkC/WK6LtBAUln55H1Ctqw45PWmqrobKoMhsYQzQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+
+ '@oxc-parser/binding-linux-x64-musl@0.127.0':
+ resolution: {integrity: sha512-5eY0B/bxf1xIUxb4NOTvOI3KWtBQfPWYyKAzgcrCt0mDibSZygVpO1Pz8bkeiSZ5Jj9+M09dkggG3H8I5d0Uyg==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
+
+ '@oxc-parser/binding-openharmony-arm64@0.127.0':
+ resolution: {integrity: sha512-Gld0ajrFTUXNtdw20fVBuTQx66FA75nIVg+//pPfR3sXkuABB4mTBhl3r9JNzrJpgW//qiwxf0nWXUWGJSL3UQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@oxc-parser/binding-wasm32-wasi@0.127.0':
+ resolution: {integrity: sha512-T6KVD7rhLzFlwGRXMnxUFfkCZD8FHnb968wVXW1mXzgRFc5RNXOBY2mPPDZ77x5Ln76ltLMgtPg0cOkU1NSrEQ==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [wasm32]
+
+ '@oxc-parser/binding-win32-arm64-msvc@0.127.0':
+ resolution: {integrity: sha512-Ujvw4X+LD1CCGULcsQcvb4YNVoBGqt+JHgNNzGGaCImELiZLk477ifUH53gIbE7EKd933NdTi25JWEr9K2HwXw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [arm64]
+ os: [win32]
+
+ '@oxc-parser/binding-win32-ia32-msvc@0.127.0':
+ resolution: {integrity: sha512-0cwxKO7KHQQQfo4Uf4B2SQrhgm+cJaP9OvFFhx52Tkg4bezsacu83GB2/In5bC415Ueeym+kXdnge/57rbSfTw==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [ia32]
+ os: [win32]
+
+ '@oxc-parser/binding-win32-x64-msvc@0.127.0':
+ resolution: {integrity: sha512-rOrnSQSCbhI2kowr9XxE7m9a8oQXnBHjnS6j95LxxAnEZ0+Fz20WlRXG4ondQb+ejjt2KOsa65sE6++L6kUd+w==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+ cpu: [x64]
+ os: [win32]
+
+ '@oxc-project/types@0.127.0':
+ resolution: {integrity: sha512-aIYXQBo4lCbO4z0R3FHeucQHpF46l2LbMdxRvqvuRuW2OxdnSkcng5B8+K12spgLDj93rtN3+J2Vac/TIO+ciQ==}
+
'@oxc-project/types@0.144.0':
resolution: {integrity: sha512-nuhZIOLuI6TFQ32I/WnUx+SCPY7SdSKwgnFHydAuoS1+Z4BRcaP+RRJmGzl9lw+0OFF7UmaESf7KQRXaNLHypg==}
+ '@oxc-resolver/binding-android-arm-eabi@11.21.2':
+ resolution: {integrity: sha512-xQoCRv+gKax9KTdwdaQNnAFOai8neay7g3jExDIORzhbrejwGSJaZNTdOJHR5ziLg2joMxOCMOFMo4zuxza2uQ==}
+ cpu: [arm]
+ os: [android]
+
+ '@oxc-resolver/binding-android-arm64@11.21.2':
+ resolution: {integrity: sha512-HF5oiE2L05yInPYCFD/4uxSrEZW4SuIfn99Y6L1xnJnzl066JR+MJs2rIdstw8A2MPlAKH+13dpFPNycjqzvGg==}
+ cpu: [arm64]
+ os: [android]
+
+ '@oxc-resolver/binding-darwin-arm64@11.21.2':
+ resolution: {integrity: sha512-UX4u49CVCAD8QZNELaW8eMGgMAGwFWYEPbvNsh+3r/gs4NX3KfpiACMVwRQT0EuH3uat9hM5Zl+Ppm9pJD8tgg==}
+ cpu: [arm64]
+ os: [darwin]
+
+ '@oxc-resolver/binding-darwin-x64@11.21.2':
+ resolution: {integrity: sha512-J9xPx7YBkrRmJ+xl561ztnMWEc1aOyjEIxBiGX1dVb3u7bGSnfObfcZk+Pd+uM0HZAPNsQ1xvD8j52A/uOSqNQ==}
+ cpu: [x64]
+ os: [darwin]
+
+ '@oxc-resolver/binding-freebsd-x64@11.21.2':
+ resolution: {integrity: sha512-fRlt7OvSaQkWj6+EDTVxawVxOlqJB2QSnBfkeCyK4RTvsGctbw3BiH2Tb7DzMs7bikc4BRBpvWP5zF9K8b54Zg==}
+ cpu: [x64]
+ os: [freebsd]
+
+ '@oxc-resolver/binding-linux-arm-gnueabihf@11.21.2':
+ resolution: {integrity: sha512-gK+vPUcPQITkGwBKpZGrcDHSlU6eDGl7AQacxS2CEKAZIBHWkOVFeJwLZ4tYnA1acJqRM5lt7yYwPCVqGHIJ7A==}
+ cpu: [arm]
+ os: [linux]
+
+ '@oxc-resolver/binding-linux-arm-musleabihf@11.21.2':
+ resolution: {integrity: sha512-L/Rgas7SrOKy/z7IH+HxSFRqVO4PuLDKLEGKvnhoCBBq3UJ0YzGBou3qMzaAGgkJwsIvX2pBF+7ojzfUhLiZxQ==}
+ cpu: [arm]
+ os: [linux]
+
+ '@oxc-resolver/binding-linux-arm64-gnu@11.21.2':
+ resolution: {integrity: sha512-CUEYvlX1Fk7E9kUMzuswru1J9HLxMwnpDeQGjQuI4ZH+iNCoa2X9T+pvyzrbsgl7WnIeTFTlNlHsRfVdf5g9/g==}
+ cpu: [arm64]
+ os: [linux]
+ libc: [glibc]
+
+ '@oxc-resolver/binding-linux-arm64-musl@11.21.2':
+ resolution: {integrity: sha512-ViN1ZibQyxwC67GpoP33oo+S9UyUnkog13vzQb9+v9bCNvrVzJuk0MRdacjtv/9xfRMVF/eqHFyl8YOeykI10Q==}
+ cpu: [arm64]
+ os: [linux]
+ libc: [musl]
+
+ '@oxc-resolver/binding-linux-ppc64-gnu@11.21.2':
+ resolution: {integrity: sha512-CU1sCqWnhGqYD5I1HedHk5pujrn7ssDkNB/AEQd/pd3D/EojVSgJUlpbafwIbyhia3PgIfkvdFpRPWSALzVumA==}
+ cpu: [ppc64]
+ os: [linux]
+ libc: [glibc]
+
+ '@oxc-resolver/binding-linux-riscv64-gnu@11.21.2':
+ resolution: {integrity: sha512-jWVyZtIHca4Gb96x7dag+y69vlei7ffjrsveLkmf2ZhqEAz6ZSBnY1GWvgZUaZlwZP62A3xD092BW97Q5VGc+g==}
+ cpu: [riscv64]
+ os: [linux]
+ libc: [glibc]
+
+ '@oxc-resolver/binding-linux-riscv64-musl@11.21.2':
+ resolution: {integrity: sha512-LF29obFqNgBUgDX7rmUK7M4D0JQG5LxhYzn3xXmECcHU9aQAdWG7NiY052qybtesEdwHQXKNTWYQ7mTsybNvWg==}
+ cpu: [riscv64]
+ os: [linux]
+ libc: [musl]
+
+ '@oxc-resolver/binding-linux-s390x-gnu@11.21.2':
+ resolution: {integrity: sha512-+NYcm+cCHBbtdQQ3A4phQTSuVRYnNHz7wrl9XRAPEovcdoqi0mb1K5ZOl+jN54ZD+q1zz3V0vltbFJmzecJKmw==}
+ cpu: [s390x]
+ os: [linux]
+ libc: [glibc]
+
+ '@oxc-resolver/binding-linux-x64-gnu@11.21.2':
+ resolution: {integrity: sha512-UQqZDdG2r2HhAOsZEgufkIWHPQ886IUyuJQkoZByvzhW8j51R4UNzGBJFkTiTnLhQnggwJRdJgFWK4uY6ZVIMw==}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+
+ '@oxc-resolver/binding-linux-x64-musl@11.21.2':
+ resolution: {integrity: sha512-3Q9PMRjalWkT6NZ4jfujuqTCFwoWErg3y3BnOgb544B8IMw4PktiwWOigMfOHNRLMghZeJ7hpfpZf4CP7rV7Og==}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
+
+ '@oxc-resolver/binding-openharmony-arm64@11.21.2':
+ resolution: {integrity: sha512-Eljeq3ndtyKhM+Es8LITi4Zl2htzuRZcrPMF3kMCsrILztvU6AjZ3FuEhHHKobPUB9rMpzLpJP5bDqXI7r+iog==}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@oxc-resolver/binding-wasm32-wasi@11.21.2':
+ resolution: {integrity: sha512-HGDbNsIywqc4LxU38+CTJNnB/6BF7rheWOJ259b4eE0aEnelYblC8x+1tEd63bp31fYne63RQz9Jb4yVnC7Yig==}
+ engines: {node: '>=14.0.0'}
+ cpu: [wasm32]
+
+ '@oxc-resolver/binding-win32-arm64-msvc@11.21.2':
+ resolution: {integrity: sha512-iWx25CBEgH49iE9q5coEGI/jb1jl5kkCY9z6U5Og67xCkQ/WFMDc2J5U78+AE91SUxM2NqSLhJC8/PLfWnImww==}
+ cpu: [arm64]
+ os: [win32]
+
+ '@oxc-resolver/binding-win32-x64-msvc@11.21.2':
+ resolution: {integrity: sha512-VPoCAhKvCQTlG7vxqaBXcmuvbh77BfnGXj8g0pbvVXpm1F/R8rDVwqIWcEbMzrI1JvJlm8v7T9uMVQb6UctMRg==}
+ cpu: [x64]
+ os: [win32]
+
'@parcel/watcher-wasm@2.6.0':
resolution: {integrity: sha512-dtjbDxKSDPQ8AmA+pS4OFaHE1FKrjtGpLGBxw85uKFkRorjNbvDM/aFPgqosu40wprbp1xw2ZSxIKqghCUHe2w==}
engines: {node: '>= 10.0.0'}
@@ -2258,6 +2528,130 @@ packages:
'@standard-schema/spec@1.1.0':
resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==}
+ '@storybook/addon-mcp@0.7.0':
+ resolution: {integrity: sha512-f/IWGRMzWynBg5kDJ3DYvvnafuSX88kykGNFzzLOlkLVpfxEZoAmQF6AS47tw25GuH6EFIqSo6ZDBLHLVyZ/IQ==}
+ peerDependencies:
+ '@storybook/addon-vitest': ^0.0.0-0 || ^9.1.16 || ^10.0.0 || ^10.1.0-0 || ^10.2.0-0 || ^10.3.0-0 || ^10.4.0-0 || ^10.5.0-0
+ storybook: ^0.0.0-0 || ^9.1.16 || ^10.0.0 || ^10.1.0-0 || ^10.2.0-0 || ^10.3.0-0 || ^10.4.0-0 || ^10.5.0-0
+ peerDependenciesMeta:
+ '@storybook/addon-vitest':
+ optional: true
+
+ '@storybook/addon-vitest@10.5.10':
+ resolution: {integrity: sha512-JNQ9DSkLfxC8qqytBCej91zBExIZ7z97B410U2zgfQPki4HkI9Ffz97a15f5yhVZ79ppIrZ/ssI+WcyWn0ykXQ==}
+ 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.5.10
+ 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.5.10':
+ resolution: {integrity: sha512-O4GgIP0tKLRueom3EmU3OaBUHKjNYj+jkOvmTIkn3PYTiWVkCuHqSKEs4ADvRyaQuLH+peHhFe4JtkNC9KbtrQ==}
+ peerDependencies:
+ storybook: ^10.5.10
+ vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0
+
+ '@storybook/csf-plugin@10.5.10':
+ resolution: {integrity: sha512-TaCLBrqVEr767+w58QDotDUiCTuE5cyRJuRcDlsKQyUIyGBv+lYD3lu8wBiVCYxgIjB/gu9HmqiC+0yx1rHzaw==}
+ peerDependencies:
+ esbuild: '*'
+ rollup: '*'
+ storybook: ^10.5.10
+ 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.1.0':
+ resolution: {integrity: sha512-Fxh9vYpX9bQqFeHRiY8h2ApeRGDzRSMLwJwNZ/AIRqnyOKHxRKL+yFe+ctEkVJmuptRE9u1Hrn8ZZNHyfDKKNg==}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+
+ '@storybook/mcp@0.8.0':
+ resolution: {integrity: sha512-G+XDgoWGrE98moXqKSee8fQyMQxoIWxRAbPG8r/HQ95pKodratevDqNyOgW+t6ZigM6AAVN1WHiFc5MI+hc8sg==}
+
+ '@storybook/nextjs-vite@10.5.10':
+ resolution: {integrity: sha512-kDzhmW3pXWVI/trOcBu0XG7irieTBBdezL3gtmw6ZVyY7RJWWMlkzbVdXha76eWCM78kseLHafAxu8KgOsCI4w==}
+ peerDependencies:
+ '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ '@types/react-dom': ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ next: ^14.1.0 || ^15.0.0 || ^16.0.0
+ 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.5.10
+ typescript: '*'
+ vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ typescript:
+ optional: true
+
+ '@storybook/react-dom-shim@10.5.10':
+ resolution: {integrity: sha512-rbu62ILo/VE3iXKmu+kWXFpD1H1Lwi0f19q/x7JnDsD2dxKS9w5znLEqPIq2qxpzi/wjjIb2iUP1cRG1d/9W5A==}
+ peerDependencies:
+ '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ '@types/react-dom': ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ 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.5.10
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@storybook/react-vite@10.5.10':
+ resolution: {integrity: sha512-xOztxefUnqKeuyvcnjspqmlDnER4cExL+liltrpdXLPJVqfFNr9lgM49FyEPajzsUVG9W/vHJWjbaQGGu1UsYQ==}
+ 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.5.10
+ typescript: '>= 4.9.x'
+ vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
+ '@storybook/react@10.5.10':
+ resolution: {integrity: sha512-4MBV5e1SXIMfPynLHzr+Mp0dwGv/FW1bklWAsS4ynBOAbC98W9p/I9vqBnUctsvE3BJkhzHQQyPwMHL5tTcHVA==}
+ peerDependencies:
+ '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ '@types/react-dom': ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ 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.5.10
+ typescript: '>= 4.9.x'
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+ typescript:
+ optional: true
+
'@sveltejs/acorn-typescript@1.0.13':
resolution: {integrity: sha512-wgKggnhZVL9Bfx1OaKKTrYY9BFRk6C8UAkQNUcIv1+llzYrIqy+RZm5HPKzn0NpEBvTVhTqB4kQyllZywsRBRQ==}
peerDependencies:
@@ -2273,6 +2667,10 @@ packages:
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/jest-dom@7.0.1':
resolution: {integrity: sha512-oMDTC3oA+6CXSO2JZnvOI7CA6oVub6kij5ggk9ohwye5slmkwxYDXcPOVxgMw/RQlticjtO0C1RZkR97HgrWMw==}
engines: {node: '>=22', npm: '>=6', yarn: '>=1'}
@@ -2298,6 +2696,32 @@ packages:
'@types/react-dom':
optional: true
+ '@testing-library/user-event@14.6.6':
+ resolution: {integrity: sha512-Jbs9FpkkIDw8FgSc6kOVsOv8JuuqGAL7J4X1oot77JxAoDlkNn2GRkd0aYRVuQ+pVQAiHWVkE4rX/dkF5fBiCw==}
+ engines: {node: '>=12', npm: '>=6'}
+ peerDependencies:
+ '@testing-library/dom': '>=7.21.4'
+
+ '@tmcp/adapter-valibot@0.1.6':
+ resolution: {integrity: sha512-drirZeNinhYLiRSMksN+m//u0ImFxtGRk1Vp425Xp/7CbBXFQdjAG+f7grssyHAukbVTGzmWsMMP6ejrGVErUA==}
+ peerDependencies:
+ tmcp: ^1.17.0
+ valibot: ^1.1.0
+
+ '@tmcp/session-manager@0.2.2':
+ resolution: {integrity: sha512-UrCRpTsxh5XnMbplspvftEYboiZWgAiXqqAUbyFTHoHMJ0LoNDy8bQd0+7qtxtT4S5Qsnv650gvs/Nbec5NTCQ==}
+ peerDependencies:
+ tmcp: ^1.16.3
+
+ '@tmcp/transport-http@0.8.6':
+ resolution: {integrity: sha512-iLcxu+tEMbkVHbhFfyXQhxfPDDTfm+F0kEw8Xg/a1rm29s4cBg1vwcpbtk02XTxsdDh8RJ1AZkQwF9WDGeb/IA==}
+ peerDependencies:
+ '@tmcp/auth': ^0.3.3 || ^0.4.0
+ tmcp: ^1.18.0
+ peerDependenciesMeta:
+ '@tmcp/auth':
+ optional: true
+
'@tsconfig/node10@1.0.13':
resolution: {integrity: sha512-gcLdvR9HO1ZJBypsOGqaP6TFEzb6vIta0KSTLt9NAQ6pXQO3cRgSVyCN6pzYqI9DlJgY71XKO0dpDhCf08b3pg==}
@@ -2316,6 +2740,18 @@ packages:
'@types/aria-query@5.0.4':
resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==}
+ '@types/babel__core@7.20.5':
+ resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==}
+
+ '@types/babel__generator@7.27.0':
+ resolution: {integrity: sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==}
+
+ '@types/babel__template@7.4.4':
+ resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==}
+
+ '@types/babel__traverse@7.28.0':
+ resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==}
+
'@types/chai@5.2.3':
resolution: {integrity: sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==}
@@ -2328,6 +2764,9 @@ packages:
'@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==}
@@ -2366,6 +2805,9 @@ packages:
'@types/react@19.2.18':
resolution: {integrity: sha512-AnzbBERsrLKtk2XSfTbYRLjQPdy116Sty4q+T+Bp3IC4l6jNBvreVPAHmpq9qhXQM7CXZPjLVmGMw9sy+hxQ3w==}
+ '@types/resolve@1.20.6':
+ resolution: {integrity: sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==}
+
'@types/retry@0.12.2':
resolution: {integrity: sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==}
@@ -2569,6 +3011,11 @@ packages:
cpu: [x64]
os: [win32]
+ '@valibot/to-json-schema@1.7.1':
+ resolution: {integrity: sha512-3qkmU6KXWh8GIThEAW3kuRHPQBMjWkKy+Ppz3WkUucx53DTpOa6siMn4xDGSOhlVyMrDaJTCTMLYPZVAIk1P0A==}
+ peerDependencies:
+ valibot: ^1.4.0
+
'@vercel/nft@0.29.4':
resolution: {integrity: sha512-6lLqMNX3TuycBPABycx7A9F1bHQR7kiQln6abjFbPrf5C/05qHM9M5E4PeTE59c7z8g6vHnx1Ioihb2AQl7BTA==}
engines: {node: '>=18'}
@@ -2598,6 +3045,9 @@ packages:
peerDependencies:
vitest: 5.0.0-beta.7
+ '@vitest/expect@3.2.4':
+ resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==}
+
'@vitest/mocker@5.0.0-beta.7':
resolution: {integrity: sha512-SczTGMNh6ksM5r8ogUwAf8zVbQPgbc6yvdZO9xBsTKT2rLUwpHn95Upod0s0Cpm3/bH898iqRBLXovRZSUbJBg==}
peerDependencies:
@@ -2609,9 +3059,15 @@ packages:
vite:
optional: true
+ '@vitest/pretty-format@3.2.4':
+ resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==}
+
'@vitest/pretty-format@5.0.0-beta.7':
resolution: {integrity: sha512-mYUiYNj9BcF4BawuqncdUlR+zNNbWOWBNsp57jJon2Gq5R2fMqTYQJWHpfvkNqkAAgt/lC6bH5+JISjLIhHa4w==}
+ '@vitest/spy@3.2.4':
+ resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==}
+
'@vitest/spy@5.0.0-beta.7':
resolution: {integrity: sha512-NiE4frPDnDjFaMvaZaj4ASyxc/c2fvSQU8Fpo7D0YNj9AetE4hcA7ewRxhlrg6dHEOt1JhhCgy67e8SCXDh5VQ==}
@@ -2620,6 +3076,9 @@ packages:
peerDependencies:
vitest: 5.0.0-beta.7
+ '@vitest/utils@3.2.4':
+ resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==}
+
'@vitest/utils@5.0.0-beta.7':
resolution: {integrity: sha512-DFjgVac0frIqGUZnQCd8lTGYfWnPJfzUNhOubZuvUMgzb+v0mdJjeMEcpmesujZIPasFOR+SzsQ4dS/BCEWGvg==}
@@ -2638,6 +3097,9 @@ packages:
'@vue/shared@3.5.41':
resolution: {integrity: sha512-IOnwSCma8j+9xJT6b8H0dEYidC80NsYmNMlZxRsukYcSoGaDBohog5hDxzeUXdFeGWFA++vWvxqOmrr96VlqMA==}
+ '@webcontainer/env@1.1.1':
+ resolution: {integrity: sha512-6aN99yL695Hi9SuIk1oC88l9o0gmxL1nGWWQ/kNy81HigJ0FoaoTXpytCj6ItzgyCEwA9kF1wixsTuv5cjsgng==}
+
'@whatwg-node/disposablestack@0.0.6':
resolution: {integrity: sha512-LOtTn+JgJvX8WfBVJtF08TGrdjuFzGJc4mkP8EdDI8ADbvO7kiexYep1o8dwnt0okb0jYclCDXF13xU7Ge4zSw==}
engines: {node: '>=18.0.0'}
@@ -2837,6 +3299,10 @@ packages:
ast-types-flow@0.0.8:
resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==}
+ ast-types@0.16.3:
+ resolution: {integrity: sha512-FvWoWYfSCM6kRxCSH+MGLHIKKGRL6A6AW7Zek2O32REPQRdg131428uRTKMBYAeRd3XXAaHDS60Wpri7CdKDrA==}
+ engines: {node: '>=4'}
+
async-function@1.0.0:
resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==}
engines: {node: '>= 0.4'}
@@ -3143,6 +3609,10 @@ 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'}
@@ -3170,6 +3640,10 @@ packages:
chardet@2.2.0:
resolution: {integrity: sha512-rddelWYNPRrXq6PtNEN2S3f6t9ILzvqaN5pVgi4kqt9jHQaXIial9PznB5iSPVlQSLNaaH22ItWz3EJtQ10+OA==}
+ check-error@2.1.3:
+ resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==}
+ engines: {node: '>= 16'}
+
chevrotain@12.0.0:
resolution: {integrity: sha512-csJvb+6kEiQaqo1woTdSAuOWdN0WTLIydkKrBnS+V5gZz0oqBrp4kQ35519QgK6TpBThiG3V1vNSHlIkv4AglQ==}
engines: {node: '>=22.0.0'}
@@ -3495,6 +3969,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-extend@0.6.0:
resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==}
engines: {node: '>=4.0.0'}
@@ -3604,6 +4082,10 @@ packages:
resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==}
engines: {node: '>=0.10.0'}
+ doctrine@3.0.0:
+ resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
+ engines: {node: '>=6.0.0'}
+
dom-accessibility-api@0.5.16:
resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==}
@@ -4035,6 +4517,11 @@ packages:
peerDependencies:
eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7
+ eslint-plugin-storybook@10.5.10:
+ resolution: {integrity: sha512-NeOu3axmhNZfRuHRciFH0a/OVgvtAJLRHAwiJjcGkPAcElNmwEPp+pqoiwxytx7kHInz7mVVoBfPwVc8kPmOLw==}
+ peerDependencies:
+ eslint: '>=8'
+
eslint-scope@8.4.0:
resolution: {integrity: sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -4054,6 +4541,7 @@ packages:
eslint@9.39.5:
resolution: {integrity: sha512-DgZS62aPLXKlnxILS/AYCoRvHaZeXceIzlXPkkGGzJWSow1aEk0lbTlxUSlyjC8jcaKxAdOnTDz+o1JFSBsyjw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+ deprecated: This version is no longer supported. Please see https://eslint.org/version-support for other options.
hasBin: true
peerDependencies:
jiti: '*'
@@ -4061,6 +4549,9 @@ packages:
jiti:
optional: true
+ esm-env@1.2.2:
+ resolution: {integrity: sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==}
+
espree@10.4.0:
resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -4458,6 +4949,9 @@ packages:
resolution: {integrity: sha512-0Ia46fDOaT7k4og1PDW4YbodWWr3scS2vAr2lTbsplOt2WkKp0vQbkI9wKis/T5LV/dqPjO3bpS/z6GTJB82LA==}
engines: {node: '>=18'}
+ globrex@0.1.2:
+ resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==}
+
gonzales-pe@4.3.0:
resolution: {integrity: sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ==}
engines: {node: '>=0.6.0'}
@@ -4606,6 +5100,11 @@ packages:
image-meta@0.2.2:
resolution: {integrity: sha512-3MOLanc3sb3LNGWQl1RlQlNWURE5g32aUphrDyFeCsxBTk08iE3VNe4CwsUZ0Qs1X+EfX0+r29Sxdpza4B+yRA==}
+ image-size@2.0.2:
+ resolution: {integrity: sha512-IRqXKlaXwgSMAMtpNzZa1ZAe8m+Sa1770Dhk8VkSsP9LS+iHD62Zd8FQKs8fbPiagBE7BzoFX23cxFnwshpV6w==}
+ engines: {node: '>=16.x'}
+ hasBin: true
+
import-fresh@3.3.1:
resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
engines: {node: '>=6'}
@@ -4961,6 +5460,9 @@ packages:
json-buffer@3.0.1:
resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==}
+ json-rpc-2.0@1.8.0:
+ resolution: {integrity: sha512-4nw+XlJbk5XokA7BtqHGu+0PEiUPfAkRzXXd1Cgjy1c3F2UI/3Gy7yr76wyJEv3X1F1SRGGF8xPAPPhelBiGmA==}
+
json-schema-ref-resolver@3.0.0:
resolution: {integrity: sha512-hOrZIVL5jyYFjzk7+y7n5JDzGlU8rfWDuYyHwGa2WA8/pcmMHezp2xsVwxrebD/Q9t8Nc5DboieySDpCp4WG4A==}
@@ -4988,6 +5490,9 @@ packages:
engines: {node: '>=6'}
hasBin: true
+ jsonc-parser@3.3.1:
+ resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==}
+
jsonpointer@5.0.1:
resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==}
engines: {node: '>=0.10.0'}
@@ -5245,6 +5750,9 @@ packages:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true
+ loupe@3.2.1:
+ resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==}
+
lru-cache@10.4.3:
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
@@ -5525,6 +6033,9 @@ packages:
resolution: {integrity: sha512-gN54ddmyzEg10orwZ2u4OOv+bjpMWdIl5jIkodK97bMq8QBSL5c0D7YX0lT1Ooz+99S7+PvFbnxzdjgHo1r41g==}
engines: {node: '>=18.0.0'}
+ module-alias@2.3.4:
+ resolution: {integrity: sha512-bOclZt8hkpuGgSSoG07PKmvzTizROilUTvLNyrMqvlC9snhs7y7GzjNWAVbISIOlhCP1T14rH1PDAV9iNyBq/w==}
+
module-definition@6.0.2:
resolution: {integrity: sha512-SvAU3lB0+Yjbq55yHY3wkRZBOh+fhU1SnIF3IFbTewv6mtAh7yUT8ACHAJ2mGIJ7tCes2QuCL/cl6m0JSZ/ArA==}
engines: {node: '>=18'}
@@ -5794,6 +6305,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.1:
resolution: {integrity: sha512-NzwMUB6C1D0+Kd+9iMS/H4k+Ck3cTX6Ckyfr/gAGlmvSE1LUQZnEZvWBi4PYmMwH/S5SMeTXnE+9uAz8uF+pWw==}
engines: {node: '>=20'}
@@ -5814,6 +6329,13 @@ packages:
resolution: {integrity: sha512-19YVAg7T+WTrxggPukVq7DjTv6+PJ867TmhCvBsYwmbFCsZd344rq2Ld1p0wo8f8Qrrhgp82c6FJRqdXWtSEhg==}
engines: {node: '>= 0.4'}
+ oxc-parser@0.127.0:
+ resolution: {integrity: sha512-bkgD4qHlN7WxLdX8bLXdaU54TtQtAIg/ZBAfm0aje/mo3MRDo3P0hZSgr4U7O3xfX+fQmR5AP04JS/TGcZLcFA==}
+ engines: {node: ^20.19.0 || >=22.12.0}
+
+ oxc-resolver@11.21.2:
+ resolution: {integrity: sha512-w5tLwYN3Zo24w5EeWJjJWZOwhYqTtC8PS2B1tIt7BZUuqTIcU07sQValbDw+rq7+AuAGzOHklgK+ifsy4lpXfw==}
+
p-event@6.0.1:
resolution: {integrity: sha512-Q6Bekk5wpzW5qIyUP4gdMEujObYstZl6DMMOSenwBvV0BlE5LkDwkjs5yHbZmdCEq2o4RJx4tE1vwxFVf2FG1w==}
engines: {node: '>=16.17'}
@@ -5954,6 +6476,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'}
+
peberminta@0.9.0:
resolution: {integrity: sha512-XIxfHpEuSJbITd1H3EeQwpcZbTLHc+VVr8ANI9t5sit565tsI4/xK3KWTUFE2e6QiangUkh3B0jihzmGnNrRsQ==}
@@ -6204,6 +6730,15 @@ packages:
resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
hasBin: true
+ react-docgen-typescript@2.4.0:
+ resolution: {integrity: sha512-ZtAp5XTO5HRzQctjPU0ybY0RRCQO19X/8fxn3w7y2VVTUbGHDKULPTL4ky3vB05euSgG5NpALhEhDPvQ56wvXg==}
+ peerDependencies:
+ typescript: '>= 4.3.x'
+
+ react-docgen@8.0.3:
+ resolution: {integrity: sha512-aEZ9qP+/M+58x2qgfSFEWH1BxLyHe5+qkLNJOZQb5iGS017jpbRnoKhNRrXPeA6RfBrZO5wZrT9DMC1UqE1f1w==}
+ engines: {node: ^20.9.0 || >=22}
+
react-dom@19.2.8:
resolution: {integrity: sha512-rVprimfGBG3DR+Tq0IQG2DT5PxKth1WIGDmj5yPmlzr4YBe7uyE+Du4oVqTDXZSHGGGXRtTJEGSSePyQCMBglQ==}
peerDependencies:
@@ -6279,6 +6814,10 @@ packages:
real-require@1.0.0:
resolution: {integrity: sha512-P4nbQYQfePJxRSmY+v/KINxVucm4NF3p3s7pJveMTtom52FR4YGltUQLB8idDXwDDWW+eYrWDFbuzUnjoWHF7g==}
+ recast@0.23.21:
+ resolution: {integrity: sha512-mFAyJq9vUbSTARLZUvAEf1z3YxlvAwswbmxMx2mPA/MSm4KmpwvwvhsH/NIrZhyOuwD60Lzyw2qh83uCbgTPYw==}
+ engines: {node: '>= 4'}
+
redent@3.0.0:
resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==}
engines: {node: '>=8'}
@@ -6352,6 +6891,11 @@ packages:
resolve-pkg-maps@1.0.0:
resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==}
+ resolve@1.22.12:
+ resolution: {integrity: sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==}
+ engines: {node: '>= 0.4'}
+ hasBin: true
+
resolve@2.0.0-next.7:
resolution: {integrity: sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==}
engines: {node: '>= 0.4'}
@@ -6620,6 +7164,9 @@ packages:
resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
engines: {node: '>= 10.x'}
+ sqids@0.3.0:
+ resolution: {integrity: sha512-lOQK1ucVg+W6n3FhRwwSeUijxe93b51Bfz5PMRMihVf1iVkl82ePQG7V5vwrhzB11v0NtsR25PSZRGiSomJaJw==}
+
stable-hash@0.0.5:
resolution: {integrity: sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==}
@@ -6653,6 +7200,21 @@ packages:
resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
engines: {node: '>= 0.4'}
+ storybook@10.5.10:
+ resolution: {integrity: sha512-Rz8k9ejFHsi7lbtJTaxZlhCUz4GkbJIKEoKDjXeLfr/ZhXip73E6keKxW0KH8iGeKiCqHAbJCV4YIQrxTOLiig==}
+ hasBin: true
+ peerDependencies:
+ '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+ prettier: ^2 || ^3
+ vite-plus: ^0.1.15 || ^0.2.0
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ prettier:
+ optional: true
+ vite-plus:
+ optional: true
+
streamx@2.28.0:
resolution: {integrity: sha512-1Yowhzjf0ivGMrTIkY9hav5TxobO9qIVqUE41fiCGMGgc3CLlf4MY+9AHmZqBWgDTue0fY9zWjYFVyf6Diuobw==}
@@ -6728,6 +7290,10 @@ packages:
resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
engines: {node: '>=8'}
+ strip-indent@4.1.1:
+ resolution: {integrity: sha512-SlyRoSkdh1dYP0PzclLE7r0M9sgbFKKMFXpFRUMNuKhQSbC6VQIGzq3E0qsfvGJaUFJPGv6Ws1NZ/haTAjfbMA==}
+ engines: {node: '>=12'}
+
strip-json-comments@2.0.1:
resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==}
engines: {node: '>=0.10.0'}
@@ -6833,6 +7399,9 @@ packages:
through@2.3.8:
resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==}
+ tiny-invariant@1.3.3:
+ resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==}
+
tinybench@6.1.3:
resolution: {integrity: sha512-8k25iNSZHnzkjp3nrpEmx6YkrTNs41PzOHYc28DR5Z2l/CId/Nzw+Ume/41jCeDDmCUMPuK5GkQ/VxJaJ2P6Qg==}
engines: {node: '>=20.0.0'}
@@ -6849,10 +7418,18 @@ packages:
resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==}
engines: {node: '>=12.0.0'}
+ tinyrainbow@2.0.0:
+ resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==}
+ engines: {node: '>=14.0.0'}
+
tinyrainbow@3.1.1:
resolution: {integrity: sha512-yau8yJdTt989Mm0Bd/236QnzEiPf2xLLTqUZRUJOo/3CB078LSwzei343DgtJVmfJKJE3TMINY1u42SQsP6mXw==}
engines: {node: '>=14.0.0'}
+ tinyspy@4.0.4:
+ resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==}
+ engines: {node: '>=14.0.0'}
+
tldts-core@7.4.10:
resolution: {integrity: sha512-KnQjp53ZekKgm/r3l+u8kJGGzYgrWdP8+Mql7a4vijh2WE0IrZWspQj/TpTxDho/YxO+AnOZnIjQcCD+q6iJsw==}
@@ -6860,6 +7437,9 @@ packages:
resolution: {integrity: sha512-GgouD1B+sWwvkaEq8vXC15DjQitxbvs12oIXELpconwm+Tg3zfcEv4jgzq3vtKverDXsg3VI8aRgNL2Nra0Iog==}
hasBin: true
+ tmcp@1.20.0:
+ resolution: {integrity: sha512-dcDximKQBGqLP/aEAVA26HcWRHhKipstg1w0fbDDJ0HcFZ6lolLU1YYmStYEn/73f534i7WrDNcjRfRYdV9CoA==}
+
tmp-promise@3.0.3:
resolution: {integrity: sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==}
@@ -6916,6 +7496,10 @@ packages:
peerDependencies:
typescript: '>=4.8.4'
+ ts-dedent@2.3.0:
+ resolution: {integrity: sha512-JfJeIHke7y2egdGGgRAvpCwYFUsHlM2gPcrVOxFkznt/4uzQ7HFmvE63iFHVLBJNDuyDOQgijDK/tXH/f6Msjg==}
+ engines: {node: '>=6.10'}
+
ts-node@10.9.2:
resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==}
hasBin: true
@@ -6930,6 +7514,17 @@ packages:
'@swc/wasm':
optional: true
+ tsconfck@3.1.6:
+ resolution: {integrity: sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==}
+ engines: {node: ^18 || >=20}
+ deprecated: unmaintained
+ hasBin: true
+ peerDependencies:
+ typescript: ^5.0.0
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
tsconfig-paths@3.15.0:
resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==}
@@ -7070,6 +7665,10 @@ packages:
resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==}
engines: {node: '>= 0.8'}
+ unplugin@2.3.11:
+ resolution: {integrity: sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==}
+ engines: {node: '>=18.12.0'}
+
unrs-resolver@1.12.2:
resolution: {integrity: sha512-dmlRxBJJayXjqTwC+JtF1HhJmgf3ftQ3YejFcZrf4+KKtJv0qDsK1pjqaaVjG7wJ5NJ6UVP1OqRMQ71Z4C3rxQ==}
@@ -7159,18 +7758,34 @@ packages:
uri-js@4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
+ uri-template-matcher@1.1.2:
+ resolution: {integrity: sha512-uZc1h12jdO3m/R77SfTEOuo6VbMhgWznaawKpBjRGSJb7i91x5PgI37NQJtG+Cerxkk0yr1pylBY2qG1kQ+aEQ==}
+
urlpattern-polyfill@10.1.0:
resolution: {integrity: sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw==}
urlpattern-polyfill@8.0.2:
resolution: {integrity: sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ==}
+ use-sync-external-store@1.6.0:
+ resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==}
+ peerDependencies:
+ react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
+
util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
v8-compile-cache-lib@3.0.1:
resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==}
+ valibot@1.2.0:
+ resolution: {integrity: sha512-mm1rxUsmOxzrwnX5arGS+U4T25RdvpPjPN4yR0u9pUBov9+zGVtO84tif1eY4r6zWxVxu3KzIyknJy3rxfRZZg==}
+ peerDependencies:
+ typescript: '>=5'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
validate-npm-package-license@3.0.4:
resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
@@ -7188,6 +7803,21 @@ packages:
vfile@6.0.3:
resolution: {integrity: sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==}
+ vite-plugin-storybook-nextjs@3.3.2:
+ resolution: {integrity: sha512-emY992wwyOfG5kDEmo7br/OWCz8YMOYhc/0YQo/vGdSqYQhTCRSvHHjjeysAr6co1F2cyoK50szd4nMitZ0k8w==}
+ peerDependencies:
+ next: ^14.1.0 || ^15.0.0 || ^16.0.0
+ storybook: ^0.0.0-0 || ^9.0.0 || ^10.0.0 || ^10.0.0-0 || ^10.1.0-0 || ^10.2.0-0 || ^10.3.0-0 || ^10.4.0-0 || ^10.5.0-0 || ^10.6.0-0
+ vite: ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0
+
+ vite-tsconfig-paths@5.1.4:
+ resolution: {integrity: sha512-cYj0LRuLV2c2sMqhqhGpaO3LretdtMn/BVX4cPLanIZuwwrkVl+lK84E/miEXkCHWXuq65rhNN4rXsBcOB3S4w==}
+ peerDependencies:
+ vite: '*'
+ peerDependenciesMeta:
+ vite:
+ optional: true
+
vite@8.2.1:
resolution: {integrity: sha512-EU/eS7BH3XROHh2YnBefjM6DBKA6ZeMZEYQbj7NLWg5wHYlhB8B/Mayd5XsgWq+NFYccDOTemRpdETWR6Ka/lw==}
engines: {node: ^20.19.0 || >=22.12.0}
@@ -7355,6 +7985,9 @@ packages:
resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==}
engines: {node: '>=20'}
+ webpack-virtual-modules@0.6.2:
+ resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==}
+
whatwg-mimetype@5.0.0:
resolution: {integrity: sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==}
engines: {node: '>=20'}
@@ -7458,6 +8091,10 @@ packages:
utf-8-validate:
optional: true
+ wsl-utils@0.1.0:
+ resolution: {integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==}
+ engines: {node: '>=18'}
+
wsl-utils@1.0.0:
resolution: {integrity: sha512-Hl0ZOAs672vg+06kfujwRhoS6/jehvULrlFkuF2dRu6pHgA8U06h3xqNIqNNU1LTXPcedxByAR4GS6pwQK0mgA==}
engines: {node: '>=20'}
@@ -7582,16 +8219,16 @@ snapshots:
'@babel/compat-data@7.29.7': {}
- '@babel/core@7.29.7':
+ '@babel/core@7.29.7(supports-color@10.2.2)':
dependencies:
'@babel/code-frame': 7.29.7
'@babel/generator': 7.29.8
'@babel/helper-compilation-targets': 7.29.7
- '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7)
+ '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)
'@babel/helpers': 7.29.7
'@babel/parser': 7.29.8
'@babel/template': 7.29.7
- '@babel/traverse': 7.29.8
+ '@babel/traverse': 7.29.8(supports-color@10.2.2)
'@babel/types': 7.29.8
'@jridgewell/remapping': 2.3.5
convert-source-map: 2.0.0
@@ -7622,41 +8259,41 @@ snapshots:
lru-cache: 5.1.1
semver: 6.3.1
- '@babel/helper-create-class-features-plugin@7.29.7(@babel/core@7.29.7)':
+ '@babel/helper-create-class-features-plugin@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)':
dependencies:
- '@babel/core': 7.29.7
+ '@babel/core': 7.29.7(supports-color@10.2.2)
'@babel/helper-annotate-as-pure': 7.29.7
- '@babel/helper-member-expression-to-functions': 7.29.7
+ '@babel/helper-member-expression-to-functions': 7.29.7(supports-color@10.2.2)
'@babel/helper-optimise-call-expression': 7.29.7
- '@babel/helper-replace-supers': 7.29.7(@babel/core@7.29.7)
- '@babel/helper-skip-transparent-expression-wrappers': 7.29.7
- '@babel/traverse': 7.29.8
+ '@babel/helper-replace-supers': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)
+ '@babel/helper-skip-transparent-expression-wrappers': 7.29.7(supports-color@10.2.2)
+ '@babel/traverse': 7.29.8(supports-color@10.2.2)
semver: 6.3.1
transitivePeerDependencies:
- supports-color
'@babel/helper-globals@7.29.7': {}
- '@babel/helper-member-expression-to-functions@7.29.7':
+ '@babel/helper-member-expression-to-functions@7.29.7(supports-color@10.2.2)':
dependencies:
- '@babel/traverse': 7.29.8
+ '@babel/traverse': 7.29.8(supports-color@10.2.2)
'@babel/types': 7.29.8
transitivePeerDependencies:
- supports-color
- '@babel/helper-module-imports@7.29.7':
+ '@babel/helper-module-imports@7.29.7(supports-color@10.2.2)':
dependencies:
- '@babel/traverse': 7.29.8
+ '@babel/traverse': 7.29.8(supports-color@10.2.2)
'@babel/types': 7.29.8
transitivePeerDependencies:
- supports-color
- '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7)':
+ '@babel/helper-module-transforms@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)':
dependencies:
- '@babel/core': 7.29.7
- '@babel/helper-module-imports': 7.29.7
+ '@babel/core': 7.29.7(supports-color@10.2.2)
+ '@babel/helper-module-imports': 7.29.7(supports-color@10.2.2)
'@babel/helper-validator-identifier': 7.29.7
- '@babel/traverse': 7.29.8
+ '@babel/traverse': 7.29.8(supports-color@10.2.2)
transitivePeerDependencies:
- supports-color
@@ -7666,18 +8303,18 @@ snapshots:
'@babel/helper-plugin-utils@7.29.7': {}
- '@babel/helper-replace-supers@7.29.7(@babel/core@7.29.7)':
+ '@babel/helper-replace-supers@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)':
dependencies:
- '@babel/core': 7.29.7
- '@babel/helper-member-expression-to-functions': 7.29.7
+ '@babel/core': 7.29.7(supports-color@10.2.2)
+ '@babel/helper-member-expression-to-functions': 7.29.7(supports-color@10.2.2)
'@babel/helper-optimise-call-expression': 7.29.7
- '@babel/traverse': 7.29.8
+ '@babel/traverse': 7.29.8(supports-color@10.2.2)
transitivePeerDependencies:
- supports-color
- '@babel/helper-skip-transparent-expression-wrappers@7.29.7':
+ '@babel/helper-skip-transparent-expression-wrappers@7.29.7(supports-color@10.2.2)':
dependencies:
- '@babel/traverse': 7.29.8
+ '@babel/traverse': 7.29.8(supports-color@10.2.2)
'@babel/types': 7.29.8
transitivePeerDependencies:
- supports-color
@@ -7701,84 +8338,84 @@ snapshots:
dependencies:
'@babel/types': 7.29.8
- '@babel/plugin-syntax-jsx@7.29.7(@babel/core@7.29.7)':
+ '@babel/plugin-syntax-jsx@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))':
dependencies:
- '@babel/core': 7.29.7
+ '@babel/core': 7.29.7(supports-color@10.2.2)
'@babel/helper-plugin-utils': 7.29.7
- '@babel/plugin-syntax-typescript@7.29.7(@babel/core@7.29.7)':
+ '@babel/plugin-syntax-typescript@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))':
dependencies:
- '@babel/core': 7.29.7
+ '@babel/core': 7.29.7(supports-color@10.2.2)
'@babel/helper-plugin-utils': 7.29.7
- '@babel/plugin-transform-modules-commonjs@7.29.7(@babel/core@7.29.7)':
+ '@babel/plugin-transform-modules-commonjs@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)':
dependencies:
- '@babel/core': 7.29.7
- '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7)
+ '@babel/core': 7.29.7(supports-color@10.2.2)
+ '@babel/helper-module-transforms': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)
'@babel/helper-plugin-utils': 7.29.7
transitivePeerDependencies:
- supports-color
- '@babel/plugin-transform-react-display-name@7.29.7(@babel/core@7.29.7)':
+ '@babel/plugin-transform-react-display-name@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))':
dependencies:
- '@babel/core': 7.29.7
+ '@babel/core': 7.29.7(supports-color@10.2.2)
'@babel/helper-plugin-utils': 7.29.7
- '@babel/plugin-transform-react-jsx-development@7.29.7(@babel/core@7.29.7)':
+ '@babel/plugin-transform-react-jsx-development@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)':
dependencies:
- '@babel/core': 7.29.7
- '@babel/plugin-transform-react-jsx': 7.29.7(@babel/core@7.29.7)
+ '@babel/core': 7.29.7(supports-color@10.2.2)
+ '@babel/plugin-transform-react-jsx': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)
transitivePeerDependencies:
- supports-color
- '@babel/plugin-transform-react-jsx@7.29.7(@babel/core@7.29.7)':
+ '@babel/plugin-transform-react-jsx@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)':
dependencies:
- '@babel/core': 7.29.7
+ '@babel/core': 7.29.7(supports-color@10.2.2)
'@babel/helper-annotate-as-pure': 7.29.7
- '@babel/helper-module-imports': 7.29.7
+ '@babel/helper-module-imports': 7.29.7(supports-color@10.2.2)
'@babel/helper-plugin-utils': 7.29.7
- '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))
'@babel/types': 7.29.8
transitivePeerDependencies:
- supports-color
- '@babel/plugin-transform-react-pure-annotations@7.29.7(@babel/core@7.29.7)':
+ '@babel/plugin-transform-react-pure-annotations@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))':
dependencies:
- '@babel/core': 7.29.7
+ '@babel/core': 7.29.7(supports-color@10.2.2)
'@babel/helper-annotate-as-pure': 7.29.7
'@babel/helper-plugin-utils': 7.29.7
- '@babel/plugin-transform-typescript@7.29.7(@babel/core@7.29.7)':
+ '@babel/plugin-transform-typescript@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)':
dependencies:
- '@babel/core': 7.29.7
+ '@babel/core': 7.29.7(supports-color@10.2.2)
'@babel/helper-annotate-as-pure': 7.29.7
- '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7)
+ '@babel/helper-create-class-features-plugin': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)
'@babel/helper-plugin-utils': 7.29.7
- '@babel/helper-skip-transparent-expression-wrappers': 7.29.7
- '@babel/plugin-syntax-typescript': 7.29.7(@babel/core@7.29.7)
+ '@babel/helper-skip-transparent-expression-wrappers': 7.29.7(supports-color@10.2.2)
+ '@babel/plugin-syntax-typescript': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))
transitivePeerDependencies:
- supports-color
- '@babel/preset-react@7.29.7(@babel/core@7.29.7)':
+ '@babel/preset-react@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)':
dependencies:
- '@babel/core': 7.29.7
+ '@babel/core': 7.29.7(supports-color@10.2.2)
'@babel/helper-plugin-utils': 7.29.7
'@babel/helper-validator-option': 7.29.7
- '@babel/plugin-transform-react-display-name': 7.29.7(@babel/core@7.29.7)
- '@babel/plugin-transform-react-jsx': 7.29.7(@babel/core@7.29.7)
- '@babel/plugin-transform-react-jsx-development': 7.29.7(@babel/core@7.29.7)
- '@babel/plugin-transform-react-pure-annotations': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-transform-react-display-name': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))
+ '@babel/plugin-transform-react-jsx': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)
+ '@babel/plugin-transform-react-jsx-development': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)
+ '@babel/plugin-transform-react-pure-annotations': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))
transitivePeerDependencies:
- supports-color
- '@babel/preset-typescript@7.29.7(@babel/core@7.29.7)':
+ '@babel/preset-typescript@7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)':
dependencies:
- '@babel/core': 7.29.7
+ '@babel/core': 7.29.7(supports-color@10.2.2)
'@babel/helper-plugin-utils': 7.29.7
'@babel/helper-validator-option': 7.29.7
- '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7)
- '@babel/plugin-transform-modules-commonjs': 7.29.7(@babel/core@7.29.7)
- '@babel/plugin-transform-typescript': 7.29.7(@babel/core@7.29.7)
+ '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))
+ '@babel/plugin-transform-modules-commonjs': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)
+ '@babel/plugin-transform-typescript': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)
transitivePeerDependencies:
- supports-color
@@ -7790,7 +8427,7 @@ snapshots:
'@babel/parser': 7.29.8
'@babel/types': 7.29.8
- '@babel/traverse@7.29.0':
+ '@babel/traverse@7.29.0(supports-color@10.2.2)':
dependencies:
'@babel/code-frame': 7.29.7
'@babel/generator': 7.29.8
@@ -7802,7 +8439,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@babel/traverse@7.29.8':
+ '@babel/traverse@7.29.8(supports-color@10.2.2)':
dependencies:
'@babel/code-frame': 7.29.7
'@babel/generator': 7.29.8
@@ -7833,12 +8470,12 @@ snapshots:
optionalDependencies:
'@opentelemetry/api': 1.9.1
- '@better-auth/drizzle-adapter@1.7.1(@better-auth/core@1.7.1(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.1))(@better-auth/utils@0.4.2)(drizzle-orm@1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(zod@4.4.3))':
+ '@better-auth/drizzle-adapter@1.7.1(@better-auth/core@1.7.1(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.1))(@better-auth/utils@0.4.2)(drizzle-orm@1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(valibot@1.2.0(typescript@6.0.3))(zod@4.4.3))':
dependencies:
'@better-auth/core': 1.7.1(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.1)
'@better-auth/utils': 0.4.2
optionalDependencies:
- drizzle-orm: 1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(zod@4.4.3)
+ drizzle-orm: 1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(valibot@1.2.0(typescript@6.0.3))(zod@4.4.3)
'@better-auth/kysely-adapter@1.7.1(@better-auth/core@1.7.1(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.1))(@better-auth/utils@0.4.2)(kysely@0.29.5)':
dependencies:
@@ -7999,21 +8636,48 @@ snapshots:
tslib: 2.8.1
optional: true
+ '@emnapi/core@1.11.0':
+ dependencies:
+ '@emnapi/wasi-threads': 1.2.2
+ tslib: 2.8.1
+ optional: true
+
+ '@emnapi/core@1.9.2':
+ dependencies:
+ '@emnapi/wasi-threads': 1.2.1
+ tslib: 2.8.1
+ optional: true
+
'@emnapi/runtime@1.10.0':
dependencies:
tslib: 2.8.1
optional: true
+ '@emnapi/runtime@1.11.0':
+ dependencies:
+ tslib: 2.8.1
+ optional: true
+
'@emnapi/runtime@1.11.3':
dependencies:
tslib: 2.8.1
optional: true
+ '@emnapi/runtime@1.9.2':
+ dependencies:
+ tslib: 2.8.1
+ optional: true
+
'@emnapi/wasi-threads@1.2.1':
dependencies:
tslib: 2.8.1
optional: true
+ '@emnapi/wasi-threads@1.2.2':
+ dependencies:
+ tslib: 2.8.1
+ optional: true
+
'@envelop/instrumentation@1.0.0':
dependencies:
'@whatwg-node/promise-helpers': 1.3.2
@@ -8175,19 +8839,19 @@ snapshots:
'@esbuild/win32-x64@0.28.1':
optional: true
- '@eslint-community/eslint-utils@4.10.1(eslint@9.39.5(jiti@2.7.0))':
+ '@eslint-community/eslint-utils@4.10.1(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))':
dependencies:
- eslint: 9.39.5(jiti@2.7.0)
+ eslint: 9.39.5(jiti@2.7.0)(supports-color@10.2.2)
eslint-visitor-keys: 3.4.3
- '@eslint-community/eslint-utils@4.9.1(eslint@9.39.5(jiti@2.7.0))':
+ '@eslint-community/eslint-utils@4.9.1(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))':
dependencies:
- eslint: 9.39.5(jiti@2.7.0)
+ eslint: 9.39.5(jiti@2.7.0)(supports-color@10.2.2)
eslint-visitor-keys: 3.4.3
'@eslint-community/regexpp@4.12.2': {}
- '@eslint/config-array@0.21.2':
+ '@eslint/config-array@0.21.2(supports-color@10.2.2)':
dependencies:
'@eslint/object-schema': 2.1.7
debug: 4.4.3(supports-color@10.2.2)
@@ -8203,7 +8867,7 @@ snapshots:
dependencies:
'@types/json-schema': 7.0.15
- '@eslint/eslintrc@3.3.6':
+ '@eslint/eslintrc@3.3.6(supports-color@10.2.2)':
dependencies:
ajv: 6.15.0
debug: 4.4.3(supports-color@10.2.2)
@@ -8541,6 +9205,14 @@ snapshots:
dependencies:
minipass: 7.1.3
+ '@joshwooding/vite-plugin-react-docgen-typescript@0.7.0(typescript@6.0.3)(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))':
+ dependencies:
+ glob: 13.0.6
+ react-docgen-typescript: 2.4.0(typescript@6.0.3)
+ vite: 8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)
+ optionalDependencies:
+ typescript: 6.0.3
+
'@jridgewell/gen-mapping@0.3.13':
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
@@ -8844,6 +9516,20 @@ snapshots:
'@tybys/wasm-util': 0.10.3
optional: true
+ '@napi-rs/wasm-runtime@1.2.3(@emnapi/core@1.11.0)(@emnapi/runtime@1.11.0)':
+ dependencies:
+ '@emnapi/core': 1.11.0
+ '@emnapi/runtime': 1.11.0
+ '@tybys/wasm-util': 0.10.3
+ optional: true
+
+ '@napi-rs/wasm-runtime@1.2.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)':
+ dependencies:
+ '@emnapi/core': 1.9.2
+ '@emnapi/runtime': 1.9.2
+ '@tybys/wasm-util': 0.10.3
+ optional: true
+
'@neondatabase/serverless@1.1.0': {}
'@netlify/ai@0.4.4':
@@ -9038,7 +9724,7 @@ snapshots:
parse-gitignore: 2.0.0
semver: 7.8.5
- '@netlify/dev@4.18.13':
+ '@netlify/dev@4.18.13(supports-color@10.2.2)':
dependencies:
'@netlify/ai': 0.4.4
'@netlify/blobs': 10.7.13(supports-color@10.2.2)
@@ -9046,11 +9732,11 @@ snapshots:
'@netlify/database-dev': 0.10.1
'@netlify/dev-utils': 5.0.0
'@netlify/edge-functions-dev': 1.0.24
- '@netlify/functions-dev': 1.3.5
+ '@netlify/functions-dev': 1.3.5(supports-color@10.2.2)
'@netlify/headers': 2.1.13
- '@netlify/images': 1.3.12(@netlify/blobs@10.7.13)
+ '@netlify/images': 1.3.12(@netlify/blobs@10.7.13(supports-color@10.2.2))
'@netlify/redirects': 3.1.15
- '@netlify/runtime': 4.1.29
+ '@netlify/runtime': 4.1.29(supports-color@10.2.2)
'@netlify/static': 3.1.12
ulid: 3.0.2
transitivePeerDependencies:
@@ -9142,7 +9828,7 @@ snapshots:
dependencies:
'@netlify/types': 2.8.0
- '@netlify/functions-dev@1.3.5':
+ '@netlify/functions-dev@1.3.5(supports-color@10.2.2)':
dependencies:
'@netlify/blobs': 10.7.13(supports-color@10.2.2)
'@netlify/dev-utils': 5.0.0
@@ -9150,7 +9836,7 @@ snapshots:
'@netlify/zip-it-and-ship-it': 15.3.4(supports-color@10.2.2)
cron-parser: 4.9.0
decache: 4.6.2
- extract-zip: 2.0.1
+ extract-zip: 2.0.1(supports-color@10.2.2)
is-stream: 4.0.1
jwt-decode: 4.0.0
lambda-local: 2.2.0
@@ -9198,9 +9884,9 @@ snapshots:
dependencies:
'@netlify/headers-parser': 10.1.1
- '@netlify/images@1.3.12(@netlify/blobs@10.7.13)':
+ '@netlify/images@1.3.12(@netlify/blobs@10.7.13(supports-color@10.2.2))':
dependencies:
- ipx: 3.1.1(@netlify/blobs@10.7.13)
+ ipx: 3.1.1(@netlify/blobs@10.7.13(supports-color@10.2.2))
transitivePeerDependencies:
- '@azure/app-configuration'
- '@azure/cosmos'
@@ -9316,7 +10002,7 @@ snapshots:
'@netlify/runtime-utils@3.0.0': {}
- '@netlify/runtime@4.1.29':
+ '@netlify/runtime@4.1.29(supports-color@10.2.2)':
dependencies:
'@netlify/blobs': 10.7.13(supports-color@10.2.2)
'@netlify/cache': 3.4.10
@@ -9380,11 +10066,13 @@ snapshots:
'@next/env@16.3.0': {}
+ '@next/env@16.3.0-preview.5': {}
+
'@next/env@16.3.1': {}
- '@next/eslint-plugin-next@16.3.1(eslint@9.39.5(jiti@2.7.0))':
+ '@next/eslint-plugin-next@16.3.1(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))':
dependencies:
- '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.5(jiti@2.7.0))
+ '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))
fast-glob: 3.3.1
transitivePeerDependencies:
- eslint
@@ -9585,8 +10273,135 @@ snapshots:
'@opentelemetry/semantic-conventions@1.43.0': {}
+ '@oxc-parser/binding-android-arm-eabi@0.127.0':
+ optional: true
+
+ '@oxc-parser/binding-android-arm64@0.127.0':
+ optional: true
+
+ '@oxc-parser/binding-darwin-arm64@0.127.0':
+ optional: true
+
+ '@oxc-parser/binding-darwin-x64@0.127.0':
+ optional: true
+
+ '@oxc-parser/binding-freebsd-x64@0.127.0':
+ optional: true
+
+ '@oxc-parser/binding-linux-arm-gnueabihf@0.127.0':
+ optional: true
+
+ '@oxc-parser/binding-linux-arm-musleabihf@0.127.0':
+ optional: true
+
+ '@oxc-parser/binding-linux-arm64-gnu@0.127.0':
+ optional: true
+
+ '@oxc-parser/binding-linux-arm64-musl@0.127.0':
+ optional: true
+
+ '@oxc-parser/binding-linux-ppc64-gnu@0.127.0':
+ optional: true
+
+ '@oxc-parser/binding-linux-riscv64-gnu@0.127.0':
+ optional: true
+
+ '@oxc-parser/binding-linux-riscv64-musl@0.127.0':
+ optional: true
+
+ '@oxc-parser/binding-linux-s390x-gnu@0.127.0':
+ optional: true
+
+ '@oxc-parser/binding-linux-x64-gnu@0.127.0':
+ optional: true
+
+ '@oxc-parser/binding-linux-x64-musl@0.127.0':
+ optional: true
+
+ '@oxc-parser/binding-openharmony-arm64@0.127.0':
+ optional: true
+
+ '@oxc-parser/binding-wasm32-wasi@0.127.0':
+ dependencies:
+ '@emnapi/core': 1.9.2
+ '@emnapi/runtime': 1.9.2
+ '@napi-rs/wasm-runtime': 1.2.3(@emnapi/core@1.9.2)(@emnapi/runtime@1.9.2)
+ optional: true
+
+ '@oxc-parser/binding-win32-arm64-msvc@0.127.0':
+ optional: true
+
+ '@oxc-parser/binding-win32-ia32-msvc@0.127.0':
+ optional: true
+
+ '@oxc-parser/binding-win32-x64-msvc@0.127.0':
+ optional: true
+
+ '@oxc-project/types@0.127.0': {}
+
'@oxc-project/types@0.144.0': {}
+ '@oxc-resolver/binding-android-arm-eabi@11.21.2':
+ optional: true
+
+ '@oxc-resolver/binding-android-arm64@11.21.2':
+ optional: true
+
+ '@oxc-resolver/binding-darwin-arm64@11.21.2':
+ optional: true
+
+ '@oxc-resolver/binding-darwin-x64@11.21.2':
+ optional: true
+
+ '@oxc-resolver/binding-freebsd-x64@11.21.2':
+ optional: true
+
+ '@oxc-resolver/binding-linux-arm-gnueabihf@11.21.2':
+ optional: true
+
+ '@oxc-resolver/binding-linux-arm-musleabihf@11.21.2':
+ optional: true
+
+ '@oxc-resolver/binding-linux-arm64-gnu@11.21.2':
+ optional: true
+
+ '@oxc-resolver/binding-linux-arm64-musl@11.21.2':
+ optional: true
+
+ '@oxc-resolver/binding-linux-ppc64-gnu@11.21.2':
+ optional: true
+
+ '@oxc-resolver/binding-linux-riscv64-gnu@11.21.2':
+ optional: true
+
+ '@oxc-resolver/binding-linux-riscv64-musl@11.21.2':
+ optional: true
+
+ '@oxc-resolver/binding-linux-s390x-gnu@11.21.2':
+ optional: true
+
+ '@oxc-resolver/binding-linux-x64-gnu@11.21.2':
+ optional: true
+
+ '@oxc-resolver/binding-linux-x64-musl@11.21.2':
+ optional: true
+
+ '@oxc-resolver/binding-openharmony-arm64@11.21.2':
+ optional: true
+
+ '@oxc-resolver/binding-wasm32-wasi@11.21.2':
+ dependencies:
+ '@emnapi/core': 1.11.0
+ '@emnapi/runtime': 1.11.0
+ '@napi-rs/wasm-runtime': 1.2.3(@emnapi/core@1.11.0)(@emnapi/runtime@1.11.0)
+ optional: true
+
+ '@oxc-resolver/binding-win32-arm64-msvc@11.21.2':
+ optional: true
+
+ '@oxc-resolver/binding-win32-x64-msvc@11.21.2':
+ optional: true
+
'@parcel/watcher-wasm@2.6.0':
dependencies:
is-glob: 4.0.3
@@ -9609,7 +10424,7 @@ snapshots:
'@pnpm/network.ca-file': 1.0.2
config-chain: 1.1.13
- '@pnpm/tabtab@0.5.4':
+ '@pnpm/tabtab@0.5.4(supports-color@10.2.2)':
dependencies:
debug: 4.4.3(supports-color@10.2.2)
enquirer: 2.4.1
@@ -9631,10 +10446,10 @@ snapshots:
react: 19.2.8
react-dom: 19.2.8(react@19.2.8)
- '@react-email/ui@6.9.2(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
+ '@react-email/ui@6.9.2(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
dependencies:
esbuild: 0.28.1
- next: 16.3.0(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
+ next: 16.3.0(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
transitivePeerDependencies:
- '@babel/core'
- '@opentelemetry/api'
@@ -9688,44 +10503,181 @@ snapshots:
'@rolldown/binding-win32-x64-msvc@1.2.4':
optional: true
- '@rolldown/pluginutils@1.0.1': {}
-
- '@rollup/pluginutils@5.4.0':
+ '@rolldown/pluginutils@1.0.1': {}
+
+ '@rollup/pluginutils@5.4.0':
+ dependencies:
+ '@types/estree': 1.0.9
+ estree-walker: 2.0.2
+ picomatch: 4.0.5
+
+ '@rtsao/scc@1.1.0': {}
+
+ '@sec-ant/readable-stream@0.4.1': {}
+
+ '@selderee/plugin-htmlparser2@0.11.0':
+ dependencies:
+ domhandler: 5.0.3
+ selderee: 0.11.0
+
+ '@sindresorhus/merge-streams@2.3.0': {}
+
+ '@sindresorhus/slugify@2.2.1':
+ dependencies:
+ '@sindresorhus/transliterate': 1.6.0
+ escape-string-regexp: 5.0.0
+
+ '@sindresorhus/transliterate@1.6.0':
+ dependencies:
+ escape-string-regexp: 5.0.0
+
+ '@so-ric/colorspace@1.1.6':
+ dependencies:
+ color: 5.0.3
+ text-hex: 1.0.0
+
+ '@socket.io/component-emitter@3.1.2': {}
+
+ '@stablelib/base64@1.0.1': {}
+
+ '@standard-schema/spec@1.1.0': {}
+
+ '@storybook/addon-mcp@0.7.0(@storybook/addon-vitest@10.5.10(@vitest/browser-playwright@5.0.0-beta.7)(@vitest/browser@5.0.0-beta.7(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-beta.7))(react@19.2.8)(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(vitest@5.0.0-beta.7))(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(typescript@6.0.3)':
+ dependencies:
+ '@storybook/mcp': 0.8.0(typescript@6.0.3)
+ '@tmcp/adapter-valibot': 0.1.6(tmcp@1.20.0(typescript@6.0.3))(valibot@1.2.0(typescript@6.0.3))
+ '@tmcp/transport-http': 0.8.6(tmcp@1.20.0(typescript@6.0.3))
+ picoquery: 2.5.0
+ storybook: 10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8)
+ tmcp: 1.20.0(typescript@6.0.3)
+ valibot: 1.2.0(typescript@6.0.3)
+ optionalDependencies:
+ '@storybook/addon-vitest': 10.5.10(@vitest/browser-playwright@5.0.0-beta.7)(@vitest/browser@5.0.0-beta.7(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-beta.7))(react@19.2.8)(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(vitest@5.0.0-beta.7)
+ transitivePeerDependencies:
+ - '@tmcp/auth'
+ - typescript
+
+ '@storybook/addon-vitest@10.5.10(@vitest/browser-playwright@5.0.0-beta.7)(@vitest/browser@5.0.0-beta.7(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-beta.7))(react@19.2.8)(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(vitest@5.0.0-beta.7)':
+ dependencies:
+ '@storybook/global': 5.0.0
+ '@storybook/icons': 2.1.0(react@19.2.8)
+ storybook: 10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8)
+ optionalDependencies:
+ '@vitest/browser': 5.0.0-beta.7(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-beta.7)
+ '@vitest/browser-playwright': 5.0.0-beta.7(playwright@1.62.1)(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-beta.7)
+ vitest: 5.0.0-beta.7(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(@vitest/browser-playwright@5.0.0-beta.7)(@vitest/ui@5.0.0-beta.7)(jsdom@30.0.1(@noble/hashes@2.3.0))(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
+ transitivePeerDependencies:
+ - react
+ optional: true
+
+ '@storybook/builder-vite@10.5.10(esbuild@0.28.1)(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))':
dependencies:
- '@types/estree': 1.0.9
- estree-walker: 2.0.2
- picomatch: 4.0.5
-
- '@rtsao/scc@1.1.0': {}
-
- '@sec-ant/readable-stream@0.4.1': {}
+ '@storybook/csf-plugin': 10.5.10(esbuild@0.28.1)(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
+ storybook: 10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8)
+ ts-dedent: 2.3.0
+ vite: 8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)
+ transitivePeerDependencies:
+ - esbuild
+ - rollup
+ - webpack
- '@selderee/plugin-htmlparser2@0.11.0':
+ '@storybook/csf-plugin@10.5.10(esbuild@0.28.1)(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))':
dependencies:
- domhandler: 5.0.3
- selderee: 0.11.0
+ storybook: 10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8)
+ unplugin: 2.3.11
+ optionalDependencies:
+ esbuild: 0.28.1
+ vite: 8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)
- '@sindresorhus/merge-streams@2.3.0': {}
+ '@storybook/global@5.0.0': {}
- '@sindresorhus/slugify@2.2.1':
+ '@storybook/icons@2.1.0(react@19.2.8)':
dependencies:
- '@sindresorhus/transliterate': 1.6.0
- escape-string-regexp: 5.0.0
+ react: 19.2.8
- '@sindresorhus/transliterate@1.6.0':
+ '@storybook/mcp@0.8.0(typescript@6.0.3)':
dependencies:
- escape-string-regexp: 5.0.0
+ '@tmcp/adapter-valibot': 0.1.6(tmcp@1.20.0(typescript@6.0.3))(valibot@1.2.0(typescript@6.0.3))
+ '@tmcp/transport-http': 0.8.6(tmcp@1.20.0(typescript@6.0.3))
+ tmcp: 1.20.0(typescript@6.0.3)
+ valibot: 1.2.0(typescript@6.0.3)
+ transitivePeerDependencies:
+ - '@tmcp/auth'
+ - typescript
- '@so-ric/colorspace@1.1.6':
+ '@storybook/nextjs-vite@10.5.10(@babel/core@7.29.7(supports-color@10.2.2))(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(esbuild@0.28.1)(next@16.3.1(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(supports-color@10.2.2)(typescript@6.0.3)(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))':
dependencies:
- color: 5.0.3
- text-hex: 1.0.0
+ '@storybook/builder-vite': 10.5.10(esbuild@0.28.1)(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
+ '@storybook/react': 10.5.10(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(supports-color@10.2.2)(typescript@6.0.3)
+ '@storybook/react-vite': 10.5.10(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(esbuild@0.28.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(supports-color@10.2.2)(typescript@6.0.3)(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
+ next: 16.3.1(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
+ react: 19.2.8
+ react-dom: 19.2.8(react@19.2.8)
+ storybook: 10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8)
+ styled-jsx: 5.1.6(@babel/core@7.29.7(supports-color@10.2.2))(react@19.2.8)
+ vite: 8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)
+ vite-plugin-storybook-nextjs: 3.3.2(next@16.3.1(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(supports-color@10.2.2)(typescript@6.0.3)(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
+ optionalDependencies:
+ '@types/react': 19.2.18
+ '@types/react-dom': 19.2.4(@types/react@19.2.18)
+ typescript: 6.0.3
+ transitivePeerDependencies:
+ - '@babel/core'
+ - babel-plugin-macros
+ - esbuild
+ - rollup
+ - supports-color
+ - webpack
- '@socket.io/component-emitter@3.1.2': {}
+ '@storybook/react-dom-shim@10.5.10(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))':
+ dependencies:
+ react: 19.2.8
+ react-dom: 19.2.8(react@19.2.8)
+ storybook: 10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8)
+ optionalDependencies:
+ '@types/react': 19.2.18
+ '@types/react-dom': 19.2.4(@types/react@19.2.18)
- '@stablelib/base64@1.0.1': {}
+ '@storybook/react-vite@10.5.10(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(esbuild@0.28.1)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(supports-color@10.2.2)(typescript@6.0.3)(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))':
+ dependencies:
+ '@joshwooding/vite-plugin-react-docgen-typescript': 0.7.0(typescript@6.0.3)(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
+ '@rollup/pluginutils': 5.4.0
+ '@storybook/builder-vite': 10.5.10(esbuild@0.28.1)(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
+ '@storybook/react': 10.5.10(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(supports-color@10.2.2)(typescript@6.0.3)
+ empathic: 2.0.1
+ magic-string: 0.30.21
+ react: 19.2.8
+ react-docgen: 8.0.3(supports-color@10.2.2)
+ react-dom: 19.2.8(react@19.2.8)
+ resolve: 1.22.12
+ storybook: 10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8)
+ tsconfig-paths: 4.2.0
+ vite: 8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)
+ optionalDependencies:
+ typescript: 6.0.3
+ transitivePeerDependencies:
+ - '@types/react'
+ - '@types/react-dom'
+ - esbuild
+ - rollup
+ - supports-color
+ - webpack
- '@standard-schema/spec@1.1.0': {}
+ '@storybook/react@10.5.10(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(supports-color@10.2.2)(typescript@6.0.3)':
+ dependencies:
+ '@storybook/global': 5.0.0
+ '@storybook/react-dom-shim': 10.5.10(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))
+ react: 19.2.8
+ react-docgen: 8.0.3(supports-color@10.2.2)
+ react-docgen-typescript: 2.4.0(typescript@6.0.3)
+ react-dom: 19.2.8(react@19.2.8)
+ storybook: 10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8)
+ optionalDependencies:
+ '@types/react': 19.2.18
+ '@types/react-dom': 19.2.4(@types/react@19.2.18)
+ typescript: 6.0.3
+ transitivePeerDependencies:
+ - supports-color
'@sveltejs/acorn-typescript@1.0.13(acorn@8.18.0)':
dependencies:
@@ -9750,6 +10702,15 @@ snapshots:
picocolors: 1.1.1
pretty-format: 27.5.1
+ '@testing-library/jest-dom@6.9.1':
+ dependencies:
+ '@adobe/css-tools': 4.5.0
+ 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/jest-dom@7.0.1(@testing-library/dom@10.4.1)(vitest@5.0.0-beta.7)':
dependencies:
'@adobe/css-tools': 4.5.0
@@ -9772,6 +10733,27 @@ snapshots:
'@types/react': 19.2.18
'@types/react-dom': 19.2.4(@types/react@19.2.18)
+ '@testing-library/user-event@14.6.6(@testing-library/dom@10.4.1)':
+ dependencies:
+ '@testing-library/dom': 10.4.1
+
+ '@tmcp/adapter-valibot@0.1.6(tmcp@1.20.0(typescript@6.0.3))(valibot@1.2.0(typescript@6.0.3))':
+ dependencies:
+ '@standard-schema/spec': 1.1.0
+ '@valibot/to-json-schema': 1.7.1(valibot@1.2.0(typescript@6.0.3))
+ tmcp: 1.20.0(typescript@6.0.3)
+ valibot: 1.2.0(typescript@6.0.3)
+
+ '@tmcp/session-manager@0.2.2(tmcp@1.20.0(typescript@6.0.3))':
+ dependencies:
+ tmcp: 1.20.0(typescript@6.0.3)
+
+ '@tmcp/transport-http@0.8.6(tmcp@1.20.0(typescript@6.0.3))':
+ dependencies:
+ '@tmcp/session-manager': 0.2.2(tmcp@1.20.0(typescript@6.0.3))
+ esm-env: 1.2.2
+ tmcp: 1.20.0(typescript@6.0.3)
+
'@tsconfig/node10@1.0.13': {}
'@tsconfig/node12@1.0.11': {}
@@ -9787,6 +10769,27 @@ snapshots:
'@types/aria-query@5.0.4': {}
+ '@types/babel__core@7.20.5':
+ dependencies:
+ '@babel/parser': 7.29.8
+ '@babel/types': 7.29.8
+ '@types/babel__generator': 7.27.0
+ '@types/babel__template': 7.4.4
+ '@types/babel__traverse': 7.28.0
+
+ '@types/babel__generator@7.27.0':
+ dependencies:
+ '@babel/types': 7.29.8
+
+ '@types/babel__template@7.4.4':
+ dependencies:
+ '@babel/parser': 7.29.8
+ '@babel/types': 7.29.8
+
+ '@types/babel__traverse@7.28.0':
+ dependencies:
+ '@babel/types': 7.29.8
+
'@types/chai@5.2.3':
dependencies:
'@types/deep-eql': 4.0.2
@@ -9802,6 +10805,8 @@ snapshots:
'@types/deep-eql@4.0.2': {}
+ '@types/doctrine@0.0.9': {}
+
'@types/estree-jsx@1.0.5':
dependencies:
'@types/estree': 1.0.9
@@ -9840,6 +10845,8 @@ snapshots:
dependencies:
csstype: 3.2.3
+ '@types/resolve@1.20.6': {}
+
'@types/retry@0.12.2': {}
'@types/triple-beam@1.3.5': {}
@@ -9859,15 +10866,15 @@ snapshots:
'@types/node': 24.13.3
optional: true
- '@typescript-eslint/eslint-plugin@8.67.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3)':
+ '@typescript-eslint/eslint-plugin@8.67.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)':
dependencies:
'@eslint-community/regexpp': 4.12.2
- '@typescript-eslint/parser': 8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3)
+ '@typescript-eslint/parser': 8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
'@typescript-eslint/scope-manager': 8.67.0
- '@typescript-eslint/type-utils': 8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3)
- '@typescript-eslint/utils': 8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3)
+ '@typescript-eslint/type-utils': 8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
+ '@typescript-eslint/utils': 8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
'@typescript-eslint/visitor-keys': 8.67.0
- eslint: 9.39.5(jiti@2.7.0)
+ eslint: 9.39.5(jiti@2.7.0)(supports-color@10.2.2)
ignore: 7.0.6
natural-compare: 1.4.0
ts-api-utils: 2.5.0(typescript@6.0.3)
@@ -9875,14 +10882,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3)':
+ '@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)':
dependencies:
'@typescript-eslint/scope-manager': 8.67.0
'@typescript-eslint/types': 8.67.0
- '@typescript-eslint/typescript-estree': 8.67.0(typescript@6.0.3)
+ '@typescript-eslint/typescript-estree': 8.67.0(supports-color@10.2.2)(typescript@6.0.3)
'@typescript-eslint/visitor-keys': 8.67.0
debug: 4.4.3(supports-color@10.2.2)
- eslint: 9.39.5(jiti@2.7.0)
+ eslint: 9.39.5(jiti@2.7.0)(supports-color@10.2.2)
typescript: 6.0.3
transitivePeerDependencies:
- supports-color
@@ -9896,7 +10903,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/project-service@8.67.0(typescript@6.0.3)':
+ '@typescript-eslint/project-service@8.67.0(supports-color@10.2.2)(typescript@6.0.3)':
dependencies:
'@typescript-eslint/tsconfig-utils': 8.67.0(typescript@6.0.3)
'@typescript-eslint/types': 8.67.0
@@ -9918,13 +10925,13 @@ snapshots:
dependencies:
typescript: 6.0.3
- '@typescript-eslint/type-utils@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3)':
+ '@typescript-eslint/type-utils@8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)':
dependencies:
'@typescript-eslint/types': 8.67.0
- '@typescript-eslint/typescript-estree': 8.67.0(typescript@6.0.3)
- '@typescript-eslint/utils': 8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3)
+ '@typescript-eslint/typescript-estree': 8.67.0(supports-color@10.2.2)(typescript@6.0.3)
+ '@typescript-eslint/utils': 8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
debug: 4.4.3(supports-color@10.2.2)
- eslint: 9.39.5(jiti@2.7.0)
+ eslint: 9.39.5(jiti@2.7.0)(supports-color@10.2.2)
ts-api-utils: 2.5.0(typescript@6.0.3)
typescript: 6.0.3
transitivePeerDependencies:
@@ -9947,9 +10954,9 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/typescript-estree@8.67.0(typescript@6.0.3)':
+ '@typescript-eslint/typescript-estree@8.67.0(supports-color@10.2.2)(typescript@6.0.3)':
dependencies:
- '@typescript-eslint/project-service': 8.67.0(typescript@6.0.3)
+ '@typescript-eslint/project-service': 8.67.0(supports-color@10.2.2)(typescript@6.0.3)
'@typescript-eslint/tsconfig-utils': 8.67.0(typescript@6.0.3)
'@typescript-eslint/types': 8.67.0
'@typescript-eslint/visitor-keys': 8.67.0
@@ -9962,13 +10969,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/utils@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3)':
+ '@typescript-eslint/utils@8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)':
dependencies:
- '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(jiti@2.7.0))
+ '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))
'@typescript-eslint/scope-manager': 8.67.0
'@typescript-eslint/types': 8.67.0
- '@typescript-eslint/typescript-estree': 8.67.0(typescript@6.0.3)
- eslint: 9.39.5(jiti@2.7.0)
+ '@typescript-eslint/typescript-estree': 8.67.0(supports-color@10.2.2)(typescript@6.0.3)
+ eslint: 9.39.5(jiti@2.7.0)(supports-color@10.2.2)
typescript: 6.0.3
transitivePeerDependencies:
- supports-color
@@ -10050,6 +11057,10 @@ snapshots:
'@unrs/resolver-binding-win32-x64-msvc@1.12.2':
optional: true
+ '@valibot/to-json-schema@1.7.1(valibot@1.2.0(typescript@6.0.3))':
+ dependencies:
+ valibot: 1.2.0(typescript@6.0.3)
+
'@vercel/nft@0.29.4(supports-color@10.2.2)':
dependencies:
'@mapbox/node-pre-gyp': 2.0.3(supports-color@10.2.2)
@@ -10105,6 +11116,14 @@ snapshots:
- utf-8-validate
- vite
+ '@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/mocker@5.0.0-beta.7(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))':
dependencies:
'@jridgewell/trace-mapping': 0.3.31
@@ -10114,10 +11133,18 @@ snapshots:
optionalDependencies:
vite: 8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)
+ '@vitest/pretty-format@3.2.4':
+ dependencies:
+ tinyrainbow: 2.0.0
+
'@vitest/pretty-format@5.0.0-beta.7':
dependencies:
tinyrainbow: 3.1.1
+ '@vitest/spy@3.2.4':
+ dependencies:
+ tinyspy: 4.0.4
+
'@vitest/spy@5.0.0-beta.7': {}
'@vitest/ui@5.0.0-beta.7(vitest@5.0.0-beta.7)':
@@ -10131,6 +11158,12 @@ snapshots:
tinyrainbow: 3.1.1
vitest: 5.0.0-beta.7(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(@vitest/browser-playwright@5.0.0-beta.7)(@vitest/ui@5.0.0-beta.7)(jsdom@30.0.1(@noble/hashes@2.3.0))(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
+ '@vitest/utils@3.2.4':
+ dependencies:
+ '@vitest/pretty-format': 3.2.4
+ loupe: 3.2.1
+ tinyrainbow: 2.0.0
+
'@vitest/utils@5.0.0-beta.7':
dependencies:
'@vitest/pretty-format': 5.0.0-beta.7
@@ -10169,6 +11202,8 @@ snapshots:
'@vue/shared@3.5.41': {}
+ '@webcontainer/env@1.1.1': {}
+
'@whatwg-node/disposablestack@0.0.6':
dependencies:
'@whatwg-node/promise-helpers': 1.3.2
@@ -10396,6 +11431,10 @@ snapshots:
ast-types-flow@0.0.8: {}
+ ast-types@0.16.3:
+ dependencies:
+ tslib: 2.8.1
+
async-function@1.0.0: {}
async-sema@3.1.1: {}
@@ -10409,17 +11448,17 @@ snapshots:
stubborn-fs: 2.0.0
when-exit: 2.1.5
- auth@1.7.1(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(chokidar@5.0.0)(drizzle-kit@1.0.0-rc.4)(drizzle-orm@1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.1)(next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(pg@8.23.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@5.0.0-beta.7):
+ auth@1.7.1(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(chokidar@5.0.0)(drizzle-kit@1.0.0-rc.4)(drizzle-orm@1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(valibot@1.2.0(typescript@6.0.3))(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.1)(next@16.3.1(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(pg@8.23.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(supports-color@10.2.2)(vitest@5.0.0-beta.7):
dependencies:
- '@babel/core': 7.29.7
- '@babel/preset-react': 7.29.7(@babel/core@7.29.7)
- '@babel/preset-typescript': 7.29.7(@babel/core@7.29.7)
+ '@babel/core': 7.29.7(supports-color@10.2.2)
+ '@babel/preset-react': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)
+ '@babel/preset-typescript': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)
'@better-auth/core': 1.7.1(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.1)
'@better-auth/telemetry': 1.7.1(@better-auth/core@1.7.1(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.1))(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)
'@better-auth/utils': 0.4.2
'@clack/prompts': 1.7.0
'@mrleebo/prisma-ast': 0.16.0
- better-auth: 1.7.1(@opentelemetry/api@1.9.1)(drizzle-kit@1.0.0-rc.4)(drizzle-orm@1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(zod@4.4.3))(next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(pg@8.23.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@5.0.0-beta.7)
+ better-auth: 1.7.1(@opentelemetry/api@1.9.1)(drizzle-kit@1.0.0-rc.4)(drizzle-orm@1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(valibot@1.2.0(typescript@6.0.3))(zod@4.4.3))(next@16.3.1(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(pg@8.23.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@5.0.0-beta.7)
c12: 4.0.0-beta.5(chokidar@5.0.0)(dotenv@17.4.2)(jiti@2.7.0)
chalk: 5.6.2
commander: 15.0.0
@@ -10535,10 +11574,10 @@ snapshots:
jsonpointer: 5.0.1
leven: 3.1.0
- better-auth@1.7.1(@opentelemetry/api@1.9.1)(drizzle-kit@1.0.0-rc.4)(drizzle-orm@1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(zod@4.4.3))(next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(pg@8.23.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@5.0.0-beta.7):
+ better-auth@1.7.1(@opentelemetry/api@1.9.1)(drizzle-kit@1.0.0-rc.4)(drizzle-orm@1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(valibot@1.2.0(typescript@6.0.3))(zod@4.4.3))(next@16.3.1(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(pg@8.23.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@5.0.0-beta.7):
dependencies:
'@better-auth/core': 1.7.1(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.1)
- '@better-auth/drizzle-adapter': 1.7.1(@better-auth/core@1.7.1(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.1))(@better-auth/utils@0.4.2)(drizzle-orm@1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(zod@4.4.3))
+ '@better-auth/drizzle-adapter': 1.7.1(@better-auth/core@1.7.1(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.1))(@better-auth/utils@0.4.2)(drizzle-orm@1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(valibot@1.2.0(typescript@6.0.3))(zod@4.4.3))
'@better-auth/kysely-adapter': 1.7.1(@better-auth/core@1.7.1(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.1))(@better-auth/utils@0.4.2)(kysely@0.29.5)
'@better-auth/memory-adapter': 1.7.1(@better-auth/core@1.7.1(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.1))(@better-auth/utils@0.4.2)
'@better-auth/mongo-adapter': 1.7.1(@better-auth/core@1.7.1(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.1))(@better-auth/utils@0.4.2)
@@ -10556,8 +11595,8 @@ snapshots:
zod: 4.4.3
optionalDependencies:
drizzle-kit: 1.0.0-rc.4
- drizzle-orm: 1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(zod@4.4.3)
- next: 16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
+ drizzle-orm: 1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(valibot@1.2.0(typescript@6.0.3))(zod@4.4.3)
+ next: 16.3.1(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
pg: 8.23.0
react: 19.2.8
react-dom: 19.2.8(react@19.2.8)
@@ -10590,7 +11629,7 @@ snapshots:
inherits: 2.0.4
readable-stream: 3.6.2
- body-parser@2.3.0:
+ body-parser@2.3.0(supports-color@10.2.2):
dependencies:
bytes: 3.1.2
content-type: 2.1.0
@@ -10708,6 +11747,14 @@ 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:
@@ -10727,6 +11774,8 @@ snapshots:
chardet@2.2.0: {}
+ check-error@2.1.3: {}
+
chevrotain@12.0.0:
dependencies:
'@chevrotain/cst-dts-gen': 12.0.0
@@ -11005,9 +12054,11 @@ snapshots:
debounce@2.2.0: {}
- debug@3.2.7:
+ debug@3.2.7(supports-color@10.2.2):
dependencies:
ms: 2.1.3
+ optionalDependencies:
+ supports-color: 10.2.2
debug@4.4.3(supports-color@10.2.2):
dependencies:
@@ -11026,6 +12077,8 @@ snapshots:
dependencies:
character-entities: 2.0.2
+ deep-eql@5.0.2: {}
+
deep-extend@0.6.0: {}
deep-is@0.1.4: {}
@@ -11135,6 +12188,10 @@ snapshots:
dependencies:
esutils: 2.0.3
+ doctrine@3.0.0:
+ dependencies:
+ esutils: 2.0.3
+
dom-accessibility-api@0.5.16: {}
dom-accessibility-api@0.6.3: {}
@@ -11177,11 +12234,12 @@ snapshots:
get-tsconfig: 4.14.3
jiti: 2.7.0
- drizzle-orm@1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(zod@4.4.3):
+ drizzle-orm@1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(valibot@1.2.0(typescript@6.0.3))(zod@4.4.3):
optionalDependencies:
'@neondatabase/serverless': 1.1.0
'@opentelemetry/api': 1.9.1
pg: 8.23.0
+ valibot: 1.2.0(typescript@6.0.3)
zod: 4.4.3
dunder-proto@1.0.1:
@@ -11218,7 +12276,7 @@ snapshots:
engine.io-parser@5.2.3: {}
- engine.io@6.6.9:
+ engine.io@6.6.9(supports-color@10.2.2):
dependencies:
'@types/cors': 2.8.19
'@types/node': 24.13.3
@@ -11456,18 +12514,18 @@ snapshots:
optionalDependencies:
source-map: 0.6.1
- eslint-config-next@16.3.1(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3):
+ eslint-config-next@16.3.1(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3):
dependencies:
- '@next/eslint-plugin-next': 16.3.1(eslint@9.39.5(jiti@2.7.0))
- eslint: 9.39.5(jiti@2.7.0)
- eslint-import-resolver-node: 0.3.10
- eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.5(jiti@2.7.0)))(eslint@9.39.5(jiti@2.7.0))
- eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.5(jiti@2.7.0)))(eslint@9.39.5(jiti@2.7.0)))(eslint@9.39.5(jiti@2.7.0))
- eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.5(jiti@2.7.0))
- eslint-plugin-react: 7.37.5(eslint@9.39.5(jiti@2.7.0))
- eslint-plugin-react-hooks: 7.1.1(eslint@9.39.5(jiti@2.7.0))
+ '@next/eslint-plugin-next': 16.3.1(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))
+ eslint: 9.39.5(jiti@2.7.0)(supports-color@10.2.2)
+ eslint-import-resolver-node: 0.3.10(supports-color@10.2.2)
+ eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)
+ eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)
+ eslint-plugin-jsx-a11y: 6.10.2(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))
+ eslint-plugin-react: 7.37.5(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))
+ eslint-plugin-react-hooks: 7.1.1(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)
globals: 16.4.0
- typescript-eslint: 8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3)
+ typescript-eslint: 8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
optionalDependencies:
typescript: 6.0.3
transitivePeerDependencies:
@@ -11476,56 +12534,56 @@ snapshots:
- eslint-plugin-import-x
- supports-color
- eslint-config-prettier@10.1.8(eslint@9.39.5(jiti@2.7.0)):
+ eslint-config-prettier@10.1.8(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2)):
dependencies:
- eslint: 9.39.5(jiti@2.7.0)
+ eslint: 9.39.5(jiti@2.7.0)(supports-color@10.2.2)
- eslint-import-resolver-node@0.3.10:
+ eslint-import-resolver-node@0.3.10(supports-color@10.2.2):
dependencies:
- debug: 3.2.7
+ debug: 3.2.7(supports-color@10.2.2)
is-core-module: 2.16.2
resolve: 2.0.0-next.7
transitivePeerDependencies:
- supports-color
- eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.5(jiti@2.7.0)))(eslint@9.39.5(jiti@2.7.0)):
+ eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2):
dependencies:
'@nolyfill/is-core-module': 1.0.39
debug: 4.4.3(supports-color@10.2.2)
- eslint: 9.39.5(jiti@2.7.0)
+ eslint: 9.39.5(jiti@2.7.0)(supports-color@10.2.2)
get-tsconfig: 4.14.3
is-bun-module: 2.0.0
stable-hash: 0.0.5
tinyglobby: 0.2.17
unrs-resolver: 1.12.2
optionalDependencies:
- eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.5(jiti@2.7.0)))(eslint@9.39.5(jiti@2.7.0)))(eslint@9.39.5(jiti@2.7.0))
+ eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)
transitivePeerDependencies:
- supports-color
- eslint-module-utils@2.14.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.5(jiti@2.7.0)))(eslint@9.39.5(jiti@2.7.0)))(eslint@9.39.5(jiti@2.7.0)):
+ eslint-module-utils@2.14.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint-import-resolver-node@0.3.10(supports-color@10.2.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2):
dependencies:
- debug: 3.2.7
+ debug: 3.2.7(supports-color@10.2.2)
optionalDependencies:
- '@typescript-eslint/parser': 8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3)
- eslint: 9.39.5(jiti@2.7.0)
- eslint-import-resolver-node: 0.3.10
- eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.5(jiti@2.7.0)))(eslint@9.39.5(jiti@2.7.0))
+ '@typescript-eslint/parser': 8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
+ eslint: 9.39.5(jiti@2.7.0)(supports-color@10.2.2)
+ eslint-import-resolver-node: 0.3.10(supports-color@10.2.2)
+ eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)
transitivePeerDependencies:
- supports-color
- eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.5(jiti@2.7.0)))(eslint@9.39.5(jiti@2.7.0)))(eslint@9.39.5(jiti@2.7.0)):
+ eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2):
dependencies:
'@rtsao/scc': 1.1.0
array-includes: 3.1.9
array.prototype.findlastindex: 1.2.6
array.prototype.flat: 1.3.3
array.prototype.flatmap: 1.3.3
- debug: 3.2.7
+ debug: 3.2.7(supports-color@10.2.2)
doctrine: 2.1.0
- eslint: 9.39.5(jiti@2.7.0)
- eslint-import-resolver-node: 0.3.10
- eslint-module-utils: 2.14.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3))(eslint-import-resolver-node@0.3.10)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.5(jiti@2.7.0)))(eslint@9.39.5(jiti@2.7.0)))(eslint@9.39.5(jiti@2.7.0))
+ eslint: 9.39.5(jiti@2.7.0)(supports-color@10.2.2)
+ eslint-import-resolver-node: 0.3.10(supports-color@10.2.2)
+ eslint-module-utils: 2.14.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint-import-resolver-node@0.3.10(supports-color@10.2.2))(eslint-import-resolver-typescript@3.10.1)(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)
hasown: 2.0.4
is-core-module: 2.16.2
is-glob: 4.0.3
@@ -11537,13 +12595,13 @@ snapshots:
string.prototype.trimend: 1.0.10
tsconfig-paths: 3.15.0
optionalDependencies:
- '@typescript-eslint/parser': 8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3)
+ '@typescript-eslint/parser': 8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
transitivePeerDependencies:
- eslint-import-resolver-typescript
- eslint-import-resolver-webpack
- supports-color
- eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.5(jiti@2.7.0)):
+ eslint-plugin-jsx-a11y@6.10.2(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2)):
dependencies:
aria-query: 5.3.2
array-includes: 3.1.9
@@ -11553,7 +12611,7 @@ snapshots:
axobject-query: 4.1.0
damerau-levenshtein: 1.0.8
emoji-regex: 9.2.2
- eslint: 9.39.5(jiti@2.7.0)
+ eslint: 9.39.5(jiti@2.7.0)(supports-color@10.2.2)
hasown: 2.0.4
jsx-ast-utils: 3.3.5
language-tags: 1.0.9
@@ -11562,18 +12620,18 @@ snapshots:
safe-regex-test: 1.1.0
string.prototype.includes: 2.0.1
- eslint-plugin-react-hooks@7.1.1(eslint@9.39.5(jiti@2.7.0)):
+ eslint-plugin-react-hooks@7.1.1(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2):
dependencies:
- '@babel/core': 7.29.7
+ '@babel/core': 7.29.7(supports-color@10.2.2)
'@babel/parser': 7.29.8
- eslint: 9.39.5(jiti@2.7.0)
+ eslint: 9.39.5(jiti@2.7.0)(supports-color@10.2.2)
hermes-parser: 0.25.1
zod: 4.4.3
zod-validation-error: 4.0.2(zod@4.4.3)
transitivePeerDependencies:
- supports-color
- eslint-plugin-react@7.37.5(eslint@9.39.5(jiti@2.7.0)):
+ eslint-plugin-react@7.37.5(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2)):
dependencies:
array-includes: 3.1.9
array.prototype.findlast: 1.2.5
@@ -11581,7 +12639,7 @@ snapshots:
array.prototype.tosorted: 1.1.4
doctrine: 2.1.0
es-iterator-helpers: 1.4.0
- eslint: 9.39.5(jiti@2.7.0)
+ eslint: 9.39.5(jiti@2.7.0)(supports-color@10.2.2)
estraverse: 5.3.0
hasown: 2.0.4
jsx-ast-utils: 3.3.5
@@ -11595,6 +12653,15 @@ snapshots:
string.prototype.matchall: 4.0.12
string.prototype.repeat: 1.0.0
+ eslint-plugin-storybook@10.5.10(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3):
+ dependencies:
+ '@typescript-eslint/types': 8.67.0
+ '@typescript-eslint/utils': 8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
+ eslint: 9.39.5(jiti@2.7.0)(supports-color@10.2.2)
+ transitivePeerDependencies:
+ - supports-color
+ - typescript
+
eslint-scope@8.4.0:
dependencies:
esrecurse: 4.3.0
@@ -11606,14 +12673,14 @@ snapshots:
eslint-visitor-keys@5.0.1: {}
- eslint@9.39.5(jiti@2.7.0):
+ eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2):
dependencies:
- '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(jiti@2.7.0))
+ '@eslint-community/eslint-utils': 4.10.1(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))
'@eslint-community/regexpp': 4.12.2
- '@eslint/config-array': 0.21.2
+ '@eslint/config-array': 0.21.2(supports-color@10.2.2)
'@eslint/config-helpers': 0.4.2
'@eslint/core': 0.17.0
- '@eslint/eslintrc': 3.3.6
+ '@eslint/eslintrc': 3.3.6(supports-color@10.2.2)
'@eslint/js': 9.39.5
'@eslint/plugin-kit': 0.4.1
'@humanfs/node': 0.16.8
@@ -11647,6 +12714,8 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ esm-env@1.2.2: {}
+
espree@10.4.0:
dependencies:
acorn: 8.18.0
@@ -11719,10 +12788,10 @@ snapshots:
dependencies:
on-headers: 1.1.0
- express@5.2.1:
+ express@5.2.1(supports-color@10.2.2):
dependencies:
accepts: 2.0.0
- body-parser: 2.3.0
+ body-parser: 2.3.0(supports-color@10.2.2)
content-disposition: 1.1.0
content-type: 1.0.5
cookie: 0.7.2
@@ -11732,7 +12801,7 @@ snapshots:
encodeurl: 2.0.0
escape-html: 1.0.3
etag: 1.8.1
- finalhandler: 2.1.1
+ finalhandler: 2.1.1(supports-color@10.2.2)
fresh: 2.0.0
http-errors: 2.0.1
merge-descriptors: 2.0.0
@@ -11743,9 +12812,9 @@ snapshots:
proxy-addr: 2.0.7
qs: 6.15.3
range-parser: 1.3.0
- router: 2.2.0
- send: 1.2.1
- serve-static: 2.2.1
+ router: 2.2.0(supports-color@10.2.2)
+ send: 1.2.1(supports-color@10.2.2)
+ serve-static: 2.2.1(supports-color@10.2.2)
statuses: 2.0.2
type-is: 2.1.0
vary: 1.1.2
@@ -11756,7 +12825,7 @@ snapshots:
extend@3.0.2: {}
- extract-zip@2.0.1:
+ extract-zip@2.0.1(supports-color@10.2.2):
dependencies:
debug: 4.4.3(supports-color@10.2.2)
get-stream: 5.2.0
@@ -11890,7 +12959,7 @@ snapshots:
filter-obj@6.1.0: {}
- finalhandler@2.1.1:
+ finalhandler@2.1.1(supports-color@10.2.2):
dependencies:
debug: 4.4.3(supports-color@10.2.2)
encodeurl: 2.0.0
@@ -11938,7 +13007,7 @@ snapshots:
dependencies:
from2: 2.3.0
- follow-redirects@1.16.0(debug@4.4.3):
+ follow-redirects@1.16.0(debug@4.4.3(supports-color@10.2.2)):
optionalDependencies:
debug: 4.4.3(supports-color@10.2.2)
@@ -12099,6 +13168,8 @@ snapshots:
slash: 5.1.0
unicorn-magic: 0.3.0
+ globrex@0.1.2: {}
+
gonzales-pe@4.3.0:
dependencies:
minimist: 1.2.8
@@ -12145,7 +13216,7 @@ snapshots:
dependencies:
function-bind: 1.1.2
- hast-util-to-jsx-runtime@2.3.6:
+ hast-util-to-jsx-runtime@2.3.6(supports-color@10.2.2):
dependencies:
'@types/estree': 1.0.9
'@types/hast': 3.0.5
@@ -12154,9 +13225,9 @@ snapshots:
devlop: 1.1.0
estree-util-is-identifier-name: 3.0.0
hast-util-whitespace: 3.0.0
- mdast-util-mdx-expression: 2.0.1
- mdast-util-mdx-jsx: 3.2.0
- mdast-util-mdxjs-esm: 2.0.1
+ mdast-util-mdx-expression: 2.0.1(supports-color@10.2.2)
+ mdast-util-mdx-jsx: 3.2.0(supports-color@10.2.2)
+ mdast-util-mdxjs-esm: 2.0.1(supports-color@10.2.2)
property-information: 7.2.0
space-separated-tokens: 2.0.2
style-to-js: 1.1.21
@@ -12233,21 +13304,21 @@ snapshots:
statuses: 2.0.2
toidentifier: 1.0.1
- http-proxy-middleware@3.0.7:
+ http-proxy-middleware@3.0.7(supports-color@10.2.2):
dependencies:
'@types/http-proxy': 1.17.17
debug: 4.4.3(supports-color@10.2.2)
- http-proxy: 1.18.1(debug@4.4.3)
+ http-proxy: 1.18.1(debug@4.4.3(supports-color@10.2.2))
is-glob: 4.0.3
is-plain-object: 5.0.0
micromatch: 4.0.8
transitivePeerDependencies:
- supports-color
- http-proxy@1.18.1(debug@4.4.3):
+ http-proxy@1.18.1(debug@4.4.3(supports-color@10.2.2)):
dependencies:
eventemitter3: 4.0.7
- follow-redirects: 1.16.0(debug@4.4.3)
+ follow-redirects: 1.16.0(debug@4.4.3(supports-color@10.2.2))
requires-port: 1.0.0
transitivePeerDependencies:
- debug
@@ -12261,7 +13332,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
- https-proxy-agent@8.0.0:
+ https-proxy-agent@8.0.0(supports-color@10.2.2):
dependencies:
agent-base: 8.0.0
debug: 4.4.3(supports-color@10.2.2)
@@ -12284,6 +13355,8 @@ snapshots:
image-meta@0.2.2: {}
+ image-size@2.0.2: {}
+
import-fresh@3.3.1:
dependencies:
parent-module: 1.0.1
@@ -12350,7 +13423,7 @@ snapshots:
ipaddr.js@2.5.0: {}
- ipx@3.1.1(@netlify/blobs@10.7.13):
+ ipx@3.1.1(@netlify/blobs@10.7.13(supports-color@10.2.2)):
dependencies:
'@fastify/accept-negotiator': 2.1.0
citty: 0.1.6
@@ -12366,7 +13439,7 @@ snapshots:
sharp: 0.34.5
svgo: 4.0.2
ufo: 1.6.4
- unstorage: 1.17.5(@netlify/blobs@10.7.13)
+ unstorage: 1.17.5(@netlify/blobs@10.7.13(supports-color@10.2.2))
xss: 1.0.15
transitivePeerDependencies:
- '@azure/app-configuration'
@@ -12654,6 +13727,8 @@ snapshots:
json-buffer@3.0.1: {}
+ json-rpc-2.0@1.8.0: {}
+
json-schema-ref-resolver@3.0.0:
dependencies:
dequal: 2.0.3
@@ -12674,6 +13749,8 @@ snapshots:
json5@2.2.3: {}
+ jsonc-parser@3.3.1: {}
+
jsonpointer@5.0.1: {}
jsonwebtoken@9.0.3:
@@ -12921,6 +13998,8 @@ snapshots:
dependencies:
js-tokens: 4.0.0
+ loupe@3.2.1: {}
+
lru-cache@10.4.3: {}
lru-cache@11.5.2: {}
@@ -12969,14 +14048,14 @@ snapshots:
unist-util-is: 6.0.1
unist-util-visit-parents: 6.0.2
- mdast-util-from-markdown@2.0.3:
+ mdast-util-from-markdown@2.0.3(supports-color@10.2.2):
dependencies:
'@types/mdast': 4.0.4
'@types/unist': 3.0.3
decode-named-character-reference: 1.3.0
devlop: 1.1.0
mdast-util-to-string: 4.0.0
- micromark: 4.0.2
+ micromark: 4.0.2(supports-color@10.2.2)
micromark-util-decode-numeric-character-reference: 2.0.2
micromark-util-decode-string: 2.0.1
micromark-util-normalize-identifier: 2.0.1
@@ -12994,67 +14073,67 @@ snapshots:
mdast-util-find-and-replace: 3.0.2
micromark-util-character: 2.1.1
- mdast-util-gfm-footnote@2.1.0:
+ mdast-util-gfm-footnote@2.1.0(supports-color@10.2.2):
dependencies:
'@types/mdast': 4.0.4
devlop: 1.1.0
- mdast-util-from-markdown: 2.0.3
+ mdast-util-from-markdown: 2.0.3(supports-color@10.2.2)
mdast-util-to-markdown: 2.1.2
micromark-util-normalize-identifier: 2.0.1
transitivePeerDependencies:
- supports-color
- mdast-util-gfm-strikethrough@2.0.0:
+ mdast-util-gfm-strikethrough@2.0.0(supports-color@10.2.2):
dependencies:
'@types/mdast': 4.0.4
- mdast-util-from-markdown: 2.0.3
+ mdast-util-from-markdown: 2.0.3(supports-color@10.2.2)
mdast-util-to-markdown: 2.1.2
transitivePeerDependencies:
- supports-color
- mdast-util-gfm-table@2.0.0:
+ mdast-util-gfm-table@2.0.0(supports-color@10.2.2):
dependencies:
'@types/mdast': 4.0.4
devlop: 1.1.0
markdown-table: 3.0.4
- mdast-util-from-markdown: 2.0.3
+ mdast-util-from-markdown: 2.0.3(supports-color@10.2.2)
mdast-util-to-markdown: 2.1.2
transitivePeerDependencies:
- supports-color
- mdast-util-gfm-task-list-item@2.0.0:
+ mdast-util-gfm-task-list-item@2.0.0(supports-color@10.2.2):
dependencies:
'@types/mdast': 4.0.4
devlop: 1.1.0
- mdast-util-from-markdown: 2.0.3
+ mdast-util-from-markdown: 2.0.3(supports-color@10.2.2)
mdast-util-to-markdown: 2.1.2
transitivePeerDependencies:
- supports-color
- mdast-util-gfm@3.1.0:
+ mdast-util-gfm@3.1.0(supports-color@10.2.2):
dependencies:
- mdast-util-from-markdown: 2.0.3
+ mdast-util-from-markdown: 2.0.3(supports-color@10.2.2)
mdast-util-gfm-autolink-literal: 2.0.1
- mdast-util-gfm-footnote: 2.1.0
- mdast-util-gfm-strikethrough: 2.0.0
- mdast-util-gfm-table: 2.0.0
- mdast-util-gfm-task-list-item: 2.0.0
+ mdast-util-gfm-footnote: 2.1.0(supports-color@10.2.2)
+ mdast-util-gfm-strikethrough: 2.0.0(supports-color@10.2.2)
+ mdast-util-gfm-table: 2.0.0(supports-color@10.2.2)
+ mdast-util-gfm-task-list-item: 2.0.0(supports-color@10.2.2)
mdast-util-to-markdown: 2.1.2
transitivePeerDependencies:
- supports-color
- mdast-util-mdx-expression@2.0.1:
+ mdast-util-mdx-expression@2.0.1(supports-color@10.2.2):
dependencies:
'@types/estree-jsx': 1.0.5
'@types/hast': 3.0.5
'@types/mdast': 4.0.4
devlop: 1.1.0
- mdast-util-from-markdown: 2.0.3
+ mdast-util-from-markdown: 2.0.3(supports-color@10.2.2)
mdast-util-to-markdown: 2.1.2
transitivePeerDependencies:
- supports-color
- mdast-util-mdx-jsx@3.2.0:
+ mdast-util-mdx-jsx@3.2.0(supports-color@10.2.2):
dependencies:
'@types/estree-jsx': 1.0.5
'@types/hast': 3.0.5
@@ -13062,7 +14141,7 @@ snapshots:
'@types/unist': 3.0.3
ccount: 2.0.1
devlop: 1.1.0
- mdast-util-from-markdown: 2.0.3
+ mdast-util-from-markdown: 2.0.3(supports-color@10.2.2)
mdast-util-to-markdown: 2.1.2
parse-entities: 4.0.2
stringify-entities: 4.0.4
@@ -13071,13 +14150,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
- mdast-util-mdxjs-esm@2.0.1:
+ mdast-util-mdxjs-esm@2.0.1(supports-color@10.2.2):
dependencies:
'@types/estree-jsx': 1.0.5
'@types/hast': 3.0.5
'@types/mdast': 4.0.4
devlop: 1.1.0
- mdast-util-from-markdown: 2.0.3
+ mdast-util-from-markdown: 2.0.3(supports-color@10.2.2)
mdast-util-to-markdown: 2.1.2
transitivePeerDependencies:
- supports-color
@@ -13307,7 +14386,7 @@ snapshots:
micromark-util-types@2.0.2: {}
- micromark@4.0.2:
+ micromark@4.0.2(supports-color@10.2.2):
dependencies:
'@types/debug': 4.1.13
debug: 4.4.3(supports-color@10.2.2)
@@ -13378,6 +14457,8 @@ snapshots:
modern-tar@0.8.4: {}
+ module-alias@2.3.4: {}
+
module-definition@6.0.2:
dependencies:
ast-module-types: 6.0.2
@@ -13420,7 +14501,7 @@ snapshots:
negotiator@1.0.0: {}
- netlify-cli@27.1.2(@types/node@24.13.3)(picomatch@4.0.5):
+ netlify-cli@27.1.2(@types/node@24.13.3)(picomatch@4.0.5)(supports-color@10.2.2):
dependencies:
'@fastify/static': 10.1.3
'@netlify/ai': 0.4.4
@@ -13429,19 +14510,19 @@ snapshots:
'@netlify/build': 36.3.5(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(picomatch@4.0.5)
'@netlify/build-info': 11.3.0
'@netlify/config': 25.2.2
- '@netlify/dev': 4.18.13
+ '@netlify/dev': 4.18.13(supports-color@10.2.2)
'@netlify/dev-utils': 5.0.0
'@netlify/edge-bundler': 16.0.3
'@netlify/edge-functions': 3.0.8
'@netlify/edge-functions-bootstrap': 3.2.0
'@netlify/headers-parser': 10.1.1
- '@netlify/images': 1.3.12(@netlify/blobs@10.7.13)
+ '@netlify/images': 1.3.12(@netlify/blobs@10.7.13(supports-color@10.2.2))
'@netlify/local-functions-proxy': 2.0.3
'@netlify/redirect-parser': 16.1.0
'@netlify/zip-it-and-ship-it': 15.3.4(supports-color@10.2.2)
'@octokit/rest': 22.0.1
'@opentelemetry/api': 1.9.1
- '@pnpm/tabtab': 0.5.4
+ '@pnpm/tabtab': 0.5.4(supports-color@10.2.2)
ansi-escapes: 7.3.0
ansi-to-html: 0.7.2
ascii-table: 0.0.9
@@ -13464,7 +14545,7 @@ snapshots:
envinfo: 7.21.0
etag: 1.8.1
execa: 5.1.1
- express: 5.2.1
+ express: 5.2.1(supports-color@10.2.2)
express-logging: 1.1.1
fastest-levenshtein: 1.0.16
fastify: 5.12.1
@@ -13474,9 +14555,9 @@ snapshots:
get-port: 5.1.1
git-repo-info: 2.1.1
gitconfiglocal: 2.1.0
- http-proxy: 1.18.1(debug@4.4.3)
- http-proxy-middleware: 3.0.7
- https-proxy-agent: 8.0.0
+ http-proxy: 1.18.1(debug@4.4.3(supports-color@10.2.2))
+ http-proxy-middleware: 3.0.7(supports-color@10.2.2)
+ https-proxy-agent: 8.0.0(supports-color@10.2.2)
inquirer: 8.2.7(@types/node@24.13.3)
inquirer-autocomplete-prompt: 1.4.0(inquirer@8.2.7(@types/node@24.13.3))
is-docker: 4.0.0
@@ -13556,7 +14637,7 @@ snapshots:
netlify-redirector@0.5.0: {}
- next@16.3.0(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8):
+ next@16.3.0(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8):
dependencies:
'@next/env': 16.3.0
'@swc/helpers': 0.5.15
@@ -13565,7 +14646,7 @@ snapshots:
postcss: 8.5.23
react: 19.2.8
react-dom: 19.2.8(react@19.2.8)
- styled-jsx: 5.1.6(@babel/core@7.29.7)(react@19.2.8)
+ styled-jsx: 5.1.6(@babel/core@7.29.7(supports-color@10.2.2))(react@19.2.8)
optionalDependencies:
'@next/swc-darwin-arm64': 16.3.0
'@next/swc-darwin-x64': 16.3.0
@@ -13582,7 +14663,7 @@ snapshots:
- '@types/node'
- babel-plugin-macros
- next@16.3.1(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8):
+ next@16.3.1(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8):
dependencies:
'@next/env': 16.3.1
'@swc/helpers': 0.5.23
@@ -13591,7 +14672,7 @@ snapshots:
postcss: 8.5.23
react: 19.2.8
react-dom: 19.2.8(react@19.2.8)
- styled-jsx: 5.1.6(@babel/core@7.29.7)(react@19.2.8)
+ styled-jsx: 5.1.6(@babel/core@7.29.7(supports-color@10.2.2))(react@19.2.8)
optionalDependencies:
'@next/swc-darwin-arm64': 16.3.1
'@next/swc-darwin-x64': 16.3.1
@@ -13772,6 +14853,13 @@ snapshots:
dependencies:
mimic-function: 5.0.1
+ open@10.2.0:
+ dependencies:
+ default-browser: 5.5.1
+ define-lazy-prop: 3.0.0
+ is-inside-container: 1.0.0
+ wsl-utils: 0.1.0
+
open@11.0.1:
dependencies:
default-browser: 5.5.1
@@ -13814,6 +14902,53 @@ snapshots:
object-keys: 1.1.1
safe-push-apply: 1.0.0
+ oxc-parser@0.127.0:
+ dependencies:
+ '@oxc-project/types': 0.127.0
+ optionalDependencies:
+ '@oxc-parser/binding-android-arm-eabi': 0.127.0
+ '@oxc-parser/binding-android-arm64': 0.127.0
+ '@oxc-parser/binding-darwin-arm64': 0.127.0
+ '@oxc-parser/binding-darwin-x64': 0.127.0
+ '@oxc-parser/binding-freebsd-x64': 0.127.0
+ '@oxc-parser/binding-linux-arm-gnueabihf': 0.127.0
+ '@oxc-parser/binding-linux-arm-musleabihf': 0.127.0
+ '@oxc-parser/binding-linux-arm64-gnu': 0.127.0
+ '@oxc-parser/binding-linux-arm64-musl': 0.127.0
+ '@oxc-parser/binding-linux-ppc64-gnu': 0.127.0
+ '@oxc-parser/binding-linux-riscv64-gnu': 0.127.0
+ '@oxc-parser/binding-linux-riscv64-musl': 0.127.0
+ '@oxc-parser/binding-linux-s390x-gnu': 0.127.0
+ '@oxc-parser/binding-linux-x64-gnu': 0.127.0
+ '@oxc-parser/binding-linux-x64-musl': 0.127.0
+ '@oxc-parser/binding-openharmony-arm64': 0.127.0
+ '@oxc-parser/binding-wasm32-wasi': 0.127.0
+ '@oxc-parser/binding-win32-arm64-msvc': 0.127.0
+ '@oxc-parser/binding-win32-ia32-msvc': 0.127.0
+ '@oxc-parser/binding-win32-x64-msvc': 0.127.0
+
+ oxc-resolver@11.21.2:
+ optionalDependencies:
+ '@oxc-resolver/binding-android-arm-eabi': 11.21.2
+ '@oxc-resolver/binding-android-arm64': 11.21.2
+ '@oxc-resolver/binding-darwin-arm64': 11.21.2
+ '@oxc-resolver/binding-darwin-x64': 11.21.2
+ '@oxc-resolver/binding-freebsd-x64': 11.21.2
+ '@oxc-resolver/binding-linux-arm-gnueabihf': 11.21.2
+ '@oxc-resolver/binding-linux-arm-musleabihf': 11.21.2
+ '@oxc-resolver/binding-linux-arm64-gnu': 11.21.2
+ '@oxc-resolver/binding-linux-arm64-musl': 11.21.2
+ '@oxc-resolver/binding-linux-ppc64-gnu': 11.21.2
+ '@oxc-resolver/binding-linux-riscv64-gnu': 11.21.2
+ '@oxc-resolver/binding-linux-riscv64-musl': 11.21.2
+ '@oxc-resolver/binding-linux-s390x-gnu': 11.21.2
+ '@oxc-resolver/binding-linux-x64-gnu': 11.21.2
+ '@oxc-resolver/binding-linux-x64-musl': 11.21.2
+ '@oxc-resolver/binding-openharmony-arm64': 11.21.2
+ '@oxc-resolver/binding-wasm32-wasi': 11.21.2
+ '@oxc-resolver/binding-win32-arm64-msvc': 11.21.2
+ '@oxc-resolver/binding-win32-x64-msvc': 11.21.2
+
p-event@6.0.1:
dependencies:
p-timeout: 6.1.4
@@ -13946,6 +15081,8 @@ snapshots:
pathe@2.0.3: {}
+ pathval@2.0.1: {}
+
peberminta@0.9.0: {}
pend@1.2.0: {}
@@ -14195,15 +15332,34 @@ snapshots:
minimist: 1.2.8
strip-json-comments: 2.0.1
+ react-docgen-typescript@2.4.0(typescript@6.0.3):
+ dependencies:
+ typescript: 6.0.3
+
+ react-docgen@8.0.3(supports-color@10.2.2):
+ dependencies:
+ '@babel/core': 7.29.7(supports-color@10.2.2)
+ '@babel/traverse': 7.29.8(supports-color@10.2.2)
+ '@babel/types': 7.29.8
+ '@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.12
+ strip-indent: 4.1.1
+ transitivePeerDependencies:
+ - supports-color
+
react-dom@19.2.8(react@19.2.8):
dependencies:
react: 19.2.8
scheduler: 0.27.0
- react-email@6.9.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8):
+ react-email@6.9.2(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(supports-color@10.2.2):
dependencies:
'@babel/parser': 7.29.2
- '@babel/traverse': 7.29.0
+ '@babel/traverse': 7.29.0(supports-color@10.2.2)
'@react-email/render': 2.1.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
chokidar: 4.0.3
commander: 13.1.0
@@ -14223,7 +15379,7 @@ snapshots:
prompts: 2.4.2
react: 19.2.8
react-dom: 19.2.8(react@19.2.8)
- socket.io: 4.8.3
+ socket.io: 4.8.3(supports-color@10.2.2)
tailwindcss: 4.3.3
tsconfig-paths: 4.2.0
transitivePeerDependencies:
@@ -14235,17 +15391,17 @@ snapshots:
react-is@17.0.2: {}
- react-markdown@10.1.0(@types/react@19.2.18)(react@19.2.8):
+ react-markdown@10.1.0(@types/react@19.2.18)(react@19.2.8)(supports-color@10.2.2):
dependencies:
'@types/hast': 3.0.5
'@types/mdast': 4.0.4
'@types/react': 19.2.18
devlop: 1.1.0
- hast-util-to-jsx-runtime: 2.3.6
+ hast-util-to-jsx-runtime: 2.3.6(supports-color@10.2.2)
html-url-attributes: 3.0.1
mdast-util-to-hast: 13.2.1
react: 19.2.8
- remark-parse: 11.0.0
+ remark-parse: 11.0.0(supports-color@10.2.2)
remark-rehype: 11.1.2
unified: 11.0.5
unist-util-visit: 5.1.0
@@ -14319,6 +15475,14 @@ snapshots:
real-require@1.0.0: {}
+ recast@0.23.21:
+ dependencies:
+ ast-types: 0.16.3
+ esprima: 4.0.1
+ source-map: 0.6.1
+ tiny-invariant: 1.3.3
+ tslib: 2.8.1
+
redent@3.0.0:
dependencies:
indent-string: 4.0.0
@@ -14352,21 +15516,21 @@ snapshots:
dependencies:
rc: 1.2.8
- remark-gfm@4.0.1:
+ remark-gfm@4.0.1(supports-color@10.2.2):
dependencies:
'@types/mdast': 4.0.4
- mdast-util-gfm: 3.1.0
+ mdast-util-gfm: 3.1.0(supports-color@10.2.2)
micromark-extension-gfm: 3.0.0
- remark-parse: 11.0.0
+ remark-parse: 11.0.0(supports-color@10.2.2)
remark-stringify: 11.0.0
unified: 11.0.5
transitivePeerDependencies:
- supports-color
- remark-parse@11.0.0:
+ remark-parse@11.0.0(supports-color@10.2.2):
dependencies:
'@types/mdast': 4.0.4
- mdast-util-from-markdown: 2.0.3
+ mdast-util-from-markdown: 2.0.3(supports-color@10.2.2)
micromark-util-types: 2.0.2
unified: 11.0.5
transitivePeerDependencies:
@@ -14416,6 +15580,13 @@ snapshots:
resolve-pkg-maps@1.0.0: {}
+ resolve@1.22.12:
+ dependencies:
+ es-errors: 1.3.0
+ is-core-module: 2.16.2
+ path-parse: 1.0.7
+ supports-preserve-symlinks-flag: 1.0.0
+
resolve@2.0.0-next.7:
dependencies:
es-errors: 1.3.0
@@ -14465,7 +15636,7 @@ snapshots:
rou3@0.9.2: {}
- router@2.2.0:
+ router@2.2.0(supports-color@10.2.2):
dependencies:
debug: 4.4.3(supports-color@10.2.2)
depd: 2.0.0
@@ -14543,7 +15714,7 @@ snapshots:
semver@7.8.5: {}
- send@1.2.1:
+ send@1.2.1(supports-color@10.2.2):
dependencies:
debug: 4.4.3(supports-color@10.2.2)
encodeurl: 2.0.0
@@ -14559,12 +15730,12 @@ snapshots:
transitivePeerDependencies:
- supports-color
- serve-static@2.2.1:
+ serve-static@2.2.1(supports-color@10.2.2):
dependencies:
encodeurl: 2.0.0
escape-html: 1.0.3
parseurl: 1.3.3
- send: 1.2.1
+ send: 1.2.1(supports-color@10.2.2)
transitivePeerDependencies:
- supports-color
@@ -14726,7 +15897,7 @@ snapshots:
smol-toml@1.8.0: {}
- socket.io-adapter@2.5.8:
+ socket.io-adapter@2.5.8(supports-color@10.2.2):
dependencies:
debug: 4.4.3(supports-color@10.2.2)
ws: 8.21.3
@@ -14735,22 +15906,22 @@ snapshots:
- supports-color
- utf-8-validate
- socket.io-parser@4.2.7:
+ socket.io-parser@4.2.7(supports-color@10.2.2):
dependencies:
'@socket.io/component-emitter': 3.1.2
debug: 4.4.3(supports-color@10.2.2)
transitivePeerDependencies:
- supports-color
- socket.io@4.8.3:
+ socket.io@4.8.3(supports-color@10.2.2):
dependencies:
accepts: 1.3.8
base64id: 2.0.0
cors: 2.8.6
debug: 4.4.3(supports-color@10.2.2)
- engine.io: 6.6.9
- socket.io-adapter: 2.5.8
- socket.io-parser: 4.2.7
+ engine.io: 6.6.9(supports-color@10.2.2)
+ socket.io-adapter: 2.5.8(supports-color@10.2.2)
+ socket.io-parser: 4.2.7(supports-color@10.2.2)
transitivePeerDependencies:
- bufferutil
- supports-color
@@ -14791,6 +15962,8 @@ snapshots:
split2@4.2.0: {}
+ sqids@0.3.0: {}
+
stable-hash@0.0.5: {}
stack-generator@2.0.10:
@@ -14819,6 +15992,33 @@ snapshots:
es-errors: 1.3.0
internal-slot: 1.1.0
+ storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8):
+ dependencies:
+ '@storybook/global': 5.0.0
+ '@storybook/icons': 2.1.0(react@19.2.8)
+ '@testing-library/dom': 10.4.1
+ '@testing-library/jest-dom': 6.9.1
+ '@testing-library/user-event': 14.6.6(@testing-library/dom@10.4.1)
+ '@vitest/expect': 3.2.4
+ '@vitest/spy': 3.2.4
+ '@webcontainer/env': 1.1.1
+ esbuild: 0.28.1
+ jsonc-parser: 3.3.1
+ open: 10.2.0
+ oxc-parser: 0.127.0
+ oxc-resolver: 11.21.2
+ recast: 0.23.21
+ semver: 7.8.5
+ use-sync-external-store: 1.6.0(react@19.2.8)
+ ws: 8.21.3
+ optionalDependencies:
+ '@types/react': 19.2.18
+ prettier: 3.9.6
+ transitivePeerDependencies:
+ - bufferutil
+ - react
+ - utf-8-validate
+
streamx@2.28.0:
dependencies:
events-universal: 1.0.1
@@ -14933,6 +16133,8 @@ snapshots:
dependencies:
min-indent: 1.0.1
+ strip-indent@4.1.1: {}
+
strip-json-comments@2.0.1: {}
strip-json-comments@3.1.1: {}
@@ -14951,12 +16153,12 @@ snapshots:
dependencies:
inline-style-parser: 0.2.7
- styled-jsx@5.1.6(@babel/core@7.29.7)(react@19.2.8):
+ styled-jsx@5.1.6(@babel/core@7.29.7(supports-color@10.2.2))(react@19.2.8):
dependencies:
client-only: 0.0.1
react: 19.2.8
optionalDependencies:
- '@babel/core': 7.29.7
+ '@babel/core': 7.29.7(supports-color@10.2.2)
supports-color@10.2.2: {}
@@ -15050,6 +16252,8 @@ snapshots:
through@2.3.8: {}
+ tiny-invariant@1.3.3: {}
+
tinybench@6.1.3: {}
tinyclip@0.1.15: {}
@@ -15061,8 +16265,12 @@ snapshots:
fdir: 6.5.0(picomatch@4.0.5)
picomatch: 4.0.5
+ tinyrainbow@2.0.0: {}
+
tinyrainbow@3.1.1: {}
+ tinyspy@4.0.4: {}
+
tldts-core@7.4.10:
optional: true
@@ -15071,6 +16279,16 @@ snapshots:
tldts-core: 7.4.10
optional: true
+ tmcp@1.20.0(typescript@6.0.3):
+ dependencies:
+ '@standard-schema/spec': 1.1.0
+ json-rpc-2.0: 1.8.0
+ sqids: 0.3.0
+ uri-template-matcher: 1.1.2
+ valibot: 1.2.0(typescript@6.0.3)
+ transitivePeerDependencies:
+ - typescript
+
tmp-promise@3.0.3:
dependencies:
tmp: 0.2.7
@@ -15117,6 +16335,8 @@ snapshots:
dependencies:
typescript: 6.0.3
+ ts-dedent@2.3.0: {}
+
ts-node@10.9.2(@types/node@24.13.3)(typescript@5.9.3):
dependencies:
'@cspotcode/source-map-support': 0.8.1
@@ -15135,6 +16355,10 @@ snapshots:
v8-compile-cache-lib: 3.0.1
yn: 3.1.1
+ tsconfck@3.1.6(typescript@6.0.3):
+ optionalDependencies:
+ typescript: 6.0.3
+
tsconfig-paths@3.15.0:
dependencies:
'@types/json5': 0.0.29
@@ -15203,13 +16427,13 @@ snapshots:
possible-typed-array-names: 1.1.0
reflect.getprototypeof: 1.0.10
- typescript-eslint@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3):
+ typescript-eslint@8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3):
dependencies:
- '@typescript-eslint/eslint-plugin': 8.67.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3))(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3)
- '@typescript-eslint/parser': 8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3)
- '@typescript-eslint/typescript-estree': 8.67.0(typescript@6.0.3)
- '@typescript-eslint/utils': 8.67.0(eslint@9.39.5(jiti@2.7.0))(typescript@6.0.3)
- eslint: 9.39.5(jiti@2.7.0)
+ '@typescript-eslint/eslint-plugin': 8.67.0(@typescript-eslint/parser@8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3))(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
+ '@typescript-eslint/parser': 8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
+ '@typescript-eslint/typescript-estree': 8.67.0(supports-color@10.2.2)(typescript@6.0.3)
+ '@typescript-eslint/utils': 8.67.0(eslint@9.39.5(jiti@2.7.0)(supports-color@10.2.2))(supports-color@10.2.2)(typescript@6.0.3)
+ eslint: 9.39.5(jiti@2.7.0)(supports-color@10.2.2)
typescript: 6.0.3
transitivePeerDependencies:
- supports-color
@@ -15295,6 +16519,13 @@ snapshots:
unpipe@1.0.0: {}
+ unplugin@2.3.11:
+ dependencies:
+ '@jridgewell/remapping': 2.3.5
+ acorn: 8.18.0
+ picomatch: 4.0.5
+ webpack-virtual-modules: 0.6.2
+
unrs-resolver@1.12.2:
dependencies:
napi-postinstall: 0.3.4
@@ -15322,7 +16553,7 @@ snapshots:
'@unrs/resolver-binding-win32-ia32-msvc': 1.12.2
'@unrs/resolver-binding-win32-x64-msvc': 1.12.2
- unstorage@1.17.5(@netlify/blobs@10.7.13):
+ unstorage@1.17.5(@netlify/blobs@10.7.13(supports-color@10.2.2)):
dependencies:
anymatch: 3.1.3
chokidar: 5.0.0
@@ -15364,14 +16595,24 @@ snapshots:
dependencies:
punycode: 2.3.1
+ uri-template-matcher@1.1.2: {}
+
urlpattern-polyfill@10.1.0: {}
urlpattern-polyfill@8.0.2: {}
+ use-sync-external-store@1.6.0(react@19.2.8):
+ dependencies:
+ react: 19.2.8
+
util-deprecate@1.0.2: {}
v8-compile-cache-lib@3.0.1: {}
+ valibot@1.2.0(typescript@6.0.3):
+ optionalDependencies:
+ typescript: 6.0.3
+
validate-npm-package-license@3.0.4:
dependencies:
spdx-correct: 3.2.0
@@ -15391,6 +16632,32 @@ snapshots:
'@types/unist': 3.0.3
vfile-message: 4.0.3
+ vite-plugin-storybook-nextjs@3.3.2(next@16.3.1(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(supports-color@10.2.2)(typescript@6.0.3)(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)):
+ dependencies:
+ '@next/env': 16.3.0-preview.5
+ image-size: 2.0.2
+ magic-string: 0.30.21
+ module-alias: 2.3.4
+ next: 16.3.1(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
+ storybook: 10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8)
+ ts-dedent: 2.3.0
+ vite: 8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)
+ vite-tsconfig-paths: 5.1.4(supports-color@10.2.2)(typescript@6.0.3)(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
+ transitivePeerDependencies:
+ - supports-color
+ - typescript
+
+ vite-tsconfig-paths@5.1.4(supports-color@10.2.2)(typescript@6.0.3)(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)):
+ dependencies:
+ debug: 4.4.3(supports-color@10.2.2)
+ globrex: 0.1.2
+ tsconfck: 3.1.6(typescript@6.0.3)
+ optionalDependencies:
+ vite: 8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)
+ transitivePeerDependencies:
+ - supports-color
+ - typescript
+
vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0):
dependencies:
lightningcss: 1.33.0
@@ -15451,6 +16718,8 @@ snapshots:
webidl-conversions@8.0.1:
optional: true
+ webpack-virtual-modules@0.6.2: {}
+
whatwg-mimetype@5.0.0:
optional: true
@@ -15597,6 +16866,10 @@ snapshots:
ws@8.21.3: {}
+ wsl-utils@0.1.0:
+ dependencies:
+ is-wsl: 3.1.1
+
wsl-utils@1.0.0:
dependencies:
is-wsl: 3.1.1
diff --git a/stories/Button.stories.ts b/stories/Button.stories.ts
new file mode 100644
index 0000000..10e9d4b
--- /dev/null
+++ b/stories/Button.stories.ts
@@ -0,0 +1,54 @@
+import type { Meta, StoryObj } from "@storybook/nextjs-vite";
+
+import { fn } from "storybook/test";
+
+import { Button } from "./Button";
+
+// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
+const meta = {
+ title: "Example/Button",
+ component: Button,
+ parameters: {
+ // Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout
+ layout: "centered",
+ },
+ // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
+ tags: ["autodocs"],
+ // More on argTypes: https://storybook.js.org/docs/api/arg-types
+ argTypes: {
+ backgroundColor: { control: "color" },
+ },
+ // Use `fn` to spy on the onClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#story-args
+ args: { onClick: fn() },
+} satisfies Meta;
+
+export default meta;
+type Story = StoryObj;
+
+// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
+export const Primary: Story = {
+ args: {
+ primary: true,
+ label: "Button",
+ },
+};
+
+export const Secondary: Story = {
+ args: {
+ label: "Button",
+ },
+};
+
+export const Large: Story = {
+ args: {
+ size: "large",
+ label: "Button",
+ },
+};
+
+export const Small: Story = {
+ args: {
+ size: "small",
+ label: "Button",
+ },
+};
diff --git a/stories/Button.tsx b/stories/Button.tsx
new file mode 100644
index 0000000..29e42f5
--- /dev/null
+++ b/stories/Button.tsx
@@ -0,0 +1,43 @@
+import "./button.css";
+
+export interface ButtonProps {
+ /** Is this the principal call to action on the page? */
+ primary?: boolean;
+ /** What background color to use */
+ backgroundColor?: string;
+ /** How large should the button be? */
+ size?: "small" | "medium" | "large";
+ /** Button contents */
+ label: string;
+ /** Optional click handler */
+ onClick?: () => void;
+}
+
+/** Primary UI component for user interaction */
+export const Button = ({
+ primary = false,
+ size = "medium",
+ backgroundColor,
+ label,
+ ...props
+}: ButtonProps) => {
+ const mode = primary
+ ? "storybook-button--primary"
+ : "storybook-button--secondary";
+ return (
+
+ );
+};
diff --git a/stories/button.css b/stories/button.css
new file mode 100644
index 0000000..04ffdf3
--- /dev/null
+++ b/stories/button.css
@@ -0,0 +1,30 @@
+.storybook-button {
+ display: inline-block;
+ cursor: pointer;
+ border: 0;
+ border-radius: 3em;
+ font-weight: 700;
+ line-height: 1;
+ font-family: "Nunito Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
+.storybook-button--primary {
+ background-color: #555ab9;
+ color: white;
+}
+.storybook-button--secondary {
+ box-shadow: rgba(0, 0, 0, 0.15) 0px 0px 0px 1px inset;
+ background-color: transparent;
+ color: #333;
+}
+.storybook-button--small {
+ padding: 10px 16px;
+ font-size: 12px;
+}
+.storybook-button--medium {
+ padding: 11px 20px;
+ font-size: 14px;
+}
+.storybook-button--large {
+ padding: 12px 24px;
+ font-size: 16px;
+}
diff --git a/vitest.config.mts b/vitest.config.mts
index 881d099..403dd01 100644
--- a/vitest.config.mts
+++ b/vitest.config.mts
@@ -40,7 +40,9 @@ export default defineConfig({
include: ["**/*.test.ts"],
exclude: [...defaultExclude, databaseIntegrationTestPattern],
environment: "node",
- sequence: { groupOrder: 0 },
+ sequence: {
+ groupOrder: 0,
+ },
},
},
{
@@ -55,7 +57,9 @@ export default defineConfig({
// sequential so each can reset the schema data before it runs.
fileParallelism: false,
isolate: true,
- sequence: { groupOrder: 1 },
+ sequence: {
+ groupOrder: 1,
+ },
},
},
{
@@ -64,13 +68,22 @@ export default defineConfig({
name: "browser",
include: ["**/*.integration.test.tsx"],
setupFiles: ["./vitest.setup.ts"],
- sequence: { groupOrder: 0 },
+ sequence: {
+ groupOrder: 0,
+ },
browser: {
enabled: true,
headless: true,
provider: playwright(),
- instances: [{ browser: "chromium" }],
- viewport: { width: 1280, height: 720 },
+ instances: [
+ {
+ browser: "chromium",
+ },
+ ],
+ viewport: {
+ width: 1280,
+ height: 720,
+ },
},
},
},
diff --git a/vitest.shims.d.ts b/vitest.shims.d.ts
new file mode 100644
index 0000000..03b1801
--- /dev/null
+++ b/vitest.shims.d.ts
@@ -0,0 +1 @@
+///
From f0ed47cd798499dc04777b21f2bf81ba44ef8835 Mon Sep 17 00:00:00 2001
From: Corbin Crutchley
Date: Tue, 1 Sep 2026 16:26:45 -0700
Subject: [PATCH 2/6] chore: migrate to CFNext
---
.storybook/main.ts | 8 +++-----
.storybook/preview.tsx | 10 +++++-----
stories/Button.stories.ts | 25 +++++++++++--------------
3 files changed, 19 insertions(+), 24 deletions(-)
diff --git a/.storybook/main.ts b/.storybook/main.ts
index 2617af8..b5ae066 100644
--- a/.storybook/main.ts
+++ b/.storybook/main.ts
@@ -1,9 +1,7 @@
-import type { StorybookConfig } from "@storybook/nextjs-vite";
-
-const config: StorybookConfig = {
+import { defineMain } from "@storybook/nextjs-vite/node";
+export default defineMain({
stories: ["../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
addons: ["@storybook/addon-mcp"],
framework: "@storybook/nextjs-vite",
staticDirs: ["../public"],
-};
-export default config;
+});
diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx
index c0adadc..3feec0d 100644
--- a/.storybook/preview.tsx
+++ b/.storybook/preview.tsx
@@ -1,7 +1,7 @@
-import type { Preview } from "@storybook/nextjs-vite";
+import { definePreview } from "@storybook/nextjs-vite";
-const preview: Preview = {
- parameters: {
+export default definePreview({
+ parameters: {
controls: {
matchers: {
color: /(background|color)$/i,
@@ -9,6 +9,6 @@ const preview: Preview = {
},
},
},
-};
-export default preview;
+ addons: []
+});
diff --git a/stories/Button.stories.ts b/stories/Button.stories.ts
index 10e9d4b..670768c 100644
--- a/stories/Button.stories.ts
+++ b/stories/Button.stories.ts
@@ -1,11 +1,11 @@
-import type { Meta, StoryObj } from "@storybook/nextjs-vite";
+import preview from "../.storybook/preview";
import { fn } from "storybook/test";
import { Button } from "./Button";
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
-const meta = {
+const meta = preview.meta({
title: "Example/Button",
component: Button,
parameters: {
@@ -20,35 +20,32 @@ const meta = {
},
// Use `fn` to spy on the onClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#story-args
args: { onClick: fn() },
-} satisfies Meta;
-
-export default meta;
-type Story = StoryObj;
+});
// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
-export const Primary: Story = {
+export const Primary = meta.story({
args: {
primary: true,
label: "Button",
},
-};
+});
-export const Secondary: Story = {
+export const Secondary = meta.story({
args: {
label: "Button",
},
-};
+});
-export const Large: Story = {
+export const Large = meta.story({
args: {
size: "large",
label: "Button",
},
-};
+});
-export const Small: Story = {
+export const Small = meta.story({
args: {
size: "small",
label: "Button",
},
-};
+});
From 14b1ae618bb4bd70e4471f468718893dcc16845b Mon Sep 17 00:00:00 2001
From: Corbin Crutchley
Date: Tue, 1 Sep 2026 16:48:09 -0700
Subject: [PATCH 3/6] chore: initial set of stories
---
.gitignore | 1 +
.prettierignore | 1 +
.storybook/main.ts | 4 +
.storybook/preview.tsx | 19 +-
app/page.tsx | 12 +-
eslint.config.mjs | 1 +
package.json | 2 +-
stories/Button.stories.ts | 51 -----
stories/Button.tsx | 43 ----
.../app/account/cancel-event-form.stories.tsx | 99 +++++++++
stories/app/account/page.stories.tsx | 57 +++++
.../app/account/sign-out-button.stories.tsx | 64 ++++++
.../admin/events/moderation-form.stories.tsx | 133 +++++++++++
stories/app/admin/events/page.stories.tsx | 87 ++++++++
.../users/admin-users-content.stories.tsx | 65 ++++++
stories/app/admin/users/page.stories.tsx | 84 +++++++
.../users/user-management-card.stories.tsx | 189 ++++++++++++++++
stories/app/auth/auth-form.stories.tsx | 210 ++++++++++++++++++
stories/app/auth/page.stories.tsx | 55 +++++
.../app/auth/reset-password/page.stories.tsx | 60 +++++
.../reset-password-form.stories.tsx | 208 +++++++++++++++++
.../app/auth/verify-email/page.stories.tsx | 65 ++++++
.../verification-result.stories.tsx | 71 ++++++
stories/app/code-of-conduct/page.stories.tsx | 12 +
.../edit/collaborator-invite-form.stories.tsx | 92 ++++++++
.../events/[eventId]/edit/page.stories.tsx | 130 +++++++++++
.../components/calendar/calendar.stories.tsx | 76 +++++++
.../non-recurring-event-card.stories.tsx | 113 ++++++++++
.../recurring-event-card.stories.tsx | 85 +++++++
.../event-chip/event-chip.stories.tsx | 60 +++++
stories/app/events/events-page.stories.tsx | 63 ++++++
stories/app/events/page.stories.tsx | 100 +++++++++
.../event-description-editor.stories.tsx | 80 +++++++
.../app/events/submit/event-form.stories.tsx | 158 +++++++++++++
stories/app/events/submit/page.stories.tsx | 25 +++
stories/app/page.stories.tsx | 22 ++
stories/button.css | 30 ---
stories/components/bridge-art.stories.tsx | 38 ++++
.../collapsible-event-description.stories.tsx | 79 +++++++
.../event-description-markdown.stories.tsx | 96 ++++++++
stories/components/join-community.stories.tsx | 79 +++++++
stories/components/site-footer.stories.tsx | 26 +++
stories/components/site-header.stories.tsx | 63 ++++++
stories/components/site-nav.stories.tsx | 84 +++++++
stories/fixtures/admin.ts | 171 ++++++++++++++
stories/fixtures/auth.ts | 46 ++++
stories/fixtures/events.ts | 148 ++++++++++++
stories/fixtures/managed-event.ts | 45 ++++
stories/fixtures/submissions.ts | 100 +++++++++
stories/story-coverage.test.ts | 42 ++++
tsconfig.json | 1 +
51 files changed, 3515 insertions(+), 130 deletions(-)
delete mode 100644 stories/Button.stories.ts
delete mode 100644 stories/Button.tsx
create mode 100644 stories/app/account/cancel-event-form.stories.tsx
create mode 100644 stories/app/account/page.stories.tsx
create mode 100644 stories/app/account/sign-out-button.stories.tsx
create mode 100644 stories/app/admin/events/moderation-form.stories.tsx
create mode 100644 stories/app/admin/events/page.stories.tsx
create mode 100644 stories/app/admin/users/admin-users-content.stories.tsx
create mode 100644 stories/app/admin/users/page.stories.tsx
create mode 100644 stories/app/admin/users/user-management-card.stories.tsx
create mode 100644 stories/app/auth/auth-form.stories.tsx
create mode 100644 stories/app/auth/page.stories.tsx
create mode 100644 stories/app/auth/reset-password/page.stories.tsx
create mode 100644 stories/app/auth/reset-password/reset-password-form.stories.tsx
create mode 100644 stories/app/auth/verify-email/page.stories.tsx
create mode 100644 stories/app/auth/verify-email/verification-result.stories.tsx
create mode 100644 stories/app/code-of-conduct/page.stories.tsx
create mode 100644 stories/app/events/[eventId]/edit/collaborator-invite-form.stories.tsx
create mode 100644 stories/app/events/[eventId]/edit/page.stories.tsx
create mode 100644 stories/app/events/components/calendar/calendar.stories.tsx
create mode 100644 stories/app/events/components/event-cards/non-recurring-event-card.stories.tsx
create mode 100644 stories/app/events/components/event-cards/recurring-event-card.stories.tsx
create mode 100644 stories/app/events/components/event-chip/event-chip.stories.tsx
create mode 100644 stories/app/events/events-page.stories.tsx
create mode 100644 stories/app/events/page.stories.tsx
create mode 100644 stories/app/events/submit/event-description-editor.stories.tsx
create mode 100644 stories/app/events/submit/event-form.stories.tsx
create mode 100644 stories/app/events/submit/page.stories.tsx
create mode 100644 stories/app/page.stories.tsx
delete mode 100644 stories/button.css
create mode 100644 stories/components/bridge-art.stories.tsx
create mode 100644 stories/components/collapsible-event-description.stories.tsx
create mode 100644 stories/components/event-description-markdown.stories.tsx
create mode 100644 stories/components/join-community.stories.tsx
create mode 100644 stories/components/site-footer.stories.tsx
create mode 100644 stories/components/site-header.stories.tsx
create mode 100644 stories/components/site-nav.stories.tsx
create mode 100644 stories/fixtures/admin.ts
create mode 100644 stories/fixtures/auth.ts
create mode 100644 stories/fixtures/events.ts
create mode 100644 stories/fixtures/managed-event.ts
create mode 100644 stories/fixtures/submissions.ts
create mode 100644 stories/story-coverage.test.ts
diff --git a/.gitignore b/.gitignore
index 453e44a..29681aa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -46,5 +46,6 @@ next-env.d.ts
.vscode/
.idea/
+.pnpm-store/
*storybook.log
storybook-static
diff --git a/.prettierignore b/.prettierignore
index 79a7a2e..dab86de 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -7,6 +7,7 @@ node_modules
coverage
out
build
+storybook-static
next-env.d.ts
*.tsbuildinfo
diff --git a/.storybook/main.ts b/.storybook/main.ts
index b5ae066..9097d78 100644
--- a/.storybook/main.ts
+++ b/.storybook/main.ts
@@ -1,7 +1,11 @@
import { defineMain } from "@storybook/nextjs-vite/node";
+
export default defineMain({
stories: ["../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
addons: ["@storybook/addon-mcp"],
framework: "@storybook/nextjs-vite",
staticDirs: ["../public"],
+ features: {
+ experimentalRSC: true,
+ },
});
diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx
index 3feec0d..2b434e6 100644
--- a/.storybook/preview.tsx
+++ b/.storybook/preview.tsx
@@ -1,14 +1,27 @@
import { definePreview } from "@storybook/nextjs-vite";
+import { sb } from "storybook/test";
+import "../app/globals.css";
+
+sb.mock(import("../lib/session.ts"));
+sb.mock(import("../lib/events/queries.ts"));
+sb.mock(import("../lib/events/actions.ts"));
+sb.mock(import("../lib/auth-client.ts"));
+sb.mock(import("../lib/auth-config.ts"));
+sb.mock(import("../lib/email-delivery.ts"));
+sb.mock(import("../app/admin/users/actions.ts"));
export default definePreview({
- parameters: {
+ addons: [],
+ parameters: {
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
+ layout: "fullscreen",
+ nextjs: {
+ appDirectory: true,
+ },
},
-
- addons: []
});
diff --git a/app/page.tsx b/app/page.tsx
index 327a601..a6f56e5 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -9,7 +9,11 @@ export const metadata: Metadata = {
"Meet people, share what you know, and find technology events around Sacramento.",
};
-export default function Home() {
+interface HomePageProps {
+ inviteLink?: string;
+}
+
+export function HomePage({ inviteLink }: HomePageProps) {
return (
@@ -119,9 +123,13 @@ export default function Home() {
in the local community.
-
+
);
}
+
+export default function Home() {
+ return ;
+}
diff --git a/eslint.config.mjs b/eslint.config.mjs
index ce98339..589f1ba 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -14,6 +14,7 @@ export default defineConfig([
".netlify/**",
"out/**",
"build/**",
+ "storybook-static/**",
"next-env.d.ts",
]),
eslintConfigPrettier,
diff --git a/package.json b/package.json
index ffdc44a..681846c 100644
--- a/package.json
+++ b/package.json
@@ -18,7 +18,7 @@
"typecheck": "next typegen && tsc --noEmit",
"test": "vitest run",
"test:watch": "vitest",
- "verify": "pnpm format:check && pnpm lint && pnpm typecheck && pnpm test && pnpm build",
+ "verify": "pnpm format:check && pnpm lint && pnpm typecheck && pnpm test && pnpm build-storybook && pnpm build",
"db:generate": "drizzle-kit generate",
"db:migrate": "netlify database migrations apply",
"db:status": "netlify database status",
diff --git a/stories/Button.stories.ts b/stories/Button.stories.ts
deleted file mode 100644
index 670768c..0000000
--- a/stories/Button.stories.ts
+++ /dev/null
@@ -1,51 +0,0 @@
-import preview from "../.storybook/preview";
-
-import { fn } from "storybook/test";
-
-import { Button } from "./Button";
-
-// More on how to set up stories at: https://storybook.js.org/docs/writing-stories#default-export
-const meta = preview.meta({
- title: "Example/Button",
- component: Button,
- parameters: {
- // Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/configure/story-layout
- layout: "centered",
- },
- // This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/writing-docs/autodocs
- tags: ["autodocs"],
- // More on argTypes: https://storybook.js.org/docs/api/arg-types
- argTypes: {
- backgroundColor: { control: "color" },
- },
- // Use `fn` to spy on the onClick arg, which will appear in the actions panel once invoked: https://storybook.js.org/docs/essentials/actions#story-args
- args: { onClick: fn() },
-});
-
-// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
-export const Primary = meta.story({
- args: {
- primary: true,
- label: "Button",
- },
-});
-
-export const Secondary = meta.story({
- args: {
- label: "Button",
- },
-});
-
-export const Large = meta.story({
- args: {
- size: "large",
- label: "Button",
- },
-});
-
-export const Small = meta.story({
- args: {
- size: "small",
- label: "Button",
- },
-});
diff --git a/stories/Button.tsx b/stories/Button.tsx
deleted file mode 100644
index 29e42f5..0000000
--- a/stories/Button.tsx
+++ /dev/null
@@ -1,43 +0,0 @@
-import "./button.css";
-
-export interface ButtonProps {
- /** Is this the principal call to action on the page? */
- primary?: boolean;
- /** What background color to use */
- backgroundColor?: string;
- /** How large should the button be? */
- size?: "small" | "medium" | "large";
- /** Button contents */
- label: string;
- /** Optional click handler */
- onClick?: () => void;
-}
-
-/** Primary UI component for user interaction */
-export const Button = ({
- primary = false,
- size = "medium",
- backgroundColor,
- label,
- ...props
-}: ButtonProps) => {
- const mode = primary
- ? "storybook-button--primary"
- : "storybook-button--secondary";
- return (
-
- );
-};
diff --git a/stories/app/account/cancel-event-form.stories.tsx b/stories/app/account/cancel-event-form.stories.tsx
new file mode 100644
index 0000000..be838cc
--- /dev/null
+++ b/stories/app/account/cancel-event-form.stories.tsx
@@ -0,0 +1,99 @@
+import preview from "@/.storybook/preview";
+import { CancelEventForm } from "@/app/account/cancel-event-form";
+import { cancelEvent } from "@/lib/events/actions";
+import { expect, mocked, spyOn } from "storybook/test";
+
+const recurringArgs = {
+ defaultOccurrenceDate: "2026-10-22",
+ eventId: "storybook-event",
+ eventTitle: "Sacramento TypeScript Weekly",
+ isRecurring: true,
+ maxOccurrenceDate: "2027-02-25",
+ minOccurrenceDate: "2026-09-01",
+};
+
+const meta = preview.meta({
+ component: CancelEventForm,
+ parameters: {
+ layout: "centered",
+ },
+ args: recurringArgs,
+ decorators: [
+ (Story) => (
+
+
+
+ ),
+ ],
+});
+
+export const RecurringEvent = meta.story({
+ beforeEach: () => {
+ mocked(cancelEvent).mockResolvedValue({ message: "", status: "idle" });
+ },
+});
+
+export const OneTimeEvent = RecurringEvent.extend({
+ args: {
+ defaultOccurrenceDate: null,
+ isRecurring: false,
+ maxOccurrenceDate: null,
+ },
+});
+
+export const NoFutureOccurrences = RecurringEvent.extend({
+ args: {
+ defaultOccurrenceDate: null,
+ },
+});
+
+export const OccurrenceCanceled = RecurringEvent.extend({
+ beforeEach: () => {
+ spyOn(window, "confirm").mockReturnValue(true);
+ mocked(cancelEvent).mockResolvedValue({
+ message: "Occurrence canceled. The rest of the series is unchanged.",
+ status: "success",
+ });
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.click(
+ canvas.getByRole("button", { name: "Cancel this date" }),
+ );
+ await expect(await canvas.findByRole("status")).toHaveTextContent(
+ "Occurrence canceled",
+ );
+ },
+});
+
+export const CancellationRejected = RecurringEvent.extend({
+ beforeEach: () => {
+ spyOn(window, "confirm").mockReturnValue(true);
+ mocked(cancelEvent).mockResolvedValue({
+ message: "That event occurrence is already canceled.",
+ status: "error",
+ });
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.click(
+ canvas.getByRole("button", { name: "Cancel this date" }),
+ );
+ await expect(await canvas.findByRole("alert")).toHaveTextContent(
+ "already canceled",
+ );
+ },
+});
+
+export const CancelingSeries = RecurringEvent.extend({
+ beforeEach: () => {
+ spyOn(window, "confirm").mockReturnValue(true);
+ mocked(cancelEvent).mockImplementation(() => new Promise(() => {}));
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.click(
+ canvas.getByRole("button", { name: "Cancel the whole series" }),
+ );
+ await expect(
+ canvas.getByRole("button", { name: "Canceling…" }),
+ ).toBeDisabled();
+ },
+});
diff --git a/stories/app/account/page.stories.tsx b/stories/app/account/page.stories.tsx
new file mode 100644
index 0000000..64fdded
--- /dev/null
+++ b/stories/app/account/page.stories.tsx
@@ -0,0 +1,57 @@
+import preview from "@/.storybook/preview";
+import AccountPage from "@/app/account/page";
+import { getSubmissionsForUser } from "@/lib/events/queries";
+import { requireSession } from "@/lib/session";
+import { createSession } from "@/stories/fixtures/auth";
+import { mixedSubmissions } from "@/stories/fixtures/submissions";
+import { mocked } from "storybook/test";
+
+const meta = preview.meta({
+ component: AccountPage,
+ title: "Pages/Account",
+ parameters: {
+ layout: "fullscreen",
+ },
+});
+
+export const NewSubmitter = meta.story({
+ beforeEach: () => {
+ mocked(requireSession).mockResolvedValue(createSession());
+ mocked(getSubmissionsForUser).mockResolvedValue([]);
+ },
+});
+
+export const AdminWithManagedEvents = NewSubmitter.extend({
+ beforeEach: () => {
+ mocked(requireSession).mockResolvedValue(
+ createSession({
+ name: "Morgan Lee",
+ role: "admin",
+ }),
+ );
+ mocked(getSubmissionsForUser).mockResolvedValue(mixedSubmissions);
+ },
+});
+
+export const Approver = NewSubmitter.extend({
+ beforeEach: () => {
+ mocked(requireSession).mockResolvedValue(
+ createSession({
+ name: "Taylor Brooks",
+ role: "approver",
+ }),
+ );
+ mocked(getSubmissionsForUser).mockResolvedValue(
+ mixedSubmissions.slice(0, 2),
+ );
+ },
+});
+
+export const Loading = NewSubmitter.extend({
+ beforeEach: () => {
+ mocked(requireSession).mockImplementation(() => new Promise(() => {}));
+ mocked(getSubmissionsForUser).mockImplementation(
+ () => new Promise(() => {}),
+ );
+ },
+});
diff --git a/stories/app/account/sign-out-button.stories.tsx b/stories/app/account/sign-out-button.stories.tsx
new file mode 100644
index 0000000..7d431cf
--- /dev/null
+++ b/stories/app/account/sign-out-button.stories.tsx
@@ -0,0 +1,64 @@
+import preview from "@/.storybook/preview";
+import { SignOutButton } from "@/app/account/sign-out-button";
+import { authClient } from "@/lib/auth-client";
+import { expect, mocked } from "storybook/test";
+
+const meta = preview.meta({
+ component: SignOutButton,
+ parameters: {
+ layout: "centered",
+ },
+});
+
+export const Idle = meta.story({
+ beforeEach: () => {
+ mocked(authClient.signOut).mockResolvedValue({
+ data: null,
+ error: null,
+ });
+ },
+});
+
+export const ServiceError = Idle.extend({
+ beforeEach: () => {
+ mocked(authClient.signOut).mockResolvedValue({
+ data: null,
+ error: {
+ code: "SESSION_REVOKE_FAILED",
+ message: "The session could not be revoked.",
+ status: 500,
+ statusText: "Internal Server Error",
+ },
+ });
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.click(canvas.getByRole("button", { name: "Sign out" }));
+ await expect(await canvas.findByRole("status")).toHaveTextContent(
+ "session could not be revoked",
+ );
+ },
+});
+
+export const NetworkError = Idle.extend({
+ beforeEach: () => {
+ mocked(authClient.signOut).mockRejectedValue(new Error("offline"));
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.click(canvas.getByRole("button", { name: "Sign out" }));
+ await expect(await canvas.findByRole("status")).toHaveTextContent(
+ "couldn't connect",
+ );
+ },
+});
+
+export const SigningOut = Idle.extend({
+ beforeEach: () => {
+ mocked(authClient.signOut).mockImplementation(() => new Promise(() => {}));
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.click(canvas.getByRole("button", { name: "Sign out" }));
+ await expect(
+ canvas.getByRole("button", { name: "Signing out…" }),
+ ).toBeDisabled();
+ },
+});
diff --git a/stories/app/admin/events/moderation-form.stories.tsx b/stories/app/admin/events/moderation-form.stories.tsx
new file mode 100644
index 0000000..f039f9f
--- /dev/null
+++ b/stories/app/admin/events/moderation-form.stories.tsx
@@ -0,0 +1,133 @@
+import preview from "@/.storybook/preview";
+import { ModerationForm } from "@/app/admin/events/moderation-form";
+import { moderateEvent, moderateEventEdit } from "@/lib/events/actions";
+import { expect, mocked } from "storybook/test";
+
+const meta = preview.meta({
+ title: "Admin/Events/Moderation Form",
+ component: ModerationForm,
+ parameters: {
+ layout: "centered",
+ },
+ args: {
+ eventId: "9ae8c027-41d6-4890-a431-1d8208b22e40",
+ eventTitle: "Sacramento Community Demo Night",
+ reviewType: "event",
+ },
+ decorators: [
+ (Story) => (
+
+
+
+ ),
+ ],
+});
+
+function mockIdleActions() {
+ mocked(moderateEvent).mockResolvedValue({ message: "", status: "idle" });
+ mocked(moderateEventEdit).mockResolvedValue({ message: "", status: "idle" });
+}
+
+export const IdleEvent = meta.story({
+ args: {},
+ beforeEach: mockIdleActions,
+ play: async ({ canvas }) => {
+ await expect(
+ canvas.getByRole("button", { name: "Approve and publish" }),
+ ).toBeEnabled();
+ await expect(
+ canvas.getByRole("button", { name: "Reject with note" }),
+ ).toBeEnabled();
+ },
+});
+
+export const IdleChangeRequest = meta.story({
+ args: {
+ eventId: "08d3130a-2097-42a1-9319-a53cd149c625",
+ eventTitle: "Civic Tech Project Clinic",
+ reviewType: "edit",
+ },
+ beforeEach: mockIdleActions,
+ play: async ({ canvas }) => {
+ await expect(
+ canvas.getByText(
+ "Approving replaces the live details with this proposed change.",
+ ),
+ ).toBeVisible();
+ await expect(
+ canvas.getByRole("button", { name: "Approve changes" }),
+ ).toBeEnabled();
+ },
+});
+
+export const PendingDecision = meta.story({
+ args: {},
+ beforeEach: () => {
+ mockIdleActions();
+ mocked(moderateEvent).mockImplementation(() => new Promise(() => {}));
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.click(
+ canvas.getByRole("button", { name: "Approve and publish" }),
+ );
+
+ for (const button of canvas.getAllByRole("button", { name: "Saving…" })) {
+ await expect(button).toBeDisabled();
+ }
+ await expect(
+ canvas.getByLabelText("Note to submitter (optional)"),
+ ).toBeDisabled();
+ },
+});
+
+export const RejectionError = meta.story({
+ args: {},
+ beforeEach: () => {
+ mockIdleActions();
+ mocked(moderateEvent).mockResolvedValue({
+ message:
+ "Explain what the submitter needs to change before resubmitting.",
+ status: "error",
+ });
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.type(
+ canvas.getByLabelText("Note to submitter (optional)"),
+ "Needs work",
+ );
+ await userEvent.click(
+ canvas.getByRole("button", { name: "Reject with note" }),
+ );
+
+ await expect(await canvas.findByRole("alert")).toHaveTextContent(
+ "Explain what the submitter needs to change",
+ );
+ },
+});
+
+export const Approved = meta.story({
+ args: {},
+ beforeEach: () => {
+ mockIdleActions();
+ mocked(moderateEvent).mockResolvedValue({
+ message: "Event approved and published.",
+ status: "success",
+ });
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.type(
+ canvas.getByLabelText("Note to submitter (optional)"),
+ "Ready for the calendar.",
+ );
+ await userEvent.click(
+ canvas.getByRole("button", { name: "Approve and publish" }),
+ );
+
+ await expect(await canvas.findByRole("status")).toHaveTextContent(
+ "Event approved and published.",
+ );
+ await expect(
+ canvas.getByLabelText("Note to submitter (optional)"),
+ ).toHaveValue("");
+ },
+});
diff --git a/stories/app/admin/events/page.stories.tsx b/stories/app/admin/events/page.stories.tsx
new file mode 100644
index 0000000..3ca1228
--- /dev/null
+++ b/stories/app/admin/events/page.stories.tsx
@@ -0,0 +1,87 @@
+import preview from "@/.storybook/preview";
+import AdminEventsPage from "@/app/admin/events/page";
+import { getPendingEventEdits, getPendingEvents } from "@/lib/events/queries";
+import { requireEventReviewerSession } from "@/lib/session";
+import { createSession } from "@/stories/fixtures/auth";
+import {
+ PENDING_ADMIN_EVENT_EDITS,
+ PENDING_ADMIN_EVENTS,
+} from "@/stories/fixtures/admin";
+import { expect, mocked } from "storybook/test";
+
+const meta = preview.meta({
+ title: "Pages/Admin/Review Events",
+ component: AdminEventsPage,
+ parameters: {
+ layout: "fullscreen",
+ },
+});
+
+function mockReviewerSession() {
+ mocked(requireEventReviewerSession).mockResolvedValue(
+ createSession({
+ email: "reviewer@example.com",
+ id: "storybook-reviewer",
+ name: "Storybook Reviewer",
+ role: "approver",
+ }),
+ );
+}
+
+export const LoadingQueues = meta.story({
+ beforeEach: () => {
+ mocked(requireEventReviewerSession).mockImplementation(
+ () => new Promise(() => {}),
+ );
+ },
+ play: async ({ canvas }) => {
+ await expect(
+ await canvas.findByRole("heading", {
+ name: "Loading submitted events…",
+ }),
+ ).toBeVisible();
+ await expect(
+ canvas.getByRole("heading", { name: "Loading proposed changes…" }),
+ ).toBeVisible();
+ },
+});
+
+export const EmptyQueues = meta.story({
+ beforeEach: () => {
+ mockReviewerSession();
+ mocked(getPendingEvents).mockResolvedValue([]);
+ mocked(getPendingEventEdits).mockResolvedValue([]);
+ },
+ play: async ({ canvas }) => {
+ await expect(
+ await canvas.findByRole("heading", {
+ name: "Nothing to review right now.",
+ }),
+ ).toBeVisible();
+ await expect(
+ canvas.getByRole("heading", {
+ name: "No event changes are waiting.",
+ }),
+ ).toBeVisible();
+ },
+});
+
+export const PopulatedQueues = meta.story({
+ beforeEach: () => {
+ mockReviewerSession();
+ mocked(getPendingEvents).mockResolvedValue(PENDING_ADMIN_EVENTS);
+ mocked(getPendingEventEdits).mockResolvedValue(PENDING_ADMIN_EVENT_EDITS);
+ },
+ play: async ({ canvas }) => {
+ await expect(
+ await canvas.findByRole("heading", {
+ name: "Sacramento Community Demo Night",
+ }),
+ ).toBeVisible();
+ await expect(
+ canvas.getByRole("heading", { name: "Civic Tech Project Clinic" }),
+ ).toBeVisible();
+ await expect(canvas.getByText("2 events waiting")).toBeVisible();
+ await expect(canvas.getByText("1 change waiting")).toBeVisible();
+ },
+});
diff --git a/stories/app/admin/users/admin-users-content.stories.tsx b/stories/app/admin/users/admin-users-content.stories.tsx
new file mode 100644
index 0000000..c4f2bb8
--- /dev/null
+++ b/stories/app/admin/users/admin-users-content.stories.tsx
@@ -0,0 +1,65 @@
+import preview from "@/.storybook/preview";
+import { AdminUsersContent } from "@/app/admin/users/admin-users-content";
+import { auth } from "@/lib/auth";
+import { requireAdminSession } from "@/lib/session";
+import {
+ CURRENT_ADMIN_LISTED_USER,
+ OTHER_LISTED_USERS,
+} from "@/stories/fixtures/admin";
+import { createSession } from "@/stories/fixtures/auth";
+import { expect, mocked } from "storybook/test";
+
+const meta = preview.meta({
+ title: "Admin/Users/User List",
+ component: AdminUsersContent,
+ parameters: {
+ layout: "padded",
+ },
+});
+
+function mockAdminSession() {
+ mocked(requireAdminSession).mockResolvedValue(
+ createSession({
+ email: CURRENT_ADMIN_LISTED_USER.email,
+ id: CURRENT_ADMIN_LISTED_USER.id,
+ name: CURRENT_ADMIN_LISTED_USER.name,
+ role: "admin",
+ }),
+ );
+}
+
+export const EmptyList = meta.story({
+ beforeEach: () => {
+ mockAdminSession();
+ mocked(auth.api.listUsers).mockResolvedValue({
+ total: 1,
+ users: [CURRENT_ADMIN_LISTED_USER],
+ });
+ },
+ play: async ({ canvas }) => {
+ await expect(
+ await canvas.findByRole("heading", { name: "No other users yet." }),
+ ).toBeVisible();
+ },
+});
+
+export const PopulatedList = meta.story({
+ beforeEach: () => {
+ mockAdminSession();
+ mocked(auth.api.listUsers).mockResolvedValue({
+ total: OTHER_LISTED_USERS.length + 1,
+ users: [CURRENT_ADMIN_LISTED_USER, ...OTHER_LISTED_USERS],
+ });
+ },
+ play: async ({ canvas }) => {
+ await expect(
+ await canvas.findByRole("heading", { name: "Alex Rivera" }),
+ ).toBeVisible();
+ await expect(
+ canvas.getByRole("heading", { name: "Devon Brooks" }),
+ ).toBeVisible();
+ await expect(
+ canvas.getByText("Banned", { selector: "span" }),
+ ).toBeVisible();
+ },
+});
diff --git a/stories/app/admin/users/page.stories.tsx b/stories/app/admin/users/page.stories.tsx
new file mode 100644
index 0000000..7227b51
--- /dev/null
+++ b/stories/app/admin/users/page.stories.tsx
@@ -0,0 +1,84 @@
+import preview from "@/.storybook/preview";
+import AdminUsersPage from "@/app/admin/users/page";
+import { auth } from "@/lib/auth";
+import { requireAdminSession } from "@/lib/session";
+import {
+ CURRENT_ADMIN_LISTED_USER,
+ OTHER_LISTED_USERS,
+} from "@/stories/fixtures/admin";
+import { createSession } from "@/stories/fixtures/auth";
+import { expect, mocked } from "storybook/test";
+
+const meta = preview.meta({
+ title: "Pages/Admin/Manage Users",
+ component: AdminUsersPage,
+ parameters: {
+ layout: "fullscreen",
+ },
+});
+
+function mockAdminSession() {
+ mocked(requireAdminSession).mockResolvedValue(
+ createSession({
+ email: CURRENT_ADMIN_LISTED_USER.email,
+ id: CURRENT_ADMIN_LISTED_USER.id,
+ name: CURRENT_ADMIN_LISTED_USER.name,
+ role: "admin",
+ }),
+ );
+}
+
+export const LoadingUserList = meta.story({
+ beforeEach: () => {
+ mocked(requireAdminSession).mockImplementation(() => new Promise(() => {}));
+ },
+ play: async ({ canvas }) => {
+ await expect(
+ await canvas.findByRole("heading", {
+ name: "Loading community accounts…",
+ }),
+ ).toBeVisible();
+ },
+});
+
+export const EmptyUserList = meta.story({
+ beforeEach: () => {
+ mockAdminSession();
+ mocked(auth.api.listUsers).mockResolvedValue({
+ total: 1,
+ users: [CURRENT_ADMIN_LISTED_USER],
+ });
+ },
+ play: async ({ canvas }) => {
+ await expect(
+ await canvas.findByRole("heading", { name: "No other users yet." }),
+ ).toBeVisible();
+ await expect(
+ canvas.queryByRole("heading", { name: "Current Admin" }),
+ ).not.toBeInTheDocument();
+ },
+});
+
+export const PopulatedUserList = meta.story({
+ beforeEach: () => {
+ mockAdminSession();
+ mocked(auth.api.listUsers).mockResolvedValue({
+ total: OTHER_LISTED_USERS.length + 1,
+ users: [CURRENT_ADMIN_LISTED_USER, ...OTHER_LISTED_USERS],
+ });
+ },
+ play: async ({ canvas }) => {
+ await expect(
+ await canvas.findByRole("heading", { name: "Alex Rivera" }),
+ ).toBeVisible();
+ await expect(
+ canvas.getByRole("heading", { name: "Samira Patel" }),
+ ).toBeVisible();
+ await expect(
+ canvas.getByRole("heading", { name: "Taylor Morgan" }),
+ ).toBeVisible();
+ await expect(
+ canvas.queryByRole("heading", { name: "Current Admin" }),
+ ).not.toBeInTheDocument();
+ },
+});
diff --git a/stories/app/admin/users/user-management-card.stories.tsx b/stories/app/admin/users/user-management-card.stories.tsx
new file mode 100644
index 0000000..fc18a47
--- /dev/null
+++ b/stories/app/admin/users/user-management-card.stories.tsx
@@ -0,0 +1,189 @@
+import preview from "@/.storybook/preview";
+import { updateUserBan, updateUserRoles } from "@/app/admin/users/actions";
+import { UserManagementCard } from "@/app/admin/users/user-management-card";
+import { STORY_MANAGED_USERS } from "@/stories/fixtures/admin";
+import { expect, mocked } from "storybook/test";
+
+const meta = preview.meta({
+ title: "Admin/Users/User Management Card",
+ component: UserManagementCard,
+ parameters: {
+ layout: "centered",
+ },
+ decorators: [
+ (Story) => (
+
+
+
+ ),
+ ],
+});
+
+function mockIdleActions() {
+ mocked(updateUserRoles).mockResolvedValue({ message: "", status: "idle" });
+ mocked(updateUserBan).mockResolvedValue({ message: "", status: "idle" });
+}
+
+export const SubmitterActive = meta.story({
+ args: {
+ user: STORY_MANAGED_USERS.submitter,
+ },
+ beforeEach: mockIdleActions,
+});
+
+export const ApproverActive = meta.story({
+ args: {
+ user: STORY_MANAGED_USERS.approver,
+ },
+ beforeEach: mockIdleActions,
+});
+
+export const AdministratorActive = meta.story({
+ args: {
+ user: STORY_MANAGED_USERS.administrator,
+ },
+ beforeEach: mockIdleActions,
+});
+
+export const BannedSubmitter = meta.story({
+ args: {
+ user: STORY_MANAGED_USERS.bannedSubmitter,
+ },
+ beforeEach: mockIdleActions,
+ play: async ({ canvas }) => {
+ await expect(
+ canvas.getByText("Banned", { selector: "span" }),
+ ).toBeVisible();
+ await expect(
+ canvas.getByRole("button", { name: "Unban account" }),
+ ).toBeEnabled();
+ },
+});
+
+export const SavingRoles = meta.story({
+ args: {
+ user: STORY_MANAGED_USERS.submitter,
+ },
+ beforeEach: () => {
+ mockIdleActions();
+ mocked(updateUserRoles).mockImplementation(() => new Promise(() => {}));
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.click(canvas.getByRole("button", { name: "Save roles" }));
+
+ await expect(
+ canvas.getByRole("button", { name: "Saving…" }),
+ ).toBeDisabled();
+ await expect(
+ canvas.getByRole("button", { name: "Ban account" }),
+ ).toBeDisabled();
+ },
+});
+
+export const RoleUpdateError = meta.story({
+ args: {
+ user: STORY_MANAGED_USERS.submitter,
+ },
+ beforeEach: () => {
+ mockIdleActions();
+ mocked(updateUserRoles).mockResolvedValue({
+ message: "Choose at least one valid role.",
+ status: "error",
+ });
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.click(canvas.getByRole("checkbox", { name: /Submitter/ }));
+ await userEvent.click(canvas.getByRole("button", { name: "Save roles" }));
+
+ await expect(await canvas.findByRole("alert")).toHaveTextContent(
+ "Choose at least one valid role.",
+ );
+ },
+});
+
+export const RolesUpdated = meta.story({
+ args: {
+ user: STORY_MANAGED_USERS.submitter,
+ },
+ beforeEach: () => {
+ mockIdleActions();
+ mocked(updateUserRoles).mockResolvedValue({
+ message: "Roles updated.",
+ status: "success",
+ });
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.click(canvas.getByRole("checkbox", { name: /Approver/ }));
+ await userEvent.click(canvas.getByRole("button", { name: "Save roles" }));
+
+ await expect(await canvas.findByRole("status")).toHaveTextContent(
+ "Roles updated.",
+ );
+ },
+});
+
+export const UnbanningAccount = meta.story({
+ args: {
+ user: STORY_MANAGED_USERS.bannedSubmitter,
+ },
+ beforeEach: () => {
+ mockIdleActions();
+ mocked(updateUserBan).mockImplementation(() => new Promise(() => {}));
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.click(
+ canvas.getByRole("button", { name: "Unban account" }),
+ );
+
+ await expect(
+ canvas.getByRole("button", { name: "Unbanning…" }),
+ ).toBeDisabled();
+ await expect(
+ canvas.getByRole("button", { name: "Save roles" }),
+ ).toBeDisabled();
+ },
+});
+
+export const UnbanError = meta.story({
+ args: {
+ user: STORY_MANAGED_USERS.bannedSubmitter,
+ },
+ beforeEach: () => {
+ mockIdleActions();
+ mocked(updateUserBan).mockResolvedValue({
+ message: "The account could not be unbanned. Try again.",
+ status: "error",
+ });
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.click(
+ canvas.getByRole("button", { name: "Unban account" }),
+ );
+
+ await expect(await canvas.findByRole("alert")).toHaveTextContent(
+ "The account could not be unbanned.",
+ );
+ },
+});
+
+export const AccountUnbanned = meta.story({
+ args: {
+ user: STORY_MANAGED_USERS.bannedSubmitter,
+ },
+ beforeEach: () => {
+ mockIdleActions();
+ mocked(updateUserBan).mockResolvedValue({
+ message: "Account unbanned.",
+ status: "success",
+ });
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.click(
+ canvas.getByRole("button", { name: "Unban account" }),
+ );
+
+ await expect(await canvas.findByRole("status")).toHaveTextContent(
+ "Account unbanned.",
+ );
+ },
+});
diff --git a/stories/app/auth/auth-form.stories.tsx b/stories/app/auth/auth-form.stories.tsx
new file mode 100644
index 0000000..ef6a103
--- /dev/null
+++ b/stories/app/auth/auth-form.stories.tsx
@@ -0,0 +1,210 @@
+import preview from "@/.storybook/preview";
+import { AuthForm } from "@/app/auth/auth-form";
+import { authClient } from "@/lib/auth-client";
+import { expect, fireEvent, mocked } from "storybook/test";
+
+const EMAIL = "person@example.com";
+const PASSWORD = "correct horse battery staple";
+
+const meta = preview.meta({
+ title: "Auth/Forms/Auth Form",
+ component: AuthForm,
+ parameters: {
+ layout: "centered",
+ },
+ args: {
+ emailDeliveryEnabled: true,
+ },
+ decorators: [
+ (Story) => (
+
+
+
+ ),
+ ],
+});
+
+export const SignIn = meta.story({
+ play: async ({ canvas }) => {
+ await expect(
+ canvas.getByRole("heading", { name: "Welcome back" }),
+ ).toBeVisible();
+ await expect(
+ canvas.getByRole("button", { name: "Sign in", pressed: true }),
+ ).toBeVisible();
+ },
+});
+
+export const SignUp = SignIn.extend({
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.click(
+ canvas.getByRole("button", { name: "Create account" }),
+ );
+
+ await expect(
+ canvas.getByRole("heading", { name: "Create an account" }),
+ ).toBeVisible();
+ await expect(canvas.getByRole("textbox", { name: "Name" })).toBeVisible();
+ },
+});
+
+export const ForgotPassword = SignIn.extend({
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.click(
+ canvas.getByRole("button", { name: "Forgot your password?" }),
+ );
+
+ await expect(
+ canvas.getByRole("heading", { name: "Reset your password" }),
+ ).toBeVisible();
+ await expect(canvas.queryByLabelText("Password")).not.toBeInTheDocument();
+ },
+});
+
+export const EmailDeliveryDisabled = SignIn.extend({
+ args: {
+ emailDeliveryEnabled: false,
+ },
+ play: async ({ canvas }) => {
+ await expect(
+ canvas.queryByRole("button", { name: "Forgot your password?" }),
+ ).not.toBeInTheDocument();
+ },
+});
+
+export const ValidationError = SignIn.extend({
+ play: async ({ canvas, canvasElement, userEvent }) => {
+ await userEvent.type(
+ canvas.getByRole("textbox", { name: "Email address" }),
+ EMAIL,
+ );
+ await userEvent.type(canvas.getByLabelText("Password"), "too short");
+
+ fireEvent.submit(canvasElement.querySelector("form")!);
+
+ await expect(await canvas.findByRole("alert")).toHaveTextContent(
+ "Your password must be at least 10 characters.",
+ );
+ await expect(canvas.getByLabelText("Password")).toHaveAttribute(
+ "aria-invalid",
+ "true",
+ );
+ },
+});
+
+export const SigningIn = SignIn.extend({
+ beforeEach: () => {
+ mocked(authClient.signIn.email).mockImplementation(
+ () => new Promise(() => {}),
+ );
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.type(
+ canvas.getByRole("textbox", { name: "Email address" }),
+ EMAIL,
+ );
+ await userEvent.type(canvas.getByLabelText("Password"), PASSWORD);
+ await userEvent.click(
+ canvas.getAllByRole("button", { name: "Sign in" }).at(-1)!,
+ );
+
+ await expect(
+ canvas.getByRole("button", { name: "Signing in…" }),
+ ).toBeDisabled();
+ },
+});
+
+export const SignInServiceError = SignIn.extend({
+ beforeEach: () => {
+ mocked(authClient.signIn.email).mockResolvedValue({
+ data: null,
+ error: {
+ code: "INVALID_EMAIL_OR_PASSWORD",
+ message: "Invalid email or password",
+ status: 401,
+ statusText: "Unauthorized",
+ },
+ });
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.type(
+ canvas.getByRole("textbox", { name: "Email address" }),
+ EMAIL,
+ );
+ await userEvent.type(canvas.getByLabelText("Password"), PASSWORD);
+ await userEvent.click(
+ canvas.getAllByRole("button", { name: "Sign in" }).at(-1)!,
+ );
+
+ await expect(await canvas.findByRole("alert")).toHaveTextContent(
+ "That email and password don't match.",
+ );
+ await expect(
+ canvas.getByRole("textbox", { name: "Email address" }),
+ ).toHaveValue(EMAIL);
+ },
+});
+
+export const SignUpEmailSent = SignIn.extend({
+ beforeEach: () => {
+ mocked(authClient.signUp.email).mockResolvedValue({
+ data: null,
+ error: null,
+ });
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.click(
+ canvas.getByRole("button", { name: "Create account" }),
+ );
+ await userEvent.type(
+ canvas.getByRole("textbox", { name: "Name" }),
+ "Pat Lee",
+ );
+ await userEvent.type(
+ canvas.getByRole("textbox", { name: "Email address" }),
+ EMAIL,
+ );
+ await userEvent.type(canvas.getByLabelText("Password"), PASSWORD);
+ await userEvent.click(
+ canvas.getAllByRole("button", { name: "Create account" }).at(-1)!,
+ );
+
+ await expect(
+ await canvas.findByRole("heading", { name: "Check your email" }),
+ ).toBeVisible();
+ await expect(canvas.getByRole("status")).toHaveTextContent(
+ "we'll send a verification link shortly",
+ );
+ },
+});
+
+export const PasswordResetEmailSent = SignIn.extend({
+ beforeEach: () => {
+ mocked(authClient.requestPasswordReset).mockResolvedValue({
+ data: null,
+ error: null,
+ });
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.click(
+ canvas.getByRole("button", { name: "Forgot your password?" }),
+ );
+ await userEvent.type(
+ canvas.getByRole("textbox", { name: "Email address" }),
+ EMAIL,
+ );
+ await userEvent.click(
+ canvas.getByRole("button", { name: "Send reset link" }),
+ );
+
+ await expect(await canvas.findByRole("status")).toHaveTextContent(
+ "If an account exists for that address",
+ );
+ },
+});
diff --git a/stories/app/auth/page.stories.tsx b/stories/app/auth/page.stories.tsx
new file mode 100644
index 0000000..4bec5fa
--- /dev/null
+++ b/stories/app/auth/page.stories.tsx
@@ -0,0 +1,55 @@
+import preview from "@/.storybook/preview";
+import AuthPage from "@/app/auth/page";
+import { isEmailDeliveryEnabled } from "@/lib/email-delivery";
+import { getCurrentSession } from "@/lib/session";
+import { expect, mocked } from "storybook/test";
+
+const meta = preview.meta({
+ title: "Pages/Auth/Sign In",
+ component: AuthPage,
+ parameters: {
+ layout: "fullscreen",
+ },
+});
+
+export const SignedOut = meta.story({
+ beforeEach: () => {
+ mocked(getCurrentSession).mockResolvedValue(null);
+ mocked(isEmailDeliveryEnabled).mockReturnValue(true);
+ },
+ play: async ({ canvas }) => {
+ await expect(
+ await canvas.findByRole("heading", { name: "Share a local tech event." }),
+ ).toBeVisible();
+ await expect(
+ canvas.getByRole("heading", { name: "Welcome back" }),
+ ).toBeVisible();
+ },
+});
+
+export const EmailDeliveryDisabled = SignedOut.extend({
+ beforeEach: () => {
+ mocked(getCurrentSession).mockResolvedValue(null);
+ mocked(isEmailDeliveryEnabled).mockReturnValue(false);
+ },
+ play: async ({ canvas }) => {
+ await expect(
+ await canvas.findByRole("heading", { name: "Welcome back" }),
+ ).toBeVisible();
+ await expect(
+ canvas.queryByRole("button", { name: "Forgot your password?" }),
+ ).not.toBeInTheDocument();
+ },
+});
+
+export const Loading = SignedOut.extend({
+ beforeEach: () => {
+ mocked(getCurrentSession).mockImplementation(() => new Promise(() => {}));
+ mocked(isEmailDeliveryEnabled).mockReturnValue(true);
+ },
+ play: async ({ canvas }) => {
+ await expect(
+ await canvas.findByRole("heading", { name: "Checking your account" }),
+ ).toBeVisible();
+ },
+});
diff --git a/stories/app/auth/reset-password/page.stories.tsx b/stories/app/auth/reset-password/page.stories.tsx
new file mode 100644
index 0000000..0ef4889
--- /dev/null
+++ b/stories/app/auth/reset-password/page.stories.tsx
@@ -0,0 +1,60 @@
+import preview from "@/.storybook/preview";
+import ResetPasswordPage from "@/app/auth/reset-password/page";
+import { expect } from "storybook/test";
+
+const meta = preview.meta({
+ title: "Pages/Auth/Reset Password",
+ component: ResetPasswordPage,
+ parameters: {
+ controls: { disable: true },
+ layout: "fullscreen",
+ },
+ args: {
+ searchParams: Promise.resolve({ token: "storybook-reset-token" }),
+ },
+});
+
+export const ValidLink = meta.story({
+ play: async ({ canvas }) => {
+ await expect(
+ await canvas.findByRole("heading", { name: "Choose a new password." }),
+ ).toBeVisible();
+ await expect(
+ canvas.getByRole("heading", { name: "Reset your password" }),
+ ).toBeVisible();
+ },
+});
+
+export const MissingToken = ValidLink.extend({
+ args: {
+ searchParams: Promise.resolve({}),
+ },
+ play: async ({ canvas }) => {
+ await expect(await canvas.findByText(/missing its token/i)).toBeVisible();
+ },
+});
+
+export const InvalidLink = ValidLink.extend({
+ args: {
+ searchParams: Promise.resolve({
+ error: "INVALID_TOKEN",
+ token: "storybook-reset-token",
+ }),
+ },
+ play: async ({ canvas }) => {
+ await expect(
+ await canvas.findByText(/invalid or has expired/i),
+ ).toBeVisible();
+ },
+});
+
+export const Loading = ValidLink.extend({
+ args: {
+ searchParams: new Promise(() => {}),
+ },
+ play: async ({ canvas }) => {
+ await expect(
+ await canvas.findByRole("heading", { name: "Checking your reset link" }),
+ ).toBeVisible();
+ },
+});
diff --git a/stories/app/auth/reset-password/reset-password-form.stories.tsx b/stories/app/auth/reset-password/reset-password-form.stories.tsx
new file mode 100644
index 0000000..1cecc5e
--- /dev/null
+++ b/stories/app/auth/reset-password/reset-password-form.stories.tsx
@@ -0,0 +1,208 @@
+import preview from "@/.storybook/preview";
+import { ResetPasswordForm } from "@/app/auth/reset-password/reset-password-form";
+import { authClient } from "@/lib/auth-client";
+import { expect, mocked } from "storybook/test";
+
+const TOKEN = "storybook-reset-token";
+const PASSWORD = "correct horse battery staple";
+
+const meta = preview.meta({
+ title: "Auth/Forms/Reset Password Form",
+ component: ResetPasswordForm,
+ parameters: {
+ layout: "centered",
+ },
+ args: {
+ error: null,
+ token: TOKEN,
+ },
+ decorators: [
+ (Story) => (
+
+
+
+ ),
+ ],
+});
+
+export const ValidToken = meta.story({
+ play: async ({ canvas }) => {
+ await expect(
+ canvas.getByRole("heading", { name: "Reset your password" }),
+ ).toBeVisible();
+ await expect(canvas.getByLabelText("New password")).toBeEnabled();
+ },
+});
+
+export const MissingToken = ValidToken.extend({
+ args: {
+ token: null,
+ },
+ play: async ({ canvas }) => {
+ await expect(canvas.getByText(/missing its token/i)).toBeVisible();
+ await expect(
+ canvas.queryByLabelText("New password"),
+ ).not.toBeInTheDocument();
+ },
+});
+
+export const InvalidToken = ValidToken.extend({
+ args: {
+ error: "INVALID_TOKEN",
+ },
+ play: async ({ canvas }) => {
+ await expect(canvas.getByText(/invalid or has expired/i)).toBeVisible();
+ await expect(
+ canvas.queryByLabelText("New password"),
+ ).not.toBeInTheDocument();
+ },
+});
+
+export const PasswordTooShort = ValidToken.extend({
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.type(canvas.getByLabelText("New password"), "too short");
+ await userEvent.type(
+ canvas.getByLabelText("Confirm new password"),
+ "too short",
+ );
+ await userEvent.click(
+ canvas.getByRole("button", { name: "Reset password" }),
+ );
+
+ await expect(await canvas.findByRole("alert")).toHaveTextContent(
+ "Your password must be at least 10 characters.",
+ );
+ },
+});
+
+export const PasswordsDoNotMatch = ValidToken.extend({
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.type(canvas.getByLabelText("New password"), PASSWORD);
+ await userEvent.type(
+ canvas.getByLabelText("Confirm new password"),
+ "a different secure password",
+ );
+ await userEvent.click(
+ canvas.getByRole("button", { name: "Reset password" }),
+ );
+
+ await expect(await canvas.findByRole("alert")).toHaveTextContent(
+ "The passwords don't match.",
+ );
+ },
+});
+
+export const ResettingPassword = ValidToken.extend({
+ beforeEach: () => {
+ mocked(authClient.resetPassword).mockImplementation(
+ () => new Promise(() => {}),
+ );
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.type(canvas.getByLabelText("New password"), PASSWORD);
+ await userEvent.type(
+ canvas.getByLabelText("Confirm new password"),
+ PASSWORD,
+ );
+ await userEvent.click(
+ canvas.getByRole("button", { name: "Reset password" }),
+ );
+
+ await expect(
+ canvas.getByRole("button", { name: "Resetting password…" }),
+ ).toBeDisabled();
+ },
+});
+
+export const PasswordReset = ValidToken.extend({
+ beforeEach: () => {
+ mocked(authClient.resetPassword).mockResolvedValue({
+ data: null,
+ error: null,
+ });
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.type(canvas.getByLabelText("New password"), PASSWORD);
+ await userEvent.type(
+ canvas.getByLabelText("Confirm new password"),
+ PASSWORD,
+ );
+ await userEvent.click(
+ canvas.getByRole("button", { name: "Reset password" }),
+ );
+
+ await expect(
+ await canvas.findByRole("heading", {
+ name: "Your password has been reset",
+ }),
+ ).toBeVisible();
+ await expect(
+ canvas.getByRole("link", { name: /Back to sign in/ }),
+ ).toHaveAttribute("href", "/auth");
+ },
+});
+
+export const ServiceError = ValidToken.extend({
+ beforeEach: () => {
+ mocked(authClient.resetPassword).mockResolvedValue({
+ data: null,
+ error: {
+ code: "SERVICE_UNAVAILABLE",
+ message: "We couldn't reset your password. Try again.",
+ status: 503,
+ statusText: "Service Unavailable",
+ },
+ });
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.type(canvas.getByLabelText("New password"), PASSWORD);
+ await userEvent.type(
+ canvas.getByLabelText("Confirm new password"),
+ PASSWORD,
+ );
+ await userEvent.click(
+ canvas.getByRole("button", { name: "Reset password" }),
+ );
+
+ await expect(await canvas.findByRole("alert")).toHaveTextContent(
+ "We couldn't reset your password. Try again.",
+ );
+ await expect(canvas.getByLabelText("New password")).toHaveValue(PASSWORD);
+ },
+});
+
+export const ServiceRejectsToken = ValidToken.extend({
+ beforeEach: () => {
+ mocked(authClient.resetPassword).mockResolvedValue({
+ data: null,
+ error: {
+ code: "TOKEN_EXPIRED",
+ message: "The reset token expired.",
+ status: 400,
+ statusText: "Bad Request",
+ },
+ });
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.type(canvas.getByLabelText("New password"), PASSWORD);
+ await userEvent.type(
+ canvas.getByLabelText("Confirm new password"),
+ PASSWORD,
+ );
+ await userEvent.click(
+ canvas.getByRole("button", { name: "Reset password" }),
+ );
+
+ await expect(
+ await canvas.findByRole("heading", {
+ name: "Request a new reset link",
+ }),
+ ).toBeVisible();
+ },
+});
diff --git a/stories/app/auth/verify-email/page.stories.tsx b/stories/app/auth/verify-email/page.stories.tsx
new file mode 100644
index 0000000..d2d3fcd
--- /dev/null
+++ b/stories/app/auth/verify-email/page.stories.tsx
@@ -0,0 +1,65 @@
+import preview from "@/.storybook/preview";
+import VerifyEmailPage from "@/app/auth/verify-email/page";
+import { expect } from "storybook/test";
+
+const meta = preview.meta({
+ title: "Pages/Auth/Verify Email",
+ component: VerifyEmailPage,
+ parameters: {
+ controls: { disable: true },
+ layout: "fullscreen",
+ },
+ args: {
+ searchParams: Promise.resolve({ error: "TOKEN_EXPIRED" }),
+ },
+});
+
+export const Expired = meta.story({
+ play: async ({ canvas }) => {
+ await expect(
+ await canvas.findByRole("heading", { name: "Verify your email." }),
+ ).toBeVisible();
+ await expect(
+ canvas.getByRole("heading", { name: "Verification link expired" }),
+ ).toBeVisible();
+ },
+});
+
+export const Invalid = Expired.extend({
+ args: {
+ searchParams: Promise.resolve({ error: "INVALID_TOKEN" }),
+ },
+ play: async ({ canvas }) => {
+ await expect(
+ await canvas.findByRole("heading", {
+ name: "Verification link unavailable",
+ }),
+ ).toBeVisible();
+ },
+});
+
+export const GenericFailure = Expired.extend({
+ args: {
+ searchParams: Promise.resolve({ error: "USER_NOT_FOUND" }),
+ },
+ play: async ({ canvas }) => {
+ await expect(
+ await canvas.findByRole("heading", {
+ name: "We couldn't verify your email",
+ }),
+ ).toBeVisible();
+ },
+});
+
+export const Loading = Expired.extend({
+ args: {
+ searchParams: new Promise(() => {}),
+ },
+ play: async ({ canvas }) => {
+ await expect(
+ await canvas.findByRole("heading", {
+ name: "Checking your verification link",
+ }),
+ ).toBeVisible();
+ },
+});
diff --git a/stories/app/auth/verify-email/verification-result.stories.tsx b/stories/app/auth/verify-email/verification-result.stories.tsx
new file mode 100644
index 0000000..3194499
--- /dev/null
+++ b/stories/app/auth/verify-email/verification-result.stories.tsx
@@ -0,0 +1,71 @@
+import preview from "@/.storybook/preview";
+import { VerifyEmailResult } from "@/app/auth/verify-email/verification-result";
+import { expect } from "storybook/test";
+
+const meta = preview.meta({
+ title: "Auth/Results/Email Verification",
+ component: VerifyEmailResult,
+ parameters: {
+ controls: { disable: true },
+ layout: "centered",
+ },
+ args: {
+ searchParams: Promise.resolve({ error: "TOKEN_EXPIRED" }),
+ },
+ decorators: [
+ (Story) => (
+
+
+
+ ),
+ ],
+});
+
+export const Expired = meta.story({
+ play: async ({ canvas }) => {
+ await expect(
+ await canvas.findByRole("heading", {
+ name: "Verification link expired",
+ }),
+ ).toBeVisible();
+ await expect(canvas.getByRole("alert")).toHaveTextContent("has expired");
+ },
+});
+
+export const Invalid = Expired.extend({
+ args: {
+ searchParams: Promise.resolve({ error: "INVALID_TOKEN" }),
+ },
+ play: async ({ canvas }) => {
+ await expect(
+ await canvas.findByRole("heading", {
+ name: "Verification link unavailable",
+ }),
+ ).toBeVisible();
+ await expect(canvas.getByRole("alert")).toHaveTextContent(
+ "invalid or has already been used",
+ );
+ },
+});
+
+export const GenericFailure = Expired.extend({
+ args: {
+ searchParams: Promise.resolve({ error: "USER_NOT_FOUND" }),
+ },
+ play: async ({ canvas }) => {
+ await expect(
+ await canvas.findByRole("heading", {
+ name: "We couldn't verify your email",
+ }),
+ ).toBeVisible();
+ await expect(
+ canvas.getByRole("link", { name: /Back to sign in/ }),
+ ).toHaveAttribute("href", "/auth");
+ },
+});
diff --git a/stories/app/code-of-conduct/page.stories.tsx b/stories/app/code-of-conduct/page.stories.tsx
new file mode 100644
index 0000000..2de5512
--- /dev/null
+++ b/stories/app/code-of-conduct/page.stories.tsx
@@ -0,0 +1,12 @@
+import preview from "@/.storybook/preview";
+import CodeOfConductPage from "@/app/code-of-conduct/page";
+
+const meta = preview.meta({
+ component: CodeOfConductPage,
+ title: "Pages/Code of Conduct",
+ parameters: {
+ layout: "fullscreen",
+ },
+});
+
+export const FullPolicy = meta.story({});
diff --git a/stories/app/events/[eventId]/edit/collaborator-invite-form.stories.tsx b/stories/app/events/[eventId]/edit/collaborator-invite-form.stories.tsx
new file mode 100644
index 0000000..109ad0f
--- /dev/null
+++ b/stories/app/events/[eventId]/edit/collaborator-invite-form.stories.tsx
@@ -0,0 +1,92 @@
+import preview from "@/.storybook/preview";
+import { CollaboratorInviteForm } from "@/app/events/[eventId]/edit/collaborator-invite-form";
+import { inviteEventCollaborator } from "@/lib/events/actions";
+import { expect, mocked } from "storybook/test";
+
+const meta = preview.meta({
+ component: CollaboratorInviteForm,
+ parameters: {
+ layout: "centered",
+ },
+ args: {
+ eventId: "storybook-event",
+ },
+ decorators: [
+ (Story) => (
+
+
+
+ ),
+ ],
+});
+
+export const Idle = meta.story({
+ beforeEach: () => {
+ mocked(inviteEventCollaborator).mockResolvedValue({
+ message: "",
+ status: "idle",
+ });
+ },
+});
+
+export const InvitationSent = Idle.extend({
+ beforeEach: () => {
+ mocked(inviteEventCollaborator).mockResolvedValue({
+ message: "Editor invitation sent to teammate@example.com.",
+ status: "success",
+ });
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.type(
+ canvas.getByRole("textbox", { name: "Account email" }),
+ "teammate@example.com",
+ );
+ await userEvent.click(
+ canvas.getByRole("button", { name: "Invite editor" }),
+ );
+ await expect(await canvas.findByRole("status")).toHaveTextContent(
+ "invitation sent",
+ );
+ },
+});
+
+export const AccountNotFound = Idle.extend({
+ beforeEach: () => {
+ mocked(inviteEventCollaborator).mockResolvedValue({
+ message: "No SacTech account uses that email address.",
+ status: "error",
+ });
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.type(
+ canvas.getByRole("textbox", { name: "Account email" }),
+ "missing@example.com",
+ );
+ await userEvent.click(
+ canvas.getByRole("button", { name: "Invite editor" }),
+ );
+ await expect(await canvas.findByRole("alert")).toHaveTextContent(
+ "No SacTech account",
+ );
+ },
+});
+
+export const Inviting = Idle.extend({
+ beforeEach: () => {
+ mocked(inviteEventCollaborator).mockImplementation(
+ () => new Promise(() => {}),
+ );
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.type(
+ canvas.getByRole("textbox", { name: "Account email" }),
+ "teammate@example.com",
+ );
+ await userEvent.click(
+ canvas.getByRole("button", { name: "Invite editor" }),
+ );
+ await expect(
+ canvas.getByRole("button", { name: "Inviting…" }),
+ ).toBeDisabled();
+ },
+});
diff --git a/stories/app/events/[eventId]/edit/page.stories.tsx b/stories/app/events/[eventId]/edit/page.stories.tsx
new file mode 100644
index 0000000..5759c07
--- /dev/null
+++ b/stories/app/events/[eventId]/edit/page.stories.tsx
@@ -0,0 +1,130 @@
+import preview from "@/.storybook/preview";
+import EditEventPage from "@/app/events/[eventId]/edit/page";
+import { getManagedEventForEdit } from "@/lib/events/queries";
+import { requireSession } from "@/lib/session";
+import { createSession } from "@/stories/fixtures/auth";
+import { createManagedEvent } from "@/stories/fixtures/managed-event";
+import { mocked } from "storybook/test";
+
+const seriesArgs = {
+ params: Promise.resolve({ eventId: "storybook-managed-event" }),
+ searchParams: Promise.resolve({ scope: "series" }),
+};
+
+const meta = preview.meta({
+ component: EditEventPage,
+ title: "Pages/Events/Edit",
+ parameters: {
+ controls: { disable: true },
+ layout: "fullscreen",
+ },
+ args: seriesArgs,
+});
+
+export const WholeSeries = meta.story({
+ beforeEach: () => {
+ mocked(requireSession).mockResolvedValue(createSession());
+ mocked(getManagedEventForEdit).mockResolvedValue(createManagedEvent());
+ },
+});
+
+export const OneOccurrence = WholeSeries.extend({
+ args: {
+ searchParams: Promise.resolve({
+ occurrenceDate: "2026-10-22",
+ scope: "occurrence",
+ }),
+ },
+ beforeEach: () => {
+ mocked(requireSession).mockResolvedValue(createSession());
+ mocked(getManagedEventForEdit).mockResolvedValue(
+ createManagedEvent({
+ occurrenceOverride: {
+ description:
+ "A special hands-on edition with extra time for guided practice.",
+ endsAt: new Date("2026-10-23T04:00:00.000Z"),
+ eventUrl: "https://example.com/typescript-workshop",
+ locationAddress: "123 J Street, Sacramento, CA 95814",
+ locationName: "The Urban Hive",
+ mode: "in_person",
+ occurrenceDate: "2026-10-22",
+ startsAt: new Date("2026-10-23T01:00:00.000Z"),
+ timezone: "America/Los_Angeles",
+ title: "TypeScript Hands-on Night",
+ },
+ }),
+ );
+ },
+});
+
+export const ChangesPending = WholeSeries.extend({
+ beforeEach: () => {
+ mocked(requireSession).mockResolvedValue(createSession());
+ mocked(getManagedEventForEdit).mockResolvedValue(
+ createManagedEvent({
+ changeRequests: [
+ {
+ createdAt: new Date("2026-08-30T18:00:00.000Z"),
+ moderationNote: null,
+ occurrenceDate: null,
+ scope: "series",
+ status: "pending",
+ },
+ ],
+ }),
+ );
+ },
+});
+
+export const ReviewerRequestedChanges = WholeSeries.extend({
+ beforeEach: () => {
+ mocked(requireSession).mockResolvedValue(createSession());
+ mocked(getManagedEventForEdit).mockResolvedValue(
+ createManagedEvent({
+ changeRequests: [
+ {
+ createdAt: new Date("2026-08-29T18:00:00.000Z"),
+ moderationNote:
+ "Please add the accessibility details for the venue before resubmitting.",
+ occurrenceDate: null,
+ scope: "series",
+ status: "rejected",
+ },
+ ],
+ }),
+ );
+ },
+});
+
+export const CanceledEvent = WholeSeries.extend({
+ beforeEach: () => {
+ mocked(requireSession).mockResolvedValue(createSession());
+ mocked(getManagedEventForEdit).mockResolvedValue(
+ createManagedEvent({
+ canceledAt: new Date("2026-08-28T18:00:00.000Z"),
+ }),
+ );
+ },
+});
+
+export const SharedWithCurrentUser = WholeSeries.extend({
+ beforeEach: () => {
+ mocked(requireSession).mockResolvedValue(createSession());
+ mocked(getManagedEventForEdit).mockResolvedValue(
+ createManagedEvent({
+ collaborators: [],
+ isOwner: false,
+ submittedBy: "another-user",
+ }),
+ );
+ },
+});
+
+export const Loading = WholeSeries.extend({
+ beforeEach: () => {
+ mocked(requireSession).mockImplementation(() => new Promise(() => {}));
+ mocked(getManagedEventForEdit).mockImplementation(
+ () => new Promise(() => {}),
+ );
+ },
+});
diff --git a/stories/app/events/components/calendar/calendar.stories.tsx b/stories/app/events/components/calendar/calendar.stories.tsx
new file mode 100644
index 0000000..ebc8f8d
--- /dev/null
+++ b/stories/app/events/components/calendar/calendar.stories.tsx
@@ -0,0 +1,76 @@
+import preview from "../../../../../.storybook/preview";
+
+import { expect } from "storybook/test";
+
+import { Calendar } from "@/app/events/components/calendar/calendar";
+import {
+ createRecurringEvent,
+ createRecurringEventWithOverride,
+ createSpecialEvent,
+ EVENT_STORY_REFERENCE_DATE,
+ MIXED_EVENTS,
+} from "@/stories/fixtures/events";
+
+const meta = preview.meta({
+ title: "Events/Components/Calendar",
+ component: Calendar,
+ parameters: {
+ layout: "padded",
+ },
+ args: {
+ events: MIXED_EVENTS,
+ referenceDate: EVENT_STORY_REFERENCE_DATE,
+ },
+ argTypes: {
+ events: { control: false },
+ },
+});
+
+export const MixedEvents = meta.story({});
+
+export const Empty = MixedEvents.extend({
+ args: {
+ events: [],
+ },
+});
+
+export const SelectedOccurrence = MixedEvents.extend({
+ args: {
+ events: [createRecurringEventWithOverride()],
+ },
+ play: async ({ canvas, userEvent }) => {
+ const occurrence = canvas.getByRole("button", {
+ name: "September 15, 2026, 1 event",
+ });
+
+ await userEvent.click(occurrence);
+
+ await expect(occurrence).toHaveAttribute("aria-pressed", "true");
+ await expect(
+ canvas.getByRole("region", { name: "September 15, 2026" }),
+ ).toBeVisible();
+ await expect(canvas.getByText("TypeScript Hands-on Night")).toBeVisible();
+ },
+});
+
+export const NextMonthWindow = meta.story({
+ args: {
+ events: [createRecurringEvent(), createSpecialEvent()],
+ },
+ play: async ({ canvas, userEvent }) => {
+ await expect(
+ canvas.getByRole("table", { name: "September 2026" }),
+ ).toBeVisible();
+
+ await userEvent.click(
+ canvas.getByRole("button", { name: "Show next month" }),
+ );
+
+ await expect(
+ canvas.queryByRole("table", { name: "September 2026" }),
+ ).not.toBeInTheDocument();
+ await expect(
+ canvas.getByRole("table", { name: "December 2026" }),
+ ).toBeVisible();
+ },
+});
diff --git a/stories/app/events/components/event-cards/non-recurring-event-card.stories.tsx b/stories/app/events/components/event-cards/non-recurring-event-card.stories.tsx
new file mode 100644
index 0000000..aa2edcc
--- /dev/null
+++ b/stories/app/events/components/event-cards/non-recurring-event-card.stories.tsx
@@ -0,0 +1,113 @@
+import preview from "../../../../../.storybook/preview";
+
+import { expect } from "storybook/test";
+
+import { NonRecurringEventsCard } from "@/app/events/components/event-cards/non-recurring-event-card";
+import {
+ createEventBlock,
+ createLongEventDescription,
+ createSpecialEvent,
+} from "@/stories/fixtures/events";
+
+const meta = preview.meta({
+ title: "Events/Components/Event Cards/Non-recurring",
+ component: NonRecurringEventsCard,
+ parameters: {
+ layout: "padded",
+ },
+ args: {
+ event: createSpecialEvent(),
+ },
+ argTypes: {
+ event: { control: false },
+ },
+ render: (args) => (
+
+ ),
+});
+
+export const InPerson = meta.story({});
+
+export const Online = InPerson.extend({
+ args: {
+ event: createSpecialEvent({
+ blocks: [
+ createEventBlock({
+ in_person: false,
+ is_online: true,
+ location_address: undefined,
+ location_description: "Online",
+ location_url: "https://events.example.com/online-design-lab",
+ slug: "online-design-lab-occurrence",
+ title: "Online Design Lab",
+ }),
+ ],
+ in_person: false,
+ is_online: true,
+ location_address: undefined,
+ location_description: "Online",
+ location_url: "https://events.example.com/online-design-lab",
+ slug: "online-design-lab",
+ title: "Online Design Lab",
+ }),
+ },
+});
+
+export const HybridMultiDay = InPerson.extend({
+ args: {
+ event: createSpecialEvent({
+ blocks: [
+ createEventBlock({
+ ends_at: new Date("2026-10-05T23:00:00.000Z"),
+ in_person: true,
+ is_online: true,
+ location_description: "Sacramento Convention Center + livestream",
+ location_url: "https://events.example.com/civic-tech-weekend",
+ slug: "civic-tech-weekend-occurrence",
+ starts_at: new Date("2026-10-03T16:00:00.000Z"),
+ title: "Civic Tech Weekend",
+ }),
+ ],
+ in_person: true,
+ is_online: true,
+ location_description: "Sacramento Convention Center + livestream",
+ location_url: "https://events.example.com/civic-tech-weekend",
+ slug: "civic-tech-weekend",
+ title: "Civic Tech Weekend",
+ }),
+ },
+});
+
+export const DatesComingSoon = InPerson.extend({
+ args: {
+ event: createSpecialEvent({
+ blocks: [],
+ location_url: undefined,
+ slug: "future-community-showcase",
+ title: "Future Community Showcase",
+ }),
+ },
+});
+
+const expandedDescriptionTail = "The final workshop details are now visible.";
+
+export const ExpandedDescription = InPerson.extend({
+ args: {
+ event: createSpecialEvent({
+ description: createLongEventDescription(expandedDescriptionTail),
+ }),
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.click(
+ canvas.getByRole("button", {
+ name: "Show more details for Sacramento Design Summit",
+ }),
+ );
+
+ await expect(
+ canvas.getByText(expandedDescriptionTail, { exact: false }),
+ ).toBeVisible();
+ },
+});
diff --git a/stories/app/events/components/event-cards/recurring-event-card.stories.tsx b/stories/app/events/components/event-cards/recurring-event-card.stories.tsx
new file mode 100644
index 0000000..c3f8b94
--- /dev/null
+++ b/stories/app/events/components/event-cards/recurring-event-card.stories.tsx
@@ -0,0 +1,85 @@
+import preview from "../../../../../.storybook/preview";
+
+import { expect } from "storybook/test";
+
+import { RecurringEventsCard } from "@/app/events/components/event-cards/recurring-event-card";
+import {
+ createLongEventDescription,
+ createRecurringEvent,
+ createRecurringEventWithOverride,
+ createWeeklyRecurrenceRule,
+ EVENT_STORY_REFERENCE_DATE,
+} from "@/stories/fixtures/events";
+
+const meta = preview.meta({
+ title: "Events/Components/Event Cards/Recurring",
+ component: RecurringEventsCard,
+ parameters: {
+ layout: "padded",
+ },
+ args: {
+ event: createRecurringEvent(),
+ referenceDate: EVENT_STORY_REFERENCE_DATE,
+ },
+ argTypes: {
+ event: { control: false },
+ },
+ render: (args) => (
+
+ ),
+});
+
+export const WeeklyOnline = meta.story({});
+
+export const OccurrenceOverride = WeeklyOnline.extend({
+ args: {
+ event: createRecurringEventWithOverride(),
+ referenceDate: "2026-09-09",
+ },
+ play: async ({ canvas }) => {
+ await expect(
+ canvas.getByRole("heading", { name: "TypeScript Hands-on Night" }),
+ ).toBeVisible();
+ await expect(canvas.getByText("In person")).toBeVisible();
+ await expect(canvas.queryByText("Online")).not.toBeInTheDocument();
+ await expect(
+ canvas.getByRole("link", {
+ name: "The Urban Hive: TypeScript Hands-on Night",
+ }),
+ ).toHaveAttribute("href", "https://events.example.com/hands-on-night");
+ },
+});
+
+export const NoUpcomingDates = WeeklyOnline.extend({
+ args: {
+ event: createRecurringEvent({
+ recurrence_rule: createWeeklyRecurrenceRule({
+ excludedDates: ["2026-09-02", "2026-09-09"],
+ occurrenceCount: 2,
+ }),
+ }),
+ },
+});
+
+const expandedDescriptionTail = "The complete recurring agenda is visible.";
+
+export const ExpandedDescription = WeeklyOnline.extend({
+ args: {
+ event: createRecurringEvent({
+ description: createLongEventDescription(expandedDescriptionTail),
+ }),
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.click(
+ canvas.getByRole("button", {
+ name: "Show more details for Sacramento TypeScript Weekly",
+ }),
+ );
+
+ await expect(
+ canvas.getByText(expandedDescriptionTail, { exact: false }),
+ ).toBeVisible();
+ },
+});
diff --git a/stories/app/events/components/event-chip/event-chip.stories.tsx b/stories/app/events/components/event-chip/event-chip.stories.tsx
new file mode 100644
index 0000000..db29bf2
--- /dev/null
+++ b/stories/app/events/components/event-chip/event-chip.stories.tsx
@@ -0,0 +1,60 @@
+import preview from "../../../../../.storybook/preview";
+
+import { EventChip } from "@/app/events/components/event-chip/event-chip";
+
+const meta = preview.meta({
+ title: "Events/Components/Event Chip",
+ component: EventChip,
+ parameters: {
+ layout: "centered",
+ },
+ args: {
+ size: "default",
+ variant: "online",
+ },
+});
+
+export const Online = meta.story({
+ args: {
+ size: "default",
+ variant: "online",
+ },
+});
+
+export const OnlineCompact = Online.extend({
+ args: {
+ size: "compact",
+ },
+});
+
+export const InPerson = Online.extend({
+ args: {
+ variant: "in-person",
+ },
+});
+
+export const RecurringDaily = meta.story({
+ args: {
+ every: "day",
+ size: "default",
+ variant: "recurring",
+ },
+});
+
+export const RecurringWeekly = RecurringDaily.extend({
+ args: {
+ every: "week",
+ },
+});
+
+export const RecurringMonthly = RecurringDaily.extend({
+ args: {
+ every: "month",
+ },
+});
+
+export const RecurringYearly = RecurringDaily.extend({
+ args: {
+ every: "year",
+ },
+});
diff --git a/stories/app/events/events-page.stories.tsx b/stories/app/events/events-page.stories.tsx
new file mode 100644
index 0000000..239f44f
--- /dev/null
+++ b/stories/app/events/events-page.stories.tsx
@@ -0,0 +1,63 @@
+import preview from "../../../.storybook/preview";
+
+import { expect } from "storybook/test";
+
+import EventsPage, { EventsCallouts } from "@/app/events/events-page";
+import {
+ EVENT_STORY_REFERENCE_DATE,
+ MIXED_EVENTS,
+} from "@/stories/fixtures/events";
+
+const meta = preview.meta({
+ title: "Events/Pages/Events Page",
+ component: EventsPage,
+ parameters: {
+ layout: "padded",
+ },
+ args: {
+ events: MIXED_EVENTS,
+ referenceDate: EVENT_STORY_REFERENCE_DATE,
+ },
+ argTypes: {
+ events: { control: false },
+ },
+});
+
+export const MixedSchedule = meta.story({});
+
+export const EmptySchedule = MixedSchedule.extend({
+ args: {
+ events: [],
+ },
+});
+
+export const FilteredToOnline = MixedSchedule.extend({
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.click(canvas.getByRole("radio", { name: "Online" }));
+
+ await expect(canvas.getByRole("radio", { name: "Online" })).toBeChecked();
+ await expect(canvas.getByRole("status")).toHaveTextContent(
+ "Showing 1 event for online.",
+ );
+ await expect(
+ canvas.getByRole("heading", {
+ name: "Sacramento TypeScript Weekly",
+ }),
+ ).toBeVisible();
+ await expect(
+ canvas.queryByRole("heading", { name: "Sacramento Design Summit" }),
+ ).not.toBeInTheDocument();
+ },
+});
+
+export const CallsToAction = meta.story({
+ render: () => ,
+ play: async ({ canvas }) => {
+ await expect(
+ canvas.getByRole("link", { name: "Join the community" }),
+ ).toHaveAttribute("href", "/#join");
+ await expect(
+ canvas.getByRole("link", { name: "Submit an event" }),
+ ).toHaveAttribute("href", "/account");
+ },
+});
diff --git a/stories/app/events/page.stories.tsx b/stories/app/events/page.stories.tsx
new file mode 100644
index 0000000..a53ca38
--- /dev/null
+++ b/stories/app/events/page.stories.tsx
@@ -0,0 +1,100 @@
+import preview from "@/.storybook/preview";
+import EventsPage, { EventsCallouts } from "@/app/events/events-page";
+import style from "@/app/events/events-page.module.css";
+import type { Event } from "@/app/events/types";
+import { BridgeArt } from "@/components/bridge-art";
+import {
+ EVENT_STORY_REFERENCE_DATE,
+ MIXED_EVENTS,
+} from "@/stories/fixtures/events";
+
+interface EventsRoutePreviewProps {
+ events: Event[];
+ referenceDate: string;
+}
+
+function EventsRoutePreview({
+ events,
+ referenceDate,
+}: EventsRoutePreviewProps) {
+ return (
+
+
+
+
+
Gather by the river
+
Find your next local tech event.
+
+ Meet people across the region who design, build, teach, and learn
+ about technology. Browse what's scheduled now.
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+const meta = preview.meta({
+ component: EventsRoutePreview,
+ title: "Pages/Events",
+ parameters: {
+ layout: "fullscreen",
+ },
+ args: {
+ events: MIXED_EVENTS,
+ referenceDate: EVENT_STORY_REFERENCE_DATE,
+ },
+});
+
+export const PopulatedCalendar = meta.story({});
+
+export const EmptyCalendar = PopulatedCalendar.extend({
+ args: {
+ events: [],
+ },
+});
+
+export const LoadingCalendar = PopulatedCalendar.extend({
+ render: () => (
+
+
+
+
+
Gather by the river
+
Find your next local tech event.
+
+
+
+
+
+
+
+
+
Community calendar
+
See what's coming up
+
+
+
+
+
Loading schedule
+
Gathering the latest event details.
+
The community calendar will be ready in a moment.
+
+
+
+
+
+
+ ),
+});
diff --git a/stories/app/events/submit/event-description-editor.stories.tsx b/stories/app/events/submit/event-description-editor.stories.tsx
new file mode 100644
index 0000000..166f49d
--- /dev/null
+++ b/stories/app/events/submit/event-description-editor.stories.tsx
@@ -0,0 +1,80 @@
+import preview from "@/.storybook/preview";
+import { EventDescriptionEditor } from "@/app/events/submit/event-description-editor";
+import { fn } from "storybook/test";
+
+const formattedDescription = `## What to expect
+
+Bring a laptop and meet other Sacramento developers.
+
+- Short project demos
+- Friendly code review
+- Time to meet collaborators
+
+> First-time attendees are especially welcome.
+
+Read the [community guidelines](/code-of-conduct) before joining.
+
+\`\`\`ts
+const greeting = "Hello, Sacramento!";
+\`\`\``;
+
+const meta = preview.meta({
+ component: EventDescriptionEditor,
+ parameters: {
+ layout: "padded",
+ },
+ args: {
+ "aria-describedby": "description-help",
+ disabled: false,
+ onChange: fn(),
+ value: "",
+ },
+ decorators: [
+ (Story) => (
+
+
+
+ Tell people what will happen and who the event is for.
+
+
+
+ ),
+ ],
+});
+
+export const Empty = meta.story({});
+
+export const Formatted = Empty.extend({
+ args: {
+ value: formattedDescription,
+ },
+});
+
+export const Invalid = Formatted.extend({
+ args: {
+ "aria-invalid": true,
+ },
+});
+
+export const Disabled = Formatted.extend({
+ args: {
+ disabled: true,
+ },
+});
+
+export const OverCharacterLimit = Empty.extend({
+ args: {
+ value: "A".repeat(4_025),
+ },
+});
+
+export const BoldText = Empty.extend({
+ play: async ({ canvas, userEvent }) => {
+ const editor = canvas.getByRole("textbox", { name: "Description" });
+ await userEvent.click(editor);
+ await userEvent.click(canvas.getByRole("button", { name: "Bold" }));
+ await userEvent.type(editor, "A hands-on community workshop");
+ },
+});
diff --git a/stories/app/events/submit/event-form.stories.tsx b/stories/app/events/submit/event-form.stories.tsx
new file mode 100644
index 0000000..bdd80c0
--- /dev/null
+++ b/stories/app/events/submit/event-form.stories.tsx
@@ -0,0 +1,158 @@
+import preview from "@/.storybook/preview";
+import {
+ EventForm,
+ type EventFormAction,
+ type EventFormValues,
+} from "@/app/events/submit/event-form";
+import type { EventFormState } from "@/lib/events/state";
+import { expect, fn } from "storybook/test";
+
+const idleAction = fn(async () => ({
+ message: "",
+ status: "idle",
+}));
+
+const baseValues: EventFormValues = {
+ description:
+ "A welcoming demo night for Sacramento developers, designers, and makers.",
+ endsAt: "2026-10-15T20:30",
+ eventUrl: "https://example.com/sacramento-demo-night",
+ locationAddress: "828 I Street, Sacramento, CA 95814",
+ locationName: "Sacramento Central Library",
+ mode: "hybrid",
+ recurrenceCount: "8",
+ recurrenceEndDate: "2027-02-18",
+ recurrenceEndType: "never",
+ recurrenceFrequency: "week",
+ recurrenceInterval: "1",
+ recurrenceMonthlyPattern: "day_of_month",
+ recurrenceWeekdays: [4],
+ recurring: false,
+ startsAt: "2026-10-15T18:00",
+ title: "Sacramento Community Demo Night",
+};
+
+const weeklyValues: EventFormValues = {
+ ...baseValues,
+ recurrenceEndType: "after_occurrences",
+ recurrenceWeekdays: [2, 4],
+ recurring: true,
+};
+
+const meta = preview.meta({
+ component: EventForm,
+ parameters: {
+ layout: "padded",
+ },
+ args: {
+ action: idleAction,
+ allowRecurrence: true,
+ variant: "submit",
+ },
+ decorators: [
+ (Story) => (
+
+
+
+ ),
+ ],
+});
+
+export const BlankSubmission = meta.story({});
+
+export const OneTimeHybridEvent = BlankSubmission.extend({
+ args: {
+ initialValues: baseValues,
+ },
+});
+
+export const WeeklySeries = OneTimeHybridEvent.extend({
+ args: {
+ initialValues: weeklyValues,
+ },
+});
+
+export const MonthlySeries = WeeklySeries.extend({
+ args: {
+ initialValues: {
+ ...weeklyValues,
+ recurrenceEndDate: "2027-10-15",
+ recurrenceEndType: "on_date",
+ recurrenceFrequency: "month",
+ recurrenceInterval: "1",
+ recurrenceMonthlyPattern: "nth_weekday",
+ },
+ },
+});
+
+export const YearlySeries = WeeklySeries.extend({
+ args: {
+ initialValues: {
+ ...weeklyValues,
+ recurrenceEndType: "never",
+ recurrenceFrequency: "year",
+ recurrenceInterval: "1",
+ },
+ },
+});
+
+export const OccurrenceEdit = OneTimeHybridEvent.extend({
+ args: {
+ allowRecurrence: false,
+ variant: "edit",
+ },
+});
+
+const validationError: EventFormState = {
+ errors: {
+ eventUrl: ["Use a complete http:// or https:// link."],
+ title: ["Use a more descriptive event title."],
+ },
+ message: "Review the highlighted fields and try again.",
+ status: "error",
+};
+
+export const ServerValidationErrors = OneTimeHybridEvent.extend({
+ args: {
+ action: fn(async () => validationError),
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.click(
+ canvas.getByRole("button", { name: "Submit event for review" }),
+ );
+ await expect(await canvas.findByRole("alert")).toHaveTextContent(
+ "Review the highlighted fields",
+ );
+ },
+});
+
+export const Submitted = OneTimeHybridEvent.extend({
+ args: {
+ action: fn(async () => ({
+ message: "Event submitted for review.",
+ status: "success",
+ })),
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.click(
+ canvas.getByRole("button", { name: "Submit event for review" }),
+ );
+ await expect(await canvas.findByRole("status")).toHaveTextContent(
+ "Event submitted for review.",
+ );
+ },
+});
+
+export const Submitting = OneTimeHybridEvent.extend({
+ args: {
+ action: fn(() => new Promise(() => {})),
+ },
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.click(
+ canvas.getByRole("button", { name: "Submit event for review" }),
+ );
+ await expect(
+ canvas.getByRole("button", { name: "Submitting…" }),
+ ).toBeDisabled();
+ },
+});
diff --git a/stories/app/events/submit/page.stories.tsx b/stories/app/events/submit/page.stories.tsx
new file mode 100644
index 0000000..611d41f
--- /dev/null
+++ b/stories/app/events/submit/page.stories.tsx
@@ -0,0 +1,25 @@
+import preview from "@/.storybook/preview";
+import SubmitEventPage from "@/app/events/submit/page";
+import { requireSession } from "@/lib/session";
+import { createSession } from "@/stories/fixtures/auth";
+import { mocked } from "storybook/test";
+
+const meta = preview.meta({
+ component: SubmitEventPage,
+ title: "Pages/Events/Submit",
+ parameters: {
+ layout: "fullscreen",
+ },
+});
+
+export const Authenticated = meta.story({
+ beforeEach: () => {
+ mocked(requireSession).mockResolvedValue(createSession());
+ },
+});
+
+export const CheckingSession = Authenticated.extend({
+ beforeEach: () => {
+ mocked(requireSession).mockImplementation(() => new Promise(() => {}));
+ },
+});
diff --git a/stories/app/page.stories.tsx b/stories/app/page.stories.tsx
new file mode 100644
index 0000000..bd74998
--- /dev/null
+++ b/stories/app/page.stories.tsx
@@ -0,0 +1,22 @@
+import preview from "@/.storybook/preview";
+import { HomePage } from "@/app/page";
+
+const meta = preview.meta({
+ component: HomePage,
+ title: "Pages/Home",
+ parameters: {
+ layout: "fullscreen",
+ },
+});
+
+export const SlackInviteAvailable = meta.story({
+ args: {
+ inviteLink: "https://join.slack.com/t/sactech/shared_invite/storybook",
+ },
+});
+
+export const SlackInviteUnavailable = SlackInviteAvailable.extend({
+ args: {
+ inviteLink: undefined,
+ },
+});
diff --git a/stories/button.css b/stories/button.css
deleted file mode 100644
index 04ffdf3..0000000
--- a/stories/button.css
+++ /dev/null
@@ -1,30 +0,0 @@
-.storybook-button {
- display: inline-block;
- cursor: pointer;
- border: 0;
- border-radius: 3em;
- font-weight: 700;
- line-height: 1;
- font-family: "Nunito Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
-}
-.storybook-button--primary {
- background-color: #555ab9;
- color: white;
-}
-.storybook-button--secondary {
- box-shadow: rgba(0, 0, 0, 0.15) 0px 0px 0px 1px inset;
- background-color: transparent;
- color: #333;
-}
-.storybook-button--small {
- padding: 10px 16px;
- font-size: 12px;
-}
-.storybook-button--medium {
- padding: 11px 20px;
- font-size: 14px;
-}
-.storybook-button--large {
- padding: 12px 24px;
- font-size: 16px;
-}
diff --git a/stories/components/bridge-art.stories.tsx b/stories/components/bridge-art.stories.tsx
new file mode 100644
index 0000000..816451f
--- /dev/null
+++ b/stories/components/bridge-art.stories.tsx
@@ -0,0 +1,38 @@
+import preview from "@/.storybook/preview";
+import { BridgeArt } from "@/components/bridge-art";
+import { expect } from "storybook/test";
+
+const meta = preview.meta({
+ title: "Components/Bridge Art",
+ component: BridgeArt,
+ parameters: {
+ layout: "centered",
+ },
+ tags: ["autodocs"],
+ decorators: [
+ (Story) => (
+
+
+
+ ),
+ ],
+});
+
+export const Full = meta.story({
+ args: {
+ compact: false,
+ },
+ play: async ({ canvasElement }) => {
+ const artwork = canvasElement.querySelector("[aria-hidden='true']");
+ const image = canvasElement.querySelector("img");
+
+ await expect(artwork).toHaveAttribute("aria-hidden", "true");
+ await expect(image).toBeInTheDocument();
+ },
+});
+
+export const Compact = Full.extend({
+ args: {
+ compact: true,
+ },
+});
diff --git a/stories/components/collapsible-event-description.stories.tsx b/stories/components/collapsible-event-description.stories.tsx
new file mode 100644
index 0000000..8a2e1cf
--- /dev/null
+++ b/stories/components/collapsible-event-description.stories.tsx
@@ -0,0 +1,79 @@
+import preview from "@/.storybook/preview";
+import { CollapsibleEventDescription } from "@/components/collapsible-event-description";
+import { expect } from "storybook/test";
+
+const longMarkdown = `${"A".repeat(295)} **bold tail stays formatted**\n\n[Event details](https://events.example.com/details)`;
+
+const meta = preview.meta({
+ title: "Components/Collapsible Event Description",
+ component: CollapsibleEventDescription,
+ parameters: {
+ layout: "centered",
+ },
+ tags: ["autodocs"],
+ decorators: [
+ (Story) => (
+
+
+
+ ),
+ ],
+});
+
+export const ExactlyAtLimit = meta.story({
+ args: {
+ eventTitle: "A concise event",
+ markdown: "A".repeat(300),
+ },
+ play: async ({ canvas }) => {
+ await expect(canvas.getByText("A".repeat(300))).toBeVisible();
+ await expect(canvas.queryByRole("button")).not.toBeInTheDocument();
+ },
+});
+
+export const LongDescription = meta.story({
+ args: {
+ eventTitle: "SacTech community night",
+ markdown: longMarkdown,
+ },
+ play: async ({ canvas }) => {
+ const toggle = canvas.getByRole("button", {
+ name: "Show more details for SacTech community night",
+ });
+
+ await expect(toggle).toHaveAttribute("aria-expanded", "false");
+ await expect(canvas.getByText("bold…").tagName).toBe("STRONG");
+ await expect(
+ canvas.queryByRole("link", { name: "Event details" }),
+ ).not.toBeInTheDocument();
+ },
+});
+
+export const Expanded = LongDescription.extend({
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.click(
+ canvas.getByRole("button", {
+ name: "Show more details for SacTech community night",
+ }),
+ );
+
+ await expect(
+ canvas.getByRole("button", {
+ name: "Show less details for SacTech community night",
+ }),
+ ).toHaveAttribute("aria-expanded", "true");
+ await expect(canvas.getByText("bold tail stays formatted").tagName).toBe(
+ "STRONG",
+ );
+ await expect(
+ canvas.getByRole("link", { name: "Event details" }),
+ ).toBeVisible();
+ },
+});
diff --git a/stories/components/event-description-markdown.stories.tsx b/stories/components/event-description-markdown.stories.tsx
new file mode 100644
index 0000000..b3a15d1
--- /dev/null
+++ b/stories/components/event-description-markdown.stories.tsx
@@ -0,0 +1,96 @@
+import preview from "@/.storybook/preview";
+import { EventDescriptionMarkdown } from "@/components/event-description-markdown";
+import { expect } from "storybook/test";
+
+const richMarkdown = [
+ "# What to expect",
+ "",
+ "Meet **Sacramento builders** and share what you are learning.",
+ "",
+ "> Bring a project, a question, or just your curiosity.",
+ "",
+ "- See community demos",
+ "- Meet a collaborator",
+ "- Try `pnpm test` with a neighbor",
+ "",
+ "```ts",
+ 'const greeting = "Hello, Sacramento!";',
+ "```",
+ "",
+ "[Event details](https://events.example.com/sac-tech)",
+].join("\n");
+
+const meta = preview.meta({
+ title: "Components/Event Description Markdown",
+ component: EventDescriptionMarkdown,
+ parameters: {
+ layout: "centered",
+ },
+ tags: ["autodocs"],
+ decorators: [
+ (Story) => (
+
+
+
+ ),
+ ],
+});
+
+export const RichContent = meta.story({
+ args: {
+ markdown: richMarkdown,
+ },
+ play: async ({ canvas }) => {
+ await expect(
+ canvas.getByRole("heading", { level: 4, name: "What to expect" }),
+ ).toBeVisible();
+ await expect(canvas.getByText("Sacramento builders").tagName).toBe(
+ "STRONG",
+ );
+ await expect(canvas.getAllByRole("listitem")).toHaveLength(3);
+ await expect(
+ canvas.getByRole("link", { name: "Event details" }),
+ ).toHaveAttribute("target", "_blank");
+ },
+});
+
+export const TruncatedContent = meta.story({
+ args: {
+ markdown: `${"A".repeat(295)} **bold ending remains valid**\n\n[Hidden link](https://example.com)`,
+ maxCharacters: 300,
+ },
+ play: async ({ canvas }) => {
+ await expect(canvas.getByText("bold…").tagName).toBe("STRONG");
+ await expect(
+ canvas.queryByRole("link", { name: "Hidden link" }),
+ ).not.toBeInTheDocument();
+ },
+});
+
+export const UnsafeInput = meta.story({
+ args: {
+ markdown: [
+ "Safe introduction.",
+ "",
+ "",
+ '
',
+ "",
+ "[Unsafe destination](javascript:alert('nope'))",
+ ].join("\n"),
+ },
+ play: async ({ canvas, canvasElement }) => {
+ await expect(canvas.getByText("Safe introduction.")).toBeVisible();
+ await expect(canvasElement.querySelector("script")).not.toBeInTheDocument();
+ await expect(canvasElement.querySelector("img")).not.toBeInTheDocument();
+ await expect(
+ canvas.getByText("Unsafe destination").closest("a"),
+ ).not.toHaveAttribute("href");
+ },
+});
diff --git a/stories/components/join-community.stories.tsx b/stories/components/join-community.stories.tsx
new file mode 100644
index 0000000..d5c3f00
--- /dev/null
+++ b/stories/components/join-community.stories.tsx
@@ -0,0 +1,79 @@
+import preview from "@/.storybook/preview";
+import { JoinCommunity } from "@/components/join-community";
+import { expect } from "storybook/test";
+
+const meta = preview.meta({
+ title: "Components/Join Community",
+ component: JoinCommunity,
+ parameters: {
+ layout: "centered",
+ nextjs: {
+ appDirectory: true,
+ },
+ },
+ tags: ["autodocs"],
+ decorators: [
+ (Story) => (
+
+
+
+ ),
+ ],
+});
+
+export const InviteUnavailable = meta.story({
+ args: {},
+ play: async ({ canvas }) => {
+ await expect(
+ canvas.getByText("We're updating the Slack invitations."),
+ ).toBeVisible();
+ await expect(
+ canvas.getByRole("link", { name: "Code of Conduct" }),
+ ).toHaveAttribute("href", "/code-of-conduct");
+ },
+});
+
+export const InviteAvailable = meta.story({
+ args: {
+ inviteLink: "https://community.example.com/sactech",
+ },
+ play: async ({ canvas }) => {
+ await expect(
+ canvas.getByRole("checkbox", { name: /I agree to the Code of Conduct/ }),
+ ).not.toBeChecked();
+ await expect(
+ canvas.getByRole("button", { name: /Join SacTech Slack/ }),
+ ).toBeEnabled();
+ },
+});
+
+export const AgreementRequired = InviteAvailable.extend({
+ play: async ({ canvas, userEvent }) => {
+ await userEvent.click(
+ canvas.getByRole("button", { name: /Join SacTech Slack/ }),
+ );
+
+ await expect(canvas.getByRole("status")).toHaveTextContent(
+ "Please agree to the Code of Conduct before joining.",
+ );
+ },
+});
+
+export const AgreementSelected = InviteAvailable.extend({
+ play: async ({ canvas, userEvent }) => {
+ const agreement = canvas.getByRole("checkbox", {
+ name: /I agree to the Code of Conduct/,
+ });
+
+ await userEvent.click(agreement);
+ await expect(agreement).toBeChecked();
+ await expect(canvas.queryByRole("status")).not.toBeInTheDocument();
+ },
+});
diff --git a/stories/components/site-footer.stories.tsx b/stories/components/site-footer.stories.tsx
new file mode 100644
index 0000000..1c86998
--- /dev/null
+++ b/stories/components/site-footer.stories.tsx
@@ -0,0 +1,26 @@
+import preview from "@/.storybook/preview";
+import { SiteFooter } from "@/components/site-footer";
+import { expect } from "storybook/test";
+
+const meta = preview.meta({
+ title: "Components/Site Footer",
+ component: SiteFooter,
+ parameters: {
+ layout: "fullscreen",
+ nextjs: {
+ appDirectory: true,
+ },
+ },
+ tags: ["autodocs"],
+});
+
+export const Default = meta.story({
+ play: async ({ canvas }) => {
+ await expect(canvas.getByRole("contentinfo")).toBeVisible();
+ await expect(canvas.getByAltText("SacTech")).toBeVisible();
+ await expect(canvas.getAllByRole("link")).toHaveLength(3);
+ await expect(
+ canvas.getByRole("navigation", { name: "Footer" }),
+ ).toBeVisible();
+ },
+});
diff --git a/stories/components/site-header.stories.tsx b/stories/components/site-header.stories.tsx
new file mode 100644
index 0000000..bc9ac0d
--- /dev/null
+++ b/stories/components/site-header.stories.tsx
@@ -0,0 +1,63 @@
+import preview from "@/.storybook/preview";
+import { SiteHeader } from "@/components/site-header";
+import { expect } from "storybook/test";
+
+const meta = preview.meta({
+ title: "Components/Site Header",
+ component: SiteHeader,
+ parameters: {
+ layout: "fullscreen",
+ nextjs: {
+ appDirectory: true,
+ navigation: {
+ pathname: "/",
+ },
+ },
+ },
+ tags: ["autodocs"],
+});
+
+export const HomeRoute = meta.story({
+ play: async ({ canvas }) => {
+ await expect(
+ canvas.getByRole("banner").querySelector("img"),
+ ).toBeInTheDocument();
+ await expect(
+ canvas.getByRole("link", { name: "Community" }),
+ ).toHaveAttribute("aria-current", "page");
+ await expect(
+ canvas.getByRole("link", { name: "Join the community" }),
+ ).toHaveAttribute("href", "/#join");
+ },
+});
+
+export const EventsRoute = HomeRoute.extend({
+ parameters: {
+ nextjs: {
+ navigation: {
+ pathname: "/events",
+ },
+ },
+ },
+ play: async ({ canvas }) => {
+ await expect(canvas.getByRole("link", { name: "Events" })).toHaveAttribute(
+ "aria-current",
+ "page",
+ );
+ },
+});
+
+export const CodeOfConductRoute = HomeRoute.extend({
+ parameters: {
+ nextjs: {
+ navigation: {
+ pathname: "/code-of-conduct",
+ },
+ },
+ },
+ play: async ({ canvas }) => {
+ await expect(
+ canvas.getByRole("link", { name: "Code of Conduct" }),
+ ).toHaveAttribute("aria-current", "page");
+ },
+});
diff --git a/stories/components/site-nav.stories.tsx b/stories/components/site-nav.stories.tsx
new file mode 100644
index 0000000..34203c0
--- /dev/null
+++ b/stories/components/site-nav.stories.tsx
@@ -0,0 +1,84 @@
+import preview from "@/.storybook/preview";
+import { SiteNav } from "@/components/site-nav";
+import { expect } from "storybook/test";
+
+const meta = preview.meta({
+ title: "Components/Site Navigation",
+ component: SiteNav,
+ parameters: {
+ layout: "centered",
+ nextjs: {
+ appDirectory: true,
+ navigation: {
+ pathname: "/",
+ },
+ },
+ },
+ tags: ["autodocs"],
+ decorators: [
+ (Story) => (
+
+
+
+ ),
+ ],
+});
+
+export const HomeRoute = meta.story({
+ play: async ({ canvas }) => {
+ await expect(
+ canvas.getByRole("link", { name: "Community" }),
+ ).toHaveAttribute("aria-current", "page");
+ },
+});
+
+export const EventsRoute = HomeRoute.extend({
+ parameters: {
+ nextjs: {
+ navigation: {
+ pathname: "/events",
+ },
+ },
+ },
+ play: async ({ canvas }) => {
+ await expect(canvas.getByRole("link", { name: "Events" })).toHaveAttribute(
+ "aria-current",
+ "page",
+ );
+ },
+});
+
+export const CodeOfConductRoute = HomeRoute.extend({
+ parameters: {
+ nextjs: {
+ navigation: {
+ pathname: "/code-of-conduct",
+ },
+ },
+ },
+ play: async ({ canvas }) => {
+ await expect(
+ canvas.getByRole("link", { name: "Code of Conduct" }),
+ ).toHaveAttribute("aria-current", "page");
+ },
+});
+
+export const UnmatchedRoute = HomeRoute.extend({
+ parameters: {
+ nextjs: {
+ navigation: {
+ pathname: "/account",
+ },
+ },
+ },
+ play: async ({ canvas }) => {
+ for (const link of canvas.getAllByRole("link")) {
+ await expect(link).not.toHaveAttribute("aria-current");
+ }
+ },
+});
diff --git a/stories/fixtures/admin.ts b/stories/fixtures/admin.ts
new file mode 100644
index 0000000..b1e5019
--- /dev/null
+++ b/stories/fixtures/admin.ts
@@ -0,0 +1,171 @@
+import type { ManagedUser } from "@/app/admin/users/user-management-card";
+import type {
+ getPendingEventEdits,
+ getPendingEvents,
+} from "@/lib/events/queries";
+
+type PendingEvents = Awaited>;
+type PendingEventEdits = Awaited>;
+
+export const PENDING_ADMIN_EVENTS = [
+ {
+ canceledOccurrences: [],
+ createdAt: new Date("2026-09-02T17:30:00.000Z"),
+ description:
+ "A welcoming evening of short demos from Sacramento developers, designers, and makers.",
+ endsAt: new Date("2026-10-16T03:30:00.000Z"),
+ eventUrl: "https://example.com/sacramento-demo-night",
+ id: "9ae8c027-41d6-4890-a431-1d8208b22e40",
+ locationAddress: "828 I Street, Sacramento, CA 95814",
+ locationName: "Sacramento Central Library",
+ mode: "hybrid",
+ recurrenceCount: null,
+ recurrenceEndDate: null,
+ recurrenceEndType: null,
+ recurrenceFrequency: null,
+ recurrenceInterval: null,
+ recurrenceMonthlyPattern: null,
+ recurrenceWeekdays: null,
+ startsAt: new Date("2026-10-16T01:00:00.000Z"),
+ submitterEmail: "maya.chen@example.com",
+ submitterName: "Maya Chen",
+ timezone: "America/Los_Angeles",
+ title: "Sacramento Community Demo Night",
+ },
+ {
+ canceledOccurrences: ["2026-11-03"],
+ createdAt: new Date("2026-09-04T20:15:00.000Z"),
+ description:
+ "A practical weekly TypeScript study group with a rotating community-led topic.",
+ endsAt: new Date("2026-10-21T02:00:00.000Z"),
+ eventUrl: "https://example.com/typescript-weekly",
+ id: "e43f00ec-4003-4855-afc6-6b9b7f654229",
+ locationAddress: null,
+ locationName: null,
+ mode: "online",
+ recurrenceCount: 8,
+ recurrenceEndDate: null,
+ recurrenceEndType: "after_occurrences",
+ recurrenceFrequency: "week",
+ recurrenceInterval: 1,
+ recurrenceMonthlyPattern: null,
+ recurrenceWeekdays: [2],
+ startsAt: new Date("2026-10-21T01:00:00.000Z"),
+ submitterEmail: "jordan.lee@example.com",
+ submitterName: "Jordan Lee",
+ timezone: "America/Los_Angeles",
+ title: "Sacramento TypeScript Weekly",
+ },
+] satisfies PendingEvents;
+
+export const PENDING_ADMIN_EVENT_EDITS = [
+ {
+ createdAt: new Date("2026-09-05T19:20:00.000Z"),
+ currentDescription:
+ "A weekly coworking session for people building civic technology.",
+ currentEndsAt: new Date("2026-10-22T03:00:00.000Z"),
+ currentEventUrl: "https://example.com/civic-tech-coworking",
+ currentLocationAddress: "915 I Street, Sacramento, CA 95814",
+ currentLocationName: "Atrium 916",
+ currentMode: "hybrid",
+ currentRecurrenceCount: 12,
+ currentRecurrenceEndDate: null,
+ currentRecurrenceEndType: "after_occurrences",
+ currentRecurrenceFrequency: "week",
+ currentRecurrenceInterval: 1,
+ currentRecurrenceMonthlyPattern: null,
+ currentRecurrenceWeekdays: [3],
+ currentStartsAt: new Date("2026-10-22T01:00:00.000Z"),
+ currentTitle: "Civic Tech Coworking",
+ description:
+ "A weekly coworking and project clinic for anyone improving public services with technology.",
+ endsAt: new Date("2026-10-22T03:30:00.000Z"),
+ eventId: "cf679f00-5bb3-4d59-b782-1825b4ac78e4",
+ eventUrl: "https://example.com/civic-tech-project-clinic",
+ hasCurrentOccurrenceOverride: false,
+ id: "08d3130a-2097-42a1-9319-a53cd149c625",
+ locationAddress: "915 I Street, Sacramento, CA 95814",
+ locationName: "Atrium 916",
+ mode: "hybrid",
+ occurrenceDate: null,
+ proposerEmail: "priya.shah@example.com",
+ proposerName: "Priya Shah",
+ recurrenceCount: null,
+ recurrenceEndDate: "2027-01-27",
+ recurrenceEndType: "on_date",
+ recurrenceFrequency: "week",
+ recurrenceInterval: 1,
+ recurrenceMonthlyPattern: null,
+ recurrenceWeekdays: [3],
+ scope: "series",
+ seriesEndsAt: new Date("2026-10-22T03:00:00.000Z"),
+ seriesStartsAt: new Date("2026-10-22T01:00:00.000Z"),
+ startsAt: new Date("2026-10-22T01:30:00.000Z"),
+ timezone: "America/Los_Angeles",
+ title: "Civic Tech Project Clinic",
+ },
+] satisfies PendingEventEdits;
+
+export const STORY_MANAGED_USERS = {
+ administrator: {
+ banned: false,
+ email: "samira.patel@example.com",
+ id: "storybook-administrator",
+ name: "Samira Patel",
+ roles: ["admin", "approver", "submitter"],
+ },
+ approver: {
+ banned: false,
+ email: "devon.brooks@example.com",
+ id: "storybook-approver",
+ name: "Devon Brooks",
+ roles: ["approver", "submitter"],
+ },
+ bannedSubmitter: {
+ banned: true,
+ email: "taylor.morgan@example.com",
+ id: "storybook-banned-submitter",
+ name: "Taylor Morgan",
+ roles: ["submitter"],
+ },
+ submitter: {
+ banned: false,
+ email: "alex.rivera@example.com",
+ id: "storybook-submitter",
+ name: "Alex Rivera",
+ roles: ["submitter"],
+ },
+} as const satisfies Record;
+
+const listedUserTimestamps = {
+ createdAt: new Date("2026-01-15T18:00:00.000Z"),
+ updatedAt: new Date("2026-08-20T18:00:00.000Z"),
+};
+
+export const CURRENT_ADMIN_LISTED_USER = {
+ ...listedUserTimestamps,
+ banExpires: null,
+ banReason: null,
+ banned: false,
+ email: "current.admin@example.com",
+ emailVerified: true,
+ id: "storybook-current-admin",
+ image: null,
+ name: "Current Admin",
+ role: "admin",
+};
+
+export const OTHER_LISTED_USERS = Object.values(STORY_MANAGED_USERS).map(
+ (user) => ({
+ ...listedUserTimestamps,
+ banExpires: null,
+ banReason: user.banned ? "Banned by a SacTech administrator." : null,
+ banned: user.banned,
+ email: user.email,
+ emailVerified: true,
+ id: user.id,
+ image: null,
+ name: user.name,
+ role: user.roles.join(","),
+ }),
+);
diff --git a/stories/fixtures/auth.ts b/stories/fixtures/auth.ts
new file mode 100644
index 0000000..aa5bd88
--- /dev/null
+++ b/stories/fixtures/auth.ts
@@ -0,0 +1,46 @@
+import type { AuthSession } from "@/lib/auth";
+
+interface SessionOptions {
+ banned?: boolean;
+ email?: string;
+ id?: string;
+ name?: string;
+ role?: string;
+}
+
+export function createSession({
+ banned = false,
+ email = "alex@example.com",
+ id = "storybook-user",
+ name = "Alex Rivera",
+ role = "submitter",
+}: SessionOptions = {}): AuthSession {
+ const createdAt = new Date("2026-01-15T18:00:00.000Z");
+ const updatedAt = new Date("2026-08-20T18:00:00.000Z");
+
+ return {
+ session: {
+ createdAt,
+ expiresAt: new Date("2027-01-15T18:00:00.000Z"),
+ id: "storybook-session",
+ ipAddress: "127.0.0.1",
+ token: "storybook-session-token",
+ updatedAt,
+ userAgent: "Storybook",
+ userId: id,
+ },
+ user: {
+ banExpires: null,
+ banReason: null,
+ banned,
+ createdAt,
+ email,
+ emailVerified: true,
+ id,
+ image: null,
+ name,
+ role,
+ updatedAt,
+ },
+ } as AuthSession;
+}
diff --git a/stories/fixtures/events.ts b/stories/fixtures/events.ts
new file mode 100644
index 0000000..23c5487
--- /dev/null
+++ b/stories/fixtures/events.ts
@@ -0,0 +1,148 @@
+import type { Event, EventBlock, RecurrenceRule } from "@/app/events/types";
+import { SACRAMENTO_TIME_ZONE } from "@/lib/events/constants";
+
+export const EVENT_STORY_REFERENCE_DATE = "2026-09-01";
+
+export function createEventBlock(
+ overrides: Partial = {},
+): EventBlock {
+ return {
+ description: "A welcoming Sacramento technology gathering.",
+ ends_at: new Date("2026-09-05T21:00:00.000Z"),
+ in_person: true,
+ is_online: false,
+ location_address: "123 J Street, Sacramento, CA",
+ location_description: "The Urban Hive",
+ location_url: "https://events.example.com/details",
+ presenters: [],
+ slug: "event-occurrence",
+ starts_at: new Date("2026-09-05T19:00:00.000Z"),
+ timezone: SACRAMENTO_TIME_ZONE,
+ title: "Event occurrence",
+ ...overrides,
+ };
+}
+
+export function createWeeklyRecurrenceRule(
+ overrides: Partial = {},
+): RecurrenceRule {
+ return {
+ endDate: null,
+ endType: "after_occurrences",
+ excludedDates: ["2026-09-09"],
+ frequency: "week",
+ interval: 1,
+ monthlyPattern: null,
+ occurrenceCount: 8,
+ weekdays: [3],
+ ...overrides,
+ };
+}
+
+export function createRecurringEvent(overrides: Partial = {}): Event {
+ const description =
+ overrides.description ??
+ "Practice TypeScript with welcoming Sacramento developers.";
+ const title = overrides.title ?? "Sacramento TypeScript Weekly";
+ const blocks = overrides.blocks ?? [
+ createEventBlock({
+ description,
+ ends_at: new Date("2026-09-02T18:00:00.000Z"),
+ in_person: false,
+ is_online: true,
+ location_address: undefined,
+ location_description: "Online",
+ slug: "typescript-weekly-seed",
+ starts_at: new Date("2026-09-02T17:00:00.000Z"),
+ title,
+ }),
+ ];
+
+ return {
+ description,
+ has_event_page: true,
+ in_person: false,
+ is_online: true,
+ is_recurring: true,
+ location_address: undefined,
+ location_description: "Online",
+ location_url: "https://events.example.com/typescript-weekly",
+ organizers: [],
+ recurrence_rule: createWeeklyRecurrenceRule(),
+ slug: "sacramento-typescript-weekly",
+ title,
+ ...overrides,
+ blocks,
+ };
+}
+
+export function createRecurringEventWithOverride(
+ overrides: Partial = {},
+): Event {
+ const event = createRecurringEvent();
+
+ return createRecurringEvent({
+ ...event,
+ blocks: [
+ ...event.blocks,
+ createEventBlock({
+ description: "Bring a laptop for a special hands-on TypeScript night.",
+ ends_at: new Date("2026-09-16T03:00:00.000Z"),
+ in_person: true,
+ is_online: false,
+ location_address: "123 J Street, Sacramento, CA",
+ location_description: "The Urban Hive",
+ location_url: "https://events.example.com/hands-on-night",
+ recurrence_date: "2026-09-16",
+ slug: "typescript-weekly-2026-09-16-override",
+ starts_at: new Date("2026-09-16T01:30:00.000Z"),
+ title: "TypeScript Hands-on Night",
+ }),
+ ],
+ recurrence_rule: createWeeklyRecurrenceRule({
+ excludedDates: ["2026-09-09", "2026-09-16"],
+ }),
+ ...overrides,
+ });
+}
+
+export function createSpecialEvent(overrides: Partial = {}): Event {
+ const description =
+ overrides.description ?? "A one-day design community event.";
+ const title = overrides.title ?? "Sacramento Design Summit";
+ const blocks = overrides.blocks ?? [
+ createEventBlock({
+ description,
+ location_description: "The Urban Hive",
+ location_url: "https://events.example.com/design-summit",
+ slug: "design-summit-occurrence",
+ title,
+ }),
+ ];
+
+ return {
+ description,
+ has_event_page: true,
+ in_person: true,
+ is_online: false,
+ is_recurring: false,
+ location_address: "123 J Street, Sacramento, CA",
+ location_description: "The Urban Hive",
+ location_url: "https://events.example.com/design-summit",
+ organizers: [],
+ recurrence_rule: null,
+ slug: "sacramento-design-summit",
+ title,
+ ...overrides,
+ blocks,
+ };
+}
+
+export function createLongEventDescription(finalSentence: string) {
+ return `${"Sacramento community members share practical ideas and make room for generous conversation. ".repeat(5)}${finalSentence}`;
+}
+
+export const MIXED_EVENTS: Event[] = [
+ createRecurringEventWithOverride(),
+ createSpecialEvent(),
+];
diff --git a/stories/fixtures/managed-event.ts b/stories/fixtures/managed-event.ts
new file mode 100644
index 0000000..91ba4f0
--- /dev/null
+++ b/stories/fixtures/managed-event.ts
@@ -0,0 +1,45 @@
+import type { getManagedEventForEdit } from "@/lib/events/queries";
+
+export type ManagedEventFixture = NonNullable<
+ Awaited>
+>;
+
+export function createManagedEvent(
+ overrides: Partial = {},
+): ManagedEventFixture {
+ return {
+ canceledAt: null,
+ canceledOccurrences: ["2026-11-05"],
+ changeRequests: [],
+ collaborators: [
+ {
+ email: "jamie@example.com",
+ name: "Jamie Chen",
+ userId: "collaborator-jamie",
+ },
+ ],
+ description:
+ "A weekly meetup for Sacramento developers to learn together and share work in progress.",
+ endsAt: new Date("2026-10-15T03:30:00.000Z"),
+ eventUrl: "https://example.com/sacramento-typescript",
+ id: "storybook-managed-event",
+ isOwner: true,
+ locationAddress: "828 I Street, Sacramento, CA 95814",
+ locationName: "Sacramento Central Library",
+ mode: "hybrid",
+ occurrenceOverride: null,
+ recurrenceCount: null,
+ recurrenceEndDate: "2027-02-25",
+ recurrenceEndType: "on_date",
+ recurrenceFrequency: "week",
+ recurrenceInterval: 1,
+ recurrenceMonthlyPattern: null,
+ recurrenceWeekdays: [4],
+ startsAt: new Date("2026-10-15T01:30:00.000Z"),
+ status: "approved",
+ submittedBy: "storybook-user",
+ timezone: "America/Los_Angeles",
+ title: "Sacramento TypeScript Weekly",
+ ...overrides,
+ };
+}
diff --git a/stories/fixtures/submissions.ts b/stories/fixtures/submissions.ts
new file mode 100644
index 0000000..2d2fb0b
--- /dev/null
+++ b/stories/fixtures/submissions.ts
@@ -0,0 +1,100 @@
+import type { getSubmissionsForUser } from "@/lib/events/queries";
+
+export type SubmissionFixture = Awaited<
+ ReturnType
+>[number];
+
+export function createSubmission(
+ overrides: Partial = {},
+): SubmissionFixture {
+ return {
+ canceledAt: null,
+ canceledOccurrences: [],
+ changeRequests: [],
+ collaborators: [],
+ createdAt: new Date("2026-08-20T18:00:00.000Z"),
+ endsAt: new Date("2026-10-15T03:30:00.000Z"),
+ id: "storybook-submission",
+ isOwner: true,
+ moderationNote: null,
+ occurrenceOverrides: [],
+ recurrenceCount: null,
+ recurrenceEndDate: "2027-02-25",
+ recurrenceEndType: "on_date",
+ recurrenceFrequency: "week",
+ recurrenceInterval: 1,
+ recurrenceMonthlyPattern: null,
+ recurrenceWeekdays: [4],
+ startsAt: new Date("2026-10-15T01:30:00.000Z"),
+ status: "approved",
+ submittedBy: "storybook-user",
+ title: "Sacramento TypeScript Weekly",
+ ...overrides,
+ };
+}
+
+export const mixedSubmissions: SubmissionFixture[] = [
+ createSubmission({
+ canceledOccurrences: ["2026-11-05", "2026-12-24"],
+ changeRequests: [
+ {
+ createdAt: new Date("2026-08-30T18:00:00.000Z"),
+ eventId: "storybook-submission",
+ id: "pending-change",
+ moderationNote: null,
+ occurrenceDate: null,
+ scope: "series",
+ status: "pending",
+ },
+ ],
+ }),
+ createSubmission({
+ changeRequests: [
+ {
+ createdAt: new Date("2026-08-29T18:00:00.000Z"),
+ eventId: "shared-demo-night",
+ id: "rejected-change",
+ moderationNote: "Please add the venue's accessibility details.",
+ occurrenceDate: null,
+ scope: "series",
+ status: "rejected",
+ },
+ ],
+ endsAt: new Date("2026-10-22T03:00:00.000Z"),
+ id: "shared-demo-night",
+ isOwner: false,
+ recurrenceEndDate: null,
+ recurrenceEndType: null,
+ recurrenceFrequency: null,
+ recurrenceInterval: null,
+ recurrenceWeekdays: null,
+ startsAt: new Date("2026-10-22T01:00:00.000Z"),
+ submittedBy: "another-user",
+ title: "Sacramento Community Demo Night",
+ }),
+ createSubmission({
+ endsAt: new Date("2026-10-29T03:00:00.000Z"),
+ id: "pending-design-meetup",
+ moderationNote: null,
+ recurrenceEndDate: null,
+ recurrenceEndType: null,
+ recurrenceFrequency: null,
+ recurrenceInterval: null,
+ recurrenceWeekdays: null,
+ startsAt: new Date("2026-10-29T01:00:00.000Z"),
+ status: "pending",
+ title: "Design Systems Meetup",
+ }),
+ createSubmission({
+ canceledAt: new Date("2026-08-28T18:00:00.000Z"),
+ endsAt: new Date("2026-09-18T03:00:00.000Z"),
+ id: "canceled-workshop",
+ recurrenceEndDate: null,
+ recurrenceEndType: null,
+ recurrenceFrequency: null,
+ recurrenceInterval: null,
+ recurrenceWeekdays: null,
+ startsAt: new Date("2026-09-18T01:00:00.000Z"),
+ title: "Canceled Accessibility Workshop",
+ }),
+];
diff --git a/stories/story-coverage.test.ts b/stories/story-coverage.test.ts
new file mode 100644
index 0000000..5cbf3cd
--- /dev/null
+++ b/stories/story-coverage.test.ts
@@ -0,0 +1,42 @@
+import { existsSync, globSync } from "node:fs";
+import { resolve } from "node:path";
+import { fileURLToPath } from "node:url";
+import { describe, expect, it } from "vitest";
+
+const projectRoot = fileURLToPath(new URL("../", import.meta.url));
+const sourcePatterns = ["app/**/*.tsx", "components/**/*.tsx"];
+const excludedSourcePatterns = [
+ "**/*.test.tsx",
+ "**/*.integration.test.tsx",
+ "**/*.stories.tsx",
+ "app/layout.tsx",
+ "app/**/opengraph-image.tsx",
+ "app/**/twitter-image.tsx",
+ "app/**/icon.tsx",
+ "app/**/apple-icon.tsx",
+];
+
+function expectedStoryPath(sourcePath: string) {
+ return `stories/${sourcePath.replace(/\.tsx$/, ".stories.tsx")}`;
+}
+
+describe("Storybook story coverage", () => {
+ it("has a mirrored story for every page and component", () => {
+ const sourcePaths = sourcePatterns
+ .flatMap((pattern) =>
+ globSync(pattern, {
+ cwd: projectRoot,
+ exclude: excludedSourcePatterns,
+ }),
+ )
+ .sort();
+ const missingStoryPaths = sourcePaths
+ .map(expectedStoryPath)
+ .filter((storyPath) => !existsSync(resolve(projectRoot, storyPath)));
+
+ expect(
+ missingStoryPaths,
+ `Missing mirrored Storybook stories:\n${missingStoryPaths.join("\n")}`,
+ ).toEqual([]);
+ });
+});
diff --git a/tsconfig.json b/tsconfig.json
index 63b95cf..8bafa52 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -3,6 +3,7 @@
"target": "ES2017",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
+ "allowImportingTsExtensions": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
From aed5efc659e981eb189d014dea7b18ba2593356c Mon Sep 17 00:00:00 2001
From: Corbin Crutchley
Date: Tue, 1 Sep 2026 16:50:03 -0700
Subject: [PATCH 4/6] chore: load all pages now
---
app/admin/users/__mocks__/actions.ts | 6 +++
lib/__mocks__/auth-client.ts | 15 +++++++
lib/__mocks__/auth-config.ts | 8 ++++
lib/__mocks__/email-delivery.ts | 4 ++
lib/__mocks__/session.ts | 42 +++++++++++++++++++
lib/events/__mocks__/actions.ts | 10 +++++
lib/events/__mocks__/queries.ts | 7 ++++
.../admin/events/moderation-form.stories.tsx | 15 +++----
8 files changed, 100 insertions(+), 7 deletions(-)
create mode 100644 app/admin/users/__mocks__/actions.ts
create mode 100644 lib/__mocks__/auth-client.ts
create mode 100644 lib/__mocks__/auth-config.ts
create mode 100644 lib/__mocks__/email-delivery.ts
create mode 100644 lib/__mocks__/session.ts
create mode 100644 lib/events/__mocks__/actions.ts
create mode 100644 lib/events/__mocks__/queries.ts
diff --git a/app/admin/users/__mocks__/actions.ts b/app/admin/users/__mocks__/actions.ts
new file mode 100644
index 0000000..5a45e8f
--- /dev/null
+++ b/app/admin/users/__mocks__/actions.ts
@@ -0,0 +1,6 @@
+import { fn } from "storybook/test";
+
+const idleResult = () => ({ message: "", status: "idle" as const });
+
+export const updateUserBan = fn(async () => idleResult());
+export const updateUserRoles = fn(async () => idleResult());
diff --git a/lib/__mocks__/auth-client.ts b/lib/__mocks__/auth-client.ts
new file mode 100644
index 0000000..0f042e3
--- /dev/null
+++ b/lib/__mocks__/auth-client.ts
@@ -0,0 +1,15 @@
+import { fn } from "storybook/test";
+
+const successfulResult = () => ({ data: null, error: null });
+
+export const authClient = {
+ requestPasswordReset: fn(async () => successfulResult()),
+ resetPassword: fn(async () => successfulResult()),
+ signIn: {
+ email: fn(async () => successfulResult()),
+ },
+ signOut: fn(async () => successfulResult()),
+ signUp: {
+ email: fn(async () => successfulResult()),
+ },
+};
diff --git a/lib/__mocks__/auth-config.ts b/lib/__mocks__/auth-config.ts
new file mode 100644
index 0000000..4e06576
--- /dev/null
+++ b/lib/__mocks__/auth-config.ts
@@ -0,0 +1,8 @@
+import { fn } from "storybook/test";
+
+export const auth = {
+ api: {
+ getSession: fn(async () => null),
+ listUsers: fn(async () => ({ total: 0, users: [] })),
+ },
+};
diff --git a/lib/__mocks__/email-delivery.ts b/lib/__mocks__/email-delivery.ts
new file mode 100644
index 0000000..9f86124
--- /dev/null
+++ b/lib/__mocks__/email-delivery.ts
@@ -0,0 +1,4 @@
+import { fn } from "storybook/test";
+
+export const isEmailDeliveryEnabled = fn(() => true);
+export const isLocalDevelopmentEnvironment = fn(() => false);
diff --git a/lib/__mocks__/session.ts b/lib/__mocks__/session.ts
new file mode 100644
index 0000000..fd7d1fe
--- /dev/null
+++ b/lib/__mocks__/session.ts
@@ -0,0 +1,42 @@
+import { fn } from "storybook/test";
+
+interface SessionLike {
+ user: {
+ role?: string | null;
+ };
+}
+
+function rolesFor(session: SessionLike | null) {
+ return new Set(
+ session?.user.role
+ ?.split(",")
+ .map((role) => role.trim())
+ .filter(Boolean) ?? ["submitter"],
+ );
+}
+
+export const getCurrentSession = fn(async () => null);
+export const requireSession = fn(async () => null);
+export const requireAdminSession = fn(async () => null);
+export const requireEventReviewerSession = fn(async () => null);
+
+export const sessionIsAdmin = fn((session: SessionLike | null) =>
+ rolesFor(session).has("admin"),
+);
+
+export const sessionCanSubmitEvents = fn(
+ (session: SessionLike | null) => session !== null,
+);
+
+export const sessionCanCancelOwnEvents = fn(
+ (session: SessionLike | null) => session !== null,
+);
+
+export const sessionCanReviewEvents = fn((session: SessionLike | null) => {
+ const roles = rolesFor(session);
+ return roles.has("admin") || roles.has("approver");
+});
+
+export const sessionCanManageUsers = fn((session: SessionLike | null) =>
+ rolesFor(session).has("admin"),
+);
diff --git a/lib/events/__mocks__/actions.ts b/lib/events/__mocks__/actions.ts
new file mode 100644
index 0000000..b43934e
--- /dev/null
+++ b/lib/events/__mocks__/actions.ts
@@ -0,0 +1,10 @@
+import { fn } from "storybook/test";
+
+const idleResult = () => ({ message: "", status: "idle" as const });
+
+export const cancelEvent = fn(async () => idleResult());
+export const inviteEventCollaborator = fn(async () => idleResult());
+export const moderateEvent = fn(async () => idleResult());
+export const moderateEventEdit = fn(async () => idleResult());
+export const requestEventEdit = fn(async () => idleResult());
+export const submitEvent = fn(async () => idleResult());
diff --git a/lib/events/__mocks__/queries.ts b/lib/events/__mocks__/queries.ts
new file mode 100644
index 0000000..798008c
--- /dev/null
+++ b/lib/events/__mocks__/queries.ts
@@ -0,0 +1,7 @@
+import { fn } from "storybook/test";
+
+export const getApprovedEvents = fn(async () => []);
+export const getManagedEventForEdit = fn(async () => null);
+export const getPendingEventEdits = fn(async () => []);
+export const getPendingEvents = fn(async () => []);
+export const getSubmissionsForUser = fn(async () => []);
diff --git a/stories/app/admin/events/moderation-form.stories.tsx b/stories/app/admin/events/moderation-form.stories.tsx
index f039f9f..a8f678f 100644
--- a/stories/app/admin/events/moderation-form.stories.tsx
+++ b/stories/app/admin/events/moderation-form.stories.tsx
@@ -29,7 +29,11 @@ function mockIdleActions() {
}
export const IdleEvent = meta.story({
- args: {},
+ args: {
+ eventId: "9ae8c027-41d6-4890-a431-1d8208b22e40",
+ eventTitle: "Sacramento Community Demo Night",
+ reviewType: "event",
+ },
beforeEach: mockIdleActions,
play: async ({ canvas }) => {
await expect(
@@ -60,8 +64,7 @@ export const IdleChangeRequest = meta.story({
},
});
-export const PendingDecision = meta.story({
- args: {},
+export const PendingDecision = IdleEvent.extend({
beforeEach: () => {
mockIdleActions();
mocked(moderateEvent).mockImplementation(() => new Promise(() => {}));
@@ -80,8 +83,7 @@ export const PendingDecision = meta.story({
},
});
-export const RejectionError = meta.story({
- args: {},
+export const RejectionError = IdleEvent.extend({
beforeEach: () => {
mockIdleActions();
mocked(moderateEvent).mockResolvedValue({
@@ -105,8 +107,7 @@ export const RejectionError = meta.story({
},
});
-export const Approved = meta.story({
- args: {},
+export const Approved = IdleEvent.extend({
beforeEach: () => {
mockIdleActions();
mocked(moderateEvent).mockResolvedValue({
From d26e9cb14bc4db96d2fb1c0476b713fbd2416baf Mon Sep 17 00:00:00 2001
From: Corbin Crutchley
Date: Tue, 1 Sep 2026 16:54:42 -0700
Subject: [PATCH 5/6] chore: various fixes
---
stories/app/admin/events/page.stories.tsx | 8 ++++++--
stories/app/events/[eventId]/edit/page.stories.tsx | 4 +++-
stories/fixtures/managed-event.ts | 2 +-
3 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/stories/app/admin/events/page.stories.tsx b/stories/app/admin/events/page.stories.tsx
index 3ca1228..a1d1715 100644
--- a/stories/app/admin/events/page.stories.tsx
+++ b/stories/app/admin/events/page.stories.tsx
@@ -81,7 +81,11 @@ export const PopulatedQueues = meta.story({
await expect(
canvas.getByRole("heading", { name: "Civic Tech Project Clinic" }),
).toBeVisible();
- await expect(canvas.getByText("2 events waiting")).toBeVisible();
- await expect(canvas.getByText("1 change waiting")).toBeVisible();
+ await expect(canvas.getByText("events waiting")).toHaveTextContent(
+ "2 events waiting",
+ );
+ await expect(canvas.getByText("change waiting")).toHaveTextContent(
+ "1 change waiting",
+ );
},
});
diff --git a/stories/app/events/[eventId]/edit/page.stories.tsx b/stories/app/events/[eventId]/edit/page.stories.tsx
index 5759c07..feb0c6b 100644
--- a/stories/app/events/[eventId]/edit/page.stories.tsx
+++ b/stories/app/events/[eventId]/edit/page.stories.tsx
@@ -7,7 +7,9 @@ import { createManagedEvent } from "@/stories/fixtures/managed-event";
import { mocked } from "storybook/test";
const seriesArgs = {
- params: Promise.resolve({ eventId: "storybook-managed-event" }),
+ params: Promise.resolve({
+ eventId: "00000000-0000-4000-8000-000000000001",
+ }),
searchParams: Promise.resolve({ scope: "series" }),
};
diff --git a/stories/fixtures/managed-event.ts b/stories/fixtures/managed-event.ts
index 91ba4f0..6d08ec2 100644
--- a/stories/fixtures/managed-event.ts
+++ b/stories/fixtures/managed-event.ts
@@ -22,7 +22,7 @@ export function createManagedEvent(
"A weekly meetup for Sacramento developers to learn together and share work in progress.",
endsAt: new Date("2026-10-15T03:30:00.000Z"),
eventUrl: "https://example.com/sacramento-typescript",
- id: "storybook-managed-event",
+ id: "00000000-0000-4000-8000-000000000001",
isOwner: true,
locationAddress: "828 I Street, Sacramento, CA 95814",
locationName: "Sacramento Central Library",
From ccdd94b78f6c5cd5615dd7991ab5626fe66cef51 Mon Sep 17 00:00:00 2001
From: Corbin Crutchley
Date: Tue, 1 Sep 2026 16:58:28 -0700
Subject: [PATCH 6/6] chore: upgrade Vitest
---
package.json | 6 +-
pnpm-lock.yaml | 173 +++++++++++++++++++++++++------------------------
2 files changed, 92 insertions(+), 87 deletions(-)
diff --git a/package.json b/package.json
index 681846c..ba0b058 100644
--- a/package.json
+++ b/package.json
@@ -63,8 +63,8 @@
"@types/react": "^19.1.8",
"@types/react-dom": "^19.1.6",
"@vitejs/plugin-react": "^6.0.5",
- "@vitest/browser": "5.0.0-beta.7",
- "@vitest/browser-playwright": "5.0.0-beta.7",
+ "@vitest/browser": "5.0.0-rc.4",
+ "@vitest/browser-playwright": "5.0.0-rc.4",
"auth": "^1.7.1",
"drizzle-kit": "1.0.0-rc.4",
"eslint": "^9.31.0",
@@ -75,7 +75,7 @@
"prettier": "3.9.6",
"typescript": "^6.0.3",
"vite": "^8.2.1",
- "vitest": "5.0.0-beta.7",
+ "vitest": "5.0.0-rc.4",
"storybook": "^10.5.10",
"@storybook/nextjs-vite": "^10.5.10",
"@storybook/addon-mcp": "^0.7.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 2b286a2..860a40f 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -46,7 +46,7 @@ importers:
version: 2.1.0(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
better-auth:
specifier: 1.7.1
- version: 1.7.1(@opentelemetry/api@1.9.1)(drizzle-kit@1.0.0-rc.4)(drizzle-orm@1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(valibot@1.2.0(typescript@6.0.3))(zod@4.4.3))(next@16.3.1(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(pg@8.23.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@5.0.0-beta.7)
+ version: 1.7.1(@opentelemetry/api@1.9.1)(drizzle-kit@1.0.0-rc.4)(drizzle-orm@1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(valibot@1.2.0(typescript@6.0.3))(zod@4.4.3))(next@16.3.1(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(pg@8.23.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@5.0.0-rc.4)
dayjs:
specifier: ^1.11.23
version: 1.11.23
@@ -92,7 +92,7 @@ importers:
version: 6.9.2(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
'@storybook/addon-mcp':
specifier: ^0.7.0
- version: 0.7.0(@storybook/addon-vitest@10.5.10(@vitest/browser-playwright@5.0.0-beta.7)(@vitest/browser@5.0.0-beta.7(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-beta.7))(react@19.2.8)(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(vitest@5.0.0-beta.7))(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(typescript@6.0.3)
+ version: 0.7.0(@storybook/addon-vitest@10.5.10(@vitest/browser-playwright@5.0.0-rc.4)(@vitest/browser@5.0.0-rc.4(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-rc.4))(react@19.2.8)(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(vitest@5.0.0-rc.4))(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(typescript@6.0.3)
'@storybook/nextjs-vite':
specifier: ^10.5.10
version: 10.5.10(@babel/core@7.29.7(supports-color@10.2.2))(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(esbuild@0.28.1)(next@16.3.1(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(supports-color@10.2.2)(typescript@6.0.3)(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
@@ -101,7 +101,7 @@ importers:
version: 10.4.1
'@testing-library/jest-dom':
specifier: ^7.0.1
- version: 7.0.1(@testing-library/dom@10.4.1)(vitest@5.0.0-beta.7)
+ version: 7.0.1(@testing-library/dom@10.4.1)(vitest@5.0.0-rc.4)
'@testing-library/react':
specifier: ^16.3.2
version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)
@@ -118,14 +118,14 @@ importers:
specifier: ^6.0.5
version: 6.0.5(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
'@vitest/browser':
- specifier: 5.0.0-beta.7
- version: 5.0.0-beta.7(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-beta.7)
+ specifier: 5.0.0-rc.4
+ version: 5.0.0-rc.4(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-rc.4)
'@vitest/browser-playwright':
- specifier: 5.0.0-beta.7
- version: 5.0.0-beta.7(playwright@1.62.1)(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-beta.7)
+ specifier: 5.0.0-rc.4
+ version: 5.0.0-rc.4(playwright@1.62.1)(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-rc.4)
auth:
specifier: ^1.7.1
- version: 1.7.1(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(chokidar@5.0.0)(drizzle-kit@1.0.0-rc.4)(drizzle-orm@1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(valibot@1.2.0(typescript@6.0.3))(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.1)(next@16.3.1(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(pg@8.23.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(supports-color@10.2.2)(vitest@5.0.0-beta.7)
+ version: 1.7.1(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(chokidar@5.0.0)(drizzle-kit@1.0.0-rc.4)(drizzle-orm@1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(valibot@1.2.0(typescript@6.0.3))(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.1)(next@16.3.1(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(pg@8.23.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(supports-color@10.2.2)(vitest@5.0.0-rc.4)
drizzle-kit:
specifier: 1.0.0-rc.4
version: 1.0.0-rc.4
@@ -160,8 +160,8 @@ importers:
specifier: ^8.2.1
version: 8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)
vitest:
- specifier: 5.0.0-beta.7
- version: 5.0.0-beta.7(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(@vitest/browser-playwright@5.0.0-beta.7)(@vitest/ui@5.0.0-beta.7)(jsdom@30.0.1(@noble/hashes@2.3.0))(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
+ specifier: 5.0.0-rc.4
+ version: 5.0.0-rc.4(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(@vitest/browser-playwright@5.0.0-rc.4)(@vitest/ui@5.0.0-rc.4)(jsdom@30.0.1(@noble/hashes@2.3.0))(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
packages:
@@ -430,8 +430,8 @@ packages:
'@better-fetch/fetch@1.3.1':
resolution: {integrity: sha512-ABkD1WhyfPZprKRQI3bhATjeiFuNWC9PXhfGWqL+sg/gKrM977oFrYkdb4msM3hgUGonr7KlOsOFT5TU2rht9g==}
- '@blazediff/core@1.9.1':
- resolution: {integrity: sha512-ehg3jIkYKulZh+8om/O25vkvSsXXwC+skXmyA87FFx6A/45eqOkZsBltMw/TVteb0mloiGT8oGRTcjRAz66zaA==}
+ '@blazediff/core@1.10.0':
+ resolution: {integrity: sha512-AOQff0zgR7cGsZL+4E7hVkmujoPUpm0J9xzWGWZj5wCjd3gmxESXAPfKyuzs93VdpQNFhHlBhfOjrcZ+XTERtQ==}
'@bramus/specificity@2.4.2':
resolution: {integrity: sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==}
@@ -3034,22 +3034,22 @@ packages:
babel-plugin-react-compiler:
optional: true
- '@vitest/browser-playwright@5.0.0-beta.7':
- resolution: {integrity: sha512-5YcoQ2FNxk3X37UILQxMjiq7PGziK8IqXSgps9+uj6dLbpCCn6vLKlrkjHJfL4v8W0+uwHrO8RnNjegHT0b72w==}
+ '@vitest/browser-playwright@5.0.0-rc.4':
+ resolution: {integrity: sha512-rU3GJlZiShdl3NOtjhi8mDw+bhZ0/vabFmJBnDDB0VxMRx0IQ8FJsRIJIFol22018C9zbU7/OK/W0EEThKxsyQ==}
peerDependencies:
playwright: '*'
- vitest: 5.0.0-beta.7
+ vitest: 5.0.0-rc.4
- '@vitest/browser@5.0.0-beta.7':
- resolution: {integrity: sha512-zcO1dsyO5lyX+MhXkyOV+9UjCaUsFnq3LBy7XYLlfWnYQKrlxfNmbgRmgL9KhCRe5fpR3AM05jDlDEbbtaOGdQ==}
+ '@vitest/browser@5.0.0-rc.4':
+ resolution: {integrity: sha512-zXTk9lxJcbZcUN8eSrsD9JObNMxds+FEnANBk9hy8Fi3h3J051ubySjZtvjR0cghASYzN/m62k/WTwID1VLjqA==}
peerDependencies:
- vitest: 5.0.0-beta.7
+ vitest: 5.0.0-rc.4
'@vitest/expect@3.2.4':
resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==}
- '@vitest/mocker@5.0.0-beta.7':
- resolution: {integrity: sha512-SczTGMNh6ksM5r8ogUwAf8zVbQPgbc6yvdZO9xBsTKT2rLUwpHn95Upod0s0Cpm3/bH898iqRBLXovRZSUbJBg==}
+ '@vitest/mocker@5.0.0-rc.4':
+ resolution: {integrity: sha512-8DLV37U8yxj9p7bXuRq5e60FvU9znAv4wrb2dP0+ElP53mZjAu5ZtwRCbqEVAoLcs7zSTHHXuNUQAuS+RWblCQ==}
peerDependencies:
msw: ^2.4.9
vite: ^6.0.0 || ^7.0.0 || ^8.0.0
@@ -3062,25 +3062,25 @@ packages:
'@vitest/pretty-format@3.2.4':
resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==}
- '@vitest/pretty-format@5.0.0-beta.7':
- resolution: {integrity: sha512-mYUiYNj9BcF4BawuqncdUlR+zNNbWOWBNsp57jJon2Gq5R2fMqTYQJWHpfvkNqkAAgt/lC6bH5+JISjLIhHa4w==}
+ '@vitest/pretty-format@5.0.0-rc.4':
+ resolution: {integrity: sha512-knCZ2O6bxmCc8ihMqKh82cKmP4Gunbotl3I9wwgSgBFsBV4aB8JkOvslHv4NEBVnTsBvkxikQKLPkm24XU7+sg==}
'@vitest/spy@3.2.4':
resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==}
- '@vitest/spy@5.0.0-beta.7':
- resolution: {integrity: sha512-NiE4frPDnDjFaMvaZaj4ASyxc/c2fvSQU8Fpo7D0YNj9AetE4hcA7ewRxhlrg6dHEOt1JhhCgy67e8SCXDh5VQ==}
+ '@vitest/spy@5.0.0-rc.4':
+ resolution: {integrity: sha512-Fti74i6fwpyXyAKOCfxA1KwGtIIEQlsHkaQj/jgO4GkeQDaXoACuqp2UdUn3B40L8C5L6nqk/rAI8n9js4u2VQ==}
- '@vitest/ui@5.0.0-beta.7':
- resolution: {integrity: sha512-z2PKZrRvT2W6S7s09cS9xqQf6CzURL0YbGCiaOvksIDQ8w/IS07g/0YujWY5c4CgavEaUmxctaDr/ru++U7aoA==}
+ '@vitest/ui@5.0.0-rc.4':
+ resolution: {integrity: sha512-KM1yR6pTo4ynRdR8fPKzTRTySClP9PQsOxdJoenB0gvAohchGWDwfvvhvrw5px7H7yp0RoycG24XLks05RmsTA==}
peerDependencies:
- vitest: 5.0.0-beta.7
+ vitest: 5.0.0-rc.4
'@vitest/utils@3.2.4':
resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==}
- '@vitest/utils@5.0.0-beta.7':
- resolution: {integrity: sha512-DFjgVac0frIqGUZnQCd8lTGYfWnPJfzUNhOubZuvUMgzb+v0mdJjeMEcpmesujZIPasFOR+SzsQ4dS/BCEWGvg==}
+ '@vitest/utils@5.0.0-rc.4':
+ resolution: {integrity: sha512-69WxjuWTGTmtFFciMPPey/gilKM7sDR40Kj0rn5A+if3k0hzT8EjQs02/4MDp8lJMx2r0vovBIKzGsIfN1YJmw==}
'@vue/compiler-core@3.5.41':
resolution: {integrity: sha512-q0Xtv/F9w2YO/7htQhtiL+Ev2WCJbe5N2hc+XfgyKkEKqWpSxknmT8QOuGdEKNdjPq0c3F7rNpFkTo3Kfrm7pg==}
@@ -5778,8 +5778,8 @@ packages:
magic-string@0.30.21:
resolution: {integrity: sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==}
- magic-string@1.2.1:
- resolution: {integrity: sha512-vCfXkt3lIJha02CjPT1igeysyHVfCsEpIeD20O+X9aJ2hML3/kKx8E9Iv1FB+aMSAlDOEAtpRWzuooQCrYwdUg==}
+ magic-string@1.2.3:
+ resolution: {integrity: sha512-Bpb0W2TbLKOZ7vJnOUnVRGq3WL2p+ISV29M6hYPL1AFCpyKZpdr5ytiXoTSSxRVhg8YW7f65+6gbG8WG6PCa/g==}
make-error@1.3.6:
resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==}
@@ -6534,6 +6534,10 @@ packages:
resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==}
engines: {node: '>=12'}
+ picomatch@4.0.7:
+ resolution: {integrity: sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==}
+ engines: {node: '>=12'}
+
picoquery@2.5.0:
resolution: {integrity: sha512-j1kgOFxtaCyoFCkpoYG2Oj3OdGakadO7HZ7o5CqyRazlmBekKhbDoUnNnXASE07xSY4nDImWZkrZv7toSxMi/g==}
@@ -7402,8 +7406,8 @@ packages:
tiny-invariant@1.3.3:
resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==}
- tinybench@6.1.3:
- resolution: {integrity: sha512-8k25iNSZHnzkjp3nrpEmx6YkrTNs41PzOHYc28DR5Z2l/CId/Nzw+Ume/41jCeDDmCUMPuK5GkQ/VxJaJ2P6Qg==}
+ tinybench@6.1.4:
+ resolution: {integrity: sha512-9APumHG7r4yOk4X4WlkmE71aZcv1gvin1czO3OQ1U9iJcFA5Ja/ygyb0vPOVHTthFozUYs8CLoLUlM8grb2lTQ==}
engines: {node: '>=20.0.0'}
tinyclip@0.1.15:
@@ -7861,20 +7865,20 @@ packages:
yaml:
optional: true
- vitest@5.0.0-beta.7:
- resolution: {integrity: sha512-YT/AWBSxJW/GHyNVQzVA7lIj39oRcEPEj1AYMi1Oko7l5GwCh8MO0ufavjVZI0oEYXcAoNmthegJhzGA2pkU2A==}
+ vitest@5.0.0-rc.4:
+ resolution: {integrity: sha512-Yd2zKNMlZ0k1iy4ar3DorcOJ+fLJmbMoawONMQwhIVRWnbbAURVWhQDk1s1eTp0Am7ZdZhk4nwu2m0IBRl5Dtw==}
engines: {node: ^22.12.0 || ^24.0.0 || >=26.0.0}
hasBin: true
peerDependencies:
'@edge-runtime/vm': '*'
'@opentelemetry/api': ^1.9.0
'@types/node': ^22.0.0 || >=24.0.0
- '@vitest/browser-playwright': 5.0.0-beta.7
- '@vitest/browser-preview': 5.0.0-beta.7
+ '@vitest/browser-playwright': 5.0.0-rc.4
+ '@vitest/browser-preview': 5.0.0-rc.4
'@vitest/browser-webdriverio': ^5.0.0-beta.5 || >=5.0.0
- '@vitest/coverage-istanbul': 5.0.0-beta.7
- '@vitest/coverage-v8': 5.0.0-beta.7
- '@vitest/ui': 5.0.0-beta.7
+ '@vitest/coverage-istanbul': 5.0.0-rc.4
+ '@vitest/coverage-v8': 5.0.0-rc.4
+ '@vitest/ui': 5.0.0-rc.4
happy-dom: '*'
jsdom: '*'
vite: ^6.4.0 || ^7.0.0 || ^8.0.0
@@ -8515,7 +8519,7 @@ snapshots:
'@better-fetch/fetch@1.3.1': {}
- '@blazediff/core@1.9.1': {}
+ '@blazediff/core@1.10.0': {}
'@bramus/specificity@2.4.2':
dependencies:
@@ -10542,7 +10546,7 @@ snapshots:
'@standard-schema/spec@1.1.0': {}
- '@storybook/addon-mcp@0.7.0(@storybook/addon-vitest@10.5.10(@vitest/browser-playwright@5.0.0-beta.7)(@vitest/browser@5.0.0-beta.7(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-beta.7))(react@19.2.8)(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(vitest@5.0.0-beta.7))(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(typescript@6.0.3)':
+ '@storybook/addon-mcp@0.7.0(@storybook/addon-vitest@10.5.10(@vitest/browser-playwright@5.0.0-rc.4)(@vitest/browser@5.0.0-rc.4(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-rc.4))(react@19.2.8)(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(vitest@5.0.0-rc.4))(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(typescript@6.0.3)':
dependencies:
'@storybook/mcp': 0.8.0(typescript@6.0.3)
'@tmcp/adapter-valibot': 0.1.6(tmcp@1.20.0(typescript@6.0.3))(valibot@1.2.0(typescript@6.0.3))
@@ -10552,20 +10556,20 @@ snapshots:
tmcp: 1.20.0(typescript@6.0.3)
valibot: 1.2.0(typescript@6.0.3)
optionalDependencies:
- '@storybook/addon-vitest': 10.5.10(@vitest/browser-playwright@5.0.0-beta.7)(@vitest/browser@5.0.0-beta.7(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-beta.7))(react@19.2.8)(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(vitest@5.0.0-beta.7)
+ '@storybook/addon-vitest': 10.5.10(@vitest/browser-playwright@5.0.0-rc.4)(@vitest/browser@5.0.0-rc.4(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-rc.4))(react@19.2.8)(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(vitest@5.0.0-rc.4)
transitivePeerDependencies:
- '@tmcp/auth'
- typescript
- '@storybook/addon-vitest@10.5.10(@vitest/browser-playwright@5.0.0-beta.7)(@vitest/browser@5.0.0-beta.7(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-beta.7))(react@19.2.8)(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(vitest@5.0.0-beta.7)':
+ '@storybook/addon-vitest@10.5.10(@vitest/browser-playwright@5.0.0-rc.4)(@vitest/browser@5.0.0-rc.4(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-rc.4))(react@19.2.8)(storybook@10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8))(vitest@5.0.0-rc.4)':
dependencies:
'@storybook/global': 5.0.0
'@storybook/icons': 2.1.0(react@19.2.8)
storybook: 10.5.10(@types/react@19.2.18)(prettier@3.9.6)(react@19.2.8)
optionalDependencies:
- '@vitest/browser': 5.0.0-beta.7(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-beta.7)
- '@vitest/browser-playwright': 5.0.0-beta.7(playwright@1.62.1)(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-beta.7)
- vitest: 5.0.0-beta.7(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(@vitest/browser-playwright@5.0.0-beta.7)(@vitest/ui@5.0.0-beta.7)(jsdom@30.0.1(@noble/hashes@2.3.0))(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
+ '@vitest/browser': 5.0.0-rc.4(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-rc.4)
+ '@vitest/browser-playwright': 5.0.0-rc.4(playwright@1.62.1)(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-rc.4)
+ vitest: 5.0.0-rc.4(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(@vitest/browser-playwright@5.0.0-rc.4)(@vitest/ui@5.0.0-rc.4)(jsdom@30.0.1(@noble/hashes@2.3.0))(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
transitivePeerDependencies:
- react
optional: true
@@ -10711,7 +10715,7 @@ snapshots:
picocolors: 1.1.1
redent: 3.0.0
- '@testing-library/jest-dom@7.0.1(@testing-library/dom@10.4.1)(vitest@5.0.0-beta.7)':
+ '@testing-library/jest-dom@7.0.1(@testing-library/dom@10.4.1)(vitest@5.0.0-rc.4)':
dependencies:
'@adobe/css-tools': 4.5.0
'@testing-library/dom': 10.4.1
@@ -10721,7 +10725,7 @@ snapshots:
picocolors: 1.1.1
redent: 3.0.0
optionalDependencies:
- vitest: 5.0.0-beta.7(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(@vitest/browser-playwright@5.0.0-beta.7)(@vitest/ui@5.0.0-beta.7)(jsdom@30.0.1(@noble/hashes@2.3.0))(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
+ vitest: 5.0.0-rc.4(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(@vitest/browser-playwright@5.0.0-rc.4)(@vitest/ui@5.0.0-rc.4)(jsdom@30.0.1(@noble/hashes@2.3.0))(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
'@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.4(@types/react@19.2.18))(@types/react@19.2.18)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)':
dependencies:
@@ -11085,30 +11089,30 @@ snapshots:
'@rolldown/pluginutils': 1.0.1
vite: 8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)
- '@vitest/browser-playwright@5.0.0-beta.7(playwright@1.62.1)(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-beta.7)':
+ '@vitest/browser-playwright@5.0.0-rc.4(playwright@1.62.1)(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-rc.4)':
dependencies:
- '@vitest/browser': 5.0.0-beta.7(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-beta.7)
- '@vitest/mocker': 5.0.0-beta.7(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
+ '@vitest/browser': 5.0.0-rc.4(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-rc.4)
+ '@vitest/mocker': 5.0.0-rc.4(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
playwright: 1.62.1
tinyrainbow: 3.1.1
- vitest: 5.0.0-beta.7(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(@vitest/browser-playwright@5.0.0-beta.7)(@vitest/ui@5.0.0-beta.7)(jsdom@30.0.1(@noble/hashes@2.3.0))(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
+ vitest: 5.0.0-rc.4(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(@vitest/browser-playwright@5.0.0-rc.4)(@vitest/ui@5.0.0-rc.4)(jsdom@30.0.1(@noble/hashes@2.3.0))(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
transitivePeerDependencies:
- bufferutil
- msw
- utf-8-validate
- vite
- '@vitest/browser@5.0.0-beta.7(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-beta.7)':
+ '@vitest/browser@5.0.0-rc.4(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-rc.4)':
dependencies:
- '@blazediff/core': 1.9.1
- '@vitest/mocker': 5.0.0-beta.7(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
- '@vitest/ui': 5.0.0-beta.7(vitest@5.0.0-beta.7)
- '@vitest/utils': 5.0.0-beta.7
- magic-string: 1.2.1
+ '@blazediff/core': 1.10.0
+ '@vitest/mocker': 5.0.0-rc.4(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
+ '@vitest/ui': 5.0.0-rc.4(vitest@5.0.0-rc.4)
+ '@vitest/utils': 5.0.0-rc.4
+ magic-string: 1.2.3
pngjs: 7.0.0
sirv: 3.0.2
tinyrainbow: 3.1.1
- vitest: 5.0.0-beta.7(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(@vitest/browser-playwright@5.0.0-beta.7)(@vitest/ui@5.0.0-beta.7)(jsdom@30.0.1(@noble/hashes@2.3.0))(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
+ vitest: 5.0.0-rc.4(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(@vitest/browser-playwright@5.0.0-rc.4)(@vitest/ui@5.0.0-rc.4)(jsdom@30.0.1(@noble/hashes@2.3.0))(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
ws: 8.21.3
transitivePeerDependencies:
- bufferutil
@@ -11124,12 +11128,12 @@ snapshots:
chai: 5.3.3
tinyrainbow: 2.0.0
- '@vitest/mocker@5.0.0-beta.7(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))':
+ '@vitest/mocker@5.0.0-rc.4(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))':
dependencies:
'@jridgewell/trace-mapping': 0.3.31
- '@vitest/spy': 5.0.0-beta.7
+ '@vitest/spy': 5.0.0-rc.4
estree-walker: 3.0.3
- magic-string: 1.2.1
+ magic-string: 1.2.3
optionalDependencies:
vite: 8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)
@@ -11137,7 +11141,7 @@ snapshots:
dependencies:
tinyrainbow: 2.0.0
- '@vitest/pretty-format@5.0.0-beta.7':
+ '@vitest/pretty-format@5.0.0-rc.4':
dependencies:
tinyrainbow: 3.1.1
@@ -11145,18 +11149,17 @@ snapshots:
dependencies:
tinyspy: 4.0.4
- '@vitest/spy@5.0.0-beta.7': {}
+ '@vitest/spy@5.0.0-rc.4': {}
- '@vitest/ui@5.0.0-beta.7(vitest@5.0.0-beta.7)':
+ '@vitest/ui@5.0.0-rc.4(vitest@5.0.0-rc.4)':
dependencies:
- '@vitest/utils': 5.0.0-beta.7
+ '@vitest/utils': 5.0.0-rc.4
fflate: 0.8.3
flatted: 3.4.4
pathe: 2.0.3
sirv: 3.0.2
- tinyglobby: 0.2.17
tinyrainbow: 3.1.1
- vitest: 5.0.0-beta.7(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(@vitest/browser-playwright@5.0.0-beta.7)(@vitest/ui@5.0.0-beta.7)(jsdom@30.0.1(@noble/hashes@2.3.0))(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
+ vitest: 5.0.0-rc.4(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(@vitest/browser-playwright@5.0.0-rc.4)(@vitest/ui@5.0.0-rc.4)(jsdom@30.0.1(@noble/hashes@2.3.0))(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
'@vitest/utils@3.2.4':
dependencies:
@@ -11164,9 +11167,9 @@ snapshots:
loupe: 3.2.1
tinyrainbow: 2.0.0
- '@vitest/utils@5.0.0-beta.7':
+ '@vitest/utils@5.0.0-rc.4':
dependencies:
- '@vitest/pretty-format': 5.0.0-beta.7
+ '@vitest/pretty-format': 5.0.0-rc.4
convert-source-map: 2.0.0
tinyrainbow: 3.1.1
@@ -11448,7 +11451,7 @@ snapshots:
stubborn-fs: 2.0.0
when-exit: 2.1.5
- auth@1.7.1(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(chokidar@5.0.0)(drizzle-kit@1.0.0-rc.4)(drizzle-orm@1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(valibot@1.2.0(typescript@6.0.3))(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.1)(next@16.3.1(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(pg@8.23.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(supports-color@10.2.2)(vitest@5.0.0-beta.7):
+ auth@1.7.1(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(chokidar@5.0.0)(drizzle-kit@1.0.0-rc.4)(drizzle-orm@1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(valibot@1.2.0(typescript@6.0.3))(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.1)(next@16.3.1(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(pg@8.23.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(supports-color@10.2.2)(vitest@5.0.0-rc.4):
dependencies:
'@babel/core': 7.29.7(supports-color@10.2.2)
'@babel/preset-react': 7.29.7(@babel/core@7.29.7(supports-color@10.2.2))(supports-color@10.2.2)
@@ -11458,7 +11461,7 @@ snapshots:
'@better-auth/utils': 0.4.2
'@clack/prompts': 1.7.0
'@mrleebo/prisma-ast': 0.16.0
- better-auth: 1.7.1(@opentelemetry/api@1.9.1)(drizzle-kit@1.0.0-rc.4)(drizzle-orm@1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(valibot@1.2.0(typescript@6.0.3))(zod@4.4.3))(next@16.3.1(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(pg@8.23.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@5.0.0-beta.7)
+ better-auth: 1.7.1(@opentelemetry/api@1.9.1)(drizzle-kit@1.0.0-rc.4)(drizzle-orm@1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(valibot@1.2.0(typescript@6.0.3))(zod@4.4.3))(next@16.3.1(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(pg@8.23.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@5.0.0-rc.4)
c12: 4.0.0-beta.5(chokidar@5.0.0)(dotenv@17.4.2)(jiti@2.7.0)
chalk: 5.6.2
commander: 15.0.0
@@ -11574,7 +11577,7 @@ snapshots:
jsonpointer: 5.0.1
leven: 3.1.0
- better-auth@1.7.1(@opentelemetry/api@1.9.1)(drizzle-kit@1.0.0-rc.4)(drizzle-orm@1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(valibot@1.2.0(typescript@6.0.3))(zod@4.4.3))(next@16.3.1(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(pg@8.23.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@5.0.0-beta.7):
+ better-auth@1.7.1(@opentelemetry/api@1.9.1)(drizzle-kit@1.0.0-rc.4)(drizzle-orm@1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(valibot@1.2.0(typescript@6.0.3))(zod@4.4.3))(next@16.3.1(@babel/core@7.29.7(supports-color@10.2.2))(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(react-dom@19.2.8(react@19.2.8))(react@19.2.8))(pg@8.23.0)(react-dom@19.2.8(react@19.2.8))(react@19.2.8)(vitest@5.0.0-rc.4):
dependencies:
'@better-auth/core': 1.7.1(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.1)
'@better-auth/drizzle-adapter': 1.7.1(@better-auth/core@1.7.1(@better-auth/utils@0.4.2)(@better-fetch/fetch@1.3.1)(@opentelemetry/api@1.9.1)(better-call@1.4.0(zod@4.4.3))(jose@6.2.9)(kysely@0.29.5)(nanostores@1.5.1))(@better-auth/utils@0.4.2)(drizzle-orm@1.0.0-rc.4(patch_hash=4106b3249c29efa09d6c2fcc4052e345c0aee75433c3047fd3aeec99fa0c0867)(@neondatabase/serverless@1.1.0)(@opentelemetry/api@1.9.1)(pg@8.23.0)(valibot@1.2.0(typescript@6.0.3))(zod@4.4.3))
@@ -11600,7 +11603,7 @@ snapshots:
pg: 8.23.0
react: 19.2.8
react-dom: 19.2.8(react@19.2.8)
- vitest: 5.0.0-beta.7(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(@vitest/browser-playwright@5.0.0-beta.7)(@vitest/ui@5.0.0-beta.7)(jsdom@30.0.1(@noble/hashes@2.3.0))(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
+ vitest: 5.0.0-rc.4(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(@vitest/browser-playwright@5.0.0-rc.4)(@vitest/ui@5.0.0-rc.4)(jsdom@30.0.1(@noble/hashes@2.3.0))(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
transitivePeerDependencies:
- '@cloudflare/workers-types'
- '@opentelemetry/api'
@@ -14018,7 +14021,7 @@ snapshots:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
- magic-string@1.2.1:
+ magic-string@1.2.3:
dependencies:
'@jridgewell/sourcemap-codec': 1.5.5
@@ -15130,6 +15133,8 @@ snapshots:
picomatch@4.0.5: {}
+ picomatch@4.0.7: {}
+
picoquery@2.5.0: {}
picospinner@3.1.2: {}
@@ -16254,7 +16259,7 @@ snapshots:
tiny-invariant@1.3.3: {}
- tinybench@6.1.3: {}
+ tinybench@6.1.4: {}
tinyclip@0.1.15: {}
@@ -16672,18 +16677,18 @@ snapshots:
jiti: 2.7.0
yaml: 2.9.0
- vitest@5.0.0-beta.7(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(@vitest/browser-playwright@5.0.0-beta.7)(@vitest/ui@5.0.0-beta.7)(jsdom@30.0.1(@noble/hashes@2.3.0))(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)):
+ vitest@5.0.0-rc.4(@opentelemetry/api@1.9.1)(@types/node@24.13.3)(@vitest/browser-playwright@5.0.0-rc.4)(@vitest/ui@5.0.0-rc.4)(jsdom@30.0.1(@noble/hashes@2.3.0))(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)):
dependencies:
'@types/chai': 5.2.3
- '@vitest/mocker': 5.0.0-beta.7(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
+ '@vitest/mocker': 5.0.0-rc.4(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))
chai: 6.2.2
es-module-lexer: 2.3.2
expect-type: 1.4.0
- magic-string: 1.2.1
+ magic-string: 1.2.3
obug: 2.1.4
- picomatch: 4.0.5
+ picomatch: 4.0.7
std-env: 4.2.0
- tinybench: 6.1.3
+ tinybench: 6.1.4
tinyexec: 1.3.0
tinyglobby: 0.2.17
vite: 8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0)
@@ -16691,8 +16696,8 @@ snapshots:
optionalDependencies:
'@opentelemetry/api': 1.9.1
'@types/node': 24.13.3
- '@vitest/browser-playwright': 5.0.0-beta.7(playwright@1.62.1)(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-beta.7)
- '@vitest/ui': 5.0.0-beta.7(vitest@5.0.0-beta.7)
+ '@vitest/browser-playwright': 5.0.0-rc.4(playwright@1.62.1)(vite@8.2.1(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(yaml@2.9.0))(vitest@5.0.0-rc.4)
+ '@vitest/ui': 5.0.0-rc.4(vitest@5.0.0-rc.4)
jsdom: 30.0.1(@noble/hashes@2.3.0)
transitivePeerDependencies:
- msw