@structuralists/scaffolding 0.4.2 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/publish.yml +11 -0
- package/.storybook/main.ts +1 -1
- package/.storybook/preview.tsx +7 -0
- package/AGENTS.md +104 -0
- package/bun.lock +79 -2
- package/package.json +7 -1
- package/src/forms/CLAUDE.md +41 -18
- package/src/forms/plan.md +270 -0
- package/src/forms/useFormState/types.ts +10 -0
- package/src/forms/useFormState/useFormState.stories.tsx +196 -0
- package/src/forms/useFormState/useFormState.test-d.ts +209 -0
- package/src/forms/useFormState/useFormState.test.tsx +134 -0
- package/src/forms/useFormState/useFormState.ts +41 -5
- package/src/forms/validations/perField.ts +11 -0
- package/src/forms/validations/types.test-d.ts +74 -1
- package/src/forms/validations/types.ts +23 -0
- package/src/forms/validators/validators.test.ts +99 -0
- package/src/forms/validators/validators.ts +95 -0
- package/vitest.config.ts +35 -0
- package/CLAUDE.md +0 -55
|
@@ -29,9 +29,20 @@ jobs:
|
|
|
29
29
|
|
|
30
30
|
- run: bun install --frozen-lockfile
|
|
31
31
|
|
|
32
|
+
- name: Cache Playwright browsers
|
|
33
|
+
uses: actions/cache@v4
|
|
34
|
+
with:
|
|
35
|
+
path: ~/.cache/ms-playwright
|
|
36
|
+
key: playwright-${{ runner.os }}-${{ hashFiles('bun.lock') }}
|
|
37
|
+
restore-keys: playwright-${{ runner.os }}-
|
|
38
|
+
|
|
39
|
+
- name: Install Playwright chromium
|
|
40
|
+
run: npx playwright install chromium --with-deps
|
|
41
|
+
|
|
32
42
|
- run: bun run typecheck
|
|
33
43
|
- run: bun run lint
|
|
34
44
|
- run: bun run test
|
|
45
|
+
- run: bun run test:storybook
|
|
35
46
|
|
|
36
47
|
- name: Configure git
|
|
37
48
|
run: |
|
package/.storybook/main.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { StorybookConfig } from '@storybook/react-vite';
|
|
|
3
3
|
const config: StorybookConfig = {
|
|
4
4
|
framework: '@storybook/react-vite',
|
|
5
5
|
stories: ['../src/**/*.stories.@(ts|tsx)'],
|
|
6
|
-
addons: ['@storybook/addon-docs'],
|
|
6
|
+
addons: ['@storybook/addon-docs', '@storybook/addon-vitest', '@storybook/addon-a11y'],
|
|
7
7
|
};
|
|
8
8
|
|
|
9
9
|
export default config;
|
package/.storybook/preview.tsx
CHANGED
|
@@ -14,6 +14,13 @@ const preview: Preview = {
|
|
|
14
14
|
parameters: {
|
|
15
15
|
layout: 'padded',
|
|
16
16
|
|
|
17
|
+
a11y: {
|
|
18
|
+
// 'todo' reports axe-core violations without failing the vitest run.
|
|
19
|
+
// Flip to 'error' once the known violations are burned down, so new
|
|
20
|
+
// ones fail `bun run test:storybook`.
|
|
21
|
+
test: 'todo',
|
|
22
|
+
},
|
|
23
|
+
|
|
17
24
|
options: {
|
|
18
25
|
storySort: {
|
|
19
26
|
order: [
|
package/AGENTS.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# @structuralists/scaffolding
|
|
2
|
+
|
|
3
|
+
Generic React component library. Storybook for dev.
|
|
4
|
+
|
|
5
|
+
Designed to be used to scaffold up an app
|
|
6
|
+
|
|
7
|
+
## Conventions
|
|
8
|
+
|
|
9
|
+
### Component prop destructuring
|
|
10
|
+
|
|
11
|
+
React components must take a single argument named `props` and destructure
|
|
12
|
+
on the first line of the function body — not in the parameter list.
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
// ✅ correct
|
|
16
|
+
export const Foo = (props: FooProps) => {
|
|
17
|
+
const { a, b, c } = props;
|
|
18
|
+
|
|
19
|
+
return <div>{a}</div>;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
// ❌ wrong — destructures in the parameter list
|
|
23
|
+
export const Foo = ({ a, b, c }: FooProps) => {
|
|
24
|
+
return <div>{a}</div>;
|
|
25
|
+
};
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Why: the destructuring line at the top of the body acts as a quick legend
|
|
29
|
+
of what the component reads from its props, scannable without parsing the
|
|
30
|
+
function signature. Keeps the call shape uniform across the package.
|
|
31
|
+
|
|
32
|
+
### Custom hook arguments
|
|
33
|
+
|
|
34
|
+
Project-defined hooks must take a single argument named `args` (an object)
|
|
35
|
+
and destructure on the first line of the function body — same shape as the
|
|
36
|
+
component-prop rule above.
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
// ✅ correct
|
|
40
|
+
export const useFoo = (args: UseFooArgs) => {
|
|
41
|
+
const { a, b, c } = args;
|
|
42
|
+
// ...
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
// ❌ wrong — positional args
|
|
46
|
+
export const useFoo = (a: string, b: number, c?: boolean) => {
|
|
47
|
+
// ...
|
|
48
|
+
};
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Why: named args read clearly at the call site (`useFoo({ a, b })`), survive
|
|
52
|
+
reordering, and let new optional fields be added without breaking callers.
|
|
53
|
+
Built-in React hooks (`useState`, `useEffect`, etc.) keep their stock
|
|
54
|
+
positional signatures — this rule applies only to hooks defined in this
|
|
55
|
+
package.
|
|
56
|
+
|
|
57
|
+
## Testing
|
|
58
|
+
|
|
59
|
+
### Story tests (the main gate)
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
bun run test:storybook # vitest run --project=storybook
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Runs **every story** as a Vitest test in real headless Chromium (via
|
|
66
|
+
`@storybook/addon-vitest`, config in `vitest.config.ts`). Stories are the
|
|
67
|
+
test suite: each story must mount without throwing, and if it has a `play`
|
|
68
|
+
function, that runs as an interaction test. Run this after any component
|
|
69
|
+
change — it is also enforced in CI alongside `bun test`.
|
|
70
|
+
|
|
71
|
+
To test behavior (not just rendering), add a `play` function to the story:
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
import { expect, fn, userEvent, within } from 'storybook/test';
|
|
75
|
+
|
|
76
|
+
export const ClickInteraction: Story = {
|
|
77
|
+
args: { children: 'Click me', onClick: fn() },
|
|
78
|
+
play: async ({ args, canvasElement }) => {
|
|
79
|
+
const canvas = within(canvasElement);
|
|
80
|
+
await userEvent.click(canvas.getByRole('button', { name: 'Click me' }));
|
|
81
|
+
await expect(args.onClick).toHaveBeenCalledTimes(1);
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Iterate on one file with `bunx vitest run --project=storybook <path-to-stories-file>`.
|
|
87
|
+
Requires a Playwright chromium binary (`bunx playwright install chromium`).
|
|
88
|
+
|
|
89
|
+
### Accessibility checks
|
|
90
|
+
|
|
91
|
+
`@storybook/addon-a11y` runs axe-core against every story in the same
|
|
92
|
+
`test:storybook` run. It is currently in **report-only mode**
|
|
93
|
+
(`a11y: { test: 'todo' }` in `.storybook/preview.tsx`): violations are
|
|
94
|
+
reported but do not fail the run, because ~20 stories have known violations
|
|
95
|
+
(mostly `color-contrast` on #888 secondary text and
|
|
96
|
+
`scrollable-region-focusable` on scrollable panels). The plan is to burn
|
|
97
|
+
those down as a follow-up, then flip to `test: 'error'` so new violations
|
|
98
|
+
fail the gate. Don't introduce new violations in the meantime.
|
|
99
|
+
|
|
100
|
+
### Unit tests
|
|
101
|
+
|
|
102
|
+
`bun test` runs `*.test.ts(x)` files with happy-dom (preloaded via
|
|
103
|
+
`bunfig.toml`). Use for hooks and non-visual logic; prefer story `play`
|
|
104
|
+
functions for component behavior.
|
package/bun.lock
CHANGED
|
@@ -10,7 +10,9 @@
|
|
|
10
10
|
},
|
|
11
11
|
"devDependencies": {
|
|
12
12
|
"@happy-dom/global-registrator": "^20.10.6",
|
|
13
|
+
"@storybook/addon-a11y": "10.4.6",
|
|
13
14
|
"@storybook/addon-docs": "^10.4.6",
|
|
15
|
+
"@storybook/addon-vitest": "10.4.6",
|
|
14
16
|
"@storybook/react": "^10.4.6",
|
|
15
17
|
"@storybook/react-vite": "^10.4.6",
|
|
16
18
|
"@testing-library/dom": "^10.4.1",
|
|
@@ -20,9 +22,12 @@
|
|
|
20
22
|
"@types/react-dom": "^19.2.3",
|
|
21
23
|
"@typescript-eslint/parser": "^8.62.1",
|
|
22
24
|
"@vitejs/plugin-react": "^6.0.3",
|
|
25
|
+
"@vitest/browser-playwright": "4.1.9",
|
|
26
|
+
"@vitest/coverage-v8": "4.1.9",
|
|
23
27
|
"eslint": "^10.6.0",
|
|
24
28
|
"eslint-plugin-boundaries": "^6.0.2",
|
|
25
29
|
"eslint-plugin-storybook": "10.4.6",
|
|
30
|
+
"playwright": "^1.61.1",
|
|
26
31
|
"prettier": "^3.9.4",
|
|
27
32
|
"react-router": "^7.18.1",
|
|
28
33
|
"storybook": "^10.4.6",
|
|
@@ -64,7 +69,7 @@
|
|
|
64
69
|
|
|
65
70
|
"@babel/helpers": ["@babel/helpers@7.29.2", "", { "dependencies": { "@babel/template": "^7.28.6", "@babel/types": "^7.29.0" } }, "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw=="],
|
|
66
71
|
|
|
67
|
-
"@babel/parser": ["@babel/parser@7.29.
|
|
72
|
+
"@babel/parser": ["@babel/parser@7.29.7", "", { "dependencies": { "@babel/types": "^7.29.7" }, "bin": "./bin/babel-parser.js" }, "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg=="],
|
|
68
73
|
|
|
69
74
|
"@babel/runtime": ["@babel/runtime@7.29.2", "", {}, "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g=="],
|
|
70
75
|
|
|
@@ -74,6 +79,10 @@
|
|
|
74
79
|
|
|
75
80
|
"@babel/types": ["@babel/types@7.29.0", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="],
|
|
76
81
|
|
|
82
|
+
"@bcoe/v8-coverage": ["@bcoe/v8-coverage@1.0.2", "", {}, "sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA=="],
|
|
83
|
+
|
|
84
|
+
"@blazediff/core": ["@blazediff/core@1.9.1", "", {}, "sha512-ehg3jIkYKulZh+8om/O25vkvSsXXwC+skXmyA87FFx6A/45eqOkZsBltMw/TVteb0mloiGT8oGRTcjRAz66zaA=="],
|
|
85
|
+
|
|
77
86
|
"@boundaries/elements": ["@boundaries/elements@2.0.1", "", { "dependencies": { "eslint-import-resolver-node": "0.3.9", "eslint-module-utils": "2.12.1", "handlebars": "4.7.9", "is-core-module": "2.16.1", "micromatch": "4.0.8" } }, "sha512-sAWO3D8PFP6pBXdxxW93SQi/KQqqhE2AAHo3AgWfdtJXwO6bfK6/wUN81XnOZk0qRC6vHzUEKhjwVD9dtDWvxg=="],
|
|
78
87
|
|
|
79
88
|
"@emnapi/core": ["@emnapi/core@1.9.2", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.1", "tslib": "^2.4.0" } }, "sha512-UC+ZhH3XtczQYfOlu3lNEkdW/p4dsJ1r/bP7H8+rhao3TTTMO1ATq/4DdIi23XuGoFY+Cz0JmCbdVl0hz9jZcA=="],
|
|
@@ -256,6 +265,8 @@
|
|
|
256
265
|
|
|
257
266
|
"@oxc-resolver/binding-win32-x64-msvc": ["@oxc-resolver/binding-win32-x64-msvc@11.23.0", "", { "os": "win32", "cpu": "x64" }, "sha512-gUGJpr+Rn6zMxm5juApV0K3U845i8t47o8k+rbO0BHbi4PoJIfSPeQmrE2dgohQm2g5k6iviNFyXCGqvmaYUpw=="],
|
|
258
267
|
|
|
268
|
+
"@polka/url": ["@polka/url@1.0.0-next.29", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="],
|
|
269
|
+
|
|
259
270
|
"@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.1.4", "", { "os": "android", "cpu": "arm64" }, "sha512-EZLpf/8y7GXkkra90ML47kzik/GMP3EMcE9bPyHmRfxLC6z9+aW5A8poCsoxjrT5GfEcNAAvWwUHjvP1pUQkfw=="],
|
|
260
271
|
|
|
261
272
|
"@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.1.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-aUi+HBvmYb7j8krl1+qJgkG8C17fO79gk3c+jPw4S8glRFc1DTija9S3EyaTSQUm5GJXYKDAsugBEhFHH2vYiQ=="],
|
|
@@ -342,8 +353,12 @@
|
|
|
342
353
|
|
|
343
354
|
"@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
|
|
344
355
|
|
|
356
|
+
"@storybook/addon-a11y": ["@storybook/addon-a11y@10.4.6", "", { "dependencies": { "@storybook/global": "^5.0.0", "axe-core": "^4.2.0" }, "peerDependencies": { "storybook": "^10.4.6" } }, "sha512-XCJy+f0DFOiCgUU9knRDlLDxVFI+AAQ3/wE/NF85zB9iDPPS2DwkSN+mas3zDgHt66zhN8Cq3/UiyCDUweV9Zw=="],
|
|
357
|
+
|
|
345
358
|
"@storybook/addon-docs": ["@storybook/addon-docs@10.4.6", "", { "dependencies": { "@mdx-js/react": "^3.0.0", "@storybook/csf-plugin": "10.4.6", "@storybook/icons": "^2.0.2", "@storybook/react-dom-shim": "10.4.6", "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", "ts-dedent": "^2.0.0" }, "peerDependencies": { "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "storybook": "^10.4.6" }, "optionalPeers": ["@types/react"] }, "sha512-aWAfP5JMiT5a3zBJizwroCRzOCqZwDTJmvsYvwMD3ilIEa/kT1vhf6Xrbk4XIPhDwbh8Hpb/Gfnka1xBYEISWg=="],
|
|
346
359
|
|
|
360
|
+
"@storybook/addon-vitest": ["@storybook/addon-vitest@10.4.6", "", { "dependencies": { "@storybook/global": "^5.0.0", "@storybook/icons": "^2.0.2" }, "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.4.6", "vitest": "^3.0.0 || ^4.0.0" }, "optionalPeers": ["@vitest/browser", "@vitest/browser-playwright", "@vitest/runner", "vitest"] }, "sha512-VvskHge0GZy86LG6kcY5Ww34z8rDV8JBxqSdUpcJVsWfIvyX6MfAbqI76LlereSyBIJGZJZsqaLwRXsQoVY+0Q=="],
|
|
361
|
+
|
|
347
362
|
"@storybook/builder-vite": ["@storybook/builder-vite@10.4.6", "", { "dependencies": { "@storybook/csf-plugin": "10.4.6", "ts-dedent": "^2.0.0" }, "peerDependencies": { "storybook": "^10.4.6", "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-BHBtD81HiXUiDQz/CaFynLtWmm7AFUQn8VnXuHipZ8KlnUANopa4yqdVuy/Gwz8ub254uFI5NMZsW/KlgWNgNg=="],
|
|
348
363
|
|
|
349
364
|
"@storybook/csf-plugin": ["@storybook/csf-plugin@10.4.6", "", { "dependencies": { "unplugin": "^2.3.5" }, "peerDependencies": { "esbuild": "*", "rollup": "*", "storybook": "^10.4.6", "vite": "*", "webpack": "*" }, "optionalPeers": ["esbuild", "rollup", "vite", "webpack"] }, "sha512-NILLxDqpA/JR/AazGWpsz+4fadJwRU4uhHephGtYpVOWnQA/DkJfKT6zpcJVq8+QA8A2zKMLX3GVKsXIrxjuDA=="],
|
|
@@ -440,6 +455,12 @@
|
|
|
440
455
|
|
|
441
456
|
"@vitejs/plugin-react": ["@vitejs/plugin-react@6.0.3", "", { "dependencies": { "@rolldown/pluginutils": "^1.0.1" }, "peerDependencies": { "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", "babel-plugin-react-compiler": "^1.0.0", "vite": "^8.0.0" }, "optionalPeers": ["@rolldown/plugin-babel", "babel-plugin-react-compiler"] }, "sha512-vmFvco5/QuC2f9Oj+wTk0+9XeDFkHxSamwZKYc7MxYwKICfvUvlMhqKI0VuICPltGqh1neqBKDvO4kes1ya8vg=="],
|
|
442
457
|
|
|
458
|
+
"@vitest/browser": ["@vitest/browser@4.1.9", "", { "dependencies": { "@blazediff/core": "1.9.1", "@vitest/mocker": "4.1.9", "@vitest/utils": "4.1.9", "magic-string": "^0.30.21", "pngjs": "^7.0.0", "sirv": "^3.0.2", "tinyrainbow": "^3.1.0", "ws": "^8.19.0" }, "peerDependencies": { "vitest": "4.1.9" } }, "sha512-j1BKtWmPcqpMhmx/L9EPLgAJpCb0zKfwoWLmqBbxaogCXHjOwHFSEoHCBfnGtx93xKQwilZ26m+UOsHqHMkRNg=="],
|
|
459
|
+
|
|
460
|
+
"@vitest/browser-playwright": ["@vitest/browser-playwright@4.1.9", "", { "dependencies": { "@vitest/browser": "4.1.9", "@vitest/mocker": "4.1.9", "tinyrainbow": "^3.1.0" }, "peerDependencies": { "playwright": "*", "vitest": "4.1.9" } }, "sha512-Bq1rOGf9waevzG3EOkO/dene6bvKTUsZMVg8S1i+WH3JcMjuXEjiahP9rAqZRELUqjBySOJsvvSWqK/B3wjKQw=="],
|
|
461
|
+
|
|
462
|
+
"@vitest/coverage-v8": ["@vitest/coverage-v8@4.1.9", "", { "dependencies": { "@bcoe/v8-coverage": "^1.0.2", "@vitest/utils": "4.1.9", "ast-v8-to-istanbul": "^1.0.0", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", "istanbul-reports": "^3.2.0", "magicast": "^0.5.2", "obug": "^2.1.1", "std-env": "^4.0.0-rc.1", "tinyrainbow": "^3.1.0" }, "peerDependencies": { "@vitest/browser": "4.1.9", "vitest": "4.1.9" }, "optionalPeers": ["@vitest/browser"] }, "sha512-G9/lgqibheLVBDRuya45EbsEXTYcWoSG+TLg7i2axuzx0Eq62eXn+aWXyaVdV5vKvFSWd6ywcX8hA7la9Pvu8g=="],
|
|
463
|
+
|
|
443
464
|
"@vitest/expect": ["@vitest/expect@3.2.4", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/spy": "3.2.4", "@vitest/utils": "3.2.4", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig=="],
|
|
444
465
|
|
|
445
466
|
"@vitest/mocker": ["@vitest/mocker@4.1.9", "", { "dependencies": { "@vitest/spy": "4.1.9", "estree-walker": "^3.0.3", "magic-string": "^0.30.21" }, "peerDependencies": { "msw": "^2.4.9", "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "optionalPeers": ["msw", "vite"] }, "sha512-EVkXzBjrPGM+cK8/ANWgBrkUCfJfb38/EfTSO8h7pWvKkyPkpWxvR7BkD2MyItMF62C97zAEoqdpUixwR/e+Rw=="],
|
|
@@ -472,6 +493,10 @@
|
|
|
472
493
|
|
|
473
494
|
"ast-types": ["ast-types@0.16.1", "", { "dependencies": { "tslib": "^2.0.1" } }, "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg=="],
|
|
474
495
|
|
|
496
|
+
"ast-v8-to-istanbul": ["ast-v8-to-istanbul@1.0.4", "", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.31", "estree-walker": "^3.0.3", "js-tokens": "^10.0.0" } }, "sha512-0bC0/4bTSrnwdhU3IsZDwEdojvuPrSg59OYZfKsLRtJZ0u8VBx9DebfqqG8bRdCC0I7vjgxmPi41P0lpkhJHtA=="],
|
|
497
|
+
|
|
498
|
+
"axe-core": ["axe-core@4.12.1", "", {}, "sha512-s7iGf5GaVMxEG0ENN9x+xTr7GFZCb1ZP/1uATUpCEK2X78nDB3RwbtFCo9pGAf9ru+VwoQ464DkaLEeRM08wJA=="],
|
|
499
|
+
|
|
475
500
|
"bail": ["bail@2.0.2", "", {}, "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw=="],
|
|
476
501
|
|
|
477
502
|
"balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="],
|
|
@@ -616,7 +641,7 @@
|
|
|
616
641
|
|
|
617
642
|
"flatted": ["flatted@3.4.2", "", {}, "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA=="],
|
|
618
643
|
|
|
619
|
-
"fsevents": ["fsevents@2.3.
|
|
644
|
+
"fsevents": ["fsevents@2.3.2", "", { "os": "darwin" }, "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA=="],
|
|
620
645
|
|
|
621
646
|
"function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="],
|
|
622
647
|
|
|
@@ -638,6 +663,8 @@
|
|
|
638
663
|
|
|
639
664
|
"hast-util-whitespace": ["hast-util-whitespace@3.0.0", "", { "dependencies": { "@types/hast": "^3.0.0" } }, "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw=="],
|
|
640
665
|
|
|
666
|
+
"html-escaper": ["html-escaper@2.0.2", "", {}, "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg=="],
|
|
667
|
+
|
|
641
668
|
"html-url-attributes": ["html-url-attributes@3.0.1", "", {}, "sha512-ol6UPyBWqsrO6EJySPz2O7ZSr856WDrEzM5zMqp+FJJLGMW35cLYmmZnl0vztAZxRUoNZJFTCohfjuIJ8I4QBQ=="],
|
|
642
669
|
|
|
643
670
|
"ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
|
|
@@ -674,6 +701,12 @@
|
|
|
674
701
|
|
|
675
702
|
"isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
|
|
676
703
|
|
|
704
|
+
"istanbul-lib-coverage": ["istanbul-lib-coverage@3.2.2", "", {}, "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg=="],
|
|
705
|
+
|
|
706
|
+
"istanbul-lib-report": ["istanbul-lib-report@3.0.1", "", { "dependencies": { "istanbul-lib-coverage": "^3.0.0", "make-dir": "^4.0.0", "supports-color": "^7.1.0" } }, "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw=="],
|
|
707
|
+
|
|
708
|
+
"istanbul-reports": ["istanbul-reports@3.2.0", "", { "dependencies": { "html-escaper": "^2.0.0", "istanbul-lib-report": "^3.0.0" } }, "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA=="],
|
|
709
|
+
|
|
677
710
|
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
|
|
678
711
|
|
|
679
712
|
"jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],
|
|
@@ -726,6 +759,10 @@
|
|
|
726
759
|
|
|
727
760
|
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
|
|
728
761
|
|
|
762
|
+
"magicast": ["magicast@0.5.3", "", { "dependencies": { "@babel/parser": "^7.29.3", "@babel/types": "^7.29.0", "source-map-js": "^1.2.1" } }, "sha512-pVKE4UdSQ7DvHzivsCIFx2BJn1mHG6KsyrFcaxFx6tONdneEuThrDx0Cj3AMg58KyN4pzYT+LHOotxDQDjNvkw=="],
|
|
763
|
+
|
|
764
|
+
"make-dir": ["make-dir@4.0.0", "", { "dependencies": { "semver": "^7.5.3" } }, "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw=="],
|
|
765
|
+
|
|
729
766
|
"mdast-util-from-markdown": ["mdast-util-from-markdown@2.0.3", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "mdast-util-to-string": "^4.0.0", "micromark": "^4.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q=="],
|
|
730
767
|
|
|
731
768
|
"mdast-util-mdx-expression": ["mdast-util-mdx-expression@2.0.1", "", { "dependencies": { "@types/estree-jsx": "^1.0.0", "@types/hast": "^3.0.0", "@types/mdast": "^4.0.0", "devlop": "^1.0.0", "mdast-util-from-markdown": "^2.0.0", "mdast-util-to-markdown": "^2.0.0" } }, "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ=="],
|
|
@@ -794,6 +831,8 @@
|
|
|
794
831
|
|
|
795
832
|
"minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="],
|
|
796
833
|
|
|
834
|
+
"mrmime": ["mrmime@2.0.1", "", {}, "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ=="],
|
|
835
|
+
|
|
797
836
|
"ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="],
|
|
798
837
|
|
|
799
838
|
"nanoid": ["nanoid@3.3.15", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA=="],
|
|
@@ -836,6 +875,12 @@
|
|
|
836
875
|
|
|
837
876
|
"picomatch": ["picomatch@4.0.4", "", {}, "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A=="],
|
|
838
877
|
|
|
878
|
+
"playwright": ["playwright@1.61.1", "", { "dependencies": { "playwright-core": "1.61.1" }, "optionalDependencies": { "fsevents": "2.3.2" }, "bin": { "playwright": "cli.js" } }, "sha512-DWnY5o3YbLWK4GovuAVwpqL+1VwGNdUGrRr++8j8PtQQzvAVZUIMjKQ90fY689sEJZJBbZVw1rXaOKSTitkzPQ=="],
|
|
879
|
+
|
|
880
|
+
"playwright-core": ["playwright-core@1.61.1", "", { "bin": { "playwright-core": "cli.js" } }, "sha512-h7Qlt6m4REp25qvIdvbDtVmD4LqVXfpRxhORv9L0jzETM05p4fuPJ3dKyuSXQxDSbXnmS79HAgi9589lGSpLkg=="],
|
|
881
|
+
|
|
882
|
+
"pngjs": ["pngjs@7.0.0", "", {}, "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow=="],
|
|
883
|
+
|
|
839
884
|
"postcss": ["postcss@8.5.16", "", { "dependencies": { "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg=="],
|
|
840
885
|
|
|
841
886
|
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
|
|
@@ -890,6 +935,8 @@
|
|
|
890
935
|
|
|
891
936
|
"siginfo": ["siginfo@2.0.0", "", {}, "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g=="],
|
|
892
937
|
|
|
938
|
+
"sirv": ["sirv@3.0.2", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g=="],
|
|
939
|
+
|
|
893
940
|
"source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
|
|
894
941
|
|
|
895
942
|
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
|
@@ -930,6 +977,8 @@
|
|
|
930
977
|
|
|
931
978
|
"to-regex-range": ["to-regex-range@5.0.1", "", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="],
|
|
932
979
|
|
|
980
|
+
"totalist": ["totalist@3.0.1", "", {}, "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ=="],
|
|
981
|
+
|
|
933
982
|
"trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="],
|
|
934
983
|
|
|
935
984
|
"trough": ["trough@2.2.0", "", {}, "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw=="],
|
|
@@ -1000,10 +1049,20 @@
|
|
|
1000
1049
|
|
|
1001
1050
|
"zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="],
|
|
1002
1051
|
|
|
1052
|
+
"@babel/core/@babel/parser": ["@babel/parser@7.29.2", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA=="],
|
|
1053
|
+
|
|
1003
1054
|
"@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
|
1004
1055
|
|
|
1056
|
+
"@babel/generator/@babel/parser": ["@babel/parser@7.29.2", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA=="],
|
|
1057
|
+
|
|
1005
1058
|
"@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
|
|
1006
1059
|
|
|
1060
|
+
"@babel/parser/@babel/types": ["@babel/types@7.29.7", "", { "dependencies": { "@babel/helper-string-parser": "^7.29.7", "@babel/helper-validator-identifier": "^7.29.7" } }, "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA=="],
|
|
1061
|
+
|
|
1062
|
+
"@babel/template/@babel/parser": ["@babel/parser@7.29.2", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA=="],
|
|
1063
|
+
|
|
1064
|
+
"@babel/traverse/@babel/parser": ["@babel/parser@7.29.2", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA=="],
|
|
1065
|
+
|
|
1007
1066
|
"@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
|
|
1008
1067
|
|
|
1009
1068
|
"@oxc-resolver/binding-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.11.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.2.2", "tslib": "^2.4.0" } }, "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ=="],
|
|
@@ -1016,12 +1075,18 @@
|
|
|
1016
1075
|
|
|
1017
1076
|
"@testing-library/jest-dom/dom-accessibility-api": ["dom-accessibility-api@0.6.3", "", {}, "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w=="],
|
|
1018
1077
|
|
|
1078
|
+
"@types/babel__core/@babel/parser": ["@babel/parser@7.29.2", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA=="],
|
|
1079
|
+
|
|
1080
|
+
"@types/babel__template/@babel/parser": ["@babel/parser@7.29.2", "", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": "./bin/babel-parser.js" }, "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA=="],
|
|
1081
|
+
|
|
1019
1082
|
"@typescript-eslint/utils/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.59.1", "", { "dependencies": { "@typescript-eslint/types": "8.59.1", "@typescript-eslint/visitor-keys": "8.59.1" } }, "sha512-LwuHQI4pDOYVKvmH2dkaJo6YZCSgouVgnS/z7yBPKBMvgtBvyLqiLy9Z6b7+m/TRcX1NFYUqZetI5Y+aT4GEfg=="],
|
|
1020
1083
|
|
|
1021
1084
|
"@typescript-eslint/utils/@typescript-eslint/types": ["@typescript-eslint/types@8.59.1", "", {}, "sha512-ZDCjgccSdYPw5Bxh+my4Z0lJU96ZDN7jbBzvmEn0FZx3RtU1C7VWl6NbDx94bwY3V5YsgwRzJPOgeY2Q/nLG8A=="],
|
|
1022
1085
|
|
|
1023
1086
|
"@typescript-eslint/utils/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.59.1", "", { "dependencies": { "@typescript-eslint/project-service": "8.59.1", "@typescript-eslint/tsconfig-utils": "8.59.1", "@typescript-eslint/types": "8.59.1", "@typescript-eslint/visitor-keys": "8.59.1", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-OUd+vJS05sSkOip+BkZ/2NS8RMxrAAJemsC6vU3kmfLyeaJT0TftHkV9mcx2107MmsBVXXexhVu4F0TZXyMl4g=="],
|
|
1024
1087
|
|
|
1088
|
+
"@vitest/browser/ws": ["ws@8.21.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g=="],
|
|
1089
|
+
|
|
1025
1090
|
"@vitest/expect/@vitest/utils": ["@vitest/utils@3.2.4", "", { "dependencies": { "@vitest/pretty-format": "3.2.4", "loupe": "^3.1.4", "tinyrainbow": "^2.0.0" } }, "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA=="],
|
|
1026
1091
|
|
|
1027
1092
|
"@vitest/expect/tinyrainbow": ["tinyrainbow@2.0.0", "", {}, "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw=="],
|
|
@@ -1030,6 +1095,10 @@
|
|
|
1030
1095
|
|
|
1031
1096
|
"@vitest/mocker/estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="],
|
|
1032
1097
|
|
|
1098
|
+
"ast-v8-to-istanbul/estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="],
|
|
1099
|
+
|
|
1100
|
+
"ast-v8-to-istanbul/js-tokens": ["js-tokens@10.0.0", "", {}, "sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q=="],
|
|
1101
|
+
|
|
1033
1102
|
"chalk/ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
|
|
1034
1103
|
|
|
1035
1104
|
"eslint-import-resolver-node/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
|
|
@@ -1048,12 +1117,20 @@
|
|
|
1048
1117
|
|
|
1049
1118
|
"rolldown/@oxc-project/types": ["@oxc-project/types@0.138.0", "", {}, "sha512-1a7ZKmrRTCoN1XMZ4L0PyyqrMnrNlLyPuOkdSX2MZg7IiIGRUyurNhAm73ptDOraoBcIordsIGKNPKUzy3ZmfA=="],
|
|
1050
1119
|
|
|
1120
|
+
"rollup/fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
|
1121
|
+
|
|
1122
|
+
"vite/fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="],
|
|
1123
|
+
|
|
1051
1124
|
"vitest/@vitest/expect": ["@vitest/expect@4.1.9", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "@types/chai": "^5.2.2", "@vitest/spy": "4.1.9", "@vitest/utils": "4.1.9", "chai": "^6.2.2", "tinyrainbow": "^3.1.0" } }, "sha512-vl/rYsUKcBr3SnQn166+XR5ZQcgMx3DQhFWdfli/cWpLnLUmbxZvyrJZotLFUryib+LtArYMSTJ5RbQ57ZqrlA=="],
|
|
1052
1125
|
|
|
1053
1126
|
"vitest/@vitest/spy": ["@vitest/spy@4.1.9", "", {}, "sha512-fHpsS6mIi+PiEW+vcRVOMkX1oSaPKne3VOclSFICPcGOmfKgXPU5iAah+wcNcj2xPrCCmfq99IDGf+EojhhvhA=="],
|
|
1054
1127
|
|
|
1055
1128
|
"vitest/tinyglobby": ["tinyglobby@0.2.16", "", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.4" } }, "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg=="],
|
|
1056
1129
|
|
|
1130
|
+
"@babel/parser/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.29.7", "", {}, "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw=="],
|
|
1131
|
+
|
|
1132
|
+
"@babel/parser/@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.29.7", "", {}, "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg=="],
|
|
1133
|
+
|
|
1057
1134
|
"@oxc-resolver/binding-wasm32-wasi/@emnapi/core/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA=="],
|
|
1058
1135
|
|
|
1059
1136
|
"@rolldown/binding-wasm32-wasi/@emnapi/core/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.2.2", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA=="],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@structuralists/scaffolding",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"main": "./index.ts",
|
|
5
5
|
"types": "./index.ts",
|
|
6
6
|
"exports": {
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"storybook": "storybook dev -p 6015",
|
|
16
16
|
"build-storybook": "storybook build",
|
|
17
17
|
"test": "bun test",
|
|
18
|
+
"test:storybook": "vitest run --project=storybook",
|
|
18
19
|
"typecheck": "tsc --noEmit",
|
|
19
20
|
"lint": "eslint src"
|
|
20
21
|
},
|
|
@@ -29,7 +30,9 @@
|
|
|
29
30
|
},
|
|
30
31
|
"devDependencies": {
|
|
31
32
|
"@happy-dom/global-registrator": "^20.10.6",
|
|
33
|
+
"@storybook/addon-a11y": "10.4.6",
|
|
32
34
|
"@storybook/addon-docs": "^10.4.6",
|
|
35
|
+
"@storybook/addon-vitest": "10.4.6",
|
|
33
36
|
"@storybook/react": "^10.4.6",
|
|
34
37
|
"@storybook/react-vite": "^10.4.6",
|
|
35
38
|
"@testing-library/dom": "^10.4.1",
|
|
@@ -39,9 +42,12 @@
|
|
|
39
42
|
"@types/react-dom": "^19.2.3",
|
|
40
43
|
"@typescript-eslint/parser": "^8.62.1",
|
|
41
44
|
"@vitejs/plugin-react": "^6.0.3",
|
|
45
|
+
"@vitest/browser-playwright": "4.1.9",
|
|
46
|
+
"@vitest/coverage-v8": "4.1.9",
|
|
42
47
|
"eslint": "^10.6.0",
|
|
43
48
|
"eslint-plugin-boundaries": "^6.0.2",
|
|
44
49
|
"eslint-plugin-storybook": "10.4.6",
|
|
50
|
+
"playwright": "^1.61.1",
|
|
45
51
|
"prettier": "^3.9.4",
|
|
46
52
|
"react-router": "^7.18.1",
|
|
47
53
|
"storybook": "^10.4.6",
|
package/src/forms/CLAUDE.md
CHANGED
|
@@ -35,24 +35,36 @@ function composition.
|
|
|
35
35
|
|
|
36
36
|
```ts
|
|
37
37
|
const constraints = perField({
|
|
38
|
-
a: (val: string | undefined) => !val ? "'a' cannot be empty" : null,
|
|
39
|
-
})
|
|
38
|
+
a: (val: string | undefined) => (!val ? "'a' cannot be empty" : null),
|
|
39
|
+
}) satisfies Validations<FormType>;
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
`perField` is the entry point that produces a `Validations<FormType>`-shaped
|
|
43
43
|
value while preserving the precise types of each individual validator.
|
|
44
44
|
|
|
45
|
-
###
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
45
|
+
### The precision-preserving ceremony, by call-site shape
|
|
46
|
+
|
|
47
|
+
The enemy is widening: if the constraints object's inferred type loses each
|
|
48
|
+
validator's specific function type, the refinement markers are lost and
|
|
49
|
+
`Refine<>` has nothing to walk. What prevents widening depends on where the
|
|
50
|
+
constraints object is written:
|
|
51
|
+
|
|
52
|
+
- **Inline in the `useFormState` call — no ceremony at all.** The hook's
|
|
53
|
+
`const V extends Validations<T>` type parameter freezes the literal type,
|
|
54
|
+
and the generic bound shape-checks against the form type. This is the
|
|
55
|
+
everyday path.
|
|
56
|
+
- **Pre-built via `perField` — add `satisfies Validations<FormType>`.**
|
|
57
|
+
`perField`'s own `const` type parameter plays the freezing role (`as const`
|
|
58
|
+
cannot be applied to a call expression — TS1355), and `satisfies` checks
|
|
59
|
+
shape against `FormType` (every key valid, every validator's input
|
|
60
|
+
compatible) without widening the way an annotation
|
|
61
|
+
`: Validations<FormType>` would.
|
|
62
|
+
- **Pre-built as a bare object literal — `as const satisfies
|
|
63
|
+
Validations<FormType>`,** both parts required: `as const` freezes,
|
|
64
|
+
`satisfies` checks.
|
|
65
|
+
|
|
66
|
+
Never *annotate* a constraints binding (`: Validations<FormType>`) — that is
|
|
67
|
+
the widening failure mode all three patterns exist to avoid.
|
|
56
68
|
|
|
57
69
|
## Standard-library validators carry refinements
|
|
58
70
|
|
|
@@ -134,11 +146,22 @@ precision end-to-end. So we wire it up before adding any consumers.
|
|
|
134
146
|
## Layout
|
|
135
147
|
|
|
136
148
|
- `useFormState/` — the hook + the value-model types (`FormValueSimple`,
|
|
137
|
-
`FormValuesObject`, `FormValueList`).
|
|
149
|
+
`FormValuesObject`, `FormValueList`). Hook surface: `{ values,
|
|
150
|
+
onValueChanges, errors, isValid, submitAttempted, submit }`; `errors` is
|
|
151
|
+
live-derived from current values each render (validators are pure and
|
|
152
|
+
cheap), `submitAttempted` lets UIs gate error display, and `submit()`
|
|
153
|
+
performs the one honest cast to `Refine<T, V>` — earned because the
|
|
154
|
+
validators just passed at runtime.
|
|
138
155
|
- `path/` — typed cursor (`Path<T>`, `ValueAt<T,P>`, `Cursor<T>`, `read()`).
|
|
139
156
|
Will be used for granular setters and for surfacing per-field
|
|
140
157
|
errors/touched state. Coupled to the form value model intentionally.
|
|
141
|
-
-
|
|
142
|
-
`Refinement<>` infra.
|
|
143
|
-
|
|
144
|
-
|
|
158
|
+
- `validations/` — `perField`, `Validations<T>`, `Refine<T,V>`,
|
|
159
|
+
`Refinement<>` infra. `Validations<T>` accepts bare
|
|
160
|
+
`(val) => string | null` functions too — they simply narrow nothing.
|
|
161
|
+
- `validators/` — the standard-library validators (`notEmpty`, `minLength`,
|
|
162
|
+
`matches`, `min`) plus `allOf`, which composes validators on one field and
|
|
163
|
+
carries the union of the parts' refinements. `allOf` derives its input type
|
|
164
|
+
as the intersection of the parts' inputs from the const tuple (not a
|
|
165
|
+
standalone inferred type parameter — that breaks without an outer
|
|
166
|
+
contextual type, e.g. inside inline constraints). `oneOf` is deferred:
|
|
167
|
+
exclusion-only markers can't express keep-only narrowing yet.
|