From 5d29e17b47a6c0c1e464574d3efe97bee5fcb422 Mon Sep 17 00:00:00 2001 From: Arata1202 Date: Fri, 28 Aug 2026 22:25:10 +0900 Subject: [PATCH 01/26] feat: add Storybook design system --- .github/workflows/test.yml | 4 + .gitignore | 3 + .storybook/main.ts | 10 + .storybook/preview.tsx | 56 + README.md | 28 +- eslint.config.mjs | 4 + package.json | 23 +- pnpm-lock.yaml | 1409 ++++++++++++++++- .../Common/AppsPromo/index.stories.tsx | 14 + .../Common/ArticleCard/index.stories.tsx | 46 + .../Common/BreadCrumb/index.stories.tsx | 35 + .../Common/CodeBlock/index.stories.tsx | 31 + .../Common/Layouts/Footer/index.stories.tsx | 14 + .../Common/Layouts/Header/index.stories.tsx | 25 + .../Common/Layouts/Sidebar/index.stories.tsx | 49 + .../Layouts/ThemeSwitch/index.stories.tsx | 15 + .../Common/Markdown/index.stories.tsx | 41 + .../Common/Pagination/index.stories.tsx | 22 + src/components/Common/Share/index.stories.tsx | 14 + .../SponsoredDisclosure/index.stories.tsx | 15 + .../Common/TableOfContent/index.stories.tsx | 22 + .../Contact/Elements/Alert/index.stories.tsx | 36 + .../Contact/Elements/Modal/index.stories.tsx | 33 + src/stories/Foundations.stories.tsx | 66 + src/stories/articleFixtures.ts | 50 + vitest.config.mts | 107 +- vitest.shims.d.ts | 1 + 27 files changed, 2114 insertions(+), 59 deletions(-) create mode 100644 .storybook/main.ts create mode 100644 .storybook/preview.tsx create mode 100644 src/components/Common/AppsPromo/index.stories.tsx create mode 100644 src/components/Common/ArticleCard/index.stories.tsx create mode 100644 src/components/Common/BreadCrumb/index.stories.tsx create mode 100644 src/components/Common/CodeBlock/index.stories.tsx create mode 100644 src/components/Common/Layouts/Footer/index.stories.tsx create mode 100644 src/components/Common/Layouts/Header/index.stories.tsx create mode 100644 src/components/Common/Layouts/Sidebar/index.stories.tsx create mode 100644 src/components/Common/Layouts/ThemeSwitch/index.stories.tsx create mode 100644 src/components/Common/Markdown/index.stories.tsx create mode 100644 src/components/Common/Pagination/index.stories.tsx create mode 100644 src/components/Common/Share/index.stories.tsx create mode 100644 src/components/Common/SponsoredDisclosure/index.stories.tsx create mode 100644 src/components/Common/TableOfContent/index.stories.tsx create mode 100644 src/components/Features/Contact/Elements/Alert/index.stories.tsx create mode 100644 src/components/Features/Contact/Elements/Modal/index.stories.tsx create mode 100644 src/stories/Foundations.stories.tsx create mode 100644 src/stories/articleFixtures.ts create mode 100644 vitest.shims.d.ts diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0643533a..0881e214 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -37,8 +37,12 @@ jobs: run: pnpm typecheck - name: Test run: pnpm test:run + - name: Build Storybook + run: pnpm build-storybook - name: Install Playwright browsers run: pnpm exec playwright install --with-deps chromium + - name: Test Storybook + run: pnpm test:storybook - name: E2E run: pnpm test:e2e go: diff --git a/.gitignore b/.gitignore index 813fda0c..5f1d1731 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,6 @@ next-env.d.ts # air /tmp + +/debug-storybook.log +/storybook-static/ diff --git a/.storybook/main.ts b/.storybook/main.ts new file mode 100644 index 00000000..e85b30e9 --- /dev/null +++ b/.storybook/main.ts @@ -0,0 +1,10 @@ +import type { StorybookConfig } from '@storybook/nextjs-vite'; + +const config: StorybookConfig = { + stories: ['../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], + addons: ['@storybook/addon-vitest', '@storybook/addon-a11y', '@storybook/addon-docs'], + framework: '@storybook/nextjs-vite', + staticDirs: ['../public'], +}; + +export default config; diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx new file mode 100644 index 00000000..9d71d734 --- /dev/null +++ b/.storybook/preview.tsx @@ -0,0 +1,56 @@ +import type { Decorator, Preview } from '@storybook/nextjs-vite'; +import { ThemeProvider } from 'next-themes'; +import '@/styles/globals.css'; + +const withTheme: Decorator = (Story, context) => { + const theme = context.globals.theme === 'dark' ? 'dark' : 'light'; + const themeClassName = theme === 'dark' ? 'DarkTheme' : 'LightTheme'; + + document.body.classList.toggle('DarkTheme', theme === 'dark'); + document.body.classList.toggle('LightTheme', theme === 'light'); + + return ( + +
+ +
+
+ ); +}; + +const preview: Preview = { + decorators: [withTheme], + globalTypes: { + theme: { + description: 'Component theme', + defaultValue: 'light', + toolbar: { + icon: 'paintbrush', + items: [ + { value: 'light', title: 'Light' }, + { value: 'dark', title: 'Dark' }, + ], + dynamicTitle: true, + }, + }, + }, + parameters: { + layout: 'fullscreen', + nextjs: { + appDirectory: true, + navigation: { + pathname: '/', + }, + }, + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/i, + }, + }, + + a11y: { test: 'error' }, + }, +}; + +export default preview; diff --git a/README.md b/README.md index 2513fe8d..0a38ca24 100644 --- a/README.md +++ b/README.md @@ -18,6 +18,7 @@ - [アーキテクチャ](#アーキテクチャ) - [環境構築](#環境構築) - [スポンサー記事](#スポンサー記事) + - [Storybook](#storybook) - [Terraform](#terraform) - [テスト](#テスト) - [OneSignalテスト通知](#onesignalテスト通知) @@ -46,7 +47,7 @@ | Infrastructure | Cloudflare Pages, Vercel, Amazon S3, Terraform | | Environment setup | Node.js, pnpm, Docker Compose | | CI/CD | GitHub Actions, CodeQL, Dependabot | -| Design | Canva(Figmaはアーカイブ済み) | +| Design | Storybook, Canva(Figmaはアーカイブ済み) | | Google | AdSense, Analytics, Search Console, reCAPTCHA | | Integrations | PWA, OneSignal, Sentry, Iframely, Instagram | @@ -168,6 +169,25 @@ microCMSの`blog` APIに以下のフィールドを追加する。

(トップへ)

+## Storybook + +共通UIと主要な表示状態はStorybookで確認する。ツールバーからLight/Darkテーマを切り替えられ、AccessibilityパネルとブラウザテストでWCAG違反や操作を検証できる。 + +```bash +# Storybookを起動 +pnpm storybook + +# 静的Storybookを生成 +pnpm build-storybook + +# StoryとアクセシビリティをChromiumで検証 +pnpm test:storybook +``` + +Storyは対象コンポーネントと同じディレクトリの`index.stories.tsx`へ配置する。基礎スタイルと共通fixtureは`src/stories/`で管理する。 + +

(トップへ)

+ ## Terraform ``` @@ -200,6 +220,10 @@ pnpm lint pnpm typecheck pnpm test:run +# Storybookの静的ビルド / ブラウザテスト +pnpm build-storybook +pnpm test:storybook + # Goの静的解析 / テスト(Docker) docker compose run --rm go go vet ./... docker compose run --rm go go test ./... @@ -247,6 +271,7 @@ scripts/send-onesignal-test-notifications.sh --send ```text . ├── .github/workflows/ # CI/CD・運用ワークフロー +├── .storybook/ # Storybook設定 ├── api/ # Vercel Functionsのエントリーポイント ├── cmd/ # ローカルGo APIサーバー ├── docker/ # 開発用Dockerイメージ @@ -258,6 +283,7 @@ scripts/send-onesignal-test-notifications.sh --send ├── src/ │ ├── app/ # Next.js App Router │ ├── components/ # UIコンポーネント +│ ├── stories/ # 基礎スタイル・共通Story fixture │ ├── config/ # 環境変数の参照 │ ├── contents/ # 固定ページのコンテンツ │ ├── hooks/ # React Hooks diff --git a/eslint.config.mjs b/eslint.config.mjs index 78a0eeae..a50855e4 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 eslint from '@eslint/js'; import tseslint from 'typescript-eslint'; import nextPlugin from '@next/eslint-plugin-next'; @@ -75,4 +78,5 @@ export default [ '@typescript-eslint/no-explicit-any': 'off', }, }, + ...storybook.configs['flat/recommended'], ]; diff --git a/package.json b/package.json index 33e44740..c7cc12a8 100644 --- a/package.json +++ b/package.json @@ -15,18 +15,21 @@ "build": "next build", "build:e2e": "node scripts/e2e/build.mjs", "start": "pnpm dlx serve@latest out", - "lint": "eslint src e2e scripts playwright.config.ts vitest.config.mts", - "lint:fix": "eslint src e2e scripts playwright.config.ts vitest.config.mts --fix", + "lint": "eslint src .storybook e2e scripts playwright.config.ts vitest.config.mts", + "lint:fix": "eslint src .storybook e2e scripts playwright.config.ts vitest.config.mts --fix", "typecheck": "tsc --noEmit", - "test": "vitest", - "test:run": "vitest run", - "test:coverage": "vitest run --coverage", + "test": "vitest --project=unit", + "test:run": "vitest run --project=unit", + "test:coverage": "vitest run --coverage --project=unit", "test:e2e": "playwright test", "test:e2e:headed": "playwright test --headed", "test:e2e:ui": "playwright test --ui", "test:e2e:report": "playwright show-report", "prepare": "husky install", - "format": "prettier --write --ignore-path .gitignore './**/*.{js,jsx,ts,tsx,mts,json,css,mjs}'" + "format": "prettier --write --ignore-path .gitignore './**/*.{js,jsx,ts,tsx,mts,json,css,mjs}'", + "storybook": "storybook dev -p 6006", + "build-storybook": "storybook build", + "test:storybook": "vitest run --project=storybook" }, "lint-staged": { "*.{js,jsx,ts,tsx,mjs,mts}": [ @@ -65,6 +68,10 @@ "@eslint/js": "^9.39.4", "@next/eslint-plugin-next": "^16.2.6", "@playwright/test": "^1.60.0", + "@storybook/addon-a11y": "^10.5.10", + "@storybook/addon-docs": "^10.5.10", + "@storybook/addon-vitest": "^10.5.10", + "@storybook/nextjs-vite": "^10.5.10", "@tailwindcss/postcss": "^4.3.0", "@testing-library/jest-dom": "^6.9.1", "@testing-library/react": "^16.3.2", @@ -73,16 +80,20 @@ "@types/react-google-recaptcha": "^2.1.9", "@types/react-slick": "^0.23.13", "@vitejs/plugin-react": "^6.0.2", + "@vitest/browser-playwright": "4.1.7", "@vitest/coverage-v8": "^4.1.7", "eslint": "^9.39.4", "eslint-config-prettier": "^10.1.8", "eslint-plugin-jsx-a11y": "^6.9.0", "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-hooks": "^7.1.1", + "eslint-plugin-storybook": "^10.5.10", "husky": "^9.1.7", "jsdom": "^29.1.1", "lint-staged": "^17.0.6", + "playwright": "^1.62.1", "prettier": "^3.8.3", + "storybook": "^10.5.10", "tailwindcss": "^4.3.0", "typescript": "^6.0.3", "typescript-eslint": "^8.60.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 97071d67..286ae9b7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -89,6 +89,18 @@ importers: '@playwright/test': specifier: ^1.60.0 version: 1.60.0 + '@storybook/addon-a11y': + specifier: ^10.5.10 + version: 10.5.10(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6)) + '@storybook/addon-docs': + specifier: ^10.5.10 + version: 10.5.10(@types/react@19.2.15)(esbuild@0.27.7)(rollup@4.60.4)(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(webpack@5.107.2(esbuild@0.27.7)) + '@storybook/addon-vitest': + specifier: ^10.5.10 + version: 10.5.10(@vitest/browser-playwright@4.1.7)(@vitest/browser@4.1.7)(@vitest/runner@4.1.7)(react@19.2.6)(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(vitest@4.1.7) + '@storybook/nextjs-vite': + specifier: ^10.5.10 + version: 10.5.10(@babel/core@7.29.7)(@types/react@19.2.15)(esbuild@0.27.7)(next@16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(rollup@4.60.4)(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(webpack@5.107.2(esbuild@0.27.7)) '@tailwindcss/postcss': specifier: ^4.3.0 version: 4.3.0 @@ -113,9 +125,12 @@ importers: '@vitejs/plugin-react': specifier: ^6.0.2 version: 6.0.2(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0)) + '@vitest/browser-playwright': + specifier: 4.1.7 + version: 4.1.7(playwright@1.62.1)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(vitest@4.1.7) '@vitest/coverage-v8': specifier: ^4.1.7 - version: 4.1.7(vitest@4.1.7) + version: 4.1.7(@vitest/browser@4.1.7)(vitest@4.1.7) eslint: specifier: ^9.39.4 version: 9.39.4(jiti@2.7.0) @@ -131,6 +146,9 @@ importers: eslint-plugin-react-hooks: specifier: ^7.1.1 version: 7.1.1(eslint@9.39.4(jiti@2.7.0)) + eslint-plugin-storybook: + specifier: ^10.5.10 + version: 10.5.10(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3) husky: specifier: ^9.1.7 version: 9.1.7 @@ -140,9 +158,15 @@ importers: lint-staged: specifier: ^17.0.6 version: 17.0.6 + playwright: + specifier: ^1.62.1 + version: 1.62.1 prettier: specifier: ^3.8.3 version: 3.8.3 + storybook: + specifier: ^10.5.10 + version: 10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6) tailwindcss: specifier: ^4.3.0 version: 4.3.0 @@ -157,7 +181,7 @@ importers: version: 8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0) vitest: specifier: ^4.1.7 - version: 4.1.7(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(@vitest/coverage-v8@4.1.7)(jsdom@29.1.1)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0)) + version: 4.1.7(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(@vitest/browser-playwright@4.1.7)(@vitest/coverage-v8@4.1.7)(jsdom@29.1.1)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0)) packages: @@ -258,6 +282,9 @@ packages: resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} engines: {node: '>=18'} + '@blazediff/core@1.9.1': + resolution: {integrity: sha512-ehg3jIkYKulZh+8om/O25vkvSsXXwC+skXmyA87FFx6A/45eqOkZsBltMw/TVteb0mloiGT8oGRTcjRAz66zaA==} + '@bramus/specificity@2.4.2': resolution: {integrity: sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==} hasBin: true @@ -301,12 +328,27 @@ 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.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==} + '@esbuild/aix-ppc64@0.27.7': resolution: {integrity: sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==} engines: {node: '>=18'} @@ -709,6 +751,15 @@ packages: '@internationalized/string@3.2.9': resolution: {integrity: sha512-kzP/M/mbQxODlmOt4bIQZ2SBVUWUSqMLXooXixnX7noche8WHaQcA+nwFN1K2KCF/cp+LDUhcJsCicwkvhD1pg==} + '@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==} @@ -731,15 +782,31 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@mdx-js/react@3.1.1': + resolution: {integrity: sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==} + peerDependencies: + '@types/react': '>=16' + react: '>=16' + '@napi-rs/wasm-runtime@1.1.4': resolution: {integrity: sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==} peerDependencies: '@emnapi/core': ^1.7.1 '@emnapi/runtime': ^1.7.1 + '@napi-rs/wasm-runtime@1.2.3': + resolution: {integrity: sha512-UMduMbqO5s5zF2NkNacMT/yK5Y5QiKvWr2+50bzIIxFDwVJ2h49b+oyjaCGPhJxd2/gC2x39EHv/gHVuu36x2Q==} + engines: {node: ^20.19.0 || ^22.13.0 || >=23.5.0} + peerDependencies: + '@emnapi/core': ^1.7.1 || ^2.0.0-alpha.4 + '@emnapi/runtime': ^1.7.1 || ^2.0.0-alpha.4 + '@next/env@16.2.6': resolution: {integrity: sha512-gd8HoHN4ufj73WmR3JmVolrpJR47ILK6LouP5xElPglaVxir6e1a7VzvTvDWkOoPXT9rkkTzyCxBu4yeZfZwcw==} + '@next/env@16.3.0-preview.5': + resolution: {integrity: sha512-XqdVR0utAWMsVc1OIyO48D32vrdmC4/uAgI3Ds088YlOO4vfGKXXVyvkGFkOZkOK0xg7bNYNfJAarX4A0tYqGg==} + '@next/eslint-plugin-next@16.2.6': resolution: {integrity: sha512-Z8l6o4JWKUl755x4R+wogD86KPeU+Ckw4K+SYG4kHeOJtRenDeK+OSbGcqZpDtbwn9DsJVdir2UxmwXuinUbUw==} @@ -845,14 +912,234 @@ packages: resolution: {integrity: sha512-/UhIkaZgPutTFmQ7RnIJGgDXZmtEJ7Dvi86xNTFWcnRxVRNk/aotsqDJYeEvDP+FSMB2SdW+pQzNMcWP0rwuNA==} 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] + + '@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] + + '@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] + + '@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] + + '@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] + + '@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] + + '@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] + + '@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] + + '@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.132.0': resolution: {integrity: sha512-FESMOxil5Se014ui/Eq8fT5uHJo6nIRwH0PfJrZJXs6Gek3ZVFOrpUv3YIZT20m+extU98Hg1Ym72U58rlsxUQ==} + '@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] + + '@oxc-resolver/binding-linux-arm64-musl@11.21.2': + resolution: {integrity: sha512-ViN1ZibQyxwC67GpoP33oo+S9UyUnkog13vzQb9+v9bCNvrVzJuk0MRdacjtv/9xfRMVF/eqHFyl8YOeykI10Q==} + cpu: [arm64] + os: [linux] + + '@oxc-resolver/binding-linux-ppc64-gnu@11.21.2': + resolution: {integrity: sha512-CU1sCqWnhGqYD5I1HedHk5pujrn7ssDkNB/AEQd/pd3D/EojVSgJUlpbafwIbyhia3PgIfkvdFpRPWSALzVumA==} + cpu: [ppc64] + os: [linux] + + '@oxc-resolver/binding-linux-riscv64-gnu@11.21.2': + resolution: {integrity: sha512-jWVyZtIHca4Gb96x7dag+y69vlei7ffjrsveLkmf2ZhqEAz6ZSBnY1GWvgZUaZlwZP62A3xD092BW97Q5VGc+g==} + cpu: [riscv64] + os: [linux] + + '@oxc-resolver/binding-linux-riscv64-musl@11.21.2': + resolution: {integrity: sha512-LF29obFqNgBUgDX7rmUK7M4D0JQG5LxhYzn3xXmECcHU9aQAdWG7NiY052qybtesEdwHQXKNTWYQ7mTsybNvWg==} + cpu: [riscv64] + os: [linux] + + '@oxc-resolver/binding-linux-s390x-gnu@11.21.2': + resolution: {integrity: sha512-+NYcm+cCHBbtdQQ3A4phQTSuVRYnNHz7wrl9XRAPEovcdoqi0mb1K5ZOl+jN54ZD+q1zz3V0vltbFJmzecJKmw==} + cpu: [s390x] + os: [linux] + + '@oxc-resolver/binding-linux-x64-gnu@11.21.2': + resolution: {integrity: sha512-UQqZDdG2r2HhAOsZEgufkIWHPQ886IUyuJQkoZByvzhW8j51R4UNzGBJFkTiTnLhQnggwJRdJgFWK4uY6ZVIMw==} + cpu: [x64] + os: [linux] + + '@oxc-resolver/binding-linux-x64-musl@11.21.2': + resolution: {integrity: sha512-3Q9PMRjalWkT6NZ4jfujuqTCFwoWErg3y3BnOgb544B8IMw4PktiwWOigMfOHNRLMghZeJ7hpfpZf4CP7rV7Og==} + cpu: [x64] + os: [linux] + + '@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] + '@playwright/test@1.60.0': resolution: {integrity: sha512-O71yZIbAh/PxDMNGns37GHBIfrVkEVyn+AXyIa5dOTfb4/xNvRWV+Vv/NMbNCtODB/pO7vLlF2OTmMVLhmr7Ag==} engines: {node: '>=18'} hasBin: true + '@polka/url@1.0.0-next.29': + resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} + '@react-aria/focus@3.22.1': resolution: {integrity: sha512-CPxtkyrBi/HYY5P3lE/57sQ6qfa0lN8E55TOm89H0kNGv0lKt+/0zP7lWERzBjRr5IxBVrQX4gFEowBN52LPaA==} peerDependencies: @@ -1251,6 +1538,132 @@ packages: '@standard-schema/spec@1.1.0': resolution: {integrity: sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==} + '@storybook/addon-a11y@10.5.10': + resolution: {integrity: sha512-RpRQV5xUbrl6hCiNrd5FSMIo6pnRZ0VZxWvEW/ASLcreGkKUW5jl2AeLCe5YROE2i80s/dU+6VPzOYKrwWNFbQ==} + peerDependencies: + storybook: ^10.5.10 + + '@storybook/addon-docs@10.5.10': + resolution: {integrity: sha512-06JoK3/a7FWI/6GzuidJP9iHp1/Vejboe6lzS1jW+d8ItpecriBt+oXh1VNmUM7i7PjI6pZnet+j51QnLyeOoQ==} + peerDependencies: + '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + storybook: ^10.5.10 + peerDependenciesMeta: + '@types/react': + 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/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 + '@swc/helpers@0.5.15': resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} @@ -1386,9 +1799,24 @@ packages: '@tybys/wasm-util@0.10.2': resolution: {integrity: sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==} + '@tybys/wasm-util@0.10.3': + resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} + '@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==} @@ -1401,6 +1829,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==} @@ -1419,6 +1850,9 @@ packages: '@types/mdast@4.0.4': resolution: {integrity: sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==} + '@types/mdx@2.0.14': + resolution: {integrity: sha512-T48PeuJtvLosNTPVhfnIp3i/n3a4g4Bad7YCq5k64D4u7NwDrAotikQ+5+sjtUvBmxCMlbo3dVL+C2dP0rWHzg==} + '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} @@ -1434,6 +1868,9 @@ packages: '@types/react@19.2.15': resolution: {integrity: sha512-eRwcGNHve+E8qtEQSSRl6urh+rFop4v8gm6O8rGv25CodbvFdLjA1vVQ1KkiFE0w0UPOnb8tDiFKL5lp0rtY5Q==} + '@types/resolve@1.20.6': + resolution: {integrity: sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==} + '@types/unist@2.0.11': resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} @@ -1515,6 +1952,17 @@ packages: babel-plugin-react-compiler: optional: true + '@vitest/browser-playwright@4.1.7': + resolution: {integrity: sha512-OlTlJej7YN6VwV7zJJoNeaCsctF+JXpzpZ4oBHUbrQFfIq+0KW2f07rprCLh9N/zRIZ0v4Mchn1QDDmWMUhPKw==} + peerDependencies: + playwright: '*' + vitest: 4.1.7 + + '@vitest/browser@4.1.7': + resolution: {integrity: sha512-N2JFGfXoEGVAut+kHeru9dD4BUMq/q5xDvBARNl0tUsly3m5KglLOu8VO/6MkDfOlgxXTycojkt6gBKsuyR+IQ==} + peerDependencies: + vitest: 4.1.7 + '@vitest/coverage-v8@4.1.7': resolution: {integrity: sha512-qsYPeXc5Q9dFLd1i8Ap+Bx8sQgcp+rFVQo4R0dDsWNBzl26ldVF1qOO+RL24K7FDrR6pA+50XedRLSoSG24bVQ==} peerDependencies: @@ -1524,6 +1972,9 @@ packages: '@vitest/browser': optional: true + '@vitest/expect@3.2.4': + resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==} + '@vitest/expect@4.1.7': resolution: {integrity: sha512-1R+tw0ortHEbZDGMymm+pN7/AFQ/RkFFdtd7EN+VBpynKmLbP8A3rpEXdshBJ7+8hQ9zBJh/i1s0yKNtxAnU7w==} @@ -1538,6 +1989,9 @@ packages: vite: optional: true + '@vitest/pretty-format@3.2.4': + resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==} + '@vitest/pretty-format@4.1.7': resolution: {integrity: sha512-umgCarTOYQWIaDMvGDRZij+6b9oVeLIyJzfN+AS88e0ZOU3QTgNNSTtjQOpcvWr3np1N0j4WgZj+sb3oYBDscw==} @@ -1547,9 +2001,15 @@ packages: '@vitest/snapshot@4.1.7': resolution: {integrity: sha512-ZacLzja+TmJeZ1h14xW2FB/WpeimUD3haBXQPyJqxvo8jQTmfeA8zv58mtjN2C7EHXZDYVcVYdYmAxjkWVvKCw==} + '@vitest/spy@3.2.4': + resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==} + '@vitest/spy@4.1.7': resolution: {integrity: sha512-kbkI5LMWakyuTIvs6fUJ5qdIVb1XVKsYJAT4OJ938cHMROYMSfmoQdZy0aaAnjbbc8F61vkoTqz/Az+/HiIu5Q==} + '@vitest/utils@3.2.4': + resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==} + '@vitest/utils@4.1.7': resolution: {integrity: sha512-T532WBu791cBxJlCl6SO+J14l81DQx6uQHm1bQbmCDY7nqlEIgkza/UFnSBNaUtSf41unldDFjdOBYEQC4b5Hw==} @@ -1598,6 +2058,9 @@ packages: '@webassemblyjs/wast-printer@1.14.1': resolution: {integrity: sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==} + '@webcontainer/env@1.1.1': + resolution: {integrity: sha512-6aN99yL695Hi9SuIk1oC88l9o0gmxL1nGWWQ/kNy81HigJ0FoaoTXpytCj6ItzgyCEwA9kF1wixsTuv5cjsgng==} + '@xtuc/ieee754@1.2.0': resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} @@ -1725,6 +2188,10 @@ packages: ast-types-flow@0.0.8: resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} + ast-types@0.16.1: + resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} + engines: {node: '>=4'} + ast-v8-to-istanbul@1.0.2: resolution: {integrity: sha512-dKmJxJsGItLmc5CYZKuEjuG6GnBs6PG4gohMhyFOWKaNQoYCuRZJDECaBlHmcG0lv2wc2E0uU8lESmBEumC3DQ==} @@ -1787,6 +2254,10 @@ packages: buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + bundle-name@4.1.0: + resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} + engines: {node: '>=18'} + call-bind-apply-helpers@1.0.2: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} @@ -1817,6 +2288,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'} @@ -1837,6 +2312,10 @@ packages: character-reference-invalid@2.0.1: resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==} + check-error@2.1.3: + resolution: {integrity: sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==} + engines: {node: '>= 16'} + cheerio-select@2.1.0: resolution: {integrity: sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==} @@ -1965,13 +2444,29 @@ packages: decode-named-character-reference@1.3.0: resolution: {integrity: sha512-GtpQYB283KrPp6nRw50q3U9/VfOutZOe103qlN7BPP6Ad27xYnOIWv4lPzo8HCAL+mMZofJ9KEy30fq6MfaK6Q==} + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} + deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + default-browser-id@5.0.1: + resolution: {integrity: sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==} + engines: {node: '>=18'} + + default-browser@5.5.1: + resolution: {integrity: sha512-m1pAzaJgZ/gssEqlOhJkPJp8Xly7QyW6xcrkUa2KKcDeDSEMP7X8xipU3snUcfisTQx0w1AGae+9UtJSfVnXGw==} + engines: {node: '>=18'} + define-data-property@1.1.4: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} engines: {node: '>= 0.4'} + define-lazy-prop@3.0.0: + resolution: {integrity: sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==} + engines: {node: '>=12'} + define-properties@1.2.1: resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} engines: {node: '>= 0.4'} @@ -1991,6 +2486,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==} @@ -2027,6 +2526,10 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + empathic@2.0.1: + resolution: {integrity: sha512-YGRs8knHhKHVShLkFET/rWAU8kmHbOV5LwN938RHI0pljAJ1Gf6SzXsSmRaEzcXTtOOmVqJ5+WtQPL5uigY50Q==} + engines: {node: '>=14'} + encoding-sniffer@0.2.1: resolution: {integrity: sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==} @@ -2138,6 +2641,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@5.1.1: resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} engines: {node: '>=8.0.0'} @@ -2172,6 +2680,11 @@ packages: resolution: {integrity: sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + esquery@1.6.0: resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} engines: {node: '>=0.10'} @@ -2337,6 +2850,9 @@ packages: resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} engines: {node: '>= 0.4'} + globrex@0.1.2: + resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} + gopd@1.2.0: resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} engines: {node: '>= 0.4'} @@ -2428,6 +2944,11 @@ packages: resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} engines: {node: '>= 4'} + 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'} @@ -2492,6 +3013,11 @@ packages: is-decimal@2.0.1: resolution: {integrity: sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==} + is-docker@3.0.0: + resolution: {integrity: sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + hasBin: true + is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -2515,6 +3041,11 @@ packages: is-hexadecimal@2.0.1: resolution: {integrity: sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==} + is-inside-container@1.0.0: + resolution: {integrity: sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==} + engines: {node: '>=14.16'} + hasBin: true + is-map@2.0.3: resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} engines: {node: '>= 0.4'} @@ -2577,6 +3108,10 @@ packages: resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} engines: {node: '>= 0.4'} + is-wsl@3.1.1: + resolution: {integrity: sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==} + engines: {node: '>=16'} + isarray@2.0.5: resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} @@ -2654,6 +3189,9 @@ packages: engines: {node: '>=6'} hasBin: true + jsonc-parser@3.3.1: + resolution: {integrity: sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==} + jsonp@0.2.1: resolution: {integrity: sha512-pfog5gdDxPdV4eP7Kg87M8/bHgshlZ5pybl+yKxAnCZ5O7lCIn7Ixydj03wOlnDQesky2BPyA91SQ+5Y/mNwzw==} @@ -2779,6 +3317,9 @@ packages: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true + loupe@3.2.1: + resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} + lru-cache@11.5.1: resolution: {integrity: sha512-RPimw/7aMdv2oqRrxKwvZXcPfwBrn/JZ2xYcY9Hus/6LaS3VOAKVWKWgNLCFSiOm1ESXinjsDlidVU7JlnCN2A==} engines: {node: 20 || >=22} @@ -2988,13 +3529,23 @@ packages: minimatch@3.1.5: resolution: {integrity: sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==} + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + minipass@7.1.3: resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==} engines: {node: '>=16 || 14 >=14.17'} + module-alias@2.3.4: + resolution: {integrity: sha512-bOclZt8hkpuGgSSoG07PKmvzTizROilUTvLNyrMqvlC9snhs7y7GzjNWAVbISIOlhCP1T14rH1PDAV9iNyBq/w==} + module-details-from-path@1.0.4: resolution: {integrity: sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==} + mrmime@2.0.1: + resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} + engines: {node: '>=10'} + ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} @@ -3094,6 +3645,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'} + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -3102,6 +3657,13 @@ packages: resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} 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-limit@3.1.0: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} @@ -3147,6 +3709,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'} + picocolors@1.1.1: resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} @@ -3163,11 +3729,25 @@ packages: engines: {node: '>=18'} hasBin: true + playwright-core@1.62.1: + resolution: {integrity: sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw==} + engines: {node: '>=20'} + hasBin: true + playwright@1.60.0: resolution: {integrity: sha512-hheHdokM8cdqCb0lcE3s+zT4t4W+vvjpGxsZlDnikarzx8tSzMebh3UiFtgqwFwnTnjYQcsyMF8ei2mCO/tpeA==} engines: {node: '>=18'} hasBin: true + playwright@1.62.1: + resolution: {integrity: sha512-0M+L3LAD8/nm554LOla9Ayx0j0tmFZ0FBcoQ7F1VuVHpM/XpiC8RcDzBQB8W5+hA8L22THxELzeF+2WcUzvcLg==} + engines: {node: '>=20'} + hasBin: true + + pngjs@7.0.0: + resolution: {integrity: sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==} + engines: {node: '>=14.19.0'} + possible-typed-array-names@1.1.0: resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} engines: {node: '>= 0.4'} @@ -3220,6 +3800,15 @@ packages: peerDependencies: react: '>=16.4.1' + 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.6: resolution: {integrity: sha512-0prMI+hvBbPjsWnxDLxlCGyM8PN6UuWjEUCYmZhO67xIV9Xasa/r/vDnq+Xyq4Lo27g8QSbO5YzARu0D1Sps3g==} peerDependencies: @@ -3273,6 +3862,10 @@ packages: resolution: {integrity: sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==} engines: {node: '>=0.10.0'} + recast@0.23.21: + resolution: {integrity: sha512-mFAyJq9vUbSTARLZUvAEf1z3YxlvAwswbmxMx2mPA/MSm4KmpwvwvhsH/NIrZhyOuwD60Lzyw2qh83uCbgTPYw==} + engines: {node: '>= 4'} + redent@3.0.0: resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} engines: {node: '>=8'} @@ -3312,6 +3905,11 @@ packages: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} + 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'} @@ -3342,6 +3940,10 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + run-applescript@7.1.0: + resolution: {integrity: sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==} + engines: {node: '>=18'} + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -3435,6 +4037,10 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + sirv@3.0.2: + resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==} + engines: {node: '>=18'} + slice-ansi@7.1.2: resolution: {integrity: sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==} engines: {node: '>=18'} @@ -3476,6 +4082,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 + string-argv@0.3.2: resolution: {integrity: sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==} engines: {node: '>=0.6.19'} @@ -3521,10 +4142,18 @@ packages: resolution: {integrity: sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==} engines: {node: '>=12'} + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + strip-indent@3.0.0: resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} engines: {node: '>=8'} + strip-indent@4.1.1: + resolution: {integrity: sha512-SlyRoSkdh1dYP0PzclLE7r0M9sgbFKKMFXpFRUMNuKhQSbC6VQIGzq3E0qsfvGJaUFJPGv6Ws1NZ/haTAjfbMA==} + engines: {node: '>=12'} + strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} @@ -3624,6 +4253,9 @@ packages: third-party-capital@1.0.20: resolution: {integrity: sha512-oB7yIimd8SuGptespDAZnNkzIz+NWaJCu2RMsbs4Wmp9zSDUM8Nhi3s2OOcqYuv3mN4hitXc8DVx+LyUmbUDiA==} + tiny-invariant@1.3.3: + resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} + tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} @@ -3635,10 +4267,18 @@ packages: resolution: {integrity: sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==} 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.0: resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} 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.2: resolution: {integrity: sha512-nwEyF4vl4RSJjwSjBUmOSxc3BFPoIFdlRthJ6e+5v9P3bHNsoD06UjuqMUspqp7vsEZ1beaHi1km+optiE17yA==} @@ -3650,6 +4290,10 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + totalist@3.0.1: + resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} + engines: {node: '>=6'} + tough-cookie@6.0.1: resolution: {integrity: sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==} engines: {node: '>=16'} @@ -3673,6 +4317,25 @@ packages: peerDependencies: typescript: '>=4.8.4' + ts-dedent@2.3.0: + resolution: {integrity: sha512-JfJeIHke7y2egdGGgRAvpCwYFUsHlM2gPcrVOxFkznt/4uzQ7HFmvE63iFHVLBJNDuyDOQgijDK/tXH/f6Msjg==} + engines: {node: '>=6.10'} + + 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@4.2.0: + resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} + engines: {node: '>=6'} + tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} @@ -3745,6 +4408,10 @@ packages: unist-util-visit@5.1.0: resolution: {integrity: sha512-m+vIdyeCOpdr/QeQCu2EzxX/ohgS8KbnPDgFni4dQsfSCtpz8UqDyY5GjRru8PDKuYn7Fq19j1CQ+nJSsGKOzg==} + unplugin@2.3.11: + resolution: {integrity: sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==} + engines: {node: '>=18.12.0'} + update-browserslist-db@1.2.3: resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} hasBin: true @@ -3765,6 +4432,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.0.14: resolution: {integrity: sha512-s4BJJ+5y1pYL6Otw51FHhVJQhPnuRinKig64g/1+EUNaJsd3gCKdD31IPFvswUgW9/60QT9oFHbZHbQK5imcxw==} engines: {node: ^20.19.0 || >=22.12.0} @@ -3868,6 +4550,9 @@ packages: resolution: {integrity: sha512-HPuy+uuoTCaaoEoI1LQ3JN9+vrPBvEesnnX1jADHy728cHSMlq4wUc4afYqahq2B1mhQVZxCXOkNTnXltr+2vQ==} engines: {node: '>=10.13.0'} + webpack-virtual-modules@0.6.2: + resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + webpack@5.107.2: resolution: {integrity: sha512-v7RhXaJbpMlV0D7hC7lb2EbnxkoeUqf9qhKr6lozx3Q48pmFrqqNRmZFUEGmi7pSwm6fCQ2H1IjvCkHqdpVdjQ==} engines: {node: '>=10.13.0'} @@ -3940,6 +4625,22 @@ packages: resolution: {integrity: sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==} engines: {node: '>=18'} + ws@8.21.3: + resolution: {integrity: sha512-201TZ/kPWxoPr/OKWjquZR1SWKXcvxdH+e1xrx89b3YbmzLMFCLfnaG1HFIgWzJOEWZ7MvpK++odZufgYR50Rw==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + wsl-utils@0.1.0: + resolution: {integrity: sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==} + engines: {node: '>=18'} + xml-js@1.6.11: resolution: {integrity: sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==} hasBin: true @@ -4105,6 +4806,8 @@ snapshots: '@bcoe/v8-coverage@1.0.2': {} + '@blazediff/core@1.9.1': {} + '@bramus/specificity@2.4.2': dependencies: css-tree: 3.2.1 @@ -4139,16 +4842,43 @@ 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.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 + '@esbuild/aix-ppc64@0.27.7': optional: true @@ -4436,6 +5166,14 @@ snapshots: dependencies: '@swc/helpers': 0.5.23 + '@joshwooding/vite-plugin-react-docgen-typescript@0.7.0(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))': + dependencies: + glob: 13.0.6 + react-docgen-typescript: 2.4.0(typescript@6.0.3) + vite: 8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0) + optionalDependencies: + typescript: 6.0.3 + '@jridgewell/gen-mapping@0.3.13': dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -4462,6 +5200,12 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 + '@mdx-js/react@3.1.1(@types/react@19.2.15)(react@19.2.6)': + dependencies: + '@types/mdx': 2.0.14 + '@types/react': 19.2.15 + react: 19.2.6 + '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': dependencies: '@emnapi/core': 1.10.0 @@ -4469,8 +5213,24 @@ snapshots: '@tybys/wasm-util': 0.10.2 optional: true + '@napi-rs/wasm-runtime@1.1.4(@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.2 + 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 + '@next/env@16.2.6': {} + '@next/env@16.3.0-preview.5': {} + '@next/eslint-plugin-next@16.2.6': dependencies: fast-glob: 3.3.1 @@ -4545,19 +5305,148 @@ snapshots: '@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1)': dependencies: - '@opentelemetry/api': 1.9.1 - '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) - '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) - '@opentelemetry/semantic-conventions': 1.41.1 + '@opentelemetry/api': 1.9.1 + '@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1) + '@opentelemetry/semantic-conventions': 1.41.1 + + '@opentelemetry/semantic-conventions@1.41.1': {} + + '@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.1.4(@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.132.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 - '@opentelemetry/semantic-conventions@1.41.1': {} + '@oxc-resolver/binding-win32-arm64-msvc@11.21.2': + optional: true - '@oxc-project/types@0.132.0': {} + '@oxc-resolver/binding-win32-x64-msvc@11.21.2': + optional: true '@playwright/test@1.60.0': dependencies: playwright: 1.60.0 + '@polka/url@1.0.0-next.29': {} + '@react-aria/focus@3.22.1(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': dependencies: '@swc/helpers': 0.5.23 @@ -4892,6 +5781,142 @@ snapshots: '@standard-schema/spec@1.1.0': {} + '@storybook/addon-a11y@10.5.10(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))': + dependencies: + '@storybook/global': 5.0.0 + axe-core: 4.10.2 + storybook: 10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6) + + '@storybook/addon-docs@10.5.10(@types/react@19.2.15)(esbuild@0.27.7)(rollup@4.60.4)(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(webpack@5.107.2(esbuild@0.27.7))': + dependencies: + '@mdx-js/react': 3.1.1(@types/react@19.2.15)(react@19.2.6) + '@storybook/csf-plugin': 10.5.10(esbuild@0.27.7)(rollup@4.60.4)(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(webpack@5.107.2(esbuild@0.27.7)) + '@storybook/icons': 2.1.0(react@19.2.6) + '@storybook/react-dom-shim': 10.5.10(@types/react@19.2.15)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6)) + react: 19.2.6 + react-dom: 19.2.6(react@19.2.6) + storybook: 10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6) + ts-dedent: 2.3.0 + optionalDependencies: + '@types/react': 19.2.15 + transitivePeerDependencies: + - '@types/react-dom' + - esbuild + - rollup + - vite + - webpack + + '@storybook/addon-vitest@10.5.10(@vitest/browser-playwright@4.1.7)(@vitest/browser@4.1.7)(@vitest/runner@4.1.7)(react@19.2.6)(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(vitest@4.1.7)': + dependencies: + '@storybook/global': 5.0.0 + '@storybook/icons': 2.1.0(react@19.2.6) + storybook: 10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6) + optionalDependencies: + '@vitest/browser': 4.1.7(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(vitest@4.1.7) + '@vitest/browser-playwright': 4.1.7(playwright@1.62.1)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(vitest@4.1.7) + '@vitest/runner': 4.1.7 + vitest: 4.1.7(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(@vitest/browser-playwright@4.1.7)(@vitest/coverage-v8@4.1.7)(jsdom@29.1.1)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0)) + transitivePeerDependencies: + - react + + '@storybook/builder-vite@10.5.10(esbuild@0.27.7)(rollup@4.60.4)(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(webpack@5.107.2(esbuild@0.27.7))': + dependencies: + '@storybook/csf-plugin': 10.5.10(esbuild@0.27.7)(rollup@4.60.4)(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(webpack@5.107.2(esbuild@0.27.7)) + storybook: 10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6) + ts-dedent: 2.3.0 + vite: 8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0) + transitivePeerDependencies: + - esbuild + - rollup + - webpack + + '@storybook/csf-plugin@10.5.10(esbuild@0.27.7)(rollup@4.60.4)(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(webpack@5.107.2(esbuild@0.27.7))': + dependencies: + storybook: 10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6) + unplugin: 2.3.11 + optionalDependencies: + esbuild: 0.27.7 + rollup: 4.60.4 + vite: 8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0) + webpack: 5.107.2(esbuild@0.27.7) + + '@storybook/global@5.0.0': {} + + '@storybook/icons@2.1.0(react@19.2.6)': + dependencies: + react: 19.2.6 + + '@storybook/nextjs-vite@10.5.10(@babel/core@7.29.7)(@types/react@19.2.15)(esbuild@0.27.7)(next@16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(rollup@4.60.4)(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(webpack@5.107.2(esbuild@0.27.7))': + dependencies: + '@storybook/builder-vite': 10.5.10(esbuild@0.27.7)(rollup@4.60.4)(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(webpack@5.107.2(esbuild@0.27.7)) + '@storybook/react': 10.5.10(@types/react@19.2.15)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(typescript@6.0.3) + '@storybook/react-vite': 10.5.10(@types/react@19.2.15)(esbuild@0.27.7)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(rollup@4.60.4)(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(webpack@5.107.2(esbuild@0.27.7)) + next: 16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + react: 19.2.6 + react-dom: 19.2.6(react@19.2.6) + storybook: 10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6) + styled-jsx: 5.1.6(@babel/core@7.29.7)(react@19.2.6) + vite: 8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0) + vite-plugin-storybook-nextjs: 3.3.2(next@16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0)) + optionalDependencies: + '@types/react': 19.2.15 + typescript: 6.0.3 + transitivePeerDependencies: + - '@babel/core' + - babel-plugin-macros + - esbuild + - rollup + - supports-color + - webpack + + '@storybook/react-dom-shim@10.5.10(@types/react@19.2.15)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))': + dependencies: + react: 19.2.6 + react-dom: 19.2.6(react@19.2.6) + storybook: 10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6) + optionalDependencies: + '@types/react': 19.2.15 + + '@storybook/react-vite@10.5.10(@types/react@19.2.15)(esbuild@0.27.7)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(rollup@4.60.4)(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(webpack@5.107.2(esbuild@0.27.7))': + dependencies: + '@joshwooding/vite-plugin-react-docgen-typescript': 0.7.0(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0)) + '@rollup/pluginutils': 5.4.0(rollup@4.60.4) + '@storybook/builder-vite': 10.5.10(esbuild@0.27.7)(rollup@4.60.4)(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(webpack@5.107.2(esbuild@0.27.7)) + '@storybook/react': 10.5.10(@types/react@19.2.15)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(typescript@6.0.3) + empathic: 2.0.1 + magic-string: 0.30.21 + react: 19.2.6 + react-docgen: 8.0.3 + react-dom: 19.2.6(react@19.2.6) + resolve: 1.22.12 + storybook: 10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6) + tsconfig-paths: 4.2.0 + vite: 8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0) + optionalDependencies: + typescript: 6.0.3 + transitivePeerDependencies: + - '@types/react' + - '@types/react-dom' + - esbuild + - rollup + - supports-color + - webpack + + '@storybook/react@10.5.10(@types/react@19.2.15)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(typescript@6.0.3)': + dependencies: + '@storybook/global': 5.0.0 + '@storybook/react-dom-shim': 10.5.10(@types/react@19.2.15)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6)) + react: 19.2.6 + react-docgen: 8.0.3 + react-docgen-typescript: 2.4.0(typescript@6.0.3) + react-dom: 19.2.6(react@19.2.6) + storybook: 10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6) + optionalDependencies: + '@types/react': 19.2.15 + typescript: 6.0.3 + transitivePeerDependencies: + - supports-color + '@swc/helpers@0.5.15': dependencies: tslib: 2.8.1 @@ -5015,8 +6040,34 @@ snapshots: tslib: 2.8.1 optional: true + '@tybys/wasm-util@0.10.3': + dependencies: + tslib: 2.8.1 + optional: true + '@types/aria-query@5.0.4': {} + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + '@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.7 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 + + '@types/babel__traverse@7.28.0': + dependencies: + '@babel/types': 7.29.7 + '@types/chai@5.2.3': dependencies: '@types/deep-eql': 4.0.2 @@ -5032,6 +6083,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 @@ -5050,6 +6103,8 @@ snapshots: dependencies: '@types/unist': 3.0.3 + '@types/mdx@2.0.14': {} + '@types/ms@2.1.0': {} '@types/node@25.9.1': @@ -5068,6 +6123,8 @@ snapshots: dependencies: csstype: 3.2.3 + '@types/resolve@1.20.6': {} + '@types/unist@2.0.11': {} '@types/unist@3.0.3': {} @@ -5170,7 +6227,37 @@ snapshots: '@rolldown/pluginutils': 1.0.1 vite: 8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0) - '@vitest/coverage-v8@4.1.7(vitest@4.1.7)': + '@vitest/browser-playwright@4.1.7(playwright@1.62.1)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(vitest@4.1.7)': + dependencies: + '@vitest/browser': 4.1.7(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(vitest@4.1.7) + '@vitest/mocker': 4.1.7(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0)) + playwright: 1.62.1 + tinyrainbow: 3.1.0 + vitest: 4.1.7(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(@vitest/browser-playwright@4.1.7)(@vitest/coverage-v8@4.1.7)(jsdom@29.1.1)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0)) + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + + '@vitest/browser@4.1.7(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(vitest@4.1.7)': + dependencies: + '@blazediff/core': 1.9.1 + '@vitest/mocker': 4.1.7(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0)) + '@vitest/utils': 4.1.7 + magic-string: 0.30.21 + pngjs: 7.0.0 + sirv: 3.0.2 + tinyrainbow: 3.1.0 + vitest: 4.1.7(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(@vitest/browser-playwright@4.1.7)(@vitest/coverage-v8@4.1.7)(jsdom@29.1.1)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0)) + ws: 8.21.3 + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + + '@vitest/coverage-v8@4.1.7(@vitest/browser@4.1.7)(vitest@4.1.7)': dependencies: '@bcoe/v8-coverage': 1.0.2 '@vitest/utils': 4.1.7 @@ -5182,7 +6269,17 @@ snapshots: obug: 2.1.1 std-env: 4.1.0 tinyrainbow: 3.1.0 - vitest: 4.1.7(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(@vitest/coverage-v8@4.1.7)(jsdom@29.1.1)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0)) + vitest: 4.1.7(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(@vitest/browser-playwright@4.1.7)(@vitest/coverage-v8@4.1.7)(jsdom@29.1.1)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0)) + optionalDependencies: + '@vitest/browser': 4.1.7(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(vitest@4.1.7) + + '@vitest/expect@3.2.4': + dependencies: + '@types/chai': 5.2.3 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 + chai: 5.3.3 + tinyrainbow: 2.0.0 '@vitest/expect@4.1.7': dependencies: @@ -5201,6 +6298,10 @@ snapshots: optionalDependencies: vite: 8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0) + '@vitest/pretty-format@3.2.4': + dependencies: + tinyrainbow: 2.0.0 + '@vitest/pretty-format@4.1.7': dependencies: tinyrainbow: 3.1.0 @@ -5217,8 +6318,18 @@ snapshots: magic-string: 0.30.21 pathe: 2.0.3 + '@vitest/spy@3.2.4': + dependencies: + tinyspy: 4.0.4 + '@vitest/spy@4.1.7': {} + '@vitest/utils@3.2.4': + dependencies: + '@vitest/pretty-format': 3.2.4 + loupe: 3.2.1 + tinyrainbow: 2.0.0 + '@vitest/utils@4.1.7': dependencies: '@vitest/pretty-format': 4.1.7 @@ -5301,6 +6412,8 @@ snapshots: '@webassemblyjs/ast': 1.14.1 '@xtuc/long': 4.2.2 + '@webcontainer/env@1.1.1': {} + '@xtuc/ieee754@1.2.0': {} '@xtuc/long@4.2.2': {} @@ -5446,6 +6559,10 @@ snapshots: ast-types-flow@0.0.8: {} + ast-types@0.16.1: + dependencies: + tslib: 2.8.1 + ast-v8-to-istanbul@1.0.2: dependencies: '@jridgewell/trace-mapping': 0.3.31 @@ -5503,6 +6620,10 @@ snapshots: buffer-from@1.1.2: {} + bundle-name@4.1.0: + dependencies: + run-applescript: 7.1.0 + call-bind-apply-helpers@1.0.2: dependencies: es-errors: 1.3.0 @@ -5538,6 +6659,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: @@ -5553,6 +6682,8 @@ snapshots: character-reference-invalid@2.0.1: {} + check-error@2.1.3: {} + cheerio-select@2.1.0: dependencies: boolbase: 1.0.0 @@ -5687,14 +6818,25 @@ snapshots: dependencies: character-entities: 2.0.2 + deep-eql@5.0.2: {} + deep-is@0.1.4: {} + default-browser-id@5.0.1: {} + + default-browser@5.5.1: + dependencies: + bundle-name: 4.1.0 + default-browser-id: 5.0.1 + define-data-property@1.1.4: dependencies: es-define-property: 1.0.1 es-errors: 1.3.0 gopd: 1.2.0 + define-lazy-prop@3.0.0: {} + define-properties@1.2.1: dependencies: define-data-property: 1.1.4 @@ -5713,6 +6855,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: {} @@ -5749,6 +6895,8 @@ snapshots: emoji-regex@9.2.2: {} + empathic@2.0.1: {} + encoding-sniffer@0.2.1: dependencies: iconv-lite: 0.6.3 @@ -5958,7 +7106,6 @@ snapshots: '@esbuild/win32-arm64': 0.27.7 '@esbuild/win32-ia32': 0.27.7 '@esbuild/win32-x64': 0.27.7 - optional: true escalade@3.2.0: {} @@ -6022,6 +7169,15 @@ snapshots: string.prototype.matchall: 4.0.12 string.prototype.repeat: 1.0.0 + eslint-plugin-storybook@10.5.10(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3): + dependencies: + '@typescript-eslint/types': 8.60.0 + '@typescript-eslint/utils': 8.60.0(eslint@9.39.4(jiti@2.7.0))(typescript@6.0.3) + eslint: 9.39.4(jiti@2.7.0) + transitivePeerDependencies: + - supports-color + - typescript + eslint-scope@5.1.1: dependencies: esrecurse: 4.3.0 @@ -6085,6 +7241,8 @@ snapshots: acorn-jsx: 5.3.2(acorn@8.16.0) eslint-visitor-keys: 4.2.1 + esprima@4.0.1: {} + esquery@1.6.0: dependencies: estraverse: 5.3.0 @@ -6239,6 +7397,8 @@ snapshots: define-properties: 1.2.1 gopd: 1.2.0 + globrex@0.1.2: {} + gopd@1.2.0: {} graceful-fs@4.2.11: {} @@ -6339,6 +7499,8 @@ snapshots: ignore@7.0.5: {} + image-size@2.0.2: {} + import-fresh@3.3.1: dependencies: parent-module: 1.0.1 @@ -6412,6 +7574,8 @@ snapshots: is-decimal@2.0.1: {} + is-docker@3.0.0: {} + is-extglob@2.1.1: {} is-finalizationregistry@1.1.1: @@ -6436,6 +7600,10 @@ snapshots: is-hexadecimal@2.0.1: {} + is-inside-container@1.0.0: + dependencies: + is-docker: 3.0.0 + is-map@2.0.3: {} is-negative-zero@2.0.3: {} @@ -6494,6 +7662,10 @@ snapshots: call-bound: 1.0.4 get-intrinsic: 1.3.0 + is-wsl@3.1.1: + dependencies: + is-inside-container: 1.0.0 + isarray@2.0.5: {} isexe@2.0.0: {} @@ -6580,6 +7752,8 @@ snapshots: json5@2.2.3: {} + jsonc-parser@3.3.1: {} + jsonp@0.2.1: dependencies: debug: 2.6.9 @@ -6698,6 +7872,8 @@ snapshots: dependencies: js-tokens: 4.0.0 + loupe@3.2.1: {} + lru-cache@11.5.1: {} lru-cache@5.1.1: @@ -7164,10 +8340,16 @@ snapshots: dependencies: brace-expansion: 1.1.15 + minimist@1.2.8: {} + minipass@7.1.3: {} + module-alias@2.3.4: {} + module-details-from-path@1.0.4: {} + mrmime@2.0.1: {} + ms@2.0.0: {} ms@2.1.3: {} @@ -7268,6 +8450,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 + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -7283,6 +8472,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-limit@3.1.0: dependencies: yocto-queue: 0.1.0 @@ -7335,6 +8571,8 @@ snapshots: pathe@2.0.3: {} + pathval@2.0.1: {} + picocolors@1.1.1: {} picomatch@2.3.2: {} @@ -7343,12 +8581,22 @@ snapshots: playwright-core@1.60.0: {} + playwright-core@1.62.1: {} + playwright@1.60.0: dependencies: playwright-core: 1.60.0 optionalDependencies: fsevents: 2.3.2 + playwright@1.62.1: + dependencies: + playwright-core: 1.62.1 + optionalDependencies: + fsevents: 2.3.2 + + pngjs@7.0.0: {} + possible-typed-array-names@1.1.0: {} postcss@8.5.15: @@ -7403,6 +8651,25 @@ snapshots: prop-types: 15.8.1 react: 19.2.6 + react-docgen-typescript@2.4.0(typescript@6.0.3): + dependencies: + typescript: 6.0.3 + + react-docgen@8.0.3: + dependencies: + '@babel/core': 7.29.7 + '@babel/traverse': 7.29.7 + '@babel/types': 7.29.7 + '@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.6(react@19.2.6): dependencies: react: 19.2.6 @@ -7473,6 +8740,14 @@ snapshots: react@19.2.6: {} + recast@0.23.21: + dependencies: + ast-types: 0.16.1 + 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 @@ -7545,6 +8820,13 @@ snapshots: resolve-from@4.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 @@ -7617,6 +8899,8 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.60.4 fsevents: 2.3.3 + run-applescript@7.1.0: {} + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 @@ -7761,6 +9045,12 @@ snapshots: signal-exit@4.1.0: {} + sirv@3.0.2: + dependencies: + '@polka/url': 1.0.0-next.29 + mrmime: 2.0.1 + totalist: 3.0.1 + slice-ansi@7.1.2: dependencies: ansi-styles: 6.2.3 @@ -7799,6 +9089,33 @@ snapshots: es-errors: 1.3.0 internal-slot: 1.1.0 + storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6): + dependencies: + '@storybook/global': 5.0.0 + '@storybook/icons': 2.1.0(react@19.2.6) + '@testing-library/dom': 10.4.1 + '@testing-library/jest-dom': 6.9.1 + '@testing-library/user-event': 14.6.1(@testing-library/dom@10.4.1) + '@vitest/expect': 3.2.4 + '@vitest/spy': 3.2.4 + '@webcontainer/env': 1.1.1 + esbuild: 0.27.7 + 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.1 + use-sync-external-store: 1.6.0(react@19.2.6) + ws: 8.21.3 + optionalDependencies: + '@types/react': 19.2.15 + prettier: 3.8.3 + transitivePeerDependencies: + - bufferutil + - react + - utf-8-validate + string-argv@0.3.2: {} string-convert@0.2.1: {} @@ -7873,10 +9190,14 @@ snapshots: dependencies: ansi-regex: 6.2.2 + strip-bom@3.0.0: {} + strip-indent@3.0.0: dependencies: min-indent: 1.0.1 + strip-indent@4.1.1: {} + strip-json-comments@3.1.1: {} style-to-js@1.1.21: @@ -7931,6 +9252,8 @@ snapshots: third-party-capital@1.0.20: {} + tiny-invariant@1.3.3: {} + tinybench@2.9.0: {} tinyexec@1.2.2: {} @@ -7940,8 +9263,12 @@ snapshots: fdir: 6.5.0(picomatch@4.0.4) picomatch: 4.0.4 + tinyrainbow@2.0.0: {} + tinyrainbow@3.1.0: {} + tinyspy@4.0.4: {} + tldts-core@7.4.2: {} tldts@7.4.2: @@ -7952,6 +9279,8 @@ snapshots: dependencies: is-number: 7.0.0 + totalist@3.0.1: {} + tough-cookie@6.0.1: dependencies: tldts: 7.4.2 @@ -7970,6 +9299,18 @@ snapshots: dependencies: typescript: 6.0.3 + ts-dedent@2.3.0: {} + + tsconfck@3.1.6(typescript@6.0.3): + optionalDependencies: + typescript: 6.0.3 + + tsconfig-paths@4.2.0: + dependencies: + json5: 2.2.3 + minimist: 1.2.8 + strip-bom: 3.0.0 + tslib@2.8.1: {} type-check@0.4.0: @@ -8077,6 +9418,13 @@ snapshots: unist-util-is: 6.0.1 unist-util-visit-parents: 6.0.2 + unplugin@2.3.11: + dependencies: + '@jridgewell/remapping': 2.3.5 + acorn: 8.16.0 + picomatch: 4.0.4 + webpack-virtual-modules: 0.6.2 + update-browserslist-db@1.2.3(browserslist@4.28.2): dependencies: browserslist: 4.28.2 @@ -8101,6 +9449,32 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 + vite-plugin-storybook-nextjs@3.3.2(next@16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.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.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + storybook: 10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6) + ts-dedent: 2.3.0 + vite: 8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0) + vite-tsconfig-paths: 5.1.4(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0)) + transitivePeerDependencies: + - supports-color + - typescript + + vite-tsconfig-paths@5.1.4(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0)): + dependencies: + debug: 4.4.3 + globrex: 0.1.2 + tsconfck: 3.1.6(typescript@6.0.3) + optionalDependencies: + vite: 8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0) + transitivePeerDependencies: + - supports-color + - typescript + vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0): dependencies: lightningcss: 1.32.0 @@ -8116,7 +9490,7 @@ snapshots: terser: 5.48.0 yaml: 2.9.0 - vitest@4.1.7(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(@vitest/coverage-v8@4.1.7)(jsdom@29.1.1)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0)): + vitest@4.1.7(@opentelemetry/api@1.9.1)(@types/node@25.9.1)(@vitest/browser-playwright@4.1.7)(@vitest/coverage-v8@4.1.7)(jsdom@29.1.1)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0)): dependencies: '@vitest/expect': 4.1.7 '@vitest/mocker': 4.1.7(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0)) @@ -8141,7 +9515,8 @@ snapshots: optionalDependencies: '@opentelemetry/api': 1.9.1 '@types/node': 25.9.1 - '@vitest/coverage-v8': 4.1.7(vitest@4.1.7) + '@vitest/browser-playwright': 4.1.7(playwright@1.62.1)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(vitest@4.1.7) + '@vitest/coverage-v8': 4.1.7(@vitest/browser@4.1.7)(vitest@4.1.7) jsdom: 29.1.1 transitivePeerDependencies: - msw @@ -8161,6 +9536,8 @@ snapshots: webpack-sources@3.5.0: {} + webpack-virtual-modules@0.6.2: {} + webpack@5.107.2(esbuild@0.27.7): dependencies: '@types/estree': 1.0.9 @@ -8294,6 +9671,12 @@ snapshots: string-width: 7.2.0 strip-ansi: 7.2.0 + ws@8.21.3: {} + + wsl-utils@0.1.0: + dependencies: + is-wsl: 3.1.1 + xml-js@1.6.11: dependencies: sax: 1.6.0 diff --git a/src/components/Common/AppsPromo/index.stories.tsx b/src/components/Common/AppsPromo/index.stories.tsx new file mode 100644 index 00000000..d86b6c5e --- /dev/null +++ b/src/components/Common/AppsPromo/index.stories.tsx @@ -0,0 +1,14 @@ +import type { Meta, StoryObj } from '@storybook/nextjs-vite'; +import AppsPromo from '.'; + +const meta = { + title: 'Marketing/Apps Promo', + component: AppsPromo, + parameters: { layout: 'fullscreen' }, + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = {}; diff --git a/src/components/Common/ArticleCard/index.stories.tsx b/src/components/Common/ArticleCard/index.stories.tsx new file mode 100644 index 00000000..5ea1cfa0 --- /dev/null +++ b/src/components/Common/ArticleCard/index.stories.tsx @@ -0,0 +1,46 @@ +import type { Meta, StoryObj } from '@storybook/nextjs-vite'; +import ArticleCard from '.'; +import { articleFixture, sponsoredArticleFixture } from '@/stories/articleFixtures'; + +const meta = { + title: 'Content/Article Card', + component: ArticleCard, + decorators: [ + (Story) => ( +
    + +
+ ), + ], + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { args: { article: articleFixture } }; + +export const Sponsored: Story = { args: { article: sponsoredArticleFixture } }; + +export const WithoutImage: Story = { + args: { + article: { + ...articleFixture, + id: 'storybook-without-image', + thumbnail: { url: '', width: 1200, height: 630 }, + }, + }, +}; + +export const LongContent: Story = { + args: { + article: { + ...articleFixture, + id: 'storybook-long-content', + title: + 'とても長い記事タイトルがカードの横幅を超えそうな場合でもレイアウトが崩れずに表示されることを確認するStory', + description: + '説明文も長くなった場合の折り返しを確認します。単語やURLが長いケースを含め、カードから内容がはみ出さないことが重要です。https://example.com/very-long-path-for-layout-verification', + }, + }, +}; diff --git a/src/components/Common/BreadCrumb/index.stories.tsx b/src/components/Common/BreadCrumb/index.stories.tsx new file mode 100644 index 00000000..9708b9bc --- /dev/null +++ b/src/components/Common/BreadCrumb/index.stories.tsx @@ -0,0 +1,35 @@ +import type { Meta, StoryObj } from '@storybook/nextjs-vite'; +import BreadCrumb from '.'; +import { articleFixture } from '@/stories/articleFixtures'; + +const meta = { + title: 'Navigation/Breadcrumb', + component: BreadCrumb, + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Article: Story = { args: { page: { type: 'article', article: articleFixture } } }; + +export const SearchResult: Story = { + args: { page: { type: 'search', searchKeyword: 'Next.js Storybook' } }, +}; + +export const Loading: Story = { + args: { page: { type: 'search' }, isLoading: true }, +}; + +export const LongTitle: Story = { + args: { + page: { + type: 'article', + article: { + ...articleFixture, + title: '画面幅が狭い場合に折り返される、とても長い記事タイトルの表示確認', + }, + }, + }, + parameters: { viewport: { defaultViewport: 'mobile1' } }, +}; diff --git a/src/components/Common/CodeBlock/index.stories.tsx b/src/components/Common/CodeBlock/index.stories.tsx new file mode 100644 index 00000000..d366231d --- /dev/null +++ b/src/components/Common/CodeBlock/index.stories.tsx @@ -0,0 +1,31 @@ +import type { Meta, StoryObj } from '@storybook/nextjs-vite'; +import CodeBlock, { codeBlockStyles } from '.'; + +const sampleCode = `export function greeting(name: string) { + return \`こんにちは、\${name}さん\`; +}`; + +const meta = { + title: 'Content/Code Block', + component: CodeBlock, + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + children: {sampleCode}, + }, +}; + +export const LongLine: Story = { + args: { + children: ( + + {`const endpoint = 'https://example.com/a/very/long/path/used/to/check/horizontal/scroll/and/line/wrapping';`} + + ), + }, +}; diff --git a/src/components/Common/Layouts/Footer/index.stories.tsx b/src/components/Common/Layouts/Footer/index.stories.tsx new file mode 100644 index 00000000..ae008051 --- /dev/null +++ b/src/components/Common/Layouts/Footer/index.stories.tsx @@ -0,0 +1,14 @@ +import type { Meta, StoryObj } from '@storybook/nextjs-vite'; +import Footer from '.'; + +const meta = { + title: 'Layout/Footer', + component: Footer, + parameters: { layout: 'fullscreen' }, + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = {}; diff --git a/src/components/Common/Layouts/Header/index.stories.tsx b/src/components/Common/Layouts/Header/index.stories.tsx new file mode 100644 index 00000000..0b3d2a65 --- /dev/null +++ b/src/components/Common/Layouts/Header/index.stories.tsx @@ -0,0 +1,25 @@ +import type { Meta, StoryObj } from '@storybook/nextjs-vite'; +import Header from '.'; + +const meta = { + title: 'Layout/Header', + component: Header, + decorators: [ + (Story) => ( +
+ +
+ ), + ], + parameters: { layout: 'fullscreen' }, + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Desktop: Story = {}; + +export const Mobile: Story = { + parameters: { viewport: { defaultViewport: 'mobile1' } }, +}; diff --git a/src/components/Common/Layouts/Sidebar/index.stories.tsx b/src/components/Common/Layouts/Sidebar/index.stories.tsx new file mode 100644 index 00000000..a84ffafc --- /dev/null +++ b/src/components/Common/Layouts/Sidebar/index.stories.tsx @@ -0,0 +1,49 @@ +import type { Meta, StoryObj } from '@storybook/nextjs-vite'; +import Sidebar from '.'; +import { unifiedArticleFixture } from '@/stories/articleFixtures'; + +const createdAt = '2026-08-01T09:00:00.000Z'; + +const tags = ['Next.js', 'TypeScript', '個人開発'].map((name, index) => ({ + id: `tag-${index + 1}`, + name, + createdAt, + updatedAt: createdAt, + publishedAt: createdAt, + revisedAt: createdAt, +})); + +const meta = { + title: 'Layout/Sidebar', + component: Sidebar, + args: { + tags, + archiveList: [ + { year: '2026', month: '8' }, + { year: '2026', month: '7' }, + { year: '2025', month: '12' }, + ], + recentArticles: [ + unifiedArticleFixture, + { + ...unifiedArticleFixture, + id: 'storybook-recent-article-2', + title: 'StorybookでUIを管理する方法', + url: '/articles/storybook-recent-article-2', + }, + ], + }, + decorators: [ + (Story) => ( +
+ +
+ ), + ], + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = {}; diff --git a/src/components/Common/Layouts/ThemeSwitch/index.stories.tsx b/src/components/Common/Layouts/ThemeSwitch/index.stories.tsx new file mode 100644 index 00000000..c0f88e65 --- /dev/null +++ b/src/components/Common/Layouts/ThemeSwitch/index.stories.tsx @@ -0,0 +1,15 @@ +import type { Meta, StoryObj } from '@storybook/nextjs-vite'; +import ThemeSwitch from '.'; + +const meta = { + title: 'Navigation/Theme Switch', + component: ThemeSwitch, + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const LightTheme: Story = { globals: { theme: 'light' } }; + +export const DarkTheme: Story = { globals: { theme: 'dark' } }; diff --git a/src/components/Common/Markdown/index.stories.tsx b/src/components/Common/Markdown/index.stories.tsx new file mode 100644 index 00000000..960ed51e --- /dev/null +++ b/src/components/Common/Markdown/index.stories.tsx @@ -0,0 +1,41 @@ +import type { Meta, StoryObj } from '@storybook/nextjs-vite'; +import Markdown from '.'; + +const content = `## 記事本文の見出し + +本文には[内部リンク](/profile)と[外部リンク](https://example.com)を含められます。 + +### リストと引用 + +- ひとつ目の項目 +- ふたつ目の項目 + +> 引用文の表示例です。 + +### 表 + +| 項目 | 内容 | +| --- | --- | +| Storybook | UIを単体で確認 | +| a11y | アクセシビリティを検査 | + +### コード + +~~~ts +const message = 'Hello Storybook'; +console.log(message); +~~~ +`; + +const meta = { + title: 'Content/Markdown', + component: Markdown, + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const ArticleContent: Story = { + args: { content, headingIds: ['article-heading', 'list-and-quote', 'table', 'code'] }, +}; diff --git a/src/components/Common/Pagination/index.stories.tsx b/src/components/Common/Pagination/index.stories.tsx new file mode 100644 index 00000000..6f9cf228 --- /dev/null +++ b/src/components/Common/Pagination/index.stories.tsx @@ -0,0 +1,22 @@ +import type { Meta, StoryObj } from '@storybook/nextjs-vite'; +import Pagination from '.'; + +const meta = { + title: 'Navigation/Pagination', + component: Pagination, + args: { totalCount: 120, basePath: '/articles' }, + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const FirstPage: Story = { args: { current: 1 } }; + +export const MiddlePage: Story = { args: { current: 6 } }; + +export const LastPage: Story = { args: { current: 12 } }; + +export const QueryPagination: Story = { + args: { current: 3, basePath: '/search', q: 'storybook', useQueryPage: true }, +}; diff --git a/src/components/Common/Share/index.stories.tsx b/src/components/Common/Share/index.stories.tsx new file mode 100644 index 00000000..c577bd92 --- /dev/null +++ b/src/components/Common/Share/index.stories.tsx @@ -0,0 +1,14 @@ +import type { Meta, StoryObj } from '@storybook/nextjs-vite'; +import Share from '.'; +import { articleFixture } from '@/stories/articleFixtures'; + +const meta = { + title: 'Content/Share', + component: Share, + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { args: { data: articleFixture } }; diff --git a/src/components/Common/SponsoredDisclosure/index.stories.tsx b/src/components/Common/SponsoredDisclosure/index.stories.tsx new file mode 100644 index 00000000..60088116 --- /dev/null +++ b/src/components/Common/SponsoredDisclosure/index.stories.tsx @@ -0,0 +1,15 @@ +import type { Meta, StoryObj } from '@storybook/nextjs-vite'; +import SponsoredDisclosure from '.'; + +const meta = { + title: 'Content/Sponsored Disclosure', + component: SponsoredDisclosure, + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = {}; + +export const Compact: Story = { args: { compact: true } }; diff --git a/src/components/Common/TableOfContent/index.stories.tsx b/src/components/Common/TableOfContent/index.stories.tsx new file mode 100644 index 00000000..8eb42788 --- /dev/null +++ b/src/components/Common/TableOfContent/index.stories.tsx @@ -0,0 +1,22 @@ +import type { Meta, StoryObj } from '@storybook/nextjs-vite'; +import TableOfContents from '.'; + +const headings = [ + { id: 'overview', title: '概要', level: 2 }, + { id: 'setup', title: 'セットアップ', level: 2 }, + { id: 'configuration', title: '設定', level: 3 }, + { id: 'verification', title: '動作確認', level: 2 }, +]; + +const meta = { + title: 'Navigation/Table of Contents', + component: TableOfContents, + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { args: { headings } }; + +export const Sidebar: Story = { args: { headings, sidebar: true } }; diff --git a/src/components/Features/Contact/Elements/Alert/index.stories.tsx b/src/components/Features/Contact/Elements/Alert/index.stories.tsx new file mode 100644 index 00000000..fd8c813d --- /dev/null +++ b/src/components/Features/Contact/Elements/Alert/index.stories.tsx @@ -0,0 +1,36 @@ +import type { Meta, StoryObj } from '@storybook/nextjs-vite'; +import { expect, fn, userEvent, within } from 'storybook/test'; +import Alert from '.'; + +const meta = { + title: 'Feedback/Contact Alert', + component: Alert, + args: { + onClose: fn(), + show: true, + title: '送信しました', + description: 'お問い合わせありがとうございます。内容を確認してご連絡します。', + }, + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Success: Story = {}; + +export const Error: Story = { + args: { + variant: 'error', + title: '送信できませんでした', + description: '時間をおいて、もう一度お試しください。', + }, +}; + +export const CloseInteraction: Story = { + play: async ({ canvasElement, args }) => { + const canvas = within(canvasElement.ownerDocument.body); + await userEvent.click(canvas.getByRole('button', { name: '通知を閉じる' })); + await expect(args.onClose).toHaveBeenCalledOnce(); + }, +}; diff --git a/src/components/Features/Contact/Elements/Modal/index.stories.tsx b/src/components/Features/Contact/Elements/Modal/index.stories.tsx new file mode 100644 index 00000000..1b68233a --- /dev/null +++ b/src/components/Features/Contact/Elements/Modal/index.stories.tsx @@ -0,0 +1,33 @@ +import type { Meta, StoryObj } from '@storybook/nextjs-vite'; +import { expect, fn, userEvent, within } from 'storybook/test'; +import Modal from '.'; + +const meta = { + title: 'Feedback/Contact Modal', + component: Modal, + args: { + title: 'お問い合わせを送信しますか?', + description: '入力内容を確認して、問題がなければ送信してください。', + confirmText: '送信する', + cancelText: '戻る', + show: true, + onClose: fn(), + onConfirm: fn(), + }, + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Confirmation: Story = {}; + +export const Loading: Story = { args: { isLoading: true, confirmText: '送信中…' } }; + +export const ConfirmInteraction: Story = { + play: async ({ canvasElement, args }) => { + const canvas = within(canvasElement.ownerDocument.body); + await userEvent.click(canvas.getByRole('button', { name: '送信する' })); + await expect(args.onConfirm).toHaveBeenCalledOnce(); + }, +}; diff --git a/src/stories/Foundations.stories.tsx b/src/stories/Foundations.stories.tsx new file mode 100644 index 00000000..6b591294 --- /dev/null +++ b/src/stories/Foundations.stories.tsx @@ -0,0 +1,66 @@ +import type { Meta, StoryObj } from '@storybook/nextjs-vite'; + +const palette = [ + { name: 'Text', variable: '--color-text-main' }, + { name: 'Secondary text', variable: '--color-text-sub' }, + { name: 'Border', variable: '--color-border' }, + { name: 'Focus', variable: '--color-focus-ring' }, + { name: 'Link', variable: '--color-link' }, + { name: 'Soft accent', variable: '--color-accent-soft-bg' }, +]; + +function Foundations() { + return ( +
+
+

Design foundations

+

+ Tailwind CSS v4を基礎に、ブログ固有のCSS変数だけを補完しています。 +

+
+ +
+

Colors

+
+ {palette.map(({ name, variable }) => ( +
+
+
+
{name}
+ {variable} +
+
+ ))} +
+
+ +
+

Typography

+
Heading 1 / 30px
+
Heading 2 / 24px
+
Heading 3 / 20px
+

Body / 16px — 読みやすい本文の基準サイズです。

+

Small / 14px — 補足情報に使用します。

+
+ +
+

Focus

+ + Tabキーでフォーカスを確認 + +
+
+ ); +} + +const meta = { + title: 'Foundations/Overview', + component: Foundations, + parameters: { layout: 'fullscreen' }, + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = {}; diff --git a/src/stories/articleFixtures.ts b/src/stories/articleFixtures.ts new file mode 100644 index 00000000..92162b25 --- /dev/null +++ b/src/stories/articleFixtures.ts @@ -0,0 +1,50 @@ +import type { Article } from '@/types/microcms'; +import type { UnifiedArticle } from '@/types/unified'; + +const publishedAt = '2026-08-01T09:00:00.000Z'; +const updatedAt = '2026-08-05T09:00:00.000Z'; + +export const articleFixture = { + id: 'storybook-article', + title: '大学生活で役立ったWebサービスと、無理なく続けるための使い方', + description: '授業や課外活動、個人開発を続ける中で実際に役立ったサービスを紹介します。', + thumbnail: { + url: '/images/thumbnail/7.webp', + width: 1200, + height: 630, + }, + categories: [ + { + id: 'programming', + name: 'プログラミング', + createdAt: publishedAt, + updatedAt, + publishedAt, + revisedAt: updatedAt, + }, + ], + tags: [], + introduction_blocks: [], + content_blocks: [], + createdAt: publishedAt, + updatedAt, + publishedAt, + revisedAt: updatedAt, +} satisfies Article; + +export const sponsoredArticleFixture: Article = { + ...articleFixture, + id: 'storybook-sponsored-article', + isSponsored: true, +}; + +export const unifiedArticleFixture = { + id: 'storybook-unified-article', + title: articleFixture.title, + description: articleFixture.description, + publishedAt, + updatedAt, + thumbnail: articleFixture.thumbnail, + url: '/articles/storybook-unified-article', + source: 'blog', +} satisfies UnifiedArticle; diff --git a/vitest.config.mts b/vitest.config.mts index c8720ae2..b1731ed6 100644 --- a/vitest.config.mts +++ b/vitest.config.mts @@ -1,5 +1,7 @@ import path from 'node:path'; import { defineConfig } from 'vitest/config'; +import { playwright } from '@vitest/browser-playwright'; +import { storybookTest } from '@storybook/addon-vitest/vitest-plugin'; export default defineConfig(async () => { const react = (await import('@vitejs/plugin-react')).default; @@ -12,45 +14,72 @@ export default defineConfig(async () => { }, }, test: { - environment: 'jsdom', - setupFiles: ['./src/test/setup.ts'], - include: ['src/**/*.{test,spec}.{ts,tsx}'], - restoreMocks: true, - clearMocks: true, - coverage: { - provider: 'v8', - reporter: ['text', 'html', 'lcov'], - reportsDirectory: 'coverage', - exclude: [ - '**/*.config.*', - '**/*.d.ts', - '.next/**', - 'coverage/**', - 'node_modules/**', - 'out/**', - 'public/**', - 'src/app/manifest.json', - 'src/app/not-found.tsx', - 'src/components/Common/Elements/SocialIcon/**', - 'src/components/Common/Layouts/Container/ContentContainer/**', - 'src/components/Common/Layouts/Container/FixedContentContainer/**', - 'src/components/Common/Layouts/Container/MainContainer/**', - 'src/components/Common/Layouts/Footer/**', - 'src/components/Common/Layouts/Sidebar/Elements/Popular/**', - 'src/components/Pages/**', - 'src/components/ThirdParties/Embedly/**', - 'src/components/ThirdParties/GoogleAdSense/index.tsx', - 'src/components/ThirdParties/GoogleAnalytics/**', - 'src/components/ThirdParties/GoogleSearchConsole/**', - 'src/components/ThirdParties/Instagram/**', - 'src/components/ThirdParties/OneSignal/**', - 'src/constants/**', - 'src/contents/**', - 'src/styles/**', - 'src/test/**', - 'src/types/**', - ], - }, + projects: [ + { + extends: true, + test: { + name: 'unit', + environment: 'jsdom', + setupFiles: ['./src/test/setup.ts'], + include: ['src/**/*.{test,spec}.{ts,tsx}'], + restoreMocks: true, + clearMocks: true, + coverage: { + provider: 'v8', + reporter: ['text', 'html', 'lcov'], + reportsDirectory: 'coverage', + exclude: [ + '**/*.config.*', + '**/*.d.ts', + '.next/**', + 'coverage/**', + 'node_modules/**', + 'out/**', + 'public/**', + 'src/app/manifest.json', + 'src/app/not-found.tsx', + 'src/components/Common/Elements/SocialIcon/**', + 'src/components/Common/Layouts/Container/ContentContainer/**', + 'src/components/Common/Layouts/Container/FixedContentContainer/**', + 'src/components/Common/Layouts/Container/MainContainer/**', + 'src/components/Common/Layouts/Footer/**', + 'src/components/Common/Layouts/Sidebar/Elements/Popular/**', + 'src/components/Pages/**', + 'src/components/ThirdParties/Embedly/**', + 'src/components/ThirdParties/GoogleAdSense/index.tsx', + 'src/components/ThirdParties/GoogleAnalytics/**', + 'src/components/ThirdParties/GoogleSearchConsole/**', + 'src/components/ThirdParties/Instagram/**', + 'src/components/ThirdParties/OneSignal/**', + 'src/constants/**', + 'src/contents/**', + 'src/styles/**', + 'src/test/**', + 'src/types/**', + ], + }, + }, + }, + { + extends: true, + plugins: [ + storybookTest({ + configDir: path.join(import.meta.dirname, '.storybook'), + }), + ], + test: { + name: 'storybook', + fileParallelism: false, + maxWorkers: 1, + browser: { + enabled: true, + provider: playwright({}), + headless: true, + instances: [{ browser: 'chromium' }], + }, + }, + }, + ], }, }; }); diff --git a/vitest.shims.d.ts b/vitest.shims.d.ts new file mode 100644 index 00000000..7782f28d --- /dev/null +++ b/vitest.shims.d.ts @@ -0,0 +1 @@ +/// \ No newline at end of file From 521b13fbcd44e9db280fa754ed09b6f0d080f6e6 Mon Sep 17 00:00:00 2001 From: Arata1202 Date: Fri, 28 Aug 2026 22:48:39 +0900 Subject: [PATCH 02/26] fix: align Playwright dependencies --- package.json | 4 ++-- pnpm-lock.yaml | 65 +++++++++++++++++++------------------------------- 2 files changed, 26 insertions(+), 43 deletions(-) diff --git a/package.json b/package.json index c7cc12a8..98becb35 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,7 @@ "devDependencies": { "@eslint/js": "^9.39.4", "@next/eslint-plugin-next": "^16.2.6", - "@playwright/test": "^1.60.0", + "@playwright/test": "1.62.1", "@storybook/addon-a11y": "^10.5.10", "@storybook/addon-docs": "^10.5.10", "@storybook/addon-vitest": "^10.5.10", @@ -91,7 +91,7 @@ "husky": "^9.1.7", "jsdom": "^29.1.1", "lint-staged": "^17.0.6", - "playwright": "^1.62.1", + "playwright": "1.62.1", "prettier": "^3.8.3", "storybook": "^10.5.10", "tailwindcss": "^4.3.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 286ae9b7..bd8beb3f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -21,10 +21,10 @@ importers: version: 2.2.0(react@19.2.6) '@next/third-parties': specifier: ^16.2.6 - version: 16.2.6(next@16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(react@19.2.6) + version: 16.2.6(next@16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.62.1)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(react@19.2.6) '@sentry/nextjs': specifier: ^10 - version: 10.55.0(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(next@16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(react@19.2.6)(webpack@5.107.2(esbuild@0.27.7)) + version: 10.55.0(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(next@16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.62.1)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(react@19.2.6)(webpack@5.107.2(esbuild@0.27.7)) cheerio: specifier: ^1.2.0 version: 1.2.0 @@ -45,7 +45,7 @@ importers: version: 3.4.0 next: specifier: ^16.2.6 - version: 16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + version: 16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.62.1)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) next-themes: specifier: ^0.4.6 version: 0.4.6(react-dom@19.2.6(react@19.2.6))(react@19.2.6) @@ -87,8 +87,8 @@ importers: specifier: ^16.2.6 version: 16.2.6 '@playwright/test': - specifier: ^1.60.0 - version: 1.60.0 + specifier: 1.62.1 + version: 1.62.1 '@storybook/addon-a11y': specifier: ^10.5.10 version: 10.5.10(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6)) @@ -100,7 +100,7 @@ importers: version: 10.5.10(@vitest/browser-playwright@4.1.7)(@vitest/browser@4.1.7)(@vitest/runner@4.1.7)(react@19.2.6)(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(vitest@4.1.7) '@storybook/nextjs-vite': specifier: ^10.5.10 - version: 10.5.10(@babel/core@7.29.7)(@types/react@19.2.15)(esbuild@0.27.7)(next@16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(rollup@4.60.4)(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(webpack@5.107.2(esbuild@0.27.7)) + version: 10.5.10(@babel/core@7.29.7)(@types/react@19.2.15)(esbuild@0.27.7)(next@16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.62.1)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(rollup@4.60.4)(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(webpack@5.107.2(esbuild@0.27.7)) '@tailwindcss/postcss': specifier: ^4.3.0 version: 4.3.0 @@ -159,7 +159,7 @@ importers: specifier: ^17.0.6 version: 17.0.6 playwright: - specifier: ^1.62.1 + specifier: 1.62.1 version: 1.62.1 prettier: specifier: ^3.8.3 @@ -1132,9 +1132,9 @@ packages: cpu: [x64] os: [win32] - '@playwright/test@1.60.0': - resolution: {integrity: sha512-O71yZIbAh/PxDMNGns37GHBIfrVkEVyn+AXyIa5dOTfb4/xNvRWV+Vv/NMbNCtODB/pO7vLlF2OTmMVLhmr7Ag==} - engines: {node: '>=18'} + '@playwright/test@1.62.1': + resolution: {integrity: sha512-DTcUc8qii+cpHvtOwggMtBRMjKZHXYWdw8syRYu2vtzuq4Wxphqq4NfCs5Zt44L6mA8rfDfj+PHnxFc/FeK6mQ==} + engines: {node: '>=20'} hasBin: true '@polka/url@1.0.0-next.29': @@ -2669,6 +2669,7 @@ packages: eslint@9.39.4: resolution: {integrity: sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==} 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: '*' @@ -3724,21 +3725,11 @@ packages: resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} engines: {node: '>=12'} - playwright-core@1.60.0: - resolution: {integrity: sha512-9bW6zvX/m0lEbgTKJ6YppOKx8H3VOPBMOCFh2irXFOT4BbHgrx5hPjwJYLT40Lu+4qtD36qKc/Hn56StUW57IA==} - engines: {node: '>=18'} - hasBin: true - playwright-core@1.62.1: resolution: {integrity: sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw==} engines: {node: '>=20'} hasBin: true - playwright@1.60.0: - resolution: {integrity: sha512-hheHdokM8cdqCb0lcE3s+zT4t4W+vvjpGxsZlDnikarzx8tSzMebh3UiFtgqwFwnTnjYQcsyMF8ei2mCO/tpeA==} - engines: {node: '>=18'} - hasBin: true - playwright@1.62.1: resolution: {integrity: sha512-0M+L3LAD8/nm554LOla9Ayx0j0tmFZ0FBcoQ7F1VuVHpM/XpiC8RcDzBQB8W5+hA8L22THxELzeF+2WcUzvcLg==} engines: {node: '>=20'} @@ -5259,9 +5250,9 @@ snapshots: '@next/swc-win32-x64-msvc@16.2.6': optional: true - '@next/third-parties@16.2.6(next@16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(react@19.2.6)': + '@next/third-parties@16.2.6(next@16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.62.1)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(react@19.2.6)': dependencies: - next: 16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + next: 16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.62.1)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) react: 19.2.6 third-party-capital: 1.0.20 @@ -5441,9 +5432,9 @@ snapshots: '@oxc-resolver/binding-win32-x64-msvc@11.21.2': optional: true - '@playwright/test@1.60.0': + '@playwright/test@1.62.1': dependencies: - playwright: 1.60.0 + playwright: 1.62.1 '@polka/url@1.0.0-next.29': {} @@ -5699,7 +5690,7 @@ snapshots: '@sentry/core@10.55.0': {} - '@sentry/nextjs@10.55.0(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(next@16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(react@19.2.6)(webpack@5.107.2(esbuild@0.27.7))': + '@sentry/nextjs@10.55.0(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(next@16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.62.1)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(react@19.2.6)(webpack@5.107.2(esbuild@0.27.7))': dependencies: '@opentelemetry/api': 1.9.1 '@opentelemetry/semantic-conventions': 1.41.1 @@ -5712,7 +5703,7 @@ snapshots: '@sentry/react': 10.55.0(react@19.2.6) '@sentry/vercel-edge': 10.55.0 '@sentry/webpack-plugin': 5.3.0(webpack@5.107.2(esbuild@0.27.7)) - next: 16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + next: 16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.62.1)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) rollup: 4.60.4 stacktrace-parser: 0.1.11 transitivePeerDependencies: @@ -5846,18 +5837,18 @@ snapshots: dependencies: react: 19.2.6 - '@storybook/nextjs-vite@10.5.10(@babel/core@7.29.7)(@types/react@19.2.15)(esbuild@0.27.7)(next@16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(rollup@4.60.4)(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(webpack@5.107.2(esbuild@0.27.7))': + '@storybook/nextjs-vite@10.5.10(@babel/core@7.29.7)(@types/react@19.2.15)(esbuild@0.27.7)(next@16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.62.1)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(rollup@4.60.4)(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(webpack@5.107.2(esbuild@0.27.7))': dependencies: '@storybook/builder-vite': 10.5.10(esbuild@0.27.7)(rollup@4.60.4)(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(webpack@5.107.2(esbuild@0.27.7)) '@storybook/react': 10.5.10(@types/react@19.2.15)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(typescript@6.0.3) '@storybook/react-vite': 10.5.10(@types/react@19.2.15)(esbuild@0.27.7)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)(rollup@4.60.4)(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0))(webpack@5.107.2(esbuild@0.27.7)) - next: 16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + next: 16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.62.1)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) react: 19.2.6 react-dom: 19.2.6(react@19.2.6) storybook: 10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6) styled-jsx: 5.1.6(@babel/core@7.29.7)(react@19.2.6) vite: 8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0) - vite-plugin-storybook-nextjs: 3.3.2(next@16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0)) + vite-plugin-storybook-nextjs: 3.3.2(next@16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.62.1)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0)) optionalDependencies: '@types/react': 19.2.15 typescript: 6.0.3 @@ -8365,7 +8356,7 @@ snapshots: react: 19.2.6 react-dom: 19.2.6(react@19.2.6) - next@16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6): + next@16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.62.1)(react-dom@19.2.6(react@19.2.6))(react@19.2.6): dependencies: '@next/env': 16.2.6 '@swc/helpers': 0.5.15 @@ -8385,7 +8376,7 @@ snapshots: '@next/swc-win32-arm64-msvc': 16.2.6 '@next/swc-win32-x64-msvc': 16.2.6 '@opentelemetry/api': 1.9.1 - '@playwright/test': 1.60.0 + '@playwright/test': 1.62.1 sharp: 0.34.5 transitivePeerDependencies: - '@babel/core' @@ -8579,16 +8570,8 @@ snapshots: picomatch@4.0.4: {} - playwright-core@1.60.0: {} - playwright-core@1.62.1: {} - playwright@1.60.0: - dependencies: - playwright-core: 1.60.0 - optionalDependencies: - fsevents: 2.3.2 - playwright@1.62.1: dependencies: playwright-core: 1.62.1 @@ -9449,13 +9432,13 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 - vite-plugin-storybook-nextjs@3.3.2(next@16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0)): + vite-plugin-storybook-nextjs@3.3.2(next@16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.62.1)(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(storybook@10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6))(typescript@6.0.3)(vite@8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.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.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.60.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + next: 16.2.6(@babel/core@7.29.7)(@opentelemetry/api@1.9.1)(@playwright/test@1.62.1)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) storybook: 10.5.10(@types/react@19.2.15)(prettier@3.8.3)(react@19.2.6) ts-dedent: 2.3.0 vite: 8.0.14(@types/node@25.9.1)(esbuild@0.27.7)(jiti@2.7.0)(terser@5.48.0)(yaml@2.9.0) From bb6f49fb3baf91322ce4e4c065f26d2615ea4be6 Mon Sep 17 00:00:00 2001 From: Arata1202 Date: Fri, 28 Aug 2026 22:53:55 +0900 Subject: [PATCH 03/26] refactor: use Storybook initial globals --- .storybook/preview.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index 9d71d734..9caa41b6 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -23,7 +23,6 @@ const preview: Preview = { globalTypes: { theme: { description: 'Component theme', - defaultValue: 'light', toolbar: { icon: 'paintbrush', items: [ @@ -34,6 +33,9 @@ const preview: Preview = { }, }, }, + initialGlobals: { + theme: 'light', + }, parameters: { layout: 'fullscreen', nextjs: { From d13515a026d651ab16712200622a49de211a4c5d Mon Sep 17 00:00:00 2001 From: Arata1202 Date: Fri, 28 Aug 2026 23:05:47 +0900 Subject: [PATCH 04/26] fix(storybook): match production component themes --- .storybook/preview.tsx | 8 +++++++- src/components/Common/ArticleCard/index.stories.tsx | 10 ---------- src/components/Common/CodeBlock/index.module.css | 1 + 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index 9caa41b6..c756db9d 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -10,7 +10,13 @@ const withTheme: Decorator = (Story, context) => { document.body.classList.toggle('LightTheme', theme === 'light'); return ( - +
diff --git a/src/components/Common/ArticleCard/index.stories.tsx b/src/components/Common/ArticleCard/index.stories.tsx index 5ea1cfa0..461fd310 100644 --- a/src/components/Common/ArticleCard/index.stories.tsx +++ b/src/components/Common/ArticleCard/index.stories.tsx @@ -22,16 +22,6 @@ export const Default: Story = { args: { article: articleFixture } }; export const Sponsored: Story = { args: { article: sponsoredArticleFixture } }; -export const WithoutImage: Story = { - args: { - article: { - ...articleFixture, - id: 'storybook-without-image', - thumbnail: { url: '', width: 1200, height: 630 }, - }, - }, -}; - export const LongContent: Story = { args: { article: { diff --git a/src/components/Common/CodeBlock/index.module.css b/src/components/Common/CodeBlock/index.module.css index 9efa634a..0241c159 100644 --- a/src/components/Common/CodeBlock/index.module.css +++ b/src/components/Common/CodeBlock/index.module.css @@ -20,6 +20,7 @@ .codeBlock > code { display: block; overflow-x: auto; + padding: 16px; background-color: var(--color-bg-code) !important; color: var(--color-text-code); } From 7b29664918e5457f2cd440654b2a13ffc1f3e9c7 Mon Sep 17 00:00:00 2001 From: Arata1202 Date: Fri, 28 Aug 2026 23:18:11 +0900 Subject: [PATCH 05/26] test(storybook): cover article table rendering --- .../Common/Markdown/index.stories.tsx | 9 +---- .../Plugins/RichText/index.stories.tsx | 36 +++++++++++++++++++ 2 files changed, 37 insertions(+), 8 deletions(-) create mode 100644 src/components/Features/Article/Elements/Plugins/RichText/index.stories.tsx diff --git a/src/components/Common/Markdown/index.stories.tsx b/src/components/Common/Markdown/index.stories.tsx index 960ed51e..f62ed07c 100644 --- a/src/components/Common/Markdown/index.stories.tsx +++ b/src/components/Common/Markdown/index.stories.tsx @@ -12,13 +12,6 @@ const content = `## 記事本文の見出し > 引用文の表示例です。 -### 表 - -| 項目 | 内容 | -| --- | --- | -| Storybook | UIを単体で確認 | -| a11y | アクセシビリティを検査 | - ### コード ~~~ts @@ -37,5 +30,5 @@ export default meta; type Story = StoryObj; export const ArticleContent: Story = { - args: { content, headingIds: ['article-heading', 'list-and-quote', 'table', 'code'] }, + args: { content, headingIds: ['article-heading', 'list-and-quote', 'code'] }, }; diff --git a/src/components/Features/Article/Elements/Plugins/RichText/index.stories.tsx b/src/components/Features/Article/Elements/Plugins/RichText/index.stories.tsx new file mode 100644 index 00000000..0af389b1 --- /dev/null +++ b/src/components/Features/Article/Elements/Plugins/RichText/index.stories.tsx @@ -0,0 +1,36 @@ +import type { Meta, StoryObj } from '@storybook/nextjs-vite'; +import RichText from '.'; + +const tableHtml = ` + + + + + + + + + + + + + + + + + +
オプション設定値
ランタイムNode.js 20.x
認証タイプNone
+`; + +const meta = { + title: 'Content/RichText', + component: RichText, + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Table: Story = { + args: { html: tableHtml }, +}; From 74d2d240fd59c269b8993903dbe46a09673312c8 Mon Sep 17 00:00:00 2001 From: Arata1202 Date: Fri, 28 Aug 2026 23:24:47 +0900 Subject: [PATCH 06/26] test(storybook): follow global theme in theme switch story --- src/components/Common/Layouts/ThemeSwitch/index.stories.tsx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/Common/Layouts/ThemeSwitch/index.stories.tsx b/src/components/Common/Layouts/ThemeSwitch/index.stories.tsx index c0f88e65..dbbc64b6 100644 --- a/src/components/Common/Layouts/ThemeSwitch/index.stories.tsx +++ b/src/components/Common/Layouts/ThemeSwitch/index.stories.tsx @@ -10,6 +10,4 @@ const meta = { export default meta; type Story = StoryObj; -export const LightTheme: Story = { globals: { theme: 'light' } }; - -export const DarkTheme: Story = { globals: { theme: 'dark' } }; +export const Default: Story = {}; From 90d90e91a0d1c6c40dac2791c0c9accc57c28200 Mon Sep 17 00:00:00 2001 From: Arata1202 Date: Fri, 28 Aug 2026 23:31:12 +0900 Subject: [PATCH 07/26] test(storybook): remove duplicate query pagination story --- src/components/Common/Pagination/index.stories.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/components/Common/Pagination/index.stories.tsx b/src/components/Common/Pagination/index.stories.tsx index 6f9cf228..90f67ad9 100644 --- a/src/components/Common/Pagination/index.stories.tsx +++ b/src/components/Common/Pagination/index.stories.tsx @@ -16,7 +16,3 @@ export const FirstPage: Story = { args: { current: 1 } }; export const MiddlePage: Story = { args: { current: 6 } }; export const LastPage: Story = { args: { current: 12 } }; - -export const QueryPagination: Story = { - args: { current: 3, basePath: '/search', q: 'storybook', useQueryPage: true }, -}; From 310eab796acdfbd7c17ca34d128e0e40539ddebf Mon Sep 17 00:00:00 2001 From: Arata1202 Date: Fri, 28 Aug 2026 23:37:13 +0900 Subject: [PATCH 08/26] fix(storybook): synchronize component theme controls --- .storybook/preview.tsx | 57 ++++++++++++++++--- .../Layouts/ThemeSwitch/index.stories.tsx | 15 ++++- 2 files changed, 63 insertions(+), 9 deletions(-) diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index c756db9d..092610e0 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -1,8 +1,49 @@ import type { Decorator, Preview } from '@storybook/nextjs-vite'; -import { ThemeProvider } from 'next-themes'; +import { useEffect, useRef, type ReactNode } from 'react'; +import { ThemeProvider, useTheme } from 'next-themes'; +import { useGlobals } from 'storybook/preview-api'; import '@/styles/globals.css'; -const withTheme: Decorator = (Story, context) => { +type Theme = 'light' | 'dark'; + +type ThemeSyncProps = { + globalTheme: Theme; + updateGlobals: (globals: Record) => void; + children: ReactNode; +}; + +function ThemeSync({ globalTheme, updateGlobals, children }: ThemeSyncProps) { + const { resolvedTheme, setTheme } = useTheme(); + const previousGlobalTheme = useRef(globalTheme); + const initialized = useRef(false); + + useEffect(() => { + if (resolvedTheme !== 'light' && resolvedTheme !== 'dark') { + return; + } + + if (!initialized.current) { + initialized.current = true; + setTheme(globalTheme); + return; + } + + if (previousGlobalTheme.current !== globalTheme) { + previousGlobalTheme.current = globalTheme; + setTheme(globalTheme); + return; + } + + if (resolvedTheme !== globalTheme) { + updateGlobals({ theme: resolvedTheme }); + } + }, [globalTheme, resolvedTheme, setTheme, updateGlobals]); + + return children; +} + +const WithTheme: Decorator = (Story, context) => { + const [, updateGlobals] = useGlobals(); const theme = context.globals.theme === 'dark' ? 'dark' : 'light'; const themeClassName = theme === 'dark' ? 'DarkTheme' : 'LightTheme'; @@ -11,21 +52,21 @@ const withTheme: Decorator = (Story, context) => { return ( -
- -
+ +
+ +
+
); }; const preview: Preview = { - decorators: [withTheme], + decorators: [WithTheme], globalTypes: { theme: { description: 'Component theme', diff --git a/src/components/Common/Layouts/ThemeSwitch/index.stories.tsx b/src/components/Common/Layouts/ThemeSwitch/index.stories.tsx index dbbc64b6..2a790d24 100644 --- a/src/components/Common/Layouts/ThemeSwitch/index.stories.tsx +++ b/src/components/Common/Layouts/ThemeSwitch/index.stories.tsx @@ -1,4 +1,5 @@ import type { Meta, StoryObj } from '@storybook/nextjs-vite'; +import { expect, userEvent } from 'storybook/test'; import ThemeSwitch from '.'; const meta = { @@ -10,4 +11,16 @@ const meta = { export default meta; type Story = StoryObj; -export const Default: Story = {}; +export const Default: Story = { + play: async ({ canvas }) => { + const switchToDarkButton = await canvas.findByRole('button', { + name: 'ダークテーマに切り替え', + }); + + await userEvent.click(switchToDarkButton); + + await expect( + canvas.getByRole('button', { name: 'ライトテーマに切り替え' }), + ).toBeInTheDocument(); + }, +}; From 16e0a4729b7a1f338bf13c61e4bdb8861935c96a Mon Sep 17 00:00:00 2001 From: Arata1202 Date: Fri, 28 Aug 2026 23:41:53 +0900 Subject: [PATCH 09/26] fix(storybook): apply mobile viewport globals --- src/components/Common/BreadCrumb/index.stories.tsx | 2 +- src/components/Common/Layouts/Header/index.stories.tsx | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/Common/BreadCrumb/index.stories.tsx b/src/components/Common/BreadCrumb/index.stories.tsx index 9708b9bc..7a5f6eae 100644 --- a/src/components/Common/BreadCrumb/index.stories.tsx +++ b/src/components/Common/BreadCrumb/index.stories.tsx @@ -31,5 +31,5 @@ export const LongTitle: Story = { }, }, }, - parameters: { viewport: { defaultViewport: 'mobile1' } }, + globals: { viewport: { value: 'mobile1', isRotated: false } }, }; diff --git a/src/components/Common/Layouts/Header/index.stories.tsx b/src/components/Common/Layouts/Header/index.stories.tsx index 0b3d2a65..e70ec1eb 100644 --- a/src/components/Common/Layouts/Header/index.stories.tsx +++ b/src/components/Common/Layouts/Header/index.stories.tsx @@ -1,4 +1,5 @@ import type { Meta, StoryObj } from '@storybook/nextjs-vite'; +import { expect } from 'storybook/test'; import Header from '.'; const meta = { @@ -21,5 +22,8 @@ type Story = StoryObj; export const Desktop: Story = {}; export const Mobile: Story = { - parameters: { viewport: { defaultViewport: 'mobile1' } }, + globals: { viewport: { value: 'mobile1', isRotated: false } }, + play: async ({ canvas }) => { + await expect(canvas.getByRole('button', { name: 'メニューを開く' })).toBeVisible(); + }, }; From 57b7c9c276580a9b81572ad21737646fcc383c3c Mon Sep 17 00:00:00 2001 From: Arata1202 Date: Fri, 28 Aug 2026 23:46:31 +0900 Subject: [PATCH 10/26] test(storybook): match production alert content --- .../Features/Contact/Elements/Alert/index.stories.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/Features/Contact/Elements/Alert/index.stories.tsx b/src/components/Features/Contact/Elements/Alert/index.stories.tsx index fd8c813d..b069671f 100644 --- a/src/components/Features/Contact/Elements/Alert/index.stories.tsx +++ b/src/components/Features/Contact/Elements/Alert/index.stories.tsx @@ -8,8 +8,8 @@ const meta = { args: { onClose: fn(), show: true, - title: '送信しました', - description: 'お問い合わせありがとうございます。内容を確認してご連絡します。', + title: 'お問い合わせありがとうございます', + description: '正常に処理が完了しました。', }, tags: ['autodocs'], } satisfies Meta; @@ -22,8 +22,8 @@ export const Success: Story = {}; export const Error: Story = { args: { variant: 'error', - title: '送信できませんでした', - description: '時間をおいて、もう一度お試しください。', + title: '送信に失敗しました', + description: '時間をおいて再度お試しください。', }, }; From c86e6cc569eacc5495364e2720347a0fdf8fac1d Mon Sep 17 00:00:00 2001 From: Arata1202 Date: Fri, 28 Aug 2026 23:52:01 +0900 Subject: [PATCH 11/26] test(storybook): match production modal content --- .../Features/Contact/Elements/Modal/index.stories.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/Features/Contact/Elements/Modal/index.stories.tsx b/src/components/Features/Contact/Elements/Modal/index.stories.tsx index 1b68233a..efdd348a 100644 --- a/src/components/Features/Contact/Elements/Modal/index.stories.tsx +++ b/src/components/Features/Contact/Elements/Modal/index.stories.tsx @@ -7,9 +7,9 @@ const meta = { component: Modal, args: { title: 'お問い合わせを送信しますか?', - description: '入力内容を確認して、問題がなければ送信してください。', - confirmText: '送信する', - cancelText: '戻る', + description: '送信ボタンは一度だけ押してください。送信完了まで数秒かかることがあります。', + confirmText: '送信', + cancelText: 'キャンセル', show: true, onClose: fn(), onConfirm: fn(), @@ -22,12 +22,12 @@ type Story = StoryObj; export const Confirmation: Story = {}; -export const Loading: Story = { args: { isLoading: true, confirmText: '送信中…' } }; +export const Loading: Story = { args: { isLoading: true, confirmText: '送信中...' } }; export const ConfirmInteraction: Story = { play: async ({ canvasElement, args }) => { const canvas = within(canvasElement.ownerDocument.body); - await userEvent.click(canvas.getByRole('button', { name: '送信する' })); + await userEvent.click(canvas.getByRole('button', { name: '送信' })); await expect(args.onConfirm).toHaveBeenCalledOnce(); }, }; From a14adac1af00deaef6c2427982c2d1d9611046dc Mon Sep 17 00:00:00 2001 From: Arata1202 Date: Sat, 29 Aug 2026 00:04:37 +0900 Subject: [PATCH 12/26] docs(storybook): document application design foundations --- src/stories/Foundations.stories.tsx | 221 +++++++++++++++++++++++----- 1 file changed, 188 insertions(+), 33 deletions(-) diff --git a/src/stories/Foundations.stories.tsx b/src/stories/Foundations.stories.tsx index 6b591294..57b60825 100644 --- a/src/stories/Foundations.stories.tsx +++ b/src/stories/Foundations.stories.tsx @@ -1,53 +1,208 @@ +import type { CSSProperties } from 'react'; import type { Meta, StoryObj } from '@storybook/nextjs-vite'; -const palette = [ - { name: 'Text', variable: '--color-text-main' }, - { name: 'Secondary text', variable: '--color-text-sub' }, - { name: 'Border', variable: '--color-border' }, - { name: 'Focus', variable: '--color-focus-ring' }, - { name: 'Link', variable: '--color-link' }, - { name: 'Soft accent', variable: '--color-accent-soft-bg' }, +type ColorToken = { + name: string; + variable: `--color-${string}`; + value: string; +}; + +type TypographyToken = { + name: string; + variable: `--font-size-${string}`; + value: string; + sample: string; +}; + +const themeColors: ColorToken[] = [ + { name: 'Light background', variable: '--color-theme-light-background', value: '#fff' }, + { name: 'Light text', variable: '--color-theme-light-text', value: '#374151' }, + { name: 'Light border', variable: '--color-theme-light-border', value: '#d1d5db' }, + { name: 'Dark background', variable: '--color-theme-dark-background', value: '#262626' }, + { name: 'Dark text', variable: '--color-theme-dark-text', value: '#fff' }, + { name: 'Dark border', variable: '--color-theme-dark-border', value: '#6b7280' }, +]; + +const contentColors: ColorToken[] = [ + { name: 'Main text', variable: '--color-text-main', value: '#333' }, + { name: 'Secondary text', variable: '--color-text-sub', value: '#999' }, + { name: 'Subtle background', variable: '--color-bg-sub', value: '#f3f3f3' }, + { name: 'Border', variable: '--color-border', value: '#ddd' }, + { name: 'Dark border', variable: '--color-border-dark', value: '#ccc' }, + { name: 'Soft accent background', variable: '--color-accent-soft-bg', value: '#eaf4fc' }, + { name: 'Soft accent text', variable: '--color-accent-soft-text', value: '#111827' }, + { name: 'Link', variable: '--color-link', value: '#1d4ed8' }, + { name: 'Link hover', variable: '--color-link-hover', value: '#1e40af' }, + { name: 'Dark link', variable: '--color-link-dark', value: '#93c5fd' }, + { name: 'Dark link hover', variable: '--color-link-dark-hover', value: '#bfdbfe' }, + { name: 'Code background', variable: '--color-bg-code', value: '#0d1117' }, + { name: 'Code text', variable: '--color-text-code', value: '#c9d1d9' }, + { name: 'Focus ring', variable: '--color-focus-ring', value: '#2563eb' }, ]; +const typography: TypographyToken[] = [ + { + name: 'Heading 1', + variable: '--font-size-content-heading-1', + value: '2rem', + sample: '記事タイトル', + }, + { + name: 'Heading 2', + variable: '--font-size-content-heading-2', + value: '1.6rem', + sample: '大見出し', + }, + { + name: 'Heading 3', + variable: '--font-size-content-heading-3', + value: '1.4rem', + sample: '中見出し', + }, + { + name: 'Heading 4', + variable: '--font-size-content-heading-4', + value: '1.2rem', + sample: '小見出し', + }, + { + name: 'Heading 5', + variable: '--font-size-content-heading-5', + value: '1.1rem', + sample: '補助見出し', + }, + { + name: 'Body', + variable: '--font-size-content-body', + value: '18px', + sample: '記事本文の基準サイズです。', + }, + { + name: 'Small', + variable: '--font-size-content-small', + value: '0.8rem', + sample: '画像キャプションなどの補足情報', + }, +]; + +function TokenDetails({ variable, value }: { variable: string; value: string }) { + return ( +
+ {variable} + {value} +
+ ); +} + +function ColorPalette({ colors }: { colors: ColorToken[] }) { + return ( +
+ {colors.map(({ name, variable, value }) => ( +
+
+ ))} +
+ ); +} + +function TypographyScale() { + return ( +
+ {typography.map(({ name, variable, value, sample }) => { + const style = { + fontSize: `var(${variable})`, + fontWeight: name.startsWith('Heading') ? 'var(--font-weight-content-heading)' : undefined, + lineHeight: name === 'Body' ? 'var(--line-height-content-body)' : undefined, + } satisfies CSSProperties; + + return ( +
+
{sample}
+
{name}
+ +
+ ); + })} +
+ ); +} + function Foundations() { return ( -
-
+
+

Design foundations

-

- Tailwind CSS v4を基礎に、ブログ固有のCSS変数だけを補完しています。 -

+
+ Tailwind CSS v4を基礎に、NextBlogApp固有のCSS変数を補完しています。 +
+
+ +
+

Theme colors

+
-
-

Colors

-
- {palette.map(({ name, variable }) => ( -
-
-
-
{name}
- {variable} -
-
- ))} +
+

Content colors

+ +
+ +
+

Content typography

+
+ 記事本文で使用するサイズ、ウェイト、行間を実際のトークンで表示しています。 +
+ +
+ +
-

Typography

-
Heading 1 / 30px
-
Heading 2 / 24px
-
Heading 3 / 20px
-

Body / 16px — 読みやすい本文の基準サイズです。

-

Small / 14px — 補足情報に使用します。

+

Code

+
+ const theme = 'NextBlogApp'; +
+
+ + + +
-
-

Focus

+
+

Focus

+
Tabキーで、実際のフォーカスリングを確認できます。
- Tabキーでフォーカスを確認 + フォーカス表示を確認 +
+ + + +
); From c05eeef572879ef29cc913cce8df919f2c816970 Mon Sep 17 00:00:00 2001 From: Arata1202 Date: Sat, 29 Aug 2026 00:11:21 +0900 Subject: [PATCH 13/26] test(storybook): keep foundation docs aligned --- .../Common/Markdown/index.stories.tsx | 6 +- src/stories/Foundations.stories.tsx | 65 ++++++++++++++----- 2 files changed, 53 insertions(+), 18 deletions(-) diff --git a/src/components/Common/Markdown/index.stories.tsx b/src/components/Common/Markdown/index.stories.tsx index f62ed07c..4ee667ae 100644 --- a/src/components/Common/Markdown/index.stories.tsx +++ b/src/components/Common/Markdown/index.stories.tsx @@ -1,7 +1,7 @@ import type { Meta, StoryObj } from '@storybook/nextjs-vite'; import Markdown from '.'; -const content = `## 記事本文の見出し +const content = `## 固定ページの見出し 本文には[内部リンク](/profile)と[外部リンク](https://example.com)を含められます。 @@ -29,6 +29,6 @@ const meta = { export default meta; type Story = StoryObj; -export const ArticleContent: Story = { - args: { content, headingIds: ['article-heading', 'list-and-quote', 'code'] }, +export const FixedPageContent: Story = { + args: { content, headingIds: ['page-heading', 'list-and-quote', 'code'] }, }; diff --git a/src/stories/Foundations.stories.tsx b/src/stories/Foundations.stories.tsx index 57b60825..1bc899cb 100644 --- a/src/stories/Foundations.stories.tsx +++ b/src/stories/Foundations.stories.tsx @@ -1,5 +1,6 @@ import type { CSSProperties } from 'react'; import type { Meta, StoryObj } from '@storybook/nextjs-vite'; +import { expect } from 'storybook/test'; type ColorToken = { name: string; @@ -85,6 +86,36 @@ const typography: TypographyToken[] = [ }, ]; +const typographyDetails = [ + { variable: '--font-weight-content-heading', value: '700' }, + { variable: '--line-height-content-body', value: '2' }, +] as const; + +const codeTokens = [ + { + variable: '--font-mono', + value: + 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace', + }, + { variable: '--font-family-content-code', value: 'menlo, inconsolata, monospace' }, + { variable: '--radius-small', value: '4px' }, +] as const; + +const focusTokens = [ + { variable: '--color-focus-ring', value: '#2563eb' }, + { variable: '--focus-ring-width', value: '2px' }, + { variable: '--focus-ring-offset', value: '2px' }, +] as const; + +const documentedTokens = [ + ...themeColors, + ...contentColors, + ...typography, + ...typographyDetails, + ...codeTokens, + ...focusTokens, +]; + function TokenDetails({ variable, value }: { variable: string; value: string }) { return (
@@ -161,8 +192,9 @@ function Foundations() {
- - + {typographyDetails.map((token) => ( + + ))}
@@ -180,15 +212,9 @@ function Foundations() { const theme = 'NextBlogApp';
- - - + {codeTokens.map((token) => ( + + ))}
@@ -199,9 +225,9 @@ function Foundations() { フォーカス表示を確認
- - - + {focusTokens.map((token) => ( + + ))}
@@ -218,4 +244,13 @@ const meta = { export default meta; type Story = StoryObj; -export const Default: Story = {}; +export const Default: Story = { + play: async () => { + const rootStyles = getComputedStyle(document.documentElement); + + for (const { variable, value } of documentedTokens) { + const actualValue = rootStyles.getPropertyValue(variable).trim().replace(/\s+/g, ' '); + await expect(actualValue).toBe(value); + } + }, +}; From a506a645740ce51c8980e2029faf6b3b1d0273ef Mon Sep 17 00:00:00 2001 From: Arata1202 Date: Sat, 29 Aug 2026 00:17:14 +0900 Subject: [PATCH 14/26] test(storybook): satisfy sponsored article constraints --- src/stories/articleFixtures.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/stories/articleFixtures.ts b/src/stories/articleFixtures.ts index 92162b25..0e00a9f0 100644 --- a/src/stories/articleFixtures.ts +++ b/src/stories/articleFixtures.ts @@ -36,6 +36,7 @@ export const sponsoredArticleFixture: Article = { ...articleFixture, id: 'storybook-sponsored-article', isSponsored: true, + sponsorUrl: 'https://sponsor.example.com', }; export const unifiedArticleFixture = { From 8e1c9da2738e2db09b054ab78e058c25c21d84be Mon Sep 17 00:00:00 2001 From: Arata1202 Date: Sat, 29 Aug 2026 00:43:27 +0900 Subject: [PATCH 15/26] test(storybook): cover remaining visual components --- .../Common/AdAlert/index.stories.tsx | 12 ++++ .../Common/ArticleList/index.stories.tsx | 56 +++++++++++++++++++ .../Layouts/ScrollToTop/index.stories.tsx | 22 ++++++++ .../Common/PageHeading/index.stories.tsx | 30 ++++++++++ .../Common/TableOfContent/index.stories.tsx | 12 ++++ .../UnifiedArticleCard/index.stories.tsx | 41 ++++++++++++++ .../Plugins/ImageSlider/index.stories.tsx | 41 ++++++++++++++ .../Elements/Plugins/ImageSlider/index.tsx | 2 +- .../Plugins/RichText/index.stories.tsx | 15 +++++ .../Plugins/SpeechBubble/index.stories.tsx | 29 ++++++++++ .../Elements/Plugins/TabBox/index.stories.tsx | 22 ++++++++ .../Plugins/WantToRead/index.stories.tsx | 13 +++++ .../Elements/Plugins/WantToRead/index.tsx | 4 +- .../Elements/RelatedArticle/index.stories.tsx | 18 ++++++ .../Article/Elements/RelatedArticle/index.tsx | 4 +- .../Elements/InputContainer/index.stories.tsx | 32 +++++++++++ .../Features/SitemapHtml/index.stories.tsx | 34 +++++++++++ src/stories/Foundations.stories.tsx | 12 +++- src/styles/globals.css | 4 +- vitest.config.mts | 3 + 20 files changed, 399 insertions(+), 7 deletions(-) create mode 100644 src/components/Common/AdAlert/index.stories.tsx create mode 100644 src/components/Common/ArticleList/index.stories.tsx create mode 100644 src/components/Common/Layouts/ScrollToTop/index.stories.tsx create mode 100644 src/components/Common/PageHeading/index.stories.tsx create mode 100644 src/components/Common/UnifiedArticleCard/index.stories.tsx create mode 100644 src/components/Features/Article/Elements/Plugins/ImageSlider/index.stories.tsx create mode 100644 src/components/Features/Article/Elements/Plugins/SpeechBubble/index.stories.tsx create mode 100644 src/components/Features/Article/Elements/Plugins/TabBox/index.stories.tsx create mode 100644 src/components/Features/Article/Elements/Plugins/WantToRead/index.stories.tsx create mode 100644 src/components/Features/Article/Elements/RelatedArticle/index.stories.tsx create mode 100644 src/components/Features/Contact/Elements/InputContainer/index.stories.tsx create mode 100644 src/components/Features/SitemapHtml/index.stories.tsx diff --git a/src/components/Common/AdAlert/index.stories.tsx b/src/components/Common/AdAlert/index.stories.tsx new file mode 100644 index 00000000..94dc27d3 --- /dev/null +++ b/src/components/Common/AdAlert/index.stories.tsx @@ -0,0 +1,12 @@ +import type { Meta, StoryObj } from '@storybook/nextjs-vite'; +import AdAlert from '.'; + +const meta = { + title: 'Feedback/Advertising Alert', + component: AdAlert, + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; +export const Default: Story = {}; diff --git a/src/components/Common/ArticleList/index.stories.tsx b/src/components/Common/ArticleList/index.stories.tsx new file mode 100644 index 00000000..a8635365 --- /dev/null +++ b/src/components/Common/ArticleList/index.stories.tsx @@ -0,0 +1,56 @@ +import type { Meta, StoryObj } from '@storybook/nextjs-vite'; +import ArticleList from '.'; +import { articleFixture, unifiedArticleFixture } from '@/stories/articleFixtures'; + +const createdAt = '2026-08-01T09:00:00.000Z'; +const tags = [ + { + id: 'storybook-tag', + name: 'Next.js', + createdAt, + updatedAt: createdAt, + publishedAt: createdAt, + revisedAt: createdAt, + }, +]; +const archiveList = [{ year: '2026', month: '8' }]; + +const meta = { + title: 'Content/Article List', + component: ArticleList, + args: { tags, archiveList }, + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Articles: Story = { + args: { + articles: [ + articleFixture, + { ...articleFixture, id: 'storybook-article-2', title: 'StorybookでUIを確認する方法' }, + ], + }, +}; + +export const MixedSources: Story = { + args: { + articles: [], + mixedArticles: [ + unifiedArticleFixture, + { + ...unifiedArticleFixture, + id: 'storybook-zenn', + source: 'zenn', + url: 'https://zenn.dev/example/articles/storybook', + title: 'Zennで公開した技術記事', + thumbnail: undefined, + thumbnailUrl: '/images/thumbnail/7.webp', + }, + ], + }, +}; + +export const Loading: Story = { args: { articles: [], isLoading: true } }; +export const Empty: Story = { args: { articles: [], emptyMessage: '該当する記事はありません' } }; diff --git a/src/components/Common/Layouts/ScrollToTop/index.stories.tsx b/src/components/Common/Layouts/ScrollToTop/index.stories.tsx new file mode 100644 index 00000000..31ab0ba8 --- /dev/null +++ b/src/components/Common/Layouts/ScrollToTop/index.stories.tsx @@ -0,0 +1,22 @@ +import type { Meta, StoryObj } from '@storybook/nextjs-vite'; +import { expect, fn, userEvent, within } from 'storybook/test'; +import ScrollTopButton from '.'; + +const meta = { + title: 'Navigation/Scroll To Top', + component: ScrollTopButton, + tags: ['autodocs'], +} satisfies Meta; +export default meta; +type Story = StoryObj; +export const Default: Story = {}; +export const ClickInteraction: Story = { + beforeEach: () => { + Object.defineProperty(window, 'scrollTo', { configurable: true, value: fn() }); + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + await userEvent.click(canvas.getByRole('button', { name: 'ページ上部へ戻る' })); + await expect(window.scrollTo).toHaveBeenCalledWith({ top: 0, behavior: 'smooth' }); + }, +}; diff --git a/src/components/Common/PageHeading/index.stories.tsx b/src/components/Common/PageHeading/index.stories.tsx new file mode 100644 index 00000000..cb2c4e00 --- /dev/null +++ b/src/components/Common/PageHeading/index.stories.tsx @@ -0,0 +1,30 @@ +import type { Meta, StoryObj } from '@storybook/nextjs-vite'; +import PageHeading from '.'; + +const meta = { + title: 'Navigation/Page Heading', + component: PageHeading, + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Home: Story = { args: { page: { type: 'home' } } }; +export const Category: Story = { + args: { + page: { + type: 'category', + category: { + id: 'programming', + name: 'プログラミング', + createdAt: '2026-08-01', + updatedAt: '2026-08-01', + publishedAt: '2026-08-01', + revisedAt: '2026-08-01', + }, + }, + }, +}; +export const Search: Story = { args: { page: { type: 'search', searchKeyword: 'Next.js' } } }; +export const SearchLoading: Story = { args: { page: { type: 'search' }, isLoading: true } }; diff --git a/src/components/Common/TableOfContent/index.stories.tsx b/src/components/Common/TableOfContent/index.stories.tsx index 8eb42788..26f10703 100644 --- a/src/components/Common/TableOfContent/index.stories.tsx +++ b/src/components/Common/TableOfContent/index.stories.tsx @@ -20,3 +20,15 @@ type Story = StoryObj; export const Default: Story = { args: { headings } }; export const Sidebar: Story = { args: { headings, sidebar: true } }; + +export const DeepHierarchy: Story = { + args: { + headings: [ + { id: 'overview', title: '概要', level: 2 }, + { id: 'configuration', title: '設定', level: 3 }, + { id: 'advanced', title: '詳細設定', level: 4 }, + { id: 'verification', title: '動作確認で確認しておきたい長い見出し', level: 2 }, + ], + }, + globals: { viewport: { value: 'mobile1', isRotated: false } }, +}; diff --git a/src/components/Common/UnifiedArticleCard/index.stories.tsx b/src/components/Common/UnifiedArticleCard/index.stories.tsx new file mode 100644 index 00000000..a1d50a2e --- /dev/null +++ b/src/components/Common/UnifiedArticleCard/index.stories.tsx @@ -0,0 +1,41 @@ +import type { Meta, StoryObj } from '@storybook/nextjs-vite'; +import UnifiedArticleCard from '.'; +import { unifiedArticleFixture } from '@/stories/articleFixtures'; + +const meta = { + title: 'Content/Unified Article Card', + component: UnifiedArticleCard, + decorators: [ + (Story) => ( +
    + +
+ ), + ], + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Blog: Story = { args: { article: unifiedArticleFixture } }; + +export const Zenn: Story = { + args: { + article: { + ...unifiedArticleFixture, + id: 'storybook-zenn-article', + title: 'Zennで公開した技術記事', + url: 'https://zenn.dev/example/articles/storybook', + source: 'zenn', + thumbnail: undefined, + thumbnailUrl: '/images/thumbnail/7.webp', + }, + }, +}; + +export const Sponsored: Story = { + args: { + article: { ...unifiedArticleFixture, id: 'storybook-unified-sponsored', isSponsored: true }, + }, +}; diff --git a/src/components/Features/Article/Elements/Plugins/ImageSlider/index.stories.tsx b/src/components/Features/Article/Elements/Plugins/ImageSlider/index.stories.tsx new file mode 100644 index 00000000..f984a5ae --- /dev/null +++ b/src/components/Features/Article/Elements/Plugins/ImageSlider/index.stories.tsx @@ -0,0 +1,41 @@ +import type { Meta, StoryObj } from '@storybook/nextjs-vite'; +import { expect, userEvent, waitFor, within } from 'storybook/test'; +import ImageSlider from '.'; + +const images = [ + { url: '/images/post/1.webp', width: 1200, height: 630 }, + { url: '/images/post/2.webp', width: 1200, height: 630 }, +]; + +const meta = { + title: 'Content/Article Plugins/Image Slider', + component: ImageSlider, + args: { block: { image_slider: images }, imageAltFallback: '記事の説明画像' }, + decorators: [ + (Story) => ( +
+ +
+ ), + ], + tags: ['autodocs'], +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const MultipleImages: Story = {}; +export const SingleImage: Story = { args: { block: { image_slider: [images[0]] } } }; +export const Mobile: Story = { globals: { viewport: { value: 'mobile1', isRotated: false } } }; +export const NextImageInteraction: Story = { + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + await userEvent.click(await canvas.findByRole('button', { name: '次の画像を表示' })); + await waitFor(() => { + expect(canvas.getByRole('button', { name: '2枚目の画像を表示中' })).toHaveAttribute( + 'aria-current', + 'true', + ); + }); + }, +}; diff --git a/src/components/Features/Article/Elements/Plugins/ImageSlider/index.tsx b/src/components/Features/Article/Elements/Plugins/ImageSlider/index.tsx index 77b65dca..97bc03e4 100644 --- a/src/components/Features/Article/Elements/Plugins/ImageSlider/index.tsx +++ b/src/components/Features/Article/Elements/Plugins/ImageSlider/index.tsx @@ -147,7 +147,7 @@ export default function ImageSlider({ block, imageAltFallback }: Props) { className={styles.slider} prevArrow={} nextArrow={} - afterChange={setCurrentSlide} + beforeChange={(_, nextSlide) => setCurrentSlide(nextSlide)} customPaging={(index) => (