@hideyukimori/nene2-ui 0.8.0 → 0.14.0

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.
Files changed (55) hide show
  1. package/README.md +96 -4
  2. package/dist/data/DataTable.js +1 -1
  3. package/dist/data/DataTable.js.map +1 -1
  4. package/dist/data/DetailList.js +1 -1
  5. package/dist/data/DetailList.js.map +1 -1
  6. package/dist/data/Pagination.js +1 -1
  7. package/dist/data/Pagination.js.map +1 -1
  8. package/dist/feedback/Badge.js +3 -3
  9. package/dist/feedback/Badge.js.map +1 -1
  10. package/dist/feedback/InlineAlert.d.ts +13 -4
  11. package/dist/feedback/InlineAlert.js +5 -5
  12. package/dist/feedback/InlineAlert.js.map +1 -1
  13. package/dist/feedback/ToastProvider.js +2 -2
  14. package/dist/feedback/ToastProvider.js.map +1 -1
  15. package/dist/forms/FormField.d.ts +11 -1
  16. package/dist/forms/FormField.js +7 -3
  17. package/dist/forms/FormField.js.map +1 -1
  18. package/dist/forms/field-context.d.ts +13 -0
  19. package/dist/forms/field-context.js +6 -1
  20. package/dist/forms/field-context.js.map +1 -1
  21. package/dist/layout/Card.js +1 -1
  22. package/dist/layout/Card.js.map +1 -1
  23. package/dist/layout/PageHeader.js +1 -1
  24. package/dist/layout/PageHeader.js.map +1 -1
  25. package/dist/lib/states.d.ts +33 -3
  26. package/dist/lib/states.js +37 -2
  27. package/dist/lib/states.js.map +1 -1
  28. package/dist/overlay/Modal.js +1 -1
  29. package/dist/overlay/Modal.js.map +1 -1
  30. package/dist/primitives/Button.js +32 -8
  31. package/dist/primitives/Button.js.map +1 -1
  32. package/dist/primitives/Checkbox.d.ts +21 -6
  33. package/dist/primitives/Checkbox.js +20 -10
  34. package/dist/primitives/Checkbox.js.map +1 -1
  35. package/dist/primitives/Input.js +2 -2
  36. package/dist/primitives/Input.js.map +1 -1
  37. package/dist/primitives/Radio.d.ts +20 -6
  38. package/dist/primitives/Radio.js +19 -10
  39. package/dist/primitives/Radio.js.map +1 -1
  40. package/dist/primitives/Select.js +2 -2
  41. package/dist/primitives/Select.js.map +1 -1
  42. package/dist/primitives/Spinner.js +1 -1
  43. package/dist/primitives/Spinner.js.map +1 -1
  44. package/dist/primitives/Switch.js +4 -2
  45. package/dist/primitives/Switch.js.map +1 -1
  46. package/dist/primitives/Text.js +1 -1
  47. package/dist/primitives/Text.js.map +1 -1
  48. package/dist/primitives/Textarea.js +2 -2
  49. package/dist/primitives/Textarea.js.map +1 -1
  50. package/dist/states/EmptyState.js +1 -1
  51. package/dist/states/EmptyState.js.map +1 -1
  52. package/dist/states/ErrorState.js +1 -1
  53. package/dist/states/ErrorState.js.map +1 -1
  54. package/package.json +1 -1
  55. package/themes/default.css +213 -2
package/README.md CHANGED
@@ -193,11 +193,11 @@ into `0`, because 2px is a 2px error — but nene-records ships nine themes at 0
193
193
  2–3px as separate product themes, so that error deletes a distinction rather than rounding
194
194
  one.
195
195
 
196
- | radius scale | exact match | within 2px | designed values collapsed |
197
- | --------------------------- | ----------: | ---------: | ------------------------: |
198
- | **the kit's nine + pill** | **69.9%** | **97.7%** | **3** (all 1px apart) |
196
+ | radius scale | exact match | within 2px | designed values collapsed |
197
+ | ---------------------------- | ----------: | ---------: | ------------------------: |
198
+ | **the kit's nine + pill** | **69.9%** | **97.7%** | **3** (all 1px apart) |
199
199
  | eight, without a `10px` step | 64.3% | 97.7% | 4 |
200
- | seven, without `2px` | 43.2% | 97.7% | 4 |
200
+ | seven, without `2px` | 43.2% | 97.7% | 4 |
201
201
 
202
202
  🔑 **A scale is judged by what it can still tell apart, not only by how far it moves things.**
203
203
 
@@ -243,6 +243,79 @@ it can be checked with a regular expression exactly as written.
243
243
  | `--color-*` | scale (palette) references | same |
244
244
  | `--brightness-*` `--opacity-*` | literals are fine | **there is no scale to reference.** A hover darkening of 95% is not a step in a series; inventing a "brightness scale" so the rule could cover it would be a scale with one real user |
245
245
 
246
+ ### 🔴 `className` lands on the root
247
+
248
+ Every component puts the caller's `className` on its **outermost** element. For `Checkbox`
249
+ and `Radio` that root is the `<label>`, not the `<input>` — use `inputClassName` to reach
250
+ the box itself.
251
+
252
+ Until 0.10.0 those two were the exception, and the exception was invisible: `className` was
253
+ accepted, applied, and landed somewhere the caller could not have wanted. Layout properties
254
+ — `self-start` in a flex row, a width, a margin — belong to the root, so a product had to
255
+ wrap every choice in a `<div>` to say them.
256
+
257
+ 🔑 The kit had already answered a symptom of this in wave 2 (`cursor-pointer` belongs to the
258
+ label, so the kit carries it). That was right and it left the reason in place. **Fixing what
259
+ a report names is not the same as fixing what it is about.**
260
+
261
+ ### 🔴 A palette that is missing a meaning
262
+
263
+ The kit's theme defines **8 of the 28 colours** in the frozen Core Token Contract v1. That
264
+ is a legal theme — the contract says what a name means, not that every name must be used —
265
+ but it stops being harmless the moment a component needs one of the twenty.
266
+
267
+ `warn` was one. Six ships define `--color-warn`; nene-payout, the product this theme was
268
+ promoted from, does not. So `--color-x-slot-alert-warn-*` pointed at `--color-danger` and a
269
+ warning rendered as an error — as nene-vault put it, **the difference reached someone
270
+ listening and no one looking**.
271
+
272
+ 🔑 Same root cause as the radius scale, and the same shape as it: **a set whose members all
273
+ resolve to one value cannot express the distinction it is named for.** Both are now checked
274
+ — radius by step count, colour by whether two meanings resolve to the same value.
275
+
276
+ Still undefined: `surface-overlay`, `surface-sunken`, `text-faint`, `text-inverse`,
277
+ `border-strong`, `accent-hover`, `accent-soft`, `on-danger`, `success`, `success-soft`,
278
+ `on-success`, `info`, `info-soft`, `on-info`, `focus-ring`, `scrim`. Two of those —
279
+ `focus-ring` and `scrim` — already have component slots pointing at substitutes.
280
+
281
+ ### 🔴 Two validity states, and only one of them is invalid
282
+
283
+ A value can be worth flagging without being wrong. nene-vault marks a retention period under
284
+ ten years, which satisfies every rule its form has.
285
+
286
+ | | ARIA | paints |
287
+ | --------- | ----------------------------------------------------- | ----------------------------------------------- |
288
+ | `error` | `aria-invalid` | `--color-x-slot-control-invalid-*` |
289
+ | `warning` | 🔴 **nothing** — announced through `aria-describedby` | `--color-x-slot-control-warn-*` via `data-warn` |
290
+
291
+ Setting `aria-invalid` on a legal value announces it as an error; leaving it off left the
292
+ field with no signal at all, because **the kit painted neither state** until 0.12.0. Seven of
293
+ nine ships paint validity themselves, so migrating onto the kit removed a signal the product
294
+ already had.
295
+
296
+ 🔑 The test guarding vault's amber border asserted `aria-invalid="true"` — the attribute, not
297
+ the paint — and stayed green through the loss. **A test can check a stand-in for the thing it
298
+ cares about; while both live in the same component that is the same test, and the moment the
299
+ real thing moves upstream the stand-in stays behind and keeps passing.** Moving an
300
+ implementation upstream produces this shape structurally.
301
+
302
+ ### 🔴 What a slot check must cover
303
+
304
+ The rule above — _every design value a component uses comes from a slot_ — was false in 26 of
305
+ 28 components until 0.9.0, and the check meant to enforce it was green throughout. It listed
306
+ the utility prefixes it knew about (`p px py … rounded`), so **colour and weight were never
307
+ inspected**: 59 palette reaches across 20 files, plus four inline `font-medium`.
308
+
309
+ It surfaced when nene-vault compared its production screens against the migrated build in a
310
+ real browser — Playwright, computed styles, element by element (2026-08-23). 73 elements
311
+ matched and 21 differed, and **every difference was inside a kit component**; the product's
312
+ own markup matched on every property. A product cannot make its controls darker than its body
313
+ text while the component writes `text-text-primary` itself.
314
+
315
+ 🔑 **A check written as an enumeration passes everything the enumeration omits.** So the
316
+ colour half of that check is not enumerated: it reads the palette out of the theme. A colour
317
+ added tomorrow is covered today.
318
+
246
319
  🔴 **Check the three namespaces that have scales, not every slot.** Until 0.6.0 this section
247
320
  said "and nothing else", while the kit's own theme held `--text-x-slot-field-label-size:
248
321
  0.75rem` and `--brightness-x-slot-hover: 95%` — so a product implementing the rule as written
@@ -263,6 +336,25 @@ a missing component — open an issue, so every product gets the answer.
263
336
  **Products: apply the same check to your own theme.** The kit can only police its own file;
264
337
  the rule is the same one, and the regular expression above is the whole implementation.
265
338
 
339
+ ## 🔴 Migrating a screen to the kit
340
+
341
+ **`<div>` → `<Stack>` is not a no-op.** The wrapper changes from block flow to flex, and
342
+ inline-level children — `Button`, `<label>`, `<span>` — change size because of it:
343
+
344
+ | what you see | why |
345
+ | -------------------------------------------- | --------------------------------------------------------------------------------------- |
346
+ | a button suddenly spans the row | `Stack` is `align-items: stretch`, so an inline-block child is stretched |
347
+ | a choice label goes from 112px wide to 582px | the same stretch |
348
+ | an icon becomes a tall rectangle | an `<svg>` with no width/height attribute has no intrinsic size and lays out at 300×150 |
349
+
350
+ The first two are flexbox working as specified; reach for `self-start` (which now lands on
351
+ the root — see above) or `items-start` on the `Stack`. The third was the kit's fault and is
352
+ bounded from 0.10.0, but only inside `Button` — **use `Icon` for artwork anywhere else**, or
353
+ give the `<svg>` a size of its own.
354
+
355
+ 🔑 Three regressions in one migration, all from one wrapper swap, all of them visible only
356
+ on screen: **nothing in a diff says that a child used to be inline** (nene-vault, 2026-08-23).
357
+
266
358
  ## What is in scope
267
359
 
268
360
  **In:** admin console and business-screen UI, page layout scaffolding, form field structure, the
@@ -12,6 +12,6 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
12
12
  * page. It is visually hidden, not absent.
13
13
  */
14
14
  export function DataTable({ columns, rows, rowKey, caption }) {
15
- return (_jsxs("table", { className: "w-full border-collapse font-sans text-text-primary", children: [_jsx("caption", { className: "sr-only", children: caption }), _jsx("thead", { children: _jsx("tr", { children: columns.map((col) => (_jsx("th", { scope: "col", className: `border-b border-border px-x-slot-table-cell-pad-x py-x-slot-table-cell-pad-y font-medium text-text-muted ${col.align === 'end' ? 'text-right' : 'text-left'}`, children: col.header }, col.key))) }) }), _jsx("tbody", { children: rows.map((row) => (_jsx("tr", { children: columns.map((col) => (_jsx("td", { className: `border-b border-border px-x-slot-table-cell-pad-x py-x-slot-table-cell-pad-y ${col.align === 'end' ? 'text-right' : 'text-left'}`, children: col.cell(row) }, col.key))) }, rowKey(row)))) })] }));
15
+ return (_jsxs("table", { className: "w-full border-collapse font-sans text-x-slot-table-fg", children: [_jsx("caption", { className: "sr-only", children: caption }), _jsx("thead", { children: _jsx("tr", { children: columns.map((col) => (_jsx("th", { scope: "col", className: `border-b border-x-slot-table-border px-x-slot-table-cell-pad-x py-x-slot-table-cell-pad-y font-x-slot-table-header text-x-slot-table-header-fg ${col.align === 'end' ? 'text-right' : 'text-left'}`, children: col.header }, col.key))) }) }), _jsx("tbody", { children: rows.map((row) => (_jsx("tr", { children: columns.map((col) => (_jsx("td", { className: `border-b border-x-slot-table-border px-x-slot-table-cell-pad-x py-x-slot-table-cell-pad-y ${col.align === 'end' ? 'text-right' : 'text-left'}`, children: col.cell(row) }, col.key))) }, rowKey(row)))) })] }));
16
16
  }
17
17
  //# sourceMappingURL=DataTable.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DataTable.js","sourceRoot":"","sources":["../../src/data/DataTable.tsx"],"names":[],"mappings":";AAsBA;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,SAAS,CAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAuB;IACpF,OAAO,CACL,iBAAO,SAAS,EAAC,oDAAoD,aACnE,kBAAS,SAAS,EAAC,SAAS,YAAE,OAAO,GAAW,EAChD,0BACE,uBACG,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CACpB,aAEE,KAAK,EAAC,KAAK,EACX,SAAS,EAAE,4GACT,GAAG,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WACvC,EAAE,YAED,GAAG,CAAC,MAAM,IANN,GAAG,CAAC,GAAG,CAOT,CACN,CAAC,GACC,GACC,EACR,0BACG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CACjB,uBACG,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CACpB,aAEE,SAAS,EAAE,gFACT,GAAG,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WACvC,EAAE,YAED,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IALT,GAAG,CAAC,GAAG,CAMT,CACN,CAAC,IAVK,MAAM,CAAC,GAAG,CAAC,CAWf,CACN,CAAC,GACI,IACF,CACT,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"DataTable.js","sourceRoot":"","sources":["../../src/data/DataTable.tsx"],"names":[],"mappings":";AAsBA;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,SAAS,CAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAuB;IACpF,OAAO,CACL,iBAAO,SAAS,EAAC,uDAAuD,aACtE,kBAAS,SAAS,EAAC,SAAS,YAAE,OAAO,GAAW,EAChD,0BACE,uBACG,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CACpB,aAEE,KAAK,EAAC,KAAK,EACX,SAAS,EAAE,kJACT,GAAG,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WACvC,EAAE,YAED,GAAG,CAAC,MAAM,IANN,GAAG,CAAC,GAAG,CAOT,CACN,CAAC,GACC,GACC,EACR,0BACG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CACjB,uBACG,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CACpB,aAEE,SAAS,EAAE,6FACT,GAAG,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,WACvC,EAAE,YAED,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IALT,GAAG,CAAC,GAAG,CAMT,CACN,CAAC,IAVK,MAAM,CAAC,GAAG,CAAC,CAWf,CACN,CAAC,GACI,IACF,CACT,CAAC;AACJ,CAAC"}
@@ -5,6 +5,6 @@ import { cx } from '../lib/cx.js';
5
5
  * label/value relationship is conveyed to assistive technology.
6
6
  */
7
7
  export function DetailList({ rows, className }) {
8
- return (_jsx("dl", { className: cx('flex flex-col gap-x-slot-detail-gap', className), children: rows.map((row) => (_jsxs("div", { className: "flex flex-col gap-x-slot-detail-row-gap border-b border-border py-x-slot-detail-row-pad-y", children: [_jsx("dt", { className: "font-sans font-medium text-text-muted", children: row.label }), _jsx("dd", { className: "font-sans text-text-primary", children: row.value })] }, row.label))) }));
8
+ return (_jsx("dl", { className: cx('flex flex-col gap-x-slot-detail-gap', className), children: rows.map((row) => (_jsxs("div", { className: "flex flex-col gap-x-slot-detail-row-gap border-b border-x-slot-detail-border py-x-slot-detail-row-pad-y", children: [_jsx("dt", { className: "font-sans font-x-slot-detail-term text-x-slot-detail-term-fg", children: row.label }), _jsx("dd", { className: "font-sans text-x-slot-detail-description-fg", children: row.value })] }, row.label))) }));
9
9
  }
10
10
  //# sourceMappingURL=DetailList.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DetailList.js","sourceRoot":"","sources":["../../src/data/DetailList.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAclC;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,EAAE,IAAI,EAAE,SAAS,EAAmB;IAC7D,OAAO,CACL,aAAI,SAAS,EAAE,EAAE,CAAC,qCAAqC,EAAE,SAAS,CAAC,YAChE,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CACjB,eAEE,SAAS,EAAC,2FAA2F,aAErG,aAAI,SAAS,EAAC,uCAAuC,YAAE,GAAG,CAAC,KAAK,GAAM,EACtE,aAAI,SAAS,EAAC,6BAA6B,YAAE,GAAG,CAAC,KAAK,GAAM,KAJvD,GAAG,CAAC,KAAK,CAKV,CACP,CAAC,GACC,CACN,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"DetailList.js","sourceRoot":"","sources":["../../src/data/DetailList.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAclC;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,EAAE,IAAI,EAAE,SAAS,EAAmB;IAC7D,OAAO,CACL,aAAI,SAAS,EAAE,EAAE,CAAC,qCAAqC,EAAE,SAAS,CAAC,YAChE,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CACjB,eAEE,SAAS,EAAC,yGAAyG,aAEnH,aAAI,SAAS,EAAC,8DAA8D,YACzE,GAAG,CAAC,KAAK,GACP,EACL,aAAI,SAAS,EAAC,6CAA6C,YAAE,GAAG,CAAC,KAAK,GAAM,KANvE,GAAG,CAAC,KAAK,CAOV,CACP,CAAC,GACC,CACN,CAAC;AACJ,CAAC"}
@@ -27,6 +27,6 @@ export function Pagination(props) {
27
27
  const atEnd = props.page === undefined ? !props.canNext : props.page >= props.pageCount;
28
28
  const goPrev = () => props.page === undefined ? props.onPrev() : props.onPageChange(props.page - 1);
29
29
  const goNext = () => props.page === undefined ? props.onNext() : props.onPageChange(props.page + 1);
30
- return (_jsx("nav", { "aria-label": label, children: _jsxs(Stack, { direction: "horizontal", gap: "2xs", align: "center", children: [_jsx(Button, { variant: "secondary", disabled: atStart, onClick: goPrev, "aria-label": previousLabel, children: previousLabel }), _jsx("span", { "aria-current": "page", className: "font-sans text-text-muted", children: status }), _jsx(Button, { variant: "secondary", disabled: atEnd, onClick: goNext, "aria-label": nextLabel, children: nextLabel })] }) }));
30
+ return (_jsx("nav", { "aria-label": label, children: _jsxs(Stack, { direction: "horizontal", gap: "2xs", align: "center", children: [_jsx(Button, { variant: "secondary", disabled: atStart, onClick: goPrev, "aria-label": previousLabel, children: previousLabel }), _jsx("span", { "aria-current": "page", className: "font-sans text-x-slot-pagination-fg", children: status }), _jsx(Button, { variant: "secondary", disabled: atEnd, onClick: goNext, "aria-label": nextLabel, children: nextLabel })] }) }));
31
31
  }
32
32
  //# sourceMappingURL=Pagination.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Pagination.js","sourceRoot":"","sources":["../../src/data/Pagination.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAyC3C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,UAAU,CAAC,KAAsB;IAC/C,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IAE1D,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC;IAC5E,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,SAAS,CAAC;IAExF,MAAM,MAAM,GAAG,GAAG,EAAE,CAClB,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;IACjF,MAAM,MAAM,GAAG,GAAG,EAAE,CAClB,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;IAEjF,OAAO,CACL,4BAAiB,KAAK,YACpB,MAAC,KAAK,IAAC,SAAS,EAAC,YAAY,EAAC,GAAG,EAAC,KAAK,EAAC,KAAK,EAAC,QAAQ,aACpD,KAAC,MAAM,IAAC,OAAO,EAAC,WAAW,EAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAc,aAAa,YACtF,aAAa,GACP,EACT,+BAAmB,MAAM,EAAC,SAAS,EAAC,2BAA2B,YAC5D,MAAM,GACF,EACP,KAAC,MAAM,IAAC,OAAO,EAAC,WAAW,EAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAc,SAAS,YAChF,SAAS,GACH,IACH,GACJ,CACP,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"Pagination.js","sourceRoot":"","sources":["../../src/data/Pagination.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAyC3C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,UAAU,CAAC,KAAsB;IAC/C,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;IAE1D,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC;IAC5E,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,SAAS,CAAC;IAExF,MAAM,MAAM,GAAG,GAAG,EAAE,CAClB,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;IACjF,MAAM,MAAM,GAAG,GAAG,EAAE,CAClB,KAAK,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC;IAEjF,OAAO,CACL,4BAAiB,KAAK,YACpB,MAAC,KAAK,IAAC,SAAS,EAAC,YAAY,EAAC,GAAG,EAAC,KAAK,EAAC,KAAK,EAAC,QAAQ,aACpD,KAAC,MAAM,IAAC,OAAO,EAAC,WAAW,EAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAc,aAAa,YACtF,aAAa,GACP,EACT,+BAAmB,MAAM,EAAC,SAAS,EAAC,qCAAqC,YACtE,MAAM,GACF,EACP,KAAC,MAAM,IAAC,OAAO,EAAC,WAAW,EAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAc,SAAS,YAChF,SAAS,GACH,IACH,GACJ,CACP,CAAC;AACJ,CAAC"}
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { cx } from '../lib/cx.js';
3
3
  const TONE_CLASS = {
4
- neutral: 'bg-surface text-text-muted border-border',
5
- accent: 'bg-accent text-on-accent border-accent',
6
- danger: 'bg-danger text-on-accent border-danger',
4
+ neutral: 'bg-x-slot-badge-neutral-bg text-x-slot-badge-neutral-fg border-x-slot-badge-neutral-border',
5
+ accent: 'bg-x-slot-badge-accent-bg text-x-slot-badge-accent-fg border-x-slot-badge-accent-border',
6
+ danger: 'bg-x-slot-badge-danger-bg text-x-slot-badge-danger-fg border-x-slot-badge-danger-border',
7
7
  };
8
8
  /**
9
9
  * A small status marker.
@@ -1 +1 @@
1
- {"version":3,"file":"Badge.js","sourceRoot":"","sources":["../../src/feedback/Badge.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAQlC,MAAM,UAAU,GAAoD;IAClE,OAAO,EAAE,0CAA0C;IACnD,MAAM,EAAE,wCAAwC;IAChD,MAAM,EAAE,wCAAwC;CACjD,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,KAAK,CAAC,EAAE,IAAI,GAAG,SAAS,EAAE,QAAQ,EAAc;IAC9D,OAAO,CACL,eACE,SAAS,EAAE,EAAE,CACX,4GAA4G,EAC5G,UAAU,CAAC,IAAI,CAAC,CACjB,YAEA,QAAQ,GACJ,CACR,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"Badge.js","sourceRoot":"","sources":["../../src/feedback/Badge.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAQlC,MAAM,UAAU,GAAoD;IAClE,OAAO,EACL,4FAA4F;IAC9F,MAAM,EAAE,yFAAyF;IACjG,MAAM,EAAE,yFAAyF;CAClG,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,KAAK,CAAC,EAAE,IAAI,GAAG,SAAS,EAAE,QAAQ,EAAc;IAC9D,OAAO,CACL,eACE,SAAS,EAAE,EAAE,CACX,4GAA4G,EAC5G,UAAU,CAAC,IAAI,CAAC,CACjB,YAEA,QAAQ,GACJ,CACR,CAAC;AACJ,CAAC"}
@@ -2,19 +2,28 @@ import type { ReactNode } from 'react';
2
2
  export interface InlineAlertProps {
3
3
  /** What the message means. `danger` is announced assertively; `info` politely. */
4
4
  tone?: 'info' | 'warn' | 'danger';
5
+ /**
6
+ * 🔴 Needed to point an `aria-describedby` at this message. Without it a product that
7
+ * wants the alert read out with a control has nowhere to put an id, and nene-vault
8
+ * wrapped the alert in a `<div>` to get one (2026-08-23). `FormField`'s `hint` is static
9
+ * help text, so it does not cover "a warning about the value that is in there now".
10
+ */
11
+ id?: string;
12
+ /** Composed after the kit's own classes (design principle 2). */
13
+ className?: string;
5
14
  children: ReactNode;
6
15
  }
7
16
  /**
8
17
  * A message attached to the thing it is about, rather than to the page.
9
18
  *
10
19
  * 🔴 Each tone reads its colours from the theme, so a product can tell "warning" from
11
- * "failure" by sight. Until it sets them, `warn` and `danger` share this palette's single
12
- * alert hue and only the announced urgency differs — and as nene-vault put it, that
13
- * difference reaches someone listening and no one looking.
20
+ * "failure" by sight. Until 0.12.0 they could not: `warn` pointed at `--color-danger`, so
21
+ * only the announced urgency differed — and as nene-vault put it, that difference reaches
22
+ * someone listening and no one looking. The palette now carries `warn` of its own.
14
23
  *
15
24
  * 🔴 The tone decides the ARIA role, not just the colour. `danger` becomes `role="alert"`,
16
25
  * which interrupts a screen reader; `info` becomes `role="status"`, which waits its turn.
17
26
  * Six ships wrote this component (three as `InlineAlert`, three as `Alert`) and the choice
18
27
  * of role is precisely the part that is easy to get wrong and invisible when you do.
19
28
  */
20
- export declare function InlineAlert({ tone, children }: InlineAlertProps): import("react").JSX.Element;
29
+ export declare function InlineAlert({ tone, id, className, children }: InlineAlertProps): import("react").JSX.Element;
@@ -9,16 +9,16 @@ const TONE_CLASS = {
9
9
  * A message attached to the thing it is about, rather than to the page.
10
10
  *
11
11
  * 🔴 Each tone reads its colours from the theme, so a product can tell "warning" from
12
- * "failure" by sight. Until it sets them, `warn` and `danger` share this palette's single
13
- * alert hue and only the announced urgency differs — and as nene-vault put it, that
14
- * difference reaches someone listening and no one looking.
12
+ * "failure" by sight. Until 0.12.0 they could not: `warn` pointed at `--color-danger`, so
13
+ * only the announced urgency differed — and as nene-vault put it, that difference reaches
14
+ * someone listening and no one looking. The palette now carries `warn` of its own.
15
15
  *
16
16
  * 🔴 The tone decides the ARIA role, not just the colour. `danger` becomes `role="alert"`,
17
17
  * which interrupts a screen reader; `info` becomes `role="status"`, which waits its turn.
18
18
  * Six ships wrote this component (three as `InlineAlert`, three as `Alert`) and the choice
19
19
  * of role is precisely the part that is easy to get wrong and invisible when you do.
20
20
  */
21
- export function InlineAlert({ tone = 'info', children }) {
22
- return (_jsx("div", { role: tone === 'danger' ? 'alert' : 'status', className: cx('rounded-x-slot-alert border p-x-slot-alert-pad font-sans', TONE_CLASS[tone]), children: children }));
21
+ export function InlineAlert({ tone = 'info', id, className, children }) {
22
+ return (_jsx("div", { id: id, role: tone === 'danger' ? 'alert' : 'status', className: cx('rounded-x-slot-alert border p-x-slot-alert-pad font-sans', TONE_CLASS[tone], className), children: children }));
23
23
  }
24
24
  //# sourceMappingURL=InlineAlert.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"InlineAlert.js","sourceRoot":"","sources":["../../src/feedback/InlineAlert.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAQlC,MAAM,UAAU,GAA0D;IACxE,IAAI,EAAE,mFAAmF;IACzF,IAAI,EAAE,mFAAmF;IACzF,MAAM,EAAE,yFAAyF;CAClG,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,WAAW,CAAC,EAAE,IAAI,GAAG,MAAM,EAAE,QAAQ,EAAoB;IACvE,OAAO,CACL,cACE,IAAI,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,EAC5C,SAAS,EAAE,EAAE,CAAC,0DAA0D,EAAE,UAAU,CAAC,IAAI,CAAC,CAAC,YAE1F,QAAQ,GACL,CACP,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"InlineAlert.js","sourceRoot":"","sources":["../../src/feedback/InlineAlert.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAiBlC,MAAM,UAAU,GAA0D;IACxE,IAAI,EAAE,mFAAmF;IACzF,IAAI,EAAE,mFAAmF;IACzF,MAAM,EAAE,yFAAyF;CAClG,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,WAAW,CAAC,EAAE,IAAI,GAAG,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,QAAQ,EAAoB;IACtF,OAAO,CACL,cACE,EAAE,EAAE,EAAE,EACN,IAAI,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,EAC5C,SAAS,EAAE,EAAE,CACX,0DAA0D,EAC1D,UAAU,CAAC,IAAI,CAAC,EAChB,SAAS,CACV,YAEA,QAAQ,GACL,CACP,CAAC;AACJ,CAAC"}
@@ -4,8 +4,8 @@ import { cx } from '../lib/cx.js';
4
4
  import { CLICKABLE_CLASS } from '../lib/states.js';
5
5
  import { ToastContext } from './toast-context.js';
6
6
  const TONE_CLASS = {
7
- info: 'bg-surface-raised text-text-primary border-border',
8
- danger: 'bg-surface-raised text-danger border-danger',
7
+ info: 'bg-x-slot-toast-bg text-x-slot-toast-fg border-x-slot-toast-border',
8
+ danger: 'bg-x-slot-toast-bg text-x-slot-toast-danger-fg border-x-slot-toast-danger-border',
9
9
  };
10
10
  /**
11
11
  * Hosts the toast queue and the live regions that announce it.
@@ -1 +1 @@
1
- {"version":3,"file":"ToastProvider.js","sourceRoot":"","sources":["../../src/feedback/ToastProvider.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ToastProvider.js","sourceRoot":"","sources":["../../src/feedback/ToastProvider.tsx"],"names":[],"mappings":"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"}
@@ -6,6 +6,16 @@ export interface FormFieldProps {
6
6
  label: string;
7
7
  /** Localized error message, or null when valid. */
8
8
  error?: string | null;
9
+ /**
10
+ * Localized warning, or null when there is nothing to flag.
11
+ *
12
+ * 🔴 Not a milder `error`. A warning marks a value the form accepts — nene-vault flags a
13
+ * retention period under ten years, which satisfies every rule the field has. So it does
14
+ * NOT set `aria-invalid`: announcing a legal value as invalid is worse than saying
15
+ * nothing. It is announced as a `role="status"` and linked through `aria-describedby`,
16
+ * and it paints through `data-warn`.
17
+ */
18
+ warning?: string | null;
9
19
  /**
10
20
  * Localized help text, shown under the control and read out with it.
11
21
  *
@@ -44,4 +54,4 @@ export interface FormFieldProps {
44
54
  * 🔴 The hint stays visible when there is an error. nene-profile hides it in that case, and
45
55
  * that is the moment the user most needs it; the error is read first instead.
46
56
  */
47
- export declare function FormField({ id, label, error, hint, labelAdornment, required, requiredMarker, children, }: FormFieldProps): import("react").JSX.Element;
57
+ export declare function FormField({ id, label, error, warning, hint, labelAdornment, required, requiredMarker, children, }: FormFieldProps): import("react").JSX.Element;
@@ -16,10 +16,14 @@ import { FieldContext } from './field-context.js';
16
16
  * 🔴 The hint stays visible when there is an error. nene-profile hides it in that case, and
17
17
  * that is the moment the user most needs it; the error is read first instead.
18
18
  */
19
- export function FormField({ id, label, error = null, hint, labelAdornment, required = false, requiredMarker, children, }) {
19
+ export function FormField({ id, label, error = null, warning = null, hint, labelAdornment, required = false, requiredMarker, children, }) {
20
20
  const errorId = error === null ? null : `${id}-error`;
21
+ const warningId = warning === null ? null : `${id}-warning`;
21
22
  const hintId = hint === undefined || hint === null ? null : `${id}-hint`;
22
- const value = useMemo(() => ({ id, errorId, hintId, required }), [id, errorId, hintId, required]);
23
- return (_jsx(FieldContext.Provider, { value: value, children: _jsxs("div", { className: "flex flex-col gap-x-slot-field-gap", children: [_jsxs("label", { htmlFor: id, className: "font-sans font-x-slot-field-label text-x-slot-field-label-size text-x-slot-field-label", children: [label, required && requiredMarker !== undefined && requiredMarker !== null ? (_jsx("span", { className: "text-danger", children: requiredMarker })) : null, labelAdornment] }), children, hintId === null ? null : (_jsx("span", { id: hintId, className: "font-sans text-x-slot-field-hint-size text-x-slot-field-hint", children: hint })), errorId === null ? null : (_jsx("p", { id: errorId, role: "alert", className: "font-sans text-x-slot-field-error-size text-x-slot-field-error", children: error }))] }) }));
23
+ const value = useMemo(() => ({ id, errorId, warningId, hintId, required }), [id, errorId, warningId, hintId, required]);
24
+ return (_jsx(FieldContext.Provider, { value: value, children: _jsxs("div", { className: "flex flex-col gap-x-slot-field-gap", children: [_jsxs("label", { htmlFor: id, className: "font-sans font-x-slot-field-label text-x-slot-field-label-size text-x-slot-field-label", children: [label, required && requiredMarker !== undefined && requiredMarker !== null ? (_jsx("span", { className: "text-x-slot-field-required-marker", children: requiredMarker })) : null, labelAdornment] }), children, hintId === null ? null : (_jsx("span", { id: hintId, className: "font-sans text-x-slot-field-hint-size text-x-slot-field-hint", children: hint })), warningId === null ? null : (
25
+ // role="status" ではなく role="alert" にすると、入力の途中で読み上げを割り込む。
26
+ // 警告は「見直す価値がある」であって「止まれ」ではないので、次の切れ目で読ませる。
27
+ _jsx("p", { id: warningId, role: "status", className: "font-sans text-x-slot-field-error-size text-x-slot-field-warning-fg", children: warning })), errorId === null ? null : (_jsx("p", { id: errorId, role: "alert", className: "font-sans text-x-slot-field-error-size text-x-slot-field-error", children: error }))] }) }));
24
28
  }
25
29
  //# sourceMappingURL=FormField.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FormField.js","sourceRoot":"","sources":["../../src/forms/FormField.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAkB,MAAM,OAAO,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAiClD;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,SAAS,CAAC,EACxB,EAAE,EACF,KAAK,EACL,KAAK,GAAG,IAAI,EACZ,IAAI,EACJ,cAAc,EACd,QAAQ,GAAG,KAAK,EAChB,cAAc,EACd,QAAQ,GACO;IACf,MAAM,OAAO,GAAG,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,QAAQ,CAAC;IACtD,MAAM,MAAM,GAAG,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,OAAO,CAAC;IACzE,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IAElG,OAAO,CACL,KAAC,YAAY,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YACjC,eAAK,SAAS,EAAC,oCAAoC,aACjD,iBACE,OAAO,EAAE,EAAE,EACX,SAAS,EAAC,wFAAwF,aAEjG,KAAK,EACL,QAAQ,IAAI,cAAc,KAAK,SAAS,IAAI,cAAc,KAAK,IAAI,CAAC,CAAC,CAAC,CACrE,eAAM,SAAS,EAAC,aAAa,YAAE,cAAc,GAAQ,CACtD,CAAC,CAAC,CAAC,IAAI,EACP,cAAc,IACT,EACP,QAAQ,EACR,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CACxB,eACE,EAAE,EAAE,MAAM,EACV,SAAS,EAAC,8DAA8D,YAEvE,IAAI,GACA,CACR,EACA,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CACzB,YACE,EAAE,EAAE,OAAO,EACX,IAAI,EAAC,OAAO,EACZ,SAAS,EAAC,gEAAgE,YAEzE,KAAK,GACJ,CACL,IACG,GACgB,CACzB,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"FormField.js","sourceRoot":"","sources":["../../src/forms/FormField.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAkB,MAAM,OAAO,CAAC;AAChD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AA2ClD;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,SAAS,CAAC,EACxB,EAAE,EACF,KAAK,EACL,KAAK,GAAG,IAAI,EACZ,OAAO,GAAG,IAAI,EACd,IAAI,EACJ,cAAc,EACd,QAAQ,GAAG,KAAK,EAChB,cAAc,EACd,QAAQ,GACO;IACf,MAAM,OAAO,GAAG,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,QAAQ,CAAC;IACtD,MAAM,SAAS,GAAG,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,UAAU,CAAC;IAC5D,MAAM,MAAM,GAAG,IAAI,KAAK,SAAS,IAAI,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,OAAO,CAAC;IACzE,MAAM,KAAK,GAAG,OAAO,CACnB,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,EACpD,CAAC,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,CAC3C,CAAC;IAEF,OAAO,CACL,KAAC,YAAY,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YACjC,eAAK,SAAS,EAAC,oCAAoC,aACjD,iBACE,OAAO,EAAE,EAAE,EACX,SAAS,EAAC,wFAAwF,aAEjG,KAAK,EACL,QAAQ,IAAI,cAAc,KAAK,SAAS,IAAI,cAAc,KAAK,IAAI,CAAC,CAAC,CAAC,CACrE,eAAM,SAAS,EAAC,mCAAmC,YAAE,cAAc,GAAQ,CAC5E,CAAC,CAAC,CAAC,IAAI,EACP,cAAc,IACT,EACP,QAAQ,EACR,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CACxB,eACE,EAAE,EAAE,MAAM,EACV,SAAS,EAAC,8DAA8D,YAEvE,IAAI,GACA,CACR,EACA,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC3B,wDAAwD;gBACxD,2CAA2C;gBAC3C,YACE,EAAE,EAAE,SAAS,EACb,IAAI,EAAC,QAAQ,EACb,SAAS,EAAC,qEAAqE,YAE9E,OAAO,GACN,CACL,EACA,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CACzB,YACE,EAAE,EAAE,OAAO,EACX,IAAI,EAAC,OAAO,EACZ,SAAS,EAAC,gEAAgE,YAEzE,KAAK,GACJ,CACL,IACG,GACgB,CACzB,CAAC;AACJ,CAAC"}
@@ -6,6 +6,13 @@ export interface FieldContextValue {
6
6
  errorId: string | null;
7
7
  /** id of the rendered hint, or null when there is no hint. */
8
8
  hintId: string | null;
9
+ /**
10
+ * id of the rendered warning, or null when there is none.
11
+ *
12
+ * 🔴 Separate from `errorId`, and deliberately not `aria-invalid`. A warning marks a
13
+ * value worth a second look, not a value the form rejects.
14
+ */
15
+ warningId: string | null;
9
16
  /** Whether the field must be filled in. */
10
17
  required: boolean;
11
18
  }
@@ -15,6 +22,12 @@ export interface FieldWiring {
15
22
  'aria-invalid'?: AriaAttributes['aria-invalid'] | undefined;
16
23
  'aria-describedby'?: string | undefined;
17
24
  'aria-required'?: AriaAttributes['aria-required'] | undefined;
25
+ /**
26
+ * Present when the field carries a warning. Not an ARIA attribute — it paints, and says
27
+ * nothing to assistive technology, because the warning text is already linked through
28
+ * `aria-describedby`.
29
+ */
30
+ 'data-warn'?: '' | undefined;
18
31
  }
19
32
  /**
20
33
  * Wire a control to the `FormField` around it.
@@ -38,14 +38,19 @@ export function useFieldWiring(explicit) {
38
38
  'aria-invalid': explicit.ariaInvalid,
39
39
  'aria-describedby': explicit.ariaDescribedBy,
40
40
  'aria-required': explicit.ariaRequired,
41
+ 'data-warn': undefined,
41
42
  };
42
43
  }
43
- const described = [field.errorId, field.hintId].filter((v) => v !== null).join(' ');
44
+ // Error first, then warning, then hint read in the order they matter.
45
+ const described = [field.errorId, field.warningId, field.hintId]
46
+ .filter((v) => v !== null)
47
+ .join(' ');
44
48
  return {
45
49
  id: explicit.id ?? field.id,
46
50
  'aria-invalid': explicit.ariaInvalid ?? (field.errorId === null ? undefined : true),
47
51
  'aria-describedby': explicit.ariaDescribedBy ?? (described === '' ? undefined : described),
48
52
  'aria-required': explicit.ariaRequired ?? (field.required ? true : undefined),
53
+ 'data-warn': field.warningId === null ? undefined : '',
49
54
  };
50
55
  }
51
56
  //# sourceMappingURL=field-context.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"field-context.js","sourceRoot":"","sources":["../../src/forms/field-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAuB,MAAM,OAAO,CAAC;AAavE,MAAM,CAAC,MAAM,YAAY,GAAG,aAAa,CAA2B,IAAI,CAAC,CAAC;AAW1E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,UAAU,cAAc,CAAC,QAK9B;IACC,MAAM,KAAK,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;IAEvC,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO;YACL,EAAE,EAAE,QAAQ,CAAC,EAAE;YACf,cAAc,EAAE,QAAQ,CAAC,WAAW;YACpC,kBAAkB,EAAE,QAAQ,CAAC,eAAe;YAC5C,eAAe,EAAE,QAAQ,CAAC,YAAY;SACvC,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEjG,OAAO;QACL,EAAE,EAAE,QAAQ,CAAC,EAAE,IAAI,KAAK,CAAC,EAAE;QAC3B,cAAc,EAAE,QAAQ,CAAC,WAAW,IAAI,CAAC,KAAK,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;QACnF,kBAAkB,EAAE,QAAQ,CAAC,eAAe,IAAI,CAAC,SAAS,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;QAC1F,eAAe,EAAE,QAAQ,CAAC,YAAY,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;KAC9E,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"field-context.js","sourceRoot":"","sources":["../../src/forms/field-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAuB,MAAM,OAAO,CAAC;AAoBvE,MAAM,CAAC,MAAM,YAAY,GAAG,aAAa,CAA2B,IAAI,CAAC,CAAC;AAiB1E;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,UAAU,cAAc,CAAC,QAK9B;IACC,MAAM,KAAK,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;IAEvC,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO;YACL,EAAE,EAAE,QAAQ,CAAC,EAAE;YACf,cAAc,EAAE,QAAQ,CAAC,WAAW;YACpC,kBAAkB,EAAE,QAAQ,CAAC,eAAe;YAC5C,eAAe,EAAE,QAAQ,CAAC,YAAY;YACtC,WAAW,EAAE,SAAS;SACvB,CAAC;IACJ,CAAC;IAED,wEAAwE;IACxE,MAAM,SAAS,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC;SAC7D,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC;SACtC,IAAI,CAAC,GAAG,CAAC,CAAC;IAEb,OAAO;QACL,EAAE,EAAE,QAAQ,CAAC,EAAE,IAAI,KAAK,CAAC,EAAE;QAC3B,cAAc,EAAE,QAAQ,CAAC,WAAW,IAAI,CAAC,KAAK,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;QACnF,kBAAkB,EAAE,QAAQ,CAAC,eAAe,IAAI,CAAC,SAAS,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;QAC1F,eAAe,EAAE,QAAQ,CAAC,YAAY,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;QAC7E,WAAW,EAAE,KAAK,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;KACvD,CAAC;AACJ,CAAC"}
@@ -8,6 +8,6 @@ import { GAP, PAD, resolve } from '../lib/spacing.js';
8
8
  * given its own colour would be a `div` with extra steps.
9
9
  */
10
10
  export function Card({ pad = 'sm', gap, raised = false, children, className, ...rest }) {
11
- return (_jsx("div", { className: cx('flex flex-col bg-surface-raised border border-border rounded-x-slot-card', raised && 'shadow-sm', resolve(pad, PAD), resolve(gap, GAP), className), ...rest, children: children }));
11
+ return (_jsx("div", { className: cx('flex flex-col bg-x-slot-card-bg border border-x-slot-card-border rounded-x-slot-card', raised && 'shadow-sm', resolve(pad, PAD), resolve(gap, GAP), className), ...rest, children: children }));
12
12
  }
13
13
  //# sourceMappingURL=Card.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Card.js","sourceRoot":"","sources":["../../src/layout/Card.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,EAA+B,MAAM,mBAAmB,CAAC;AAUnF;;;;;GAKG;AACH,MAAM,UAAU,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAI,EAAa;IAC/F,OAAO,CACL,cACE,SAAS,EAAE,EAAE,CACX,0EAA0E,EAC1E,MAAM,IAAI,WAAW,EACrB,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,EACjB,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,EACjB,SAAS,CACV,KACG,IAAI,YAEP,QAAQ,GACL,CACP,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"Card.js","sourceRoot":"","sources":["../../src/layout/Card.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,EAA+B,MAAM,mBAAmB,CAAC;AAUnF;;;;;GAKG;AACH,MAAM,UAAU,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,IAAI,EAAa;IAC/F,OAAO,CACL,cACE,SAAS,EAAE,EAAE,CACX,sFAAsF,EACtF,MAAM,IAAI,WAAW,EACrB,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,EACjB,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,EACjB,SAAS,CACV,KACG,IAAI,YAEP,QAAQ,GACL,CACP,CAAC;AACJ,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { cx } from '../lib/cx.js';
3
3
  export function PageHeader({ title, actions, className }) {
4
- return (_jsxs("header", { className: cx('flex items-center justify-between py-x-slot-page-header-pad-y', className), children: [_jsx("h1", { className: "font-sans font-medium text-text-primary", children: title }), actions] }));
4
+ return (_jsxs("header", { className: cx('flex items-center justify-between py-x-slot-page-header-pad-y', className), children: [_jsx("h1", { className: "font-sans font-x-slot-page-header text-x-slot-page-header-fg", children: title }), actions] }));
5
5
  }
6
6
  //# sourceMappingURL=PageHeader.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"PageHeader.js","sourceRoot":"","sources":["../../src/layout/PageHeader.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAUlC,MAAM,UAAU,UAAU,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAmB;IACvE,OAAO,CACL,kBACE,SAAS,EAAE,EAAE,CAAC,+DAA+D,EAAE,SAAS,CAAC,aAEzF,aAAI,SAAS,EAAC,yCAAyC,YAAE,KAAK,GAAM,EACnE,OAAO,IACD,CACV,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"PageHeader.js","sourceRoot":"","sources":["../../src/layout/PageHeader.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAUlC,MAAM,UAAU,UAAU,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAmB;IACvE,OAAO,CACL,kBACE,SAAS,EAAE,EAAE,CAAC,+DAA+D,EAAE,SAAS,CAAC,aAEzF,aAAI,SAAS,EAAC,8DAA8D,YAAE,KAAK,GAAM,EACxF,OAAO,IACD,CACV,CAAC;AACJ,CAAC"}
@@ -44,7 +44,7 @@
44
44
  * 🔴 `outline-offset` is therefore load-bearing, not decoration. Do not set it to 0.
45
45
  */
46
46
  /** Keyboard focus indicator. Colour comes from the theme, never from a caller. */
47
- export declare const FOCUS_CLASS = "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-text-primary";
47
+ export declare const FOCUS_CLASS = "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-x-slot-focus-ring";
48
48
  /**
49
49
  * Disabled appearance. The opacity is a theme token (`--opacity-x-disabled`) because a
50
50
  * literal here would be a design value living outside themes/default.css.
@@ -64,6 +64,36 @@ export declare const DISABLED_CLASS = "disabled:opacity-x-disabled disabled:curs
64
64
  */
65
65
  export declare const HOVER_CLASS = "hover:brightness-x-slot-hover active:brightness-x-slot-press disabled:hover:brightness-100 disabled:active:brightness-100";
66
66
  /** Controls that can be focused and disabled — every interactive primitive in the kit. */
67
- export declare const CONTROL_CLASS = "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-text-primary disabled:opacity-x-disabled disabled:cursor-not-allowed";
67
+ /**
68
+ * Validity, painted.
69
+ *
70
+ * 🔴 Two states, and only one of them is `aria-invalid`. A value can be worth flagging
71
+ * without being wrong: nene-vault marks a retention period under ten years, which satisfies
72
+ * every rule the form has. Setting `aria-invalid` there would announce a legal value as an
73
+ * error, and not setting it left the field with no signal at all — the kit painted neither.
74
+ * So the warning is `data-warn`, an attribute that carries no ARIA meaning; the message
75
+ * beside it is what a screen reader gets, through `aria-describedby`.
76
+ *
77
+ * The error keeps `aria-invalid`, which is what it is for.
78
+ */
79
+ export declare const VALIDITY_CLASS: string;
80
+ /**
81
+ * The minimum a control may be on a touch screen.
82
+ *
83
+ * 🔴 Deliberately NOT part of `CONTROL_CLASS`, though everything else here is. This has to
84
+ * go on the element that *is* the target, and for a checkbox that is the `<label>`, not the
85
+ * `<input>` — the box is `size-x-slot-choice-box` (16px square), so a minimum height on it
86
+ * produces a 44×16 rectangle instead of a bigger target. Folding it into the shared bundle
87
+ * would have applied it there, and the result would have looked like a styling bug rather
88
+ * than a mis-placed constraint.
89
+ *
90
+ * 🔴 It only works at all because the elements that carry it are flex containers. A
91
+ * `min-height` on an `inline-block` leaves the label at the top of the taller box; with
92
+ * `items-center` it stays centred. `Button` became one in 0.13.0 for an unrelated reason
93
+ * (an icon and its label sat on a shared baseline), and that turned out to be a
94
+ * prerequisite for this.
95
+ */
96
+ export declare const TOUCH_CLASS = "pointer-coarse:min-h-x-slot-control-touch-min";
97
+ export declare const CONTROL_CLASS: string;
68
98
  /** Controls that are also clicked: buttons, switches, the toast dismiss. */
69
- export declare const CLICKABLE_CLASS = "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-text-primary disabled:opacity-x-disabled disabled:cursor-not-allowed hover:brightness-x-slot-hover active:brightness-x-slot-press disabled:hover:brightness-100 disabled:active:brightness-100";
99
+ export declare const CLICKABLE_CLASS: string;
@@ -44,7 +44,7 @@
44
44
  * 🔴 `outline-offset` is therefore load-bearing, not decoration. Do not set it to 0.
45
45
  */
46
46
  /** Keyboard focus indicator. Colour comes from the theme, never from a caller. */
47
- export const FOCUS_CLASS = 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-text-primary';
47
+ export const FOCUS_CLASS = 'focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-x-slot-focus-ring';
48
48
  /**
49
49
  * Disabled appearance. The opacity is a theme token (`--opacity-x-disabled`) because a
50
50
  * literal here would be a design value living outside themes/default.css.
@@ -64,7 +64,42 @@ export const DISABLED_CLASS = 'disabled:opacity-x-disabled disabled:cursor-not-a
64
64
  */
65
65
  export const HOVER_CLASS = 'hover:brightness-x-slot-hover active:brightness-x-slot-press disabled:hover:brightness-100 disabled:active:brightness-100';
66
66
  /** Controls that can be focused and disabled — every interactive primitive in the kit. */
67
- export const CONTROL_CLASS = `${FOCUS_CLASS} ${DISABLED_CLASS}`;
67
+ /**
68
+ * Validity, painted.
69
+ *
70
+ * 🔴 Two states, and only one of them is `aria-invalid`. A value can be worth flagging
71
+ * without being wrong: nene-vault marks a retention period under ten years, which satisfies
72
+ * every rule the form has. Setting `aria-invalid` there would announce a legal value as an
73
+ * error, and not setting it left the field with no signal at all — the kit painted neither.
74
+ * So the warning is `data-warn`, an attribute that carries no ARIA meaning; the message
75
+ * beside it is what a screen reader gets, through `aria-describedby`.
76
+ *
77
+ * The error keeps `aria-invalid`, which is what it is for.
78
+ */
79
+ export const VALIDITY_CLASS = [
80
+ 'aria-invalid:border-x-slot-control-invalid-border',
81
+ 'aria-invalid:bg-x-slot-control-invalid-bg',
82
+ 'data-[warn]:border-x-slot-control-warn-border',
83
+ 'data-[warn]:bg-x-slot-control-warn-bg',
84
+ ].join(' ');
85
+ /**
86
+ * The minimum a control may be on a touch screen.
87
+ *
88
+ * 🔴 Deliberately NOT part of `CONTROL_CLASS`, though everything else here is. This has to
89
+ * go on the element that *is* the target, and for a checkbox that is the `<label>`, not the
90
+ * `<input>` — the box is `size-x-slot-choice-box` (16px square), so a minimum height on it
91
+ * produces a 44×16 rectangle instead of a bigger target. Folding it into the shared bundle
92
+ * would have applied it there, and the result would have looked like a styling bug rather
93
+ * than a mis-placed constraint.
94
+ *
95
+ * 🔴 It only works at all because the elements that carry it are flex containers. A
96
+ * `min-height` on an `inline-block` leaves the label at the top of the taller box; with
97
+ * `items-center` it stays centred. `Button` became one in 0.13.0 for an unrelated reason
98
+ * (an icon and its label sat on a shared baseline), and that turned out to be a
99
+ * prerequisite for this.
100
+ */
101
+ export const TOUCH_CLASS = 'pointer-coarse:min-h-x-slot-control-touch-min';
102
+ export const CONTROL_CLASS = `${FOCUS_CLASS} ${DISABLED_CLASS} ${VALIDITY_CLASS}`;
68
103
  /** Controls that are also clicked: buttons, switches, the toast dismiss. */
69
104
  export const CLICKABLE_CLASS = `${CONTROL_CLASS} ${HOVER_CLASS}`;
70
105
  //# sourceMappingURL=states.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"states.js","sourceRoot":"","sources":["../../src/lib/states.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH,kFAAkF;AAClF,MAAM,CAAC,MAAM,WAAW,GACtB,2FAA2F,CAAC;AAE9F;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,yDAAyD,CAAC;AAExF;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,WAAW,GACtB,2HAA2H,CAAC;AAE9H,0FAA0F;AAC1F,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,WAAW,IAAI,cAAc,EAAE,CAAC;AAEhE,4EAA4E;AAC5E,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,aAAa,IAAI,WAAW,EAAE,CAAC"}
1
+ {"version":3,"file":"states.js","sourceRoot":"","sources":["../../src/lib/states.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH,kFAAkF;AAClF,MAAM,CAAC,MAAM,WAAW,GACtB,gGAAgG,CAAC;AAEnG;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,yDAAyD,CAAC;AAExF;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,WAAW,GACtB,2HAA2H,CAAC;AAE9H,0FAA0F;AAC1F;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,mDAAmD;IACnD,2CAA2C;IAC3C,+CAA+C;IAC/C,uCAAuC;CACxC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAEZ;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,+CAA+C,CAAC;AAE3E,MAAM,CAAC,MAAM,aAAa,GAAG,GAAG,WAAW,IAAI,cAAc,IAAI,cAAc,EAAE,CAAC;AAElF,4EAA4E;AAC5E,MAAM,CAAC,MAAM,eAAe,GAAG,GAAG,aAAa,IAAI,WAAW,EAAE,CAAC"}
@@ -42,6 +42,6 @@ export function Modal({ open, onClose, title, children }) {
42
42
  return (_jsx("dialog", { ref: ref, "aria-label": title,
43
43
  // The browser fires `close` for Esc as well as for close(); routing both through the
44
44
  // caller keeps `open` from drifting out of sync with what is on screen.
45
- onClose: onClose, onCancel: onClose, className: cx('bg-surface-raised text-text-primary border border-border rounded-x-slot-modal', 'p-x-slot-modal-pad font-sans backdrop:bg-text-primary/50'), children: children }));
45
+ onClose: onClose, onCancel: onClose, className: cx('bg-x-slot-modal-bg text-x-slot-modal-fg border border-x-slot-modal-border rounded-x-slot-modal', 'p-x-slot-modal-pad font-sans backdrop:bg-x-slot-modal-scrim/50'), children: children }));
46
46
  }
47
47
  //# sourceMappingURL=Modal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Modal.js","sourceRoot":"","sources":["../../src/overlay/Modal.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAkB,MAAM,OAAO,CAAC;AAC1D,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAWlC;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,KAAK,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAc;IAClE,MAAM,GAAG,GAAG,MAAM,CAAoB,IAAI,CAAC,CAAC;IAE5C,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC;QACvB,IAAI,EAAE,KAAK,IAAI;YAAE,OAAO;QAExB,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,OAAO,EAAE,CAAC,SAAS,KAAK,UAAU,EAAE,CAAC;gBACvC,IAAI,CAAC,EAAE,CAAC,IAAI;oBAAE,EAAE,CAAC,SAAS,EAAE,CAAC;YAC/B,CAAC;iBAAM,CAAC;gBACN,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAC9B,CAAC;YACD,OAAO;QACT,CAAC;QAED,IAAI,OAAO,EAAE,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;YACnC,IAAI,EAAE,CAAC,IAAI;gBAAE,EAAE,CAAC,KAAK,EAAE,CAAC;QAC1B,CAAC;aAAM,CAAC;YACN,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,OAAO,CACL,iBACE,GAAG,EAAE,GAAG,gBACI,KAAK;QACjB,qFAAqF;QACrF,wEAAwE;QACxE,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,OAAO,EACjB,SAAS,EAAE,EAAE,CACX,+EAA+E,EAC/E,0DAA0D,CAC3D,YAEA,QAAQ,GACF,CACV,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"Modal.js","sourceRoot":"","sources":["../../src/overlay/Modal.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,EAAkB,MAAM,OAAO,CAAC;AAC1D,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAWlC;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,KAAK,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAc;IAClE,MAAM,GAAG,GAAG,MAAM,CAAoB,IAAI,CAAC,CAAC;IAE5C,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,EAAE,GAAG,GAAG,CAAC,OAAO,CAAC;QACvB,IAAI,EAAE,KAAK,IAAI;YAAE,OAAO;QAExB,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,OAAO,EAAE,CAAC,SAAS,KAAK,UAAU,EAAE,CAAC;gBACvC,IAAI,CAAC,EAAE,CAAC,IAAI;oBAAE,EAAE,CAAC,SAAS,EAAE,CAAC;YAC/B,CAAC;iBAAM,CAAC;gBACN,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAC9B,CAAC;YACD,OAAO;QACT,CAAC;QAED,IAAI,OAAO,EAAE,CAAC,KAAK,KAAK,UAAU,EAAE,CAAC;YACnC,IAAI,EAAE,CAAC,IAAI;gBAAE,EAAE,CAAC,KAAK,EAAE,CAAC;QAC1B,CAAC;aAAM,CAAC;YACN,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;QAC7B,CAAC;IACH,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,OAAO,CACL,iBACE,GAAG,EAAE,GAAG,gBACI,KAAK;QACjB,qFAAqF;QACrF,wEAAwE;QACxE,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,OAAO,EACjB,SAAS,EAAE,EAAE,CACX,gGAAgG,EAChG,gEAAgE,CACjE,YAEA,QAAQ,GACF,CACV,CAAC;AACJ,CAAC"}