ds-react smoke test
+ +Clicks: {clicks}
+Input value: {inputValue}
+Checked: {String(checked)}
+diff --git a/.changeset/tame-hounds-yell.md b/.changeset/tame-hounds-yell.md new file mode 100644 index 0000000000..7954f9430d --- /dev/null +++ b/.changeset/tame-hounds-yell.md @@ -0,0 +1,7 @@ +--- +'@baloise/ds-react': minor +'@baloise/ds-core': patch +--- + +**react**: add `@baloise/ds-react`, generated React component wrappers for the design system, plus a `useDesignSystem()` bootstrapping helper +**core**: wire up the Stencil React output target (`@stencil/react-output-target`) to generate `@baloise/ds-react`'s bindings on build diff --git a/.github/workflows/actions/archive-download/action.yml b/.github/workflows/actions/archive-download/action.yml index 0028968f54..7d73764634 100644 --- a/.github/workflows/actions/archive-download/action.yml +++ b/.github/workflows/actions/archive-download/action.yml @@ -14,7 +14,7 @@ runs: using: 'composite' steps: - name: Download Archive - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: ${{ inputs.name }} path: ${{ inputs.path }} diff --git a/.github/workflows/actions/archive-upload/action.yml b/.github/workflows/actions/archive-upload/action.yml index f52ae68142..32143477bc 100644 --- a/.github/workflows/actions/archive-upload/action.yml +++ b/.github/workflows/actions/archive-upload/action.yml @@ -21,7 +21,7 @@ runs: run: zip -q -r ${{ inputs.output }} ${{ inputs.paths }} shell: bash - name: Upload Archive - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: ${{ inputs.name }} path: ${{ inputs.output }} diff --git a/.github/workflows/actions/setup-environment/action.yml b/.github/workflows/actions/setup-environment/action.yml index 8ad89d78aa..149ba9fcc2 100644 --- a/.github/workflows/actions/setup-environment/action.yml +++ b/.github/workflows/actions/setup-environment/action.yml @@ -43,7 +43,7 @@ runs: git log -1 --oneline - name: Setup pnpm - uses: pnpm/action-setup@v4 + uses: pnpm/action-setup@v6 - name: Setup Node.js environment uses: actions/setup-node@v6 @@ -51,7 +51,6 @@ runs: node-version: 24 cache: 'pnpm' registry-url: 'https://registry.npmjs.org' - always-auth: true ## setup-node writes the registry config to a runner-temp .npmrc (not the ## repo checkout or $HOME) and resolves the auth token from NODE_AUTH_TOKEN diff --git a/.github/workflows/continuous.yml b/.github/workflows/continuous.yml index 78d0a2f142..e8d193599a 100644 --- a/.github/workflows/continuous.yml +++ b/.github/workflows/continuous.yml @@ -152,3 +152,53 @@ jobs: name: playwright-report-shard-${{ matrix.shardIndex }} path: packages/core/playwright-report retention-days: 7 + + react: + name: ๐งช React + runs-on: ubuntu-24.04 + timeout-minutes: 30 + needs: [assembleInformation] + env: + HUSKY: 0 + CI: 1 + strategy: + fail-fast: false + matrix: + apps: [v19] + steps: + - name: Check out code + uses: actions/checkout@v7 + with: + ref: ${{ needs.assembleInformation.outputs.branch }} + fetch-depth: 2 + + - uses: ./.github/workflows/actions/setup-environment + with: + branch: ${{ needs.assembleInformation.outputs.branch }} + action: ${{ needs.assembleInformation.outputs.action }} + + - name: Install dependencies + run: pnpm install --frozen-lockfile + + - name: Scaffold and link the ${{ matrix.apps }} smoke-test app + run: bash test/react/build.sh ${{ matrix.apps }} + + - name: Install Playwright browsers + working-directory: test/react/${{ matrix.apps }} + run: pnpm exec playwright install --with-deps chromium + + - name: Build app + working-directory: test/react/${{ matrix.apps }} + run: pnpm run build + + - name: Run Playwright tests + working-directory: test/react/${{ matrix.apps }} + run: pnpm exec playwright test + + - name: Upload Playwright HTML report + if: always() + uses: actions/upload-artifact@v7 + with: + name: react-playwright-report-${{ matrix.apps }} + path: test/react/${{ matrix.apps }}/playwright-report + retention-days: 7 diff --git a/CONTEXT-MAP.md b/CONTEXT-MAP.md index a5ae4a1ccd..2333380ac3 100644 --- a/CONTEXT-MAP.md +++ b/CONTEXT-MAP.md @@ -12,6 +12,7 @@ This file maps the multi-context layout of this monorepo. Each context has its o | **CSS & Styles** | `packages/css/CONTEXT.md` | Global CSS, utility classes, responsive design, theming, CSS variable conventions | | **Assets** | `packages/assets/CONTEXT.md` | Fonts, icons, images, asset management, brand guidelines | | **Playwright** | `packages/playwright/CONTEXT.md` | E2E testing library, page objects, accessibility testing, visual regression | +| **React Bindings** | `packages/react/CONTEXT.md` | Generated React component wrappers, `useDesignSystem()` bootstrapping | | **Documentation** | `docs/CONTEXT.md` | Storybook setup, documentation patterns, MDX authoring, component showcase | | **Internal Libraries** | `libs/CONTEXT.md` | ESLint plugin, output targets (Angular), shared utilities, code generation | diff --git a/docs/adr/0003-ds-react-no-custom-output-target.md b/docs/adr/0003-ds-react-no-custom-output-target.md new file mode 100644 index 0000000000..6240ca501e --- /dev/null +++ b/docs/adr/0003-ds-react-no-custom-output-target.md @@ -0,0 +1,51 @@ +# 3. `ds-react` uses the off-the-shelf Stencil React output target directly, no custom `libs/output-target-react` + +Date: 2026-07-21 + +## Status + +Accepted + +## Context + +`libs/output-target-angular` exists as a custom package because Angular +bindings need non-trivial extra logic: `ValueAccessorConfig`s that wire +form components (`ds-select`, `ds-checkbox`, `ds-date`, โฆ) into Angular's +`ControlValueAccessor`/reactive-forms machinery, which the stock +`@angular/*` output-targets ecosystem doesn't provide out of the box. +That custom layer is why `libs/output-target-angular` is its own package +with its own generator code (`generate-angular-component.ts`, +`generate-value-accessors.ts`, etc.). + +React has no equivalent problem. `@stencil/react-output-target` already +generates typed function-component wrappers with JSX props/events for +every Stencil component, and the previous Baloise design system (see +`packages/core/config/stencil.bindings.react.ts` on the old +`design-system` `main` branch) only ever called `reactOutputTarget(...)` +directly from a thin config file โ it never needed a custom wrapper +package for React, unlike Angular. + +## Decision + +`ds-react` bindings are generated by calling `reactOutputTarget()` from +`@stencil/react-output-target` directly inside a new +`packages/core/config/stencil.bindings.react.ts`, registered in +`stencil.config.ts`'s `outputTargets`. No `libs/output-target-react` +package is created. No `excludeComponents` are configured โ every +`ds-*` component gets a React wrapper, and no React-specific +value-accessor-style exclusions are needed, because React consumers +handle controlled/uncontrolled state themselves via the generated +props/events, not via a forms integration layer. + +## Consequences + +- Less code to own and test than Angular's binding layer โ the generated + wrappers are a direct pass-through of Stencil's component metadata. +- If a genuine React-specific customization need shows up later (e.g. a + custom prop-forwarding rule, a Next.js-specific wrapper), it will need + its own design โ this ADR does not rule that out, it just says today's + scope doesn't require it. +- Keeps `libs/output-target-angular` as the only precedent for "custom + output-target logic," which should make it obvious to a future reader + that React was a deliberate case of "the stock tool was enough," not an + oversight. diff --git a/docs/adr/0004-react-smoke-test-app-outside-workspace.md b/docs/adr/0004-react-smoke-test-app-outside-workspace.md new file mode 100644 index 0000000000..7c4cf675b4 --- /dev/null +++ b/docs/adr/0004-react-smoke-test-app-outside-workspace.md @@ -0,0 +1,50 @@ +# 4. React framework smoke-test app lives outside the pnpm workspace, linked via `pnpm link` + +Date: 2026-07-21 + +## Status + +Accepted + +## Context + +The design system is a pnpm workspace managed by Turborepo. If the React +smoke-test app (`test/react/v19`, generated by `test/react/build.sh`) were +added as a workspace member, `@baloise/ds-react` and `@baloise/ds-core` +would resolve to each other purely through pnpm's workspace protocol โ +symlinks into the monorepo's own `node_modules`, bypassing npm package +resolution entirely. + +The old Baloise design system's equivalent app (`test/react/v19` on the +`main` branch of the previous repo) deliberately lived outside its Nx +workspace and linked to the built packages via `npm link`, simulating what +an external consumer actually experiences: installing `@baloise/ds-react` +from the registry and resolving it through its `package.json` +`exports`/`main`/`peerDependencies`. That's the whole point of the smoke +test โ catching packaging problems (wrong `exports` map, a dependency +that should have been a `peerDependency`, a file missing from `files:`) +that workspace-protocol resolution can silently paper over. + +## Decision + +`test/react/` stays outside the pnpm workspace (not listed in the root +`pnpm-workspace.yaml`). `test/react/build.sh` builds `@baloise/ds-core` +and `@baloise/ds-react` from their `dist/` output and links them into the +generated app via `pnpm link`, mirroring the old repo's `npm link` +approach. The generated app has its own `package.json`, +`node_modules`, and lockfile, entirely separate from the monorepo's. + +## Consequences + +- The smoke test actually exercises the published package shape, not just + the source tree โ a real regression class (broken `exports`, missing + build output, wrong peer dependency) is caught here that a workspace + member app would miss. +- Slightly more setup than a workspace-member app would need: `build.sh` + has to build and link explicitly rather than relying on pnpm's automatic + workspace symlinking, and CI has to run that script rather than just + `pnpm install`. +- This app is intentionally _not_ wired through `turbo run` as a workspace + task โ it's invoked directly (`bash test/react/build.sh v19`, then + `pnpm --dir test/react/v19 ...`), both from CI and from the root + `react:app` convenience script. diff --git a/docs/adr/0005-duplicate-pnpm-overrides.md b/docs/adr/0005-duplicate-pnpm-overrides.md new file mode 100644 index 0000000000..51ade44685 --- /dev/null +++ b/docs/adr/0005-duplicate-pnpm-overrides.md @@ -0,0 +1,66 @@ +# 5. Duplicate pnpm `overrides` in both `pnpm-workspace.yaml` and `package.json` + +Date: 2026-07-21 + +## Status + +Accepted + +## Context + +pnpm dependency overrides (used here to force patched versions of +transitive devDependencies like `brace-expansion` and `js-yaml` that carry +high-severity advisories) moved from `package.json`'s `pnpm.overrides` +field to `pnpm-workspace.yaml`'s `overrides` field in pnpm 11. Running +`pnpm install` locally (pnpm 11.12.0) now prints: + +``` +[WARN] The "pnpm" field in package.json is no longer read by pnpm. The +following keys were ignored: "pnpm.overrides". +``` + +...and only applies the `pnpm-workspace.yaml` copy. This makes the +`package.json` copy look like dead config that should be deleted. + +It isn't. Removing it broke the Vercel build: `pnpm install +--frozen-lockfile` (configured in `vercel.json`) failed there once +`package.json`'s `pnpm.overrides` no longer matched what the lockfile +expected, even though `pnpm-workspace.yaml`'s `overrides` were untouched +and the exact same `pnpm@11.12.0` is pinned via `packageManager` and +resolved through corepack (`ENABLE_EXPERIMENTAL_COREPACK=1`). In practice, +Vercel's install path is sensitive to the `package.json` copy in a way +local pnpm is not. + +## Decision + +Keep both override blocks โ `overrides` in `pnpm-workspace.yaml` and +`pnpm.overrides` in `package.json` โ and require them to stay identical. + +Enforcement: + +- `scripts/check-overrides.mjs` parses both files and fails if the + override sets don't match exactly (ignoring an informational + `_comment` key in `package.json`'s block, see below). +- The root `lint` script (`package.json`) runs this check after `turbo +run lint`, so it runs in CI alongside normal linting and fails the + build on drift. +- Each file carries a short comment pointing at the other and at this + ADR. `package.json` is strict JSON and can't hold a `//` comment, so + the pointer lives as a `_comment` string _sibling_ of `overrides` + inside the `pnpm` object โ not a key inside the `overrides` map + itself, where pnpm would try to parse it as a `package@range` rule + and fail on `"Kept in sync..."` not being a valid version. + +When adding, changing, or removing an override: update both files in the +same commit. The check script will catch it if you forget. + +## Consequences + +- Two files to touch for one logical change; mildly annoying but cheap + compared to a broken Vercel deploy. +- The `_comment` key is invisible to pnpm's override resolution (it's + outside the `overrides` map) but is technically dead data from pnpm's + point of view โ it exists purely for the next human reading the file. +- If a future pnpm/Vercel upgrade makes `pnpm-workspace.yaml` the single + source of truth everywhere, this ADR and the duplication it describes + should be revisited and likely deleted. diff --git a/docs/plans/ds-react-implementation-plan.md b/docs/plans/ds-react-implementation-plan.md new file mode 100644 index 0000000000..04997be3d4 --- /dev/null +++ b/docs/plans/ds-react-implementation-plan.md @@ -0,0 +1,148 @@ +# Implementation Plan: `ds-react` package + +Status: ready for implementation. Nothing in this plan has been implemented or committed yet. + +Related decisions: [ADR-0003](../adr/0003-ds-react-no-custom-output-target.md) (no custom output-target lib), [ADR-0004](../adr/0004-react-smoke-test-app-outside-workspace.md) (smoke-test app lives outside the workspace). + +## Scope + +Add React bindings for the Stencil component library, generated by +`@stencil/react-output-target`, published as `@baloise/ds-react`, verified +in CI by scaffolding a real (outside-workspace) React app and running +Playwright against it, plus a one-command local script to scaffold that +same app for manual poking. + +Explicitly out of scope for this pass: SSR/hydrate support +(`hydrateModule`), a custom `libs/output-target-react`, reusing +`packages/playwright`'s component-mount fixtures, and re-enabling the +still-dormant Angular pipeline. + +## Steps + +### 1. Stencil output target (`packages/core`) + +- [ ] Add `@stencil/react-output-target` as a dev dependency of + `packages/core`. +- [ ] Add `packages/core/config/stencil.bindings.react.ts`: + ```ts + import { reactOutputTarget } from '@stencil/react-output-target' + import { docComponents } from './doc.components' + + export const ReactGenerator = () => + reactOutputTarget({ + outDir: '../react/src/generated', + excludeComponents: docComponents, + customElementsDir: 'components', + }) + ``` +- [ ] In `stencil.config.ts`, uncomment/replace the `ReactGenerator` import + and add it to `outputTargets` (guarded the same way as the other + `!IS_DS_DEVELOPMENT && !IS_DS_DOCUMENTATION` targets). +- [ ] `pnpm build` (core) and confirm `packages/react/src/generated/*` is + produced. + +### 2. New package `packages/react` (`@baloise/ds-react`) + +- [ ] `package.json`: + - `name: "@baloise/ds-react"`, version matching current DS versioning. + - `peerDependencies`: `react`, `react-dom`. + - `dependencies`: `@stencil/react-output-target`, `@baloise/ds-core`. + - `scripts.build`: `tsc` (matches `packages/tokens`, `libs/output-target-angular` convention โ no bundler). + - `files: ["dist/"]`. +- [ ] `tsconfig.json` / `tsconfig.lib.json` per repo convention. +- [ ] `src/index.ts`: + ```ts + import type { BalConfig } from '@baloise/ds-core/components' + import { initializeBaloiseDesignSystem } from '@baloise/ds-core/components' + + interface BaloiseDesignSystemReactConfig { + defaults?: BalConfig + } + + export const useBaloiseDesignSystem = (config: BaloiseDesignSystemReactConfig = {}) => { + initializeBaloiseDesignSystem({ + ...config.defaults, + httpFormSubmit: false, + }) + } + + export * from './generated/components' + ``` + (adjust import names to match this repo's actual `@baloise/ds-core` + init API โ confirm the equivalent of `initializeBaloiseDesignSystem` + before copying verbatim.) +- [ ] `eslint.config.js` / lint config per repo convention. +- [ ] `packages/react/CONTEXT.md` documenting the package (purpose, that + it's a thin re-export layer, pointer to ADR-0003). +- [ ] Add a row for the new context in root `CONTEXT-MAP.md`. +- [ ] `pnpm changeset` entry for the new package. + +### 3. Framework smoke-test app template (`test/react/`) + +- [ ] `test/react/base/app/`: Vite + React scaffold (`src/App.tsx`, + `src/main.tsx`, `index.html`, `vite.config.ts`, `tsconfig*.json`, + `eslint.config.js`) exercising a representative set of components, + including at least one form component. +- [ ] `test/react/base/app/playwright.config.ts` + `e2e/*.spec.ts`: + standalone Playwright config (not `packages/playwright`'s + fixtures) โ specs covering: app renders, a component emits an + event on interaction (e.g. button click / input change), no + console errors on load. +- [ ] `test/react/base/v19/package.json`: version overlay pinning + `react`/`react-dom` to the latest major, plus `@playwright/test` + devDependency, `scripts.link` (pnpm link step), `scripts.copy` + (copies `packages/react/src` into `src/generated`, mirroring old + repo's `copy.sh`). +- [ ] `test/react/build.sh`: clean + copy `base/app` + version overlay + into `test/react/v19/`, then build `@baloise/ds-core` and + `@baloise/ds-react`, then `pnpm link` them into the generated app + (per ADR-0004) โ not a pnpm workspace member. +- [ ] `test/react/start.sh`: starts the generated app's dev server. +- [ ] Ensure `test/react/` (except `base/`) is gitignored โ it's + generated output. + +### 4. Root convenience script + +- [ ] Add `react:app` (naming TBD at implementation time โ check for + collisions with existing script names) to root `package.json`, + running `build.sh v19` then `start.sh v19`, so `pnpm react:app` + scaffolds and launches the app in one command, alongside + `pnpm start` / `pnpm docs`. + +### 5. CI (`.github/workflows/continuous.yml`) + +- [ ] Add a `react:` job: + - `needs: [build]` + - `strategy.matrix.apps: [v19]` (single entry, structured so a second + version overlay + matrix entry is a copy-paste addition later) + - Steps: checkout โ `./.github/workflows/actions/setup-environment` โ + `pnpm install --frozen-lockfile` โ `pnpm exec turbo run build + --filter=@baloise/ds-core --filter=@baloise/ds-react` โ `bash + test/react/build.sh ${{ matrix.apps }}` โ `pnpm exec playwright + install --with-deps chromium` (in the generated app dir) โ run the + generated app's Playwright tests โ upload the HTML report as an + artifact on failure (same pattern as the existing `playwright` job). + - No per-package archive-download plumbing needed โ matches how the + existing `playwright` job rebuilds fresh via `turbo` rather than + downloading `upload-distribution-archives` zips. + +### 6. Docs / cleanup + +- [ ] Update `TODOS.md`: mark "Anuglar React โ Add frameworks back after + migrating too shadow dom" as at least partially done, or split into + separate Angular/React rows if Angular is still pending. +- [ ] Confirm `README.md` / `docs/` mention `@baloise/ds-react` alongside + the other published packages once it's ready to publish. + +## Open items to confirm during implementation + +- Exact name/API of `@baloise/ds-core`'s init function (the old + `initializeBaloiseDesignSystem` may have a different name in this repo) + โ check `packages/core/src` before copying `index.ts` verbatim. +- Exact root script name for step 4 (`react:app` vs alternative) โ check + for naming collisions in root `package.json` at implementation time. +- Whether any components need excluding beyond `docComponents` (form + components did *not* need excluding for Angular's raw wrapper either โ + only Angular's *value-accessor* layer treats them specially โ so the + expectation is no additional exclusions for React, but verify once the + first build runs). diff --git a/package.json b/package.json index 6725e61fb1..dd29a3150c 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "homepage": "https://design.baloise.dev", "security": "https://github.com/baloise/design-system/security/advisories/new", "license": "Apache-2.0", - "packageManager": "pnpm@11.12.0", + "packageManager": "pnpm@11.15.1", "engines": { "node": ">=24 <25" }, @@ -16,6 +16,7 @@ "start:force": "turbo run build --force && pnpm start", "docs": "turbo run build --filter=@baloise/ds-core && node scripts/build-docs.mjs --serve && storybook dev -p 6006 --config-dir docs/.storybook", "docs:preview": "turbo run build --filter=@baloise/ds-core --force && node scripts/build-docs.mjs && http-server docs/dist -p 6006", + "react:app": "bash test/react/build.sh v19 && bash test/react/start.sh v19", "_playwright": "=============================================== Playwright =================================================", "play": "pnpm --filter @baloise/ds-core play", "play:file": "pnpm --filter @baloise/ds-core play:file", @@ -32,7 +33,7 @@ "assets": "turbo run build --filter=@baloise/ds-assets --force", "core": "turbo run build --filter=@baloise/ds-core --force", "_test": "===================================================== Test & Lint ===============================================", - "lint": "turbo run lint", + "lint": "turbo run lint && node scripts/check-overrides.mjs", "test": "turbo run test", "_utilities": "================================================ Utilities =================================================", "kill:ports": "node -e \"require('kill-port')(4000).catch(()=>{})\"", @@ -75,6 +76,7 @@ "fast-glob": "3.3.3", "fs-extra": "catalog:", "glob": "13.0.6", + "js-yaml": "4.3.0", "jsdom": "29.1.1", "jsonc-eslint-parser": "3.1.0", "kill-port": "2.0.1", @@ -99,8 +101,12 @@ "@oxc-parser/binding-linux-x64-gnu": "0.140.0" }, "pnpm": { + "_comment": "overrides below kept in sync with pnpm-workspace.yaml โ required for Vercel installs. See docs/adr/0005-duplicate-pnpm-overrides.md", "overrides": { - "@swc/cli>minimatch@9>brace-expansion": "2.1.2" + "brace-expansion@>=2.0.0 <2.1.2": "2.1.2", + "brace-expansion@>=3.0.0 <5.0.7": "5.0.7", + "js-yaml@>=4.0.0 <4.3.0": "4.3.0", + "js-yaml@>=3.0.0 <3.15.0": "3.15.0" } } } diff --git a/packages/core/config/doc.components.ts b/packages/core/config/doc.components.ts deleted file mode 100644 index 16ad8f40c1..0000000000 --- a/packages/core/config/doc.components.ts +++ /dev/null @@ -1 +0,0 @@ -export const docComponents = ['ds-doc-app'] diff --git a/packages/core/config/stencil.bindings.angular.ts b/packages/core/config/stencil.bindings.angular.ts index 3bfce2a5b3..6c6999c8f8 100644 --- a/packages/core/config/stencil.bindings.angular.ts +++ b/packages/core/config/stencil.bindings.angular.ts @@ -1,5 +1,4 @@ import { ValueAccessorConfig, angularOutputTarget } from 'libs-output-target-angular' -import { docComponents } from './doc.components' export const angularValueAccessorBindings: ValueAccessorConfig[] = [ { @@ -45,7 +44,6 @@ export const AngularGenerator = () => directivesArrayFile: '../angular/src/generated/proxies-list.ts', valueAccessorConfigs: angularValueAccessorBindings, excludeComponents: [ - ...docComponents, 'ds-segment', 'ds-checkbox-group', 'ds-checkbox', diff --git a/packages/core/config/stencil.bindings.react.ts b/packages/core/config/stencil.bindings.react.ts index d719267c33..f845d95327 100644 --- a/packages/core/config/stencil.bindings.react.ts +++ b/packages/core/config/stencil.bindings.react.ts @@ -1,9 +1,7 @@ import { reactOutputTarget } from '@stencil/react-output-target' -import { docComponents } from './doc.components' export const ReactGenerator = (): any => reactOutputTarget({ outDir: '../react/src/generated', - excludeComponents: docComponents, customElementsDir: 'components', }) diff --git a/packages/core/package.json b/packages/core/package.json index 4ff682ffa9..e6b0d8e1d6 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -60,6 +60,7 @@ }, "devDependencies": { "@baloise/ds-playwright": "20.0.0-next.4", + "@stencil/react-output-target": "1.6.1", "@types/lodash": "4.17.24", "@types/luxon": "3.7.2", "compression": "catalog:", diff --git a/packages/core/src/utils/helpers.ts b/packages/core/src/utils/helpers.ts index a0f666b405..92419c2776 100644 --- a/packages/core/src/utils/helpers.ts +++ b/packages/core/src/utils/helpers.ts @@ -6,6 +6,14 @@ import { type DsConfig } from '@global' declare const __zone_symbol__requestAnimationFrame: any declare const requestAnimationFrame: any +// Reads the live config directly off `window` instead of importing `useDsConfig` from '@global', +// which would pull in a module cycle that isn't resolved yet when this file's exports are called +// eagerly at other modules' top level (e.g. breakpoints.subject.ts -> window-resize.listener.ts). +const getDsConfig = (): DsConfig | undefined => { + const win = window as any + return win && win.DesignSystem && win.DesignSystem.config +} + /** * Request Largest Contentful Paint (LCP) callback */ @@ -226,21 +234,9 @@ const transitionEnd = ( export const addEventListener = (el: any, eventName: string, callback: any, opts?: any) => { if (dsBrowser.hasWindow) { - // Lazy import to break circular dependency: import only when function is called - try { - // eslint-disable-next-line @typescript-eslint/no-require-imports - const { useDsConfig } = require('@global') as typeof import('@global') - const config = useDsConfig() - if (config) { - const ael = config._ael - if (ael) { - return ael(el, eventName, callback, opts) - } else if (config._ael) { - return config._ael(el, eventName, callback, opts) - } - } - } catch { - // Fallback if @global is not yet initialized + const config = getDsConfig() + if (config && config._ael) { + return config._ael(el, eventName, callback, opts) } } @@ -249,21 +245,9 @@ export const addEventListener = (el: any, eventName: string, callback: any, opts export const removeEventListener = (el: any, eventName: string, callback: any, opts?: any) => { if (dsBrowser.hasWindow) { - // Lazy import to break circular dependency: import only when function is called - try { - // eslint-disable-next-line @typescript-eslint/no-require-imports - const { useDsConfig } = require('@global') as typeof import('@global') - const config = useDsConfig() - if (config) { - const rel = config._rel - if (rel) { - return rel(el, eventName, callback, opts) - } else if (config._rel) { - return config._rel(el, eventName, callback, opts) - } - } - } catch { - // Fallback if @global is not yet initialized + const config = getDsConfig() + if (config && config._rel) { + return config._rel(el, eventName, callback, opts) } } diff --git a/packages/core/src/utils/number.ts b/packages/core/src/utils/number.ts index ece608b256..641577182a 100644 --- a/packages/core/src/utils/number.ts +++ b/packages/core/src/utils/number.ts @@ -1,18 +1,12 @@ -import { defaultLocale } from '@global' +import { defaultLocale, useDsConfig } from '@global' const getLocale = (): string => { - try { - // eslint-disable-next-line @typescript-eslint/no-require-imports - const { useDsConfig } = require('@global') as typeof import('@global') - const config = useDsConfig() - // workaround for swiss french locale which uses non standard number formatting - if (config && config.locale && config.locale === 'fr-CH') { - return 'de-CH' - } - return (config && config.locale) || defaultLocale - } catch { - return defaultLocale + const config = useDsConfig() + // workaround for swiss french locale which uses non standard number formatting + if (config && config.locale && config.locale === 'fr-CH') { + return 'de-CH' } + return (config && config.locale) || defaultLocale } export function getDecimalSeparator(): string { diff --git a/packages/core/stencil.config.ts b/packages/core/stencil.config.ts index 381861418d..12e3fae34d 100644 --- a/packages/core/stencil.config.ts +++ b/packages/core/stencil.config.ts @@ -7,7 +7,7 @@ import { join, parse, resolve } from 'path' import { webOutputTarget } from 'libs-output-target-web' import { enrichComponentDocsJson } from './config/docs-json-no-timestamp' // import { AngularGenerator } from './config/stencil.bindings.angular' -// import { ReactGenerator } from './config/stencil.bindings.react' +import { ReactGenerator } from './config/stencil.bindings.react' const IS_DS_RELEASE = process.env.DS_RELEASE === 'true' const IS_DS_DEVELOPMENT = process.env.DS_DEVELOPMENT === 'true' @@ -126,6 +126,13 @@ export const config: Config = { webOutputTarget({ dir: 'components', }), + /** + * Generates React component wrappers for each Stencil component in ../react/src/generated, + * consumed by the @baloise/ds-react package. Requires the dist-custom-elements output target above. + * + * {@link https://www.npmjs.com/package/@stencil/react-output-target} + */ + !IS_DS_DEVELOPMENT && !IS_DS_DOCUMENTATION && ReactGenerator(), /** * The www output target type is oriented for webapps and websites, hosted from an http server, which can benefit * from prerendering and service workers, such as this very site you're reading. If the outputTarget config is not diff --git a/packages/react/CONTEXT.md b/packages/react/CONTEXT.md new file mode 100644 index 0000000000..35aebdf730 --- /dev/null +++ b/packages/react/CONTEXT.md @@ -0,0 +1,37 @@ +# CONTEXT โ packages/react (React Bindings) + +This document captures domain language, architectural patterns, and key concepts specific to the React bindings package. + +## Overview + +**packages/react** (`@baloise/ds-react`) is a thin, published wrapper around the Stencil-generated web components in `packages/core`, giving React consumers typed function-component wrappers (props, typed events, refs) instead of raw custom elements. + +It is generated, not hand-authored: the React wrappers themselves come from `@stencil/react-output-target`, invoked directly from `packages/core/config/stencil.bindings.react.ts` as part of the core build (see [[packages/core|packages/core/CONTEXT.md]]). Unlike Angular bindings, this package needs no custom output-target logic โ see [ADR-0003](../../docs/adr/0003-ds-react-no-custom-output-target.md). + +## Core Concepts + +### Generated vs. authored code + +- `src/generated/components.ts` โ fully generated by the Stencil React output target on every `@baloise/ds-core` build. Never hand-edited; regenerates from scratch each build. +- `src/index.ts` โ the only hand-authored file. Re-exports the generated components and exposes `bootstrapDesignSystem()`, a thin call into `@baloise/ds-core`'s `initializeDesignSystem()` for React apps that want to set brand/region/language defaults. + +### Build + +Plain `tsc` compile (`tsc -p tsconfig.lib.json`), matching `packages/tokens` and `libs/output-target-angular` โ no bundler, since this package is a straight re-export layer. + +### Verifying the package works + +The package's real-world behavior (does it actually work when installed by a React app?) is verified separately by the framework smoke-test app in `test/react/`, not by unit tests in this package. See the root `CONTEXT.md` / `docs/adr/0004-react-smoke-test-app-outside-workspace.md` for why that app deliberately lives outside the pnpm workspace. + +## Key Constraints + +- `react` / `react-dom` are `peerDependencies` โ consumers supply their own version. +- No SSR/hydrate support yet (`hydrateModule` is not configured) โ client-side only. +- No component exclusions โ every `ds-*` component gets a React wrapper. + +## Related Contexts + +See [CONTEXT-MAP.md](../../CONTEXT-MAP.md) for: + +- [[packages/core|packages/core/CONTEXT.md]] โ owns the Stencil components and the output target that generates this package's bindings +- [[root|CONTEXT.md]] โ repository-level concepts diff --git a/packages/react/eslint.config.ts b/packages/react/eslint.config.ts new file mode 100644 index 0000000000..a6d3fa264e --- /dev/null +++ b/packages/react/eslint.config.ts @@ -0,0 +1,4 @@ +import tseslint from 'typescript-eslint' +import baseConfig from '../../eslint.config.base' + +export default tseslint.config(...baseConfig) diff --git a/packages/react/package.json b/packages/react/package.json new file mode 100644 index 0000000000..4b989a4f3c --- /dev/null +++ b/packages/react/package.json @@ -0,0 +1,43 @@ +{ + "name": "@baloise/ds-react", + "version": "20.0.0-next.4", + "description": "The Helvetia Design System is an open source project for styling awesome web applications that follow the Helvetia corporate styling guidelines.", + "repository": { + "type": "git", + "url": "git+https://github.com/baloise/design-system.git" + }, + "publishConfig": { + "access": "public" + }, + "homepage": "https://design.baloise.dev", + "security": "https://github.com/baloise/design-system/security/advisories/new", + "license": "Apache-2.0", + "type": "module", + "main": "dist/index.js", + "module": "dist/index.js", + "types": "dist/index.d.ts", + "files": [ + "dist/" + ], + "scripts": { + "build": "tsc -p tsconfig.lib.json", + "build:clean": "rimraf dist", + "lint": "eslint ." + }, + "peerDependencies": { + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "dependencies": { + "@baloise/ds-core": "20.0.0-next.4", + "@stencil/react-output-target": "1.6.1" + }, + "devDependencies": { + "@types/react": "19.2.17", + "@types/react-dom": "19.2.3", + "eslint": "catalog:", + "react": "19.2.7", + "react-dom": "19.2.7", + "typescript": "catalog:" + } +} diff --git a/packages/react/src/index.ts b/packages/react/src/index.ts new file mode 100644 index 0000000000..9bac7d9bab --- /dev/null +++ b/packages/react/src/index.ts @@ -0,0 +1,14 @@ +import { DsConfig, initializeDesignSystem } from '@baloise/ds-core' + +interface DsReactConfig { + defaults?: DsConfig +} + +export const bootstrapDesignSystem = (config: DsReactConfig = {}) => { + initializeDesignSystem({ + ...config.defaults, + httpFormSubmit: false, + }) +} + +export * from './generated/components' diff --git a/packages/react/tsconfig.json b/packages/react/tsconfig.json new file mode 100644 index 0000000000..6c5ce377d7 --- /dev/null +++ b/packages/react/tsconfig.json @@ -0,0 +1,14 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "jsx": "react-jsx", + "paths": {} + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + } + ] +} diff --git a/packages/react/tsconfig.lib.json b/packages/react/tsconfig.lib.json new file mode 100644 index 0000000000..3061b3626d --- /dev/null +++ b/packages/react/tsconfig.lib.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "rootDir": "src", + "outDir": "dist", + "declaration": true, + "types": ["node"] + }, + "include": ["src/**/*.ts", "src/**/*.tsx"], + "exclude": ["src/**/*.spec.ts", "src/**/*.test.ts"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c1b0df0aaf..c6348aaaf7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -68,7 +68,10 @@ catalogs: version: 4.1.10 overrides: - '@swc/cli>minimatch@9>brace-expansion': 2.1.2 + brace-expansion@>=2.0.0 <2.1.2: 2.1.2 + brace-expansion@>=3.0.0 <5.0.7: 5.0.7 + js-yaml@>=4.0.0 <4.3.0: 4.3.0 + js-yaml@>=3.0.0 <3.15.0: 3.15.0 importers: @@ -106,13 +109,13 @@ importers: version: 3.2.3(@stencil/core@4.43.5) '@storybook/addon-docs': specifier: 'catalog:' - version: 10.5.2(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(esbuild@0.28.1)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react@19.2.7))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass-embedded@1.100.0)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0)) + version: 10.5.2(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(esbuild@0.28.1)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass-embedded@1.100.0)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0)) '@storybook/addon-links': specifier: 'catalog:' - version: 10.5.2(@types/react@19.2.17)(react@19.2.7)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react@19.2.7)) + version: 10.5.2(@types/react@19.2.17)(react@19.2.7)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)) '@storybook/html-vite': specifier: 'catalog:' - version: 10.5.2(esbuild@0.28.1)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react@19.2.7))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass-embedded@1.100.0)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0)) + version: 10.5.2(esbuild@0.28.1)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass-embedded@1.100.0)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0)) '@swc/cli': specifier: 0.8.1 version: 0.8.1(@swc/core@1.15.43)(chokidar@5.0.0) @@ -170,6 +173,9 @@ importers: glob: specifier: 13.0.6 version: 13.0.6 + js-yaml: + specifier: 4.3.0 + version: 4.3.0 jsdom: specifier: 29.1.1 version: 29.1.1 @@ -199,7 +205,7 @@ importers: version: 1.9.2 storybook: specifier: 'catalog:' - version: 10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react@19.2.7) + version: 10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) style-dictionary: specifier: 5.5.0 version: 5.5.0(tslib@2.8.1) @@ -248,13 +254,13 @@ importers: version: link:../packages/tokens '@storybook/addon-docs': specifier: 'catalog:' - version: 10.5.2(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(esbuild@0.28.1)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react@19.2.7))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass-embedded@1.100.0)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0)) + version: 10.5.2(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(esbuild@0.28.1)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass-embedded@1.100.0)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0)) '@storybook/addon-links': specifier: 'catalog:' - version: 10.5.2(@types/react@19.2.17)(react@19.2.7)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react@19.2.7)) + version: 10.5.2(@types/react@19.2.17)(react@19.2.7)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)) '@storybook/html-vite': specifier: 'catalog:' - version: 10.5.2(esbuild@0.28.1)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react@19.2.7))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass-embedded@1.100.0)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0)) + version: 10.5.2(esbuild@0.28.1)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass-embedded@1.100.0)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0)) lodash: specifier: 'catalog:' version: 4.18.1 @@ -266,7 +272,7 @@ importers: version: 19.2.7(react@19.2.7) storybook: specifier: 'catalog:' - version: 10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react@19.2.7) + version: 10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) devDependencies: '@types/react': specifier: 19.2.17 @@ -398,6 +404,9 @@ importers: '@baloise/ds-playwright': specifier: 20.0.0-next.4 version: link:../playwright + '@stencil/react-output-target': + specifier: 1.6.1 + version: 1.6.1(@stencil/core@4.43.5)(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) '@types/lodash': specifier: 4.17.24 version: 4.17.24 @@ -470,6 +479,34 @@ importers: specifier: 'catalog:' version: 4.1.10(@types/node@24.13.3)(@vitest/ui@4.1.10)(jsdom@29.1.1)(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass-embedded@1.100.0)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0)) + packages/react: + dependencies: + '@baloise/ds-core': + specifier: 20.0.0-next.4 + version: link:../core + '@stencil/react-output-target': + specifier: 1.6.1 + version: 1.6.1(@stencil/core@4.43.5)(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + devDependencies: + '@types/react': + specifier: 19.2.17 + version: 19.2.17 + '@types/react-dom': + specifier: 19.2.3 + version: 19.2.3(@types/react@19.2.17) + eslint: + specifier: 'catalog:' + version: 10.7.0(jiti@2.7.0) + react: + specifier: 19.2.7 + version: 19.2.7 + react-dom: + specifier: 19.2.7 + version: 19.2.7(react@19.2.7) + typescript: + specifier: 'catalog:' + version: 5.6.3 + packages/tokens: devDependencies: eslint: @@ -519,8 +556,8 @@ packages: resolution: {integrity: sha512-ppj9ouYku+RX0ljtgZd+KMO5mkM2bCqg8H2PYAFWnLsHEIKIdRojqbJ2i3eVHrisuxy7nOFCmngTDdWtUCdXUQ==} engines: {node: '>=6.9.0'} - '@babel/runtime@7.27.3': - resolution: {integrity: sha512-7EYtGezsdiDMyY80+65EzwiGmcJqpmcZCojSXaRgdrBaGtWTgDZKq69cPIVped6MkIM78cTQ2GOiEYjwOlG4xw==} + '@babel/runtime@7.29.7': + resolution: {integrity: sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==} engines: {node: '>=6.9.0'} '@borewit/text-codec@0.2.2': @@ -876,24 +913,24 @@ 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.11.1': resolution: {integrity: sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==} - '@emnapi/core@1.11.2': - resolution: {integrity: sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA==} - '@emnapi/core@1.9.2': resolution: {integrity: sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA==} '@emnapi/runtime@1.10.0': resolution: {integrity: sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==} + '@emnapi/runtime@1.11.0': + resolution: {integrity: sha512-55coeOFKHv1ywEcUXJtWU5f+Jr/W5tZDvZig8DLKSwUN1JpROQ4rk/SNOQiFWmaR/VKF4zuFyW1B8JduOSv6Pg==} + '@emnapi/runtime@1.11.1': resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==} - '@emnapi/runtime@1.11.2': - resolution: {integrity: sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==} - '@emnapi/runtime@1.9.2': resolution: {integrity: sha512-3U4+MIWHImeyu1wnmVygh5WlgfYDtyf0k8AbLhMFxOipihf6nrWC4syIm/SwEeec0mNSafiiNnMJwbza/Is6Lw==} @@ -1142,8 +1179,8 @@ packages: '@iconify/types@2.0.0': resolution: {integrity: sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==} - '@iconify/utils@3.1.4': - resolution: {integrity: sha512-b1S7B1k9ohZ+iNTi2ATxbRYG9fTrJmUT0rc46bvVnNxqNRGW7dyo/vRREwyniI5IRN2RSJHDcm+s3BjWrSAjHw==} + '@iconify/utils@3.1.3': + resolution: {integrity: sha512-LPKOXPn/zV+zis1oOfGWogaXVpqUybF3ZS6SCZIsz8vg0ivVp9+fVqyYB7xq0aiST/VhUQYGO1qo6uoYSiEJqw==} '@inquirer/external-editor@1.0.3': resolution: {integrity: sha512-RWbSrDiYmO4LbejWY7ttpxczuwQyZLBUyygsA9Nsv95hpzUWwnNTVQmAq3xuh7vNwCp07UTmE5i11XAEExx4RA==} @@ -1718,106 +1755,106 @@ packages: '@oxc-project/types@0.139.0': resolution: {integrity: sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==} - '@oxc-resolver/binding-android-arm-eabi@11.24.2': - resolution: {integrity: sha512-y09e0L0SRI2OA2tUIrjBgoV3eH5hvUKXNkJqXmNo5V2WxIjyC7I7aJfRLMEVpA8yi95f90gFDvO0VMgrDw+vwA==} + '@oxc-resolver/binding-android-arm-eabi@11.21.3': + resolution: {integrity: sha512-eNU11A2WNizh04v3uyaJCootrHIaS0B9aHYXvAvVnPNk4xYSjMUjHnhQ6dewPN2MRYDskV85d1N0Aw0WNWhcyg==} cpu: [arm] os: [android] - '@oxc-resolver/binding-android-arm64@11.24.2': - resolution: {integrity: sha512-cl4icWaZFnLdg8m6qtnh5rBMuGbxc/ptStFHLeCNwr+2cZjkjNwQu/jYRS0CHlnPecOJMpuS5M6/BH+0J/YkEg==} + '@oxc-resolver/binding-android-arm64@11.21.3': + resolution: {integrity: sha512-8Q+ZjTLvn2dIcWsrmhdrEihm7q+ag/k+mkry7Z+t0QbbHaVxXQfvH9AewyVMh/WrpEKhQ3DDgx9fYbqeCpeOEw==} cpu: [arm64] os: [android] - '@oxc-resolver/binding-darwin-arm64@11.24.2': - resolution: {integrity: sha512-At29QEMF6HajbQvgY8K6OXnHD1x9rad74xBEfmCB6ZqCGsdq75aK7tOYcTbOanMy8qdIBrfL3SMr3p/lfSlb9w==} + '@oxc-resolver/binding-darwin-arm64@11.21.3': + resolution: {integrity: sha512-wkh0qKZGHXVUDxFw3oA1TXnU2BDYY/r775oJflGeIr8uDPPoN2pk8gijQIzYRT6hoql/lg3+Tx/SaTn9e2/aGg==} cpu: [arm64] os: [darwin] - '@oxc-resolver/binding-darwin-x64@11.24.2': - resolution: {integrity: sha512-A5Kqr1EUj4oIL5CF4WRssq/o5P0Y11cwoFouMRmQ7YnC/A8V93nv1nb7aSU8HwcgmXropjLNkVTl4MN87cu28Q==} + '@oxc-resolver/binding-darwin-x64@11.21.3': + resolution: {integrity: sha512-HbNc23FAQYbuyDV2vBWMez4u4mrsm5RAkniGZAWqr6lYZ3N4beeqIb776jzwRl8qL2zRhHVXpUj97X0QgogVzg==} cpu: [x64] os: [darwin] - '@oxc-resolver/binding-freebsd-x64@11.24.2': - resolution: {integrity: sha512-R5xkRBRRz7ceH/P5Jrc6G7FmdUdgpLYyESFAUDVTNQ9K0sGPxcp4ljiwEwEqsvNcQ4sYbMRrWcHHBCu7ksAJVw==} + '@oxc-resolver/binding-freebsd-x64@11.21.3': + resolution: {integrity: sha512-K6xNsTUPEUdfrn0+kbMq5nOUB5w1C5pavPQngt4TM2FpN91lP0PBe2srSpamb4d69O7h86oAi/qWX/kZNRSjkw==} cpu: [x64] os: [freebsd] - '@oxc-resolver/binding-linux-arm-gnueabihf@11.24.2': - resolution: {integrity: sha512-k/RuYL4L/R58IBn3wT5ma3Wh4k62bp1eYCFRWCmMsasUOqL+H6sW0VGFadEzKWXFFlz+2uIMoeMk9ySSZJHgbg==} + '@oxc-resolver/binding-linux-arm-gnueabihf@11.21.3': + resolution: {integrity: sha512-VcFmOpcpWX1zoEy8M58tR2M9YxM+Z9RuQhqAx5q0CTmrruaP7Gveejg75hzd/5sg5nk9G3aLALEa3hE2FsmmTQ==} cpu: [arm] os: [linux] - '@oxc-resolver/binding-linux-arm-musleabihf@11.24.2': - resolution: {integrity: sha512-bnHAak3ujYfH5pKk4NieFNbvYvernfoQDgwLddbZ3OtMYrem87/qjlA+u+aKG0oZcqSLGCful/6/CEA+aeAgaA==} + '@oxc-resolver/binding-linux-arm-musleabihf@11.21.3': + resolution: {integrity: sha512-quVoxFLBy43hWaQbbDtQNRwAX5vX76mv7n64icAtQcJ3eNgVeblqmkupF/hAneNthdqSlnd1sTjb3aQSaDPaCQ==} cpu: [arm] os: [linux] - '@oxc-resolver/binding-linux-arm64-gnu@11.24.2': - resolution: {integrity: sha512-vDT3KHgzYp47gmtNOqL2VNhCyl5Zv643eyxm//A68J8DeUGXrvD1pZFiaT4jSfe+RInfnn1R2yVHye4enx6RnA==} + '@oxc-resolver/binding-linux-arm64-gnu@11.21.3': + resolution: {integrity: sha512-X0AqNZgcD07Q4V3RDK18/vYOj/HQT/FnmEFGYS2jTWqY7JO13ryE3TEs3eAIgUJhBnNkpEaiXqz3VK8M7qQhWQ==} cpu: [arm64] os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-arm64-musl@11.24.2': - resolution: {integrity: sha512-+kMlQvbzfyEYtu5FcjE4p+ttBLpKW4d/AsAsuE69BxV6V4twZJeIQZFfD8gh/wqglY0MkPSezWXQH0jBV13MUw==} + '@oxc-resolver/binding-linux-arm64-musl@11.21.3': + resolution: {integrity: sha512-YkaQnaKYdbuaXvRt5Qd0GpbihzVnyfR6z1SpYfIUC6RTu4NF7lDKPjVkYb+jRI2gedVO2rVpN35Y6akG6ud4Lw==} cpu: [arm64] os: [linux] libc: [musl] - '@oxc-resolver/binding-linux-ppc64-gnu@11.24.2': - resolution: {integrity: sha512-shjfMhmZ3gq9fv/w7bi3PnZlgOPG+2QAOFf0BJF0EgBSIGZ6PMLN2zbGEblTUYB/NKVDRyYhE2ff3dJ1QqNPkA==} + '@oxc-resolver/binding-linux-ppc64-gnu@11.21.3': + resolution: {integrity: sha512-gB9HwhrPiFqUzDeEq+y/CgAijz1YdI6BnXz5GaH2Pa9cWdutchlkGFAiAuGb/PjVQpiK6NFKzFuztxrweoit7A==} cpu: [ppc64] os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-riscv64-gnu@11.24.2': - resolution: {integrity: sha512-zGelwFR5oRo+b69k8Lrzun86DyUHzfKN6cnjbR9l7Z7NIRznOE/2ZvPa1IUKqAL2PzAXOdwkfVqNvO1H2RlpAw==} + '@oxc-resolver/binding-linux-riscv64-gnu@11.21.3': + resolution: {integrity: sha512-zjDWBlYk8QGv0H8dsPUWqkfjYIIjG2TvspGkzXL0eImbgxtZorA/klKeHyolevoT3Kvbi+1iMr9Lhrh7jf54Og==} cpu: [riscv64] os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-riscv64-musl@11.24.2': - resolution: {integrity: sha512-qxZ1SWCXJY0eyhAlP6Lmo9F2Nrtx7EkYj9oCgL8apDPCwXwCEDA2U697bbT81JIc2IrVjxO4KX6WU2N+oN9Z4w==} + '@oxc-resolver/binding-linux-riscv64-musl@11.21.3': + resolution: {integrity: sha512-4UfsQvacV388y1zpXL7C1x1FNYaV52JtuNRiuzrfQA2z1z6ElVrsidkGsrvQ5EgeSq1Pj7kaKqrgGkvFuxJ/tw==} cpu: [riscv64] os: [linux] libc: [musl] - '@oxc-resolver/binding-linux-s390x-gnu@11.24.2': - resolution: {integrity: sha512-sGCecF3cx2DFlH4t/z7ApnOnXqN48p5p5mlHDEnHTAukQa2P+qMVE4CwyWE9W+q/m3QJ7kKfGrIjax31f44oFQ==} + '@oxc-resolver/binding-linux-s390x-gnu@11.21.3': + resolution: {integrity: sha512-b5uH+HKH0MP5mNBYaK75SKsJbw52URqrx2LavYdq6wb0l3ExAG5niYRP9DWUNHdKilpaBVM2bXk9HNWrH3ew7Q==} cpu: [s390x] os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-x64-gnu@11.24.2': - resolution: {integrity: sha512-k/VlMMcSzMlahb3/fENM4rTlsJ0s3fFROA0KXPBmKggqmTSaE383sl8F3KCOXPLmVsYfW6hCitMhXCEtNeZxxg==} + '@oxc-resolver/binding-linux-x64-gnu@11.21.3': + resolution: {integrity: sha512-PjYlmilBpNRh2ntXNYAK3Am5w/nPfEpnU/96iNx7CI8EzAn12J4JRiec63wHJTH31nLoCNxBg/829pN+3CfG3Q==} cpu: [x64] os: [linux] libc: [glibc] - '@oxc-resolver/binding-linux-x64-musl@11.24.2': - resolution: {integrity: sha512-8hbnZyNi97b/8wapYaIF9+t9GmZKBW2vunaOc3h9HGJptH7b7XpvZqOTBSm/MpTjr7H497BlgOaSfLUdhmy2bw==} + '@oxc-resolver/binding-linux-x64-musl@11.21.3': + resolution: {integrity: sha512-QTBAb7JuHlZ7JUEyM8UiQi2f7m/L4swBhP2TNpYIDc9Wp/wRw1G/8sl6i13aIzQAXH7LKIm294LeOHd0lQR8zA==} cpu: [x64] os: [linux] libc: [musl] - '@oxc-resolver/binding-openharmony-arm64@11.24.2': - resolution: {integrity: sha512-MvyGik3a6pVgZ0t/kWlbmFxFLmXQJwgLsY2eYFHLpy0wGwRbfzeIGgDwQ3kXqE30z+kSXennRkCrT7TUvkptNg==} + '@oxc-resolver/binding-openharmony-arm64@11.21.3': + resolution: {integrity: sha512-4j1DFwjwv36ec9kds0jU/ucQ5Ha4ERO/H95BxR5JFf0kqUUAJ1kwII7XhTc1vZrkdJkvLGC9Q2MbpObpum8RBg==} cpu: [arm64] os: [openharmony] - '@oxc-resolver/binding-wasm32-wasi@11.24.2': - resolution: {integrity: sha512-vHcssMPwO08RTvj/c0iOBz90attxyG3wQJ0dTcyEQK43LRpcdLWZlV5feBhv6Isn6ahbQIzHbCgfa81+RiML0Q==} + '@oxc-resolver/binding-wasm32-wasi@11.21.3': + resolution: {integrity: sha512-i8oluoel5kru/j1WNrjmQSiA3GQ7wvIYVR1IwIoZtKogAhya2iub+ZKIeSIkcJOrnzQ18Tzl/F+kL3fYOxZLvA==} engines: {node: '>=14.0.0'} cpu: [wasm32] - '@oxc-resolver/binding-win32-arm64-msvc@11.24.2': - resolution: {integrity: sha512-uokJqro2iBqkFvJdKQLP7d8/BUmFwESQFVmIJUQKj1Xn1a/LysJoe1vmeECLF5b3jsV8CAL5sEMJXX6SdK9Nhg==} + '@oxc-resolver/binding-win32-arm64-msvc@11.21.3': + resolution: {integrity: sha512-M/8dw8dD6aOs+NlPJax401CZB9I7Aut84isQLgALGGwke4Afvw+/7yYhZb94yXf6t2sPLhQLmSmtSV+2FhsOWg==} cpu: [arm64] os: [win32] - '@oxc-resolver/binding-win32-x64-msvc@11.24.2': - resolution: {integrity: sha512-UqGPmo56KDfLlfXFAFIrNflHT8tFxWGEivWg3Zeyp4Uy2NlKN1FGPr6/BxcLGG3+kZ6Wp14g5Uj+n71boqZfiw==} + '@oxc-resolver/binding-win32-x64-msvc@11.21.3': + resolution: {integrity: sha512-H7BCt/VnS9hnmMp42eGhZ99izSCRvlnWwy/N71K1/J8QoExwY4262Z8QiEkMDtduRJrztayDxETTckmUuAVL9Q==} cpu: [x64] os: [win32] @@ -2153,10 +2190,11 @@ packages: peerDependencies: storybook: ^10.5.2 - '@storybook/icons@2.1.0': - resolution: {integrity: sha512-Fxh9vYpX9bQqFeHRiY8h2ApeRGDzRSMLwJwNZ/AIRqnyOKHxRKL+yFe+ctEkVJmuptRE9u1Hrn8ZZNHyfDKKNg==} + '@storybook/icons@2.0.2': + resolution: {integrity: sha512-KZBCpXsshAIjczYNXR/rlxEtCUX/eAbpFNwKi8bcOomrLA4t/SyPz5RF+lVPO2oZBUE4sAkt43mfJUevQDSEEw==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 '@storybook/react-dom-shim@10.5.2': resolution: {integrity: sha512-TbdYVLuD7gwj1CFsDJhCHUiwfVmzFWzalKEUGy9XgXyNpyOV1CYRsdmRdhaOHgmn2ljQZuTAxSnG7NlElghVaw==} @@ -3245,8 +3283,8 @@ packages: resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} engines: {node: '>= 0.4'} - es-module-lexer@2.3.1: - resolution: {integrity: sha512-shc1dbU90Yl/xq1QrC7QRtfcwURZuVRfPhZbDoldJ1cn1gzDvBaBWlv0eFolj5+0znnPJz5TXLxsN77X/12KTA==} + es-module-lexer@2.1.0: + resolution: {integrity: sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==} es-object-atoms@1.1.2: resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} @@ -3353,8 +3391,8 @@ packages: resolution: {integrity: sha512-9Be3ZoN4LmYR90tUoVu2te2BsbzHfhJyfEiAVfz7N5/zv+jduIfLrV2xdQXOHbaD6KgpGdO9PRPM1Y4Q9QkPkA==} engines: {node: ^18.19.0 || >=20.5.0} - expect-type@1.4.0: - resolution: {integrity: sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==} + expect-type@1.3.0: + resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==} engines: {node: '>=12.0.0'} express@5.2.1: @@ -3662,10 +3700,6 @@ packages: resolution: {integrity: sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==} engines: {node: '>=0.10.0'} - iconv-lite@0.7.3: - resolution: {integrity: sha512-IKXpvIzjnC9XTAUbVBcMfGS0EPaIXtW6v+zr+RRp+hqULEpo0owZax6wyRwPOJbWbzjYspQwusTsfVr0ifh4uQ==} - engines: {node: '>=0.10.0'} - ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} @@ -3673,8 +3707,8 @@ packages: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} - ignore@7.0.6: - resolution: {integrity: sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==} + ignore@7.0.5: + resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==} engines: {node: '>= 4'} imask@7.6.1: @@ -4111,8 +4145,8 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - nanoid@3.3.16: - resolution: {integrity: sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==} + nanoid@3.3.15: + resolution: {integrity: sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true @@ -4185,8 +4219,8 @@ packages: resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} engines: {node: '>= 0.4'} - obug@2.1.4: - resolution: {integrity: sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==} + obug@2.1.3: + resolution: {integrity: sha512-9miFgM2OFba7hB+pRgvtV84pYTBaoTHohvmIgiRt6dRIzbwEOIaNaP+dIlGs2fNFoB0SeISs0Jz5WFVRid6Xyg==} engines: {node: '>=12.20.0'} ofetch@1.5.1: @@ -4226,8 +4260,8 @@ packages: resolution: {integrity: sha512-SJ3/7ZPbgie8dr5Z9BI/M51zZbpXba+hRSG0MDzVwMW5CRQg2fjYE0jHGlLX4eeiibGgC/mzoDFKSDHwVZEHRQ==} engines: {node: ^20.19.0 || >=22.12.0} - oxc-resolver@11.24.2: - resolution: {integrity: sha512-FY91FiDBj7ls5MsFS9jN3tjz2o0/zsdSsymlakySaBwVJZorHhkWyICLZMKxlu1R9vYo+sd3z1jwb4J8x7bNDw==} + oxc-resolver@11.21.3: + resolution: {integrity: sha512-2Mx3fKQz7+xgrBONjsxOgCGtMHOn38/HxMzW1I5efwXB5a4lRN0Vp40gYUJFBWJslcrvwoofTrqoTnLbwTd3pA==} oxc-walker@0.7.0: resolution: {integrity: sha512-54B4KUhrzbzc4sKvKwVYm7E2PgeROpGba0/2nlNZMqfDyca+yOor5IMb4WLGBatGDT0nkzYdYuzylg7n3YfB7A==} @@ -4280,8 +4314,8 @@ packages: package-manager-detector@0.2.11: resolution: {integrity: sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ==} - package-manager-detector@1.7.0: - resolution: {integrity: sha512-xg1eHpwYL/D/HEdWw2goFZP6vV0FH7W+PZ5rFkGjdIDLtxq7EkzBUeT3m+lndYCt8wKbmofUu1MUdMCXkCk9ZQ==} + package-manager-detector@1.6.0: + resolution: {integrity: sha512-61A5ThoTiDG/C8s8UMZwSorAGwMJ0ERVGj2OjoW5pAalsNOg15+iQiPzrLJ4jhZ1HJzmC2PIHT2oEiH3R5fzNA==} parse-ms@4.0.0: resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==} @@ -4346,6 +4380,10 @@ packages: resolution: {integrity: sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==} engines: {node: '>=8.6'} + picomatch@4.0.4: + resolution: {integrity: sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==} + engines: {node: '>=12'} + picomatch@4.0.5: resolution: {integrity: sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==} engines: {node: '>=12'} @@ -4488,8 +4526,8 @@ packages: resolution: {integrity: sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==} engines: {node: '>= 20.19.0'} - recast@0.23.12: - resolution: {integrity: sha512-dEWRjcINDu/F4l2dYx57ugBtD7HV9KXESyxhzw/MqWLeglJrsjJKqACPyUPg+6AF8mIgm+Zi0dZ3ACoIg+QtpA==} + recast@0.23.11: + resolution: {integrity: sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA==} engines: {node: '>= 4'} redent@3.0.0: @@ -4836,8 +4874,8 @@ packages: resolution: {integrity: sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==} engines: {node: '>= 0.8'} - std-env@4.2.0: - resolution: {integrity: sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==} + std-env@4.1.0: + resolution: {integrity: sha512-Rq7ybcX2RuC55r9oaPVEW7/xu3tj8u4GeBYHBWCychFtzMIr86A7e3PPEBPT37sHStKX3+TiX/Fr/ACmJLVlLQ==} storybook@10.5.2: resolution: {integrity: sha512-zkYxVZoDMj8njzZc3EH5UyY7885wpi9a1mmWVwFiNHSo+i5r2Go84E2OI1cdOctRymLkNvgs1j5jqAKA0ftBqg==} @@ -5146,8 +5184,8 @@ packages: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} - unplugin-utils@0.3.2: - resolution: {integrity: sha512-xVToRh2CTmLk2HnEG7ac4rl1MJTT3RFkpS8B++/SnB0kXvuaavD+n3m/vrzyWQOdJNSZQACnbz01pnppbwV5BA==} + unplugin-utils@0.3.1: + resolution: {integrity: sha512-5lWVjgi6vuHhJ526bI4nlCOmkCIF3nnfXkCMDeMJrtdvxTs6ZFCM8oNufGTsDbKv/tJ/xj8RpvXjRuPBZJuJog==} engines: {node: '>=20.19.0'} unplugin@2.3.11: @@ -5331,8 +5369,8 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - ws@8.21.1: - resolution: {integrity: sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw==} + ws@8.21.0: + resolution: {integrity: sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -5397,7 +5435,7 @@ snapshots: '@antfu/install-pkg@1.1.0': dependencies: - package-manager-detector: 1.7.0 + package-manager-detector: 1.6.0 tinyexec: 1.2.4 '@asamuzakjp/css-color@5.1.11': @@ -5437,7 +5475,7 @@ snapshots: dependencies: core-js-pure: 3.49.0 - '@babel/runtime@7.27.3': {} + '@babel/runtime@7.29.7': {} '@borewit/text-codec@0.2.2': {} @@ -5883,13 +5921,13 @@ snapshots: tslib: 2.8.1 optional: true - '@emnapi/core@1.11.1': + '@emnapi/core@1.11.0': dependencies: '@emnapi/wasi-threads': 1.2.2 tslib: 2.8.1 optional: true - '@emnapi/core@1.11.2': + '@emnapi/core@1.11.1': dependencies: '@emnapi/wasi-threads': 1.2.2 tslib: 2.8.1 @@ -5906,12 +5944,12 @@ snapshots: tslib: 2.8.1 optional: true - '@emnapi/runtime@1.11.1': + '@emnapi/runtime@1.11.0': dependencies: tslib: 2.8.1 optional: true - '@emnapi/runtime@1.11.2': + '@emnapi/runtime@1.11.1': dependencies: tslib: 2.8.1 optional: true @@ -6076,7 +6114,7 @@ snapshots: '@iconify/types@2.0.0': {} - '@iconify/utils@3.1.4': + '@iconify/utils@3.1.3': dependencies: '@antfu/install-pkg': 1.1.0 '@iconify/types': 2.0.0 @@ -6085,7 +6123,7 @@ snapshots: '@inquirer/external-editor@1.0.3(@types/node@24.13.3)': dependencies: chardet: 2.2.0 - iconv-lite: 0.7.3 + iconv-lite: 0.7.2 optionalDependencies: '@types/node': 24.13.3 @@ -6243,14 +6281,14 @@ snapshots: '@manypkg/find-root@1.1.0': dependencies: - '@babel/runtime': 7.27.3 + '@babel/runtime': 7.29.7 '@types/node': 12.20.55 find-up: 4.1.0 fs-extra: 8.1.0 '@manypkg/get-packages@1.1.3': dependencies: - '@babel/runtime': 7.27.3 + '@babel/runtime': 7.29.7 '@changesets/types': 4.1.0 '@manypkg/find-root': 1.1.0 fs-extra: 8.1.0 @@ -6342,17 +6380,17 @@ snapshots: '@tybys/wasm-util': 0.10.3 optional: true - '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.0)(@emnapi/runtime@1.11.0)': dependencies: - '@emnapi/core': 1.11.1 - '@emnapi/runtime': 1.11.1 + '@emnapi/core': 1.11.0 + '@emnapi/runtime': 1.11.0 '@tybys/wasm-util': 0.10.3 optional: true - '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)': + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': dependencies: - '@emnapi/core': 1.11.2 - '@emnapi/runtime': 1.11.2 + '@emnapi/core': 1.11.1 + '@emnapi/runtime': 1.11.1 '@tybys/wasm-util': 0.10.3 optional: true @@ -6515,65 +6553,65 @@ snapshots: '@oxc-project/types@0.139.0': {} - '@oxc-resolver/binding-android-arm-eabi@11.24.2': + '@oxc-resolver/binding-android-arm-eabi@11.21.3': optional: true - '@oxc-resolver/binding-android-arm64@11.24.2': + '@oxc-resolver/binding-android-arm64@11.21.3': optional: true - '@oxc-resolver/binding-darwin-arm64@11.24.2': + '@oxc-resolver/binding-darwin-arm64@11.21.3': optional: true - '@oxc-resolver/binding-darwin-x64@11.24.2': + '@oxc-resolver/binding-darwin-x64@11.21.3': optional: true - '@oxc-resolver/binding-freebsd-x64@11.24.2': + '@oxc-resolver/binding-freebsd-x64@11.21.3': optional: true - '@oxc-resolver/binding-linux-arm-gnueabihf@11.24.2': + '@oxc-resolver/binding-linux-arm-gnueabihf@11.21.3': optional: true - '@oxc-resolver/binding-linux-arm-musleabihf@11.24.2': + '@oxc-resolver/binding-linux-arm-musleabihf@11.21.3': optional: true - '@oxc-resolver/binding-linux-arm64-gnu@11.24.2': + '@oxc-resolver/binding-linux-arm64-gnu@11.21.3': optional: true - '@oxc-resolver/binding-linux-arm64-musl@11.24.2': + '@oxc-resolver/binding-linux-arm64-musl@11.21.3': optional: true - '@oxc-resolver/binding-linux-ppc64-gnu@11.24.2': + '@oxc-resolver/binding-linux-ppc64-gnu@11.21.3': optional: true - '@oxc-resolver/binding-linux-riscv64-gnu@11.24.2': + '@oxc-resolver/binding-linux-riscv64-gnu@11.21.3': optional: true - '@oxc-resolver/binding-linux-riscv64-musl@11.24.2': + '@oxc-resolver/binding-linux-riscv64-musl@11.21.3': optional: true - '@oxc-resolver/binding-linux-s390x-gnu@11.24.2': + '@oxc-resolver/binding-linux-s390x-gnu@11.21.3': optional: true - '@oxc-resolver/binding-linux-x64-gnu@11.24.2': + '@oxc-resolver/binding-linux-x64-gnu@11.21.3': optional: true - '@oxc-resolver/binding-linux-x64-musl@11.24.2': + '@oxc-resolver/binding-linux-x64-musl@11.21.3': optional: true - '@oxc-resolver/binding-openharmony-arm64@11.24.2': + '@oxc-resolver/binding-openharmony-arm64@11.21.3': optional: true - '@oxc-resolver/binding-wasm32-wasi@11.24.2': + '@oxc-resolver/binding-wasm32-wasi@11.21.3': dependencies: - '@emnapi/core': 1.11.2 - '@emnapi/runtime': 1.11.2 - '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + '@emnapi/core': 1.11.0 + '@emnapi/runtime': 1.11.0 + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.0)(@emnapi/runtime@1.11.0) optional: true - '@oxc-resolver/binding-win32-arm64-msvc@11.24.2': + '@oxc-resolver/binding-win32-arm64-msvc@11.21.3': optional: true - '@oxc-resolver/binding-win32-x64-msvc@11.24.2': + '@oxc-resolver/binding-win32-x64-msvc@11.21.3': optional: true '@parcel/watcher-android-arm64@2.5.6': @@ -6620,7 +6658,7 @@ snapshots: detect-libc: 2.1.2 is-glob: 4.0.3 node-addon-api: 7.1.1 - picomatch: 4.0.5 + picomatch: 4.0.4 optionalDependencies: '@parcel/watcher-android-arm64': 2.5.6 '@parcel/watcher-darwin-arm64': 2.5.6 @@ -6758,15 +6796,15 @@ snapshots: '@stencil/core': 4.43.5 sass-embedded: 1.100.0 - '@storybook/addon-docs@10.5.2(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(esbuild@0.28.1)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react@19.2.7))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass-embedded@1.100.0)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0))': + '@storybook/addon-docs@10.5.2(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(esbuild@0.28.1)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass-embedded@1.100.0)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0))': dependencies: '@mdx-js/react': 3.1.1(@types/react@19.2.17)(react@19.2.7) - '@storybook/csf-plugin': 10.5.2(esbuild@0.28.1)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react@19.2.7))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass-embedded@1.100.0)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0)) - '@storybook/icons': 2.1.0(react@19.2.7) - '@storybook/react-dom-shim': 10.5.2(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react@19.2.7)) + '@storybook/csf-plugin': 10.5.2(esbuild@0.28.1)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass-embedded@1.100.0)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0)) + '@storybook/icons': 2.0.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + '@storybook/react-dom-shim': 10.5.2(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) - storybook: 10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react@19.2.7) + storybook: 10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) ts-dedent: 2.3.0 optionalDependencies: '@types/react': 19.2.17 @@ -6777,18 +6815,18 @@ snapshots: - vite - webpack - '@storybook/addon-links@10.5.2(@types/react@19.2.17)(react@19.2.7)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react@19.2.7))': + '@storybook/addon-links@10.5.2(@types/react@19.2.17)(react@19.2.7)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))': dependencies: '@storybook/global': 5.0.0 - storybook: 10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react@19.2.7) + storybook: 10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) optionalDependencies: '@types/react': 19.2.17 react: 19.2.7 - '@storybook/builder-vite@10.5.2(esbuild@0.28.1)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react@19.2.7))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass-embedded@1.100.0)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0))': + '@storybook/builder-vite@10.5.2(esbuild@0.28.1)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass-embedded@1.100.0)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0))': dependencies: - '@storybook/csf-plugin': 10.5.2(esbuild@0.28.1)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react@19.2.7))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass-embedded@1.100.0)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0)) - storybook: 10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react@19.2.7) + '@storybook/csf-plugin': 10.5.2(esbuild@0.28.1)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass-embedded@1.100.0)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0)) + storybook: 10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) ts-dedent: 2.3.0 vite: 8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass-embedded@1.100.0)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0) transitivePeerDependencies: @@ -6796,9 +6834,9 @@ snapshots: - rollup - webpack - '@storybook/csf-plugin@10.5.2(esbuild@0.28.1)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react@19.2.7))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass-embedded@1.100.0)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0))': + '@storybook/csf-plugin@10.5.2(esbuild@0.28.1)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass-embedded@1.100.0)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0))': dependencies: - storybook: 10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react@19.2.7) + storybook: 10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) unplugin: 2.3.11 optionalDependencies: esbuild: 0.28.1 @@ -6806,32 +6844,33 @@ snapshots: '@storybook/global@5.0.0': {} - '@storybook/html-vite@10.5.2(esbuild@0.28.1)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react@19.2.7))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass-embedded@1.100.0)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0))': + '@storybook/html-vite@10.5.2(esbuild@0.28.1)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass-embedded@1.100.0)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0))': dependencies: - '@storybook/builder-vite': 10.5.2(esbuild@0.28.1)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react@19.2.7))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass-embedded@1.100.0)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0)) - '@storybook/html': 10.5.2(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react@19.2.7)) - storybook: 10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react@19.2.7) + '@storybook/builder-vite': 10.5.2(esbuild@0.28.1)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(vite@8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass-embedded@1.100.0)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0)) + '@storybook/html': 10.5.2(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)) + storybook: 10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) vite: 8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass-embedded@1.100.0)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0) transitivePeerDependencies: - esbuild - rollup - webpack - '@storybook/html@10.5.2(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react@19.2.7))': + '@storybook/html@10.5.2(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))': dependencies: '@storybook/global': 5.0.0 - storybook: 10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react@19.2.7) + storybook: 10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) ts-dedent: 2.3.0 - '@storybook/icons@2.1.0(react@19.2.7)': + '@storybook/icons@2.0.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) - '@storybook/react-dom-shim@10.5.2(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react@19.2.7))': + '@storybook/react-dom-shim@10.5.2(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react-dom@19.2.7(react@19.2.7))(react@19.2.7))': dependencies: react: 19.2.7 react-dom: 19.2.7(react@19.2.7) - storybook: 10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react@19.2.7) + storybook: 10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) optionalDependencies: '@types/react': 19.2.17 '@types/react-dom': 19.2.3(@types/react@19.2.17) @@ -6918,7 +6957,7 @@ snapshots: '@testing-library/dom@10.4.1': dependencies: '@babel/code-frame': 7.29.7 - '@babel/runtime': 7.27.3 + '@babel/runtime': 7.29.7 '@types/aria-query': 5.0.4 aria-query: 5.3.0 dom-accessibility-api: 0.5.16 @@ -7041,7 +7080,7 @@ snapshots: '@typescript-eslint/utils': 8.64.0(eslint@10.7.0(jiti@2.7.0))(typescript@5.6.3) '@typescript-eslint/visitor-keys': 8.64.0 eslint: 10.7.0(jiti@2.7.0) - ignore: 7.0.6 + ignore: 7.0.5 natural-compare: 1.4.0 ts-api-utils: 2.5.0(typescript@5.6.3) typescript: 5.6.3 @@ -7139,7 +7178,7 @@ snapshots: pathe: 2.0.3 perfect-debounce: 2.1.0 tinyglobby: 0.2.17 - unplugin-utils: 0.3.2 + unplugin-utils: 0.3.1 '@unocss/config@66.7.5': dependencies: @@ -7168,7 +7207,7 @@ snapshots: '@unocss/preset-icons@66.7.5': dependencies: - '@iconify/utils': 3.1.4 + '@iconify/utils': 3.1.3 '@unocss/core': 66.7.5 ofetch: 1.5.1 @@ -7249,7 +7288,7 @@ snapshots: magic-string: 0.30.21 pathe: 2.0.3 tinyglobby: 0.2.17 - unplugin-utils: 0.3.2 + unplugin-utils: 0.3.1 vite: 8.1.5(@types/node@24.13.3)(esbuild@0.28.1)(jiti@2.7.0)(sass-embedded@1.100.0)(sass@1.101.0)(tsx@4.23.1)(yaml@2.9.0) '@vitest/expect@3.2.4': @@ -7822,7 +7861,7 @@ snapshots: cspell-glob@10.0.1: dependencies: '@cspell/url': 10.0.1 - picomatch: 4.0.5 + picomatch: 4.0.4 cspell-grammar@10.0.1: dependencies: @@ -8052,7 +8091,7 @@ snapshots: es-errors@1.3.0: {} - es-module-lexer@2.3.1: {} + es-module-lexer@2.1.0: {} es-object-atoms@1.1.2: dependencies: @@ -8213,7 +8252,7 @@ snapshots: strip-final-newline: 4.0.0 yoctocolors: 2.1.2 - expect-type@1.4.0: {} + expect-type@1.3.0: {} express@5.2.1: dependencies: @@ -8281,9 +8320,9 @@ snapshots: dependencies: reusify: 1.1.0 - fdir@6.5.0(picomatch@4.0.5): + fdir@6.5.0(picomatch@4.0.4): optionalDependencies: - picomatch: 4.0.5 + picomatch: 4.0.4 fflate@0.8.3: {} @@ -8566,15 +8605,11 @@ snapshots: dependencies: safer-buffer: 2.1.2 - iconv-lite@0.7.3: - dependencies: - safer-buffer: 2.1.2 - ieee754@1.2.1: {} ignore@5.3.2: {} - ignore@7.0.6: {} + ignore@7.0.5: {} imask@7.6.1: dependencies: @@ -8951,7 +8986,7 @@ snapshots: ms@2.1.3: {} - nanoid@3.3.16: {} + nanoid@3.3.15: {} natural-compare@1.4.0: {} @@ -9009,7 +9044,7 @@ snapshots: has-symbols: 1.1.0 object-keys: 1.1.1 - obug@2.1.4: {} + obug@2.1.3: {} ofetch@1.5.1: dependencies: @@ -9099,27 +9134,27 @@ snapshots: '@oxc-parser/binding-win32-ia32-msvc': 0.131.0 '@oxc-parser/binding-win32-x64-msvc': 0.131.0 - oxc-resolver@11.24.2: + oxc-resolver@11.21.3: optionalDependencies: - '@oxc-resolver/binding-android-arm-eabi': 11.24.2 - '@oxc-resolver/binding-android-arm64': 11.24.2 - '@oxc-resolver/binding-darwin-arm64': 11.24.2 - '@oxc-resolver/binding-darwin-x64': 11.24.2 - '@oxc-resolver/binding-freebsd-x64': 11.24.2 - '@oxc-resolver/binding-linux-arm-gnueabihf': 11.24.2 - '@oxc-resolver/binding-linux-arm-musleabihf': 11.24.2 - '@oxc-resolver/binding-linux-arm64-gnu': 11.24.2 - '@oxc-resolver/binding-linux-arm64-musl': 11.24.2 - '@oxc-resolver/binding-linux-ppc64-gnu': 11.24.2 - '@oxc-resolver/binding-linux-riscv64-gnu': 11.24.2 - '@oxc-resolver/binding-linux-riscv64-musl': 11.24.2 - '@oxc-resolver/binding-linux-s390x-gnu': 11.24.2 - '@oxc-resolver/binding-linux-x64-gnu': 11.24.2 - '@oxc-resolver/binding-linux-x64-musl': 11.24.2 - '@oxc-resolver/binding-openharmony-arm64': 11.24.2 - '@oxc-resolver/binding-wasm32-wasi': 11.24.2 - '@oxc-resolver/binding-win32-arm64-msvc': 11.24.2 - '@oxc-resolver/binding-win32-x64-msvc': 11.24.2 + '@oxc-resolver/binding-android-arm-eabi': 11.21.3 + '@oxc-resolver/binding-android-arm64': 11.21.3 + '@oxc-resolver/binding-darwin-arm64': 11.21.3 + '@oxc-resolver/binding-darwin-x64': 11.21.3 + '@oxc-resolver/binding-freebsd-x64': 11.21.3 + '@oxc-resolver/binding-linux-arm-gnueabihf': 11.21.3 + '@oxc-resolver/binding-linux-arm-musleabihf': 11.21.3 + '@oxc-resolver/binding-linux-arm64-gnu': 11.21.3 + '@oxc-resolver/binding-linux-arm64-musl': 11.21.3 + '@oxc-resolver/binding-linux-ppc64-gnu': 11.21.3 + '@oxc-resolver/binding-linux-riscv64-gnu': 11.21.3 + '@oxc-resolver/binding-linux-riscv64-musl': 11.21.3 + '@oxc-resolver/binding-linux-s390x-gnu': 11.21.3 + '@oxc-resolver/binding-linux-x64-gnu': 11.21.3 + '@oxc-resolver/binding-linux-x64-musl': 11.21.3 + '@oxc-resolver/binding-openharmony-arm64': 11.21.3 + '@oxc-resolver/binding-wasm32-wasi': 11.21.3 + '@oxc-resolver/binding-win32-arm64-msvc': 11.21.3 + '@oxc-resolver/binding-win32-x64-msvc': 11.21.3 oxc-walker@0.7.0(oxc-parser@0.131.0): dependencies: @@ -9164,7 +9199,7 @@ snapshots: dependencies: quansync: 0.2.11 - package-manager-detector@1.7.0: {} + package-manager-detector@1.6.0: {} parse-ms@4.0.0: {} @@ -9210,6 +9245,8 @@ snapshots: picomatch@2.3.2: {} + picomatch@4.0.4: {} + picomatch@4.0.5: {} pify@4.0.1: {} @@ -9238,7 +9275,7 @@ snapshots: postcss@8.5.19: dependencies: - nanoid: 3.3.16 + nanoid: 3.3.15 picocolors: 1.1.1 source-map-js: 1.2.1 @@ -9343,7 +9380,7 @@ snapshots: readdirp@5.0.0: {} - recast@0.23.12: + recast@0.23.11: dependencies: ast-types: 0.16.1 esprima: 4.0.1 @@ -9690,12 +9727,12 @@ snapshots: statuses@2.0.2: {} - std-env@4.2.0: {} + std-env@4.1.0: {} - storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react@19.2.7): + storybook@10.5.2(@types/react@19.2.17)(prettier@3.9.5)(react-dom@19.2.7(react@19.2.7))(react@19.2.7): dependencies: '@storybook/global': 5.0.0 - '@storybook/icons': 2.1.0(react@19.2.7) + '@storybook/icons': 2.0.2(react-dom@19.2.7(react@19.2.7))(react@19.2.7) '@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) @@ -9706,17 +9743,18 @@ snapshots: jsonc-parser: 3.3.1 open: 10.2.0 oxc-parser: 0.127.0 - oxc-resolver: 11.24.2 - recast: 0.23.12 + oxc-resolver: 11.21.3 + recast: 0.23.11 semver: 7.8.5 use-sync-external-store: 1.6.0(react@19.2.7) - ws: 8.21.1 + ws: 8.21.0 optionalDependencies: '@types/react': 19.2.17 prettier: 3.9.5 transitivePeerDependencies: - bufferutil - react + - react-dom - utf-8-validate stream@0.0.3: @@ -9886,8 +9924,8 @@ snapshots: tinyglobby@0.2.17: dependencies: - fdir: 6.5.0(picomatch@4.0.5) - picomatch: 4.0.5 + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 tinyrainbow@2.0.0: {} @@ -10040,16 +10078,16 @@ snapshots: unpipe@1.0.0: {} - unplugin-utils@0.3.2: + unplugin-utils@0.3.1: dependencies: pathe: 2.0.3 - picomatch: 4.0.5 + picomatch: 4.0.4 unplugin@2.3.11: dependencies: '@jridgewell/remapping': 2.3.5 acorn: 8.17.0 - picomatch: 4.0.5 + picomatch: 4.0.4 webpack-virtual-modules: 0.6.2 update-browserslist-db@1.2.3(browserslist@4.28.6): @@ -10115,13 +10153,13 @@ snapshots: '@vitest/snapshot': 4.1.10 '@vitest/spy': 4.1.10 '@vitest/utils': 4.1.10 - es-module-lexer: 2.3.1 - expect-type: 1.4.0 + es-module-lexer: 2.1.0 + expect-type: 1.3.0 magic-string: 0.30.21 - obug: 2.1.4 + obug: 2.1.3 pathe: 2.0.3 - picomatch: 4.0.5 - std-env: 4.2.0 + picomatch: 4.0.4 + std-env: 4.1.0 tinybench: 2.9.0 tinyexec: 1.2.4 tinyglobby: 0.2.17 @@ -10195,7 +10233,7 @@ snapshots: wrappy@1.0.2: {} - ws@8.21.1: {} + ws@8.21.0: {} wsl-utils@0.1.0: dependencies: diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index a7146910bf..f9a218dacc 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -30,8 +30,15 @@ catalog: vite: 8.1.5 vitest: 4.1.10 +# Kept in sync with package.json's "pnpm.overrides" โ pnpm 11 reads +# overrides from here locally, but Vercel's install only picks up the +# copy in package.json (frozen-lockfile broke there without it). +# See docs/adr/0005-duplicate-pnpm-overrides.md overrides: - '@swc/cli>minimatch@9>brace-expansion': 2.1.2 + 'brace-expansion@>=2.0.0 <2.1.2': 2.1.2 + 'brace-expansion@>=3.0.0 <5.0.7': 5.0.7 + 'js-yaml@>=4.0.0 <4.3.0': 4.3.0 + 'js-yaml@>=3.0.0 <3.15.0': 3.15.0 # Dependency lifecycle scripts are blocked by default (strictDepBuilds). # These native-build packages are explicitly allowed to run their scripts. diff --git a/scripts/check-overrides.mjs b/scripts/check-overrides.mjs new file mode 100644 index 0000000000..fcc345df05 --- /dev/null +++ b/scripts/check-overrides.mjs @@ -0,0 +1,45 @@ +/** + * Check that pnpm overrides in package.json and pnpm-workspace.yaml stay in sync. + * + * pnpm 11 reads overrides from pnpm-workspace.yaml locally, but Vercel's + * install only picks up the copy in package.json's "pnpm.overrides" + * (see docs/adr/0005-duplicate-pnpm-overrides.md). Both must be kept + * identical or one environment silently resolves a different, possibly + * vulnerable, dependency version than the other. + * + * Run with: node scripts/check-overrides.mjs + */ +import { readFileSync } from 'node:fs' +import { dirname, resolve } from 'node:path' +import { fileURLToPath } from 'node:url' +import yaml from 'js-yaml' + +const __dirname = dirname(fileURLToPath(import.meta.url)) +const workspaceRoot = resolve(__dirname, '..') + +const pkg = JSON.parse(readFileSync(resolve(workspaceRoot, 'package.json'), 'utf-8')) +const ws = yaml.load(readFileSync(resolve(workspaceRoot, 'pnpm-workspace.yaml'), 'utf-8')) + +const fromPackageJson = { ...pkg.pnpm?.overrides } +delete fromPackageJson._comment + +const fromWorkspaceYaml = ws.overrides ?? {} + +const normalize = overrides => + JSON.stringify( + Object.entries(overrides) + .map(([key, value]) => [key, String(value)]) + .sort(([a], [b]) => a.localeCompare(b)), + ) + +if (normalize(fromPackageJson) !== normalize(fromWorkspaceYaml)) { + console.error( + 'pnpm overrides are out of sync between package.json ("pnpm.overrides") and pnpm-workspace.yaml ("overrides").\n' + + 'Both must be updated together โ see docs/adr/0005-duplicate-pnpm-overrides.md.\n\n' + + `package.json: ${JSON.stringify(fromPackageJson, null, 2)}\n\n` + + `pnpm-workspace.yaml: ${JSON.stringify(fromWorkspaceYaml, null, 2)}`, + ) + process.exit(1) +} + +console.log('pnpm overrides are in sync.') diff --git a/test/react/base/app/.gitignore b/test/react/base/app/.gitignore new file mode 100644 index 0000000000..c59b0a7702 --- /dev/null +++ b/test/react/base/app/.gitignore @@ -0,0 +1,6 @@ +node_modules +dist +dist-ssr +*.local +playwright-report +test-results diff --git a/test/react/base/app/e2e/app.spec.ts b/test/react/base/app/e2e/app.spec.ts new file mode 100644 index 0000000000..19ab0b05ef --- /dev/null +++ b/test/react/base/app/e2e/app.spec.ts @@ -0,0 +1,45 @@ +import { expect, test } from '@playwright/test' + +test('renders without console errors', async ({ page }) => { + const errors: string[] = [] + page.on('console', message => { + if (message.type() === 'error') { + errors.push(message.text()) + } + }) + + await page.goto('/') + + await expect(page.getByRole('heading', { name: 'ds-react smoke test' })).toBeVisible() + expect(errors).toEqual([]) +}) + +test('ds-button fires dsClick and updates React state', async ({ page }) => { + await page.goto('/') + + const clicks = page.getByTestId('clicks') + await expect(clicks).toHaveText('Clicks: 0') + + await page.getByTestId('button').click() + + await expect(clicks).toHaveText('Clicks: 1') +}) + +test('ds-input fires dsInput and updates React state', async ({ page }) => { + await page.goto('/') + + await page.getByTestId('input').locator('input').fill('hello') + + await expect(page.getByTestId('input-value')).toHaveText('Input value: hello') +}) + +test('ds-checkbox fires dsChange and updates React state', async ({ page }) => { + await page.goto('/') + + const checked = page.getByTestId('checked') + await expect(checked).toHaveText('Checked: false') + + await page.getByTestId('checkbox').locator('input[type="checkbox"]').click() + + await expect(checked).toHaveText('Checked: true') +}) diff --git a/test/react/base/app/eslint.config.js b/test/react/base/app/eslint.config.js new file mode 100644 index 0000000000..74a3377d0a --- /dev/null +++ b/test/react/base/app/eslint.config.js @@ -0,0 +1,25 @@ +import js from '@eslint/js' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' +import globals from 'globals' +import tseslint from 'typescript-eslint' + +export default tseslint.config( + { ignores: ['dist'] }, + { + extends: [js.configs.recommended, ...tseslint.configs.recommended], + files: ['**/*.{ts,tsx}'], + languageOptions: { + ecmaVersion: 2022, + globals: globals.browser, + }, + plugins: { + 'react-hooks': reactHooks, + 'react-refresh': reactRefresh, + }, + rules: { + ...reactHooks.configs.recommended.rules, + 'react-refresh/only-export-components': ['warn', { allowConstantExport: true }], + }, + }, +) diff --git a/test/react/base/app/index.html b/test/react/base/app/index.html new file mode 100644 index 0000000000..615b94776e --- /dev/null +++ b/test/react/base/app/index.html @@ -0,0 +1,12 @@ + + +
+ + +Clicks: {clicks}
+Input value: {inputValue}
+Checked: {String(checked)}
+