@hideyukimori/nene2-ui 0.7.0 → 0.11.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 (48) hide show
  1. package/README.md +76 -1
  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/ToastProvider.js +2 -2
  11. package/dist/feedback/ToastProvider.js.map +1 -1
  12. package/dist/forms/FormField.js +1 -1
  13. package/dist/forms/FormField.js.map +1 -1
  14. package/dist/layout/Card.js +1 -1
  15. package/dist/layout/Card.js.map +1 -1
  16. package/dist/layout/PageHeader.js +1 -1
  17. package/dist/layout/PageHeader.js.map +1 -1
  18. package/dist/lib/states.d.ts +3 -3
  19. package/dist/lib/states.js +1 -1
  20. package/dist/lib/states.js.map +1 -1
  21. package/dist/overlay/Modal.js +1 -1
  22. package/dist/overlay/Modal.js.map +1 -1
  23. package/dist/primitives/Button.js +16 -5
  24. package/dist/primitives/Button.js.map +1 -1
  25. package/dist/primitives/Checkbox.d.ts +21 -6
  26. package/dist/primitives/Checkbox.js +19 -9
  27. package/dist/primitives/Checkbox.js.map +1 -1
  28. package/dist/primitives/Input.js +1 -1
  29. package/dist/primitives/Input.js.map +1 -1
  30. package/dist/primitives/Radio.d.ts +20 -6
  31. package/dist/primitives/Radio.js +18 -9
  32. package/dist/primitives/Radio.js.map +1 -1
  33. package/dist/primitives/Select.js +1 -1
  34. package/dist/primitives/Select.js.map +1 -1
  35. package/dist/primitives/Spinner.js +1 -1
  36. package/dist/primitives/Spinner.js.map +1 -1
  37. package/dist/primitives/Switch.js +3 -1
  38. package/dist/primitives/Switch.js.map +1 -1
  39. package/dist/primitives/Text.js +1 -1
  40. package/dist/primitives/Text.js.map +1 -1
  41. package/dist/primitives/Textarea.js +1 -1
  42. package/dist/primitives/Textarea.js.map +1 -1
  43. package/dist/states/EmptyState.js +1 -1
  44. package/dist/states/EmptyState.js.map +1 -1
  45. package/dist/states/ErrorState.js +1 -1
  46. package/dist/states/ErrorState.js.map +1 -1
  47. package/package.json +1 -1
  48. package/themes/default.css +176 -1
package/README.md CHANGED
@@ -153,7 +153,16 @@ component follows.
153
153
 
154
154
  ### ① The scale — 🔒 do not redefine
155
155
 
156
- `--spacing-x-3xs` … `--spacing-x-2xl`, and the radius and colour tokens they point at.
156
+ `--spacing-x-3xs` … `--spacing-x-2xl`, `--radius-x-none` `--radius-x-3xl` plus
157
+ `--radius-x-pill`, `--text-x-2xs` … `--text-x-xl`, and the colour palette.
158
+
159
+ 🔴 **A namespace with one step has no slots, only aliases.** Until 0.8.0 the radius
160
+ namespace held a single value and eight slots pointed at it, so a product following the
161
+ rules could render exactly one rounding — and every structural check passed, because the
162
+ slots existed and their defaults referenced the scale. The scale had been promoted verbatim
163
+ from the one product with the fewest conformance violations, which turned out to be the
164
+ product with the fewest choices. **A component implementation may come from one ship; the
165
+ set of choices may only come from the fleet's distribution.**
157
166
 
158
167
  ```css
159
168
  --spacing-x-slot-card-pad: 1.375rem; /* 🔴 no */
@@ -177,6 +186,21 @@ to match it also fits _worse_, not better:
177
186
  More exact matches, five times the worst error — a scale bent toward one histogram drops its
178
187
  own ends.
179
188
 
189
+ The radius scale was measured the same way, across the 266 radius values ten products apply
190
+ (2026-08-23). Candidates were scored on a second axis as well: whether two values that exist
191
+ **by design** land on the same step. Average error alone would have accepted folding `2px`
192
+ into `0`, because 2px is a 2px error — but nene-records ships nine themes at 0px and three at
193
+ 2–3px as separate product themes, so that error deletes a distinction rather than rounding
194
+ one.
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) |
199
+ | eight, without a `10px` step | 64.3% | 97.7% | 4 |
200
+ | seven, without `2px` | 43.2% | 97.7% | 4 |
201
+
202
+ 🔑 **A scale is judged by what it can still tell apart, not only by how far it moves things.**
203
+
180
204
  🔑 **The scale is the set you keep to. The slots are what your brand looks like.**
181
205
 
182
206
  ### 🔴 One slot is not yours to tune
@@ -219,6 +243,38 @@ it can be checked with a regular expression exactly as written.
219
243
  | `--color-*` | scale (palette) references | same |
220
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 |
221
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
+ ### 🔴 What a slot check must cover
262
+
263
+ The rule above — _every design value a component uses comes from a slot_ — was false in 26 of
264
+ 28 components until 0.9.0, and the check meant to enforce it was green throughout. It listed
265
+ the utility prefixes it knew about (`p px py … rounded`), so **colour and weight were never
266
+ inspected**: 59 palette reaches across 20 files, plus four inline `font-medium`.
267
+
268
+ It surfaced when nene-vault compared its production screens against the migrated build in a
269
+ real browser — Playwright, computed styles, element by element (2026-08-23). 73 elements
270
+ matched and 21 differed, and **every difference was inside a kit component**; the product's
271
+ own markup matched on every property. A product cannot make its controls darker than its body
272
+ text while the component writes `text-text-primary` itself.
273
+
274
+ 🔑 **A check written as an enumeration passes everything the enumeration omits.** So the
275
+ colour half of that check is not enumerated: it reads the palette out of the theme. A colour
276
+ added tomorrow is covered today.
277
+
222
278
  🔴 **Check the three namespaces that have scales, not every slot.** Until 0.6.0 this section
223
279
  said "and nothing else", while the kit's own theme held `--text-x-slot-field-label-size:
224
280
  0.75rem` and `--brightness-x-slot-hover: 95%` — so a product implementing the rule as written
@@ -239,6 +295,25 @@ a missing component — open an issue, so every product gets the answer.
239
295
  **Products: apply the same check to your own theme.** The kit can only police its own file;
240
296
  the rule is the same one, and the regular expression above is the whole implementation.
241
297
 
298
+ ## 🔴 Migrating a screen to the kit
299
+
300
+ **`<div>` → `<Stack>` is not a no-op.** The wrapper changes from block flow to flex, and
301
+ inline-level children — `Button`, `<label>`, `<span>` — change size because of it:
302
+
303
+ | what you see | why |
304
+ | -------------------------------------------- | --------------------------------------------------------------------------------------- |
305
+ | a button suddenly spans the row | `Stack` is `align-items: stretch`, so an inline-block child is stretched |
306
+ | a choice label goes from 112px wide to 582px | the same stretch |
307
+ | an icon becomes a tall rectangle | an `<svg>` with no width/height attribute has no intrinsic size and lays out at 300×150 |
308
+
309
+ The first two are flexbox working as specified; reach for `self-start` (which now lands on
310
+ the root — see above) or `items-start` on the `Stack`. The third was the kit's fault and is
311
+ bounded from 0.10.0, but only inside `Button` — **use `Icon` for artwork anywhere else**, or
312
+ give the `<svg>` a size of its own.
313
+
314
+ 🔑 Three regressions in one migration, all from one wrapper swap, all of them visible only
315
+ on screen: **nothing in a diff says that a child used to be inline** (nene-vault, 2026-08-23).
316
+
242
317
  ## What is in scope
243
318
 
244
319
  **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"}
@@ -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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"}
@@ -20,6 +20,6 @@ export function FormField({ id, label, error = null, hint, labelAdornment, requi
20
20
  const errorId = error === null ? null : `${id}-error`;
21
21
  const hintId = hint === undefined || hint === null ? null : `${id}-hint`;
22
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
+ 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-error-fg", 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 }))] }) }));
24
24
  }
25
25
  //# 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;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,4BAA4B,YAAE,cAAc,GAAQ,CACrE,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"}
@@ -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,6 @@ 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
+ export declare const CONTROL_CLASS = "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-x-slot-focus-ring disabled:opacity-x-disabled disabled:cursor-not-allowed";
68
68
  /** 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";
69
+ export declare const CLICKABLE_CLASS = "focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-x-slot-focus-ring 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";
@@ -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.
@@ -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,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"}
@@ -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"}
@@ -2,12 +2,12 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { cx } from '../lib/cx.js';
3
3
  import { CLICKABLE_CLASS } from '../lib/states.js';
4
4
  const VARIANT_CLASS = {
5
- primary: 'bg-accent text-on-accent',
6
- secondary: 'bg-surface-raised text-text-primary border-border',
7
- danger: 'bg-danger text-on-accent',
5
+ primary: 'bg-x-slot-button-primary-bg text-x-slot-button-primary-fg',
6
+ secondary: 'bg-x-slot-button-secondary-bg text-x-slot-button-secondary-fg border-x-slot-button-secondary-border',
7
+ danger: 'bg-x-slot-button-danger-bg text-x-slot-button-danger-fg',
8
8
  // No fill and no border: for the third action in a row, where two framed buttons would
9
9
  // compete with each other. nene-vault ships this variant already.
10
- ghost: 'bg-transparent text-text-primary',
10
+ ghost: 'bg-transparent text-x-slot-button-ghost-fg',
11
11
  };
12
12
  const SIZE_CLASS = {
13
13
  md: 'px-x-slot-button-pad-x py-x-slot-button-pad-y',
@@ -18,7 +18,18 @@ const SIZE_CLASS = {
18
18
  // taller than the others. nene-vault puts a primary and a secondary side by side in seven
19
19
  // modal footers, where that shows up as a step (measured 2026-08-23); its own Button carries
20
20
  // the same transparent border for the same reason.
21
- const BASE_CLASS = `rounded-x-slot-button border border-transparent font-sans font-medium ${CLICKABLE_CLASS}`;
21
+ // 🔴 `[&_svg]:max-*` bounds a raw `<svg>` child without sizing it. An svg with no width or
22
+ // height attribute lays out at the replaced-element default of 300x150; a `max-height` pulls
23
+ // it back and, because a `viewBox` gives the element an intrinsic ratio, the width follows.
24
+ // `max-width` covers the svg that has no viewBox either.
25
+ //
26
+ // 🔴 Not `[&_svg]:size-*`. That would outrank the plain `h-5 w-5` an `Icon` sets on itself
27
+ // — an arbitrary variant compiles to a descendant selector, which is more specific than a
28
+ // single class — so `<Icon size="sm">` inside a button would render at the button's size
29
+ // instead of its own. A maximum cannot collide with a height: different property, and it
30
+ // leaves anything already smaller alone.
31
+ const SVG_BOUND = '[&_svg]:max-h-x-slot-button-icon [&_svg]:max-w-x-slot-button-icon';
32
+ const BASE_CLASS = `rounded-x-slot-button border border-transparent font-sans text-x-slot-button-size font-x-slot-button ${SVG_BOUND} ${CLICKABLE_CLASS}`;
22
33
  export function Button({ variant = 'primary', size = 'md', children, type = 'button', className, ...rest }) {
23
34
  return (_jsx("button", { type: type, className: cx(BASE_CLASS, SIZE_CLASS[size], VARIANT_CLASS[variant], className), ...rest, children: children }));
24
35
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Button.js","sourceRoot":"","sources":["../../src/primitives/Button.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAcnD,MAAM,aAAa,GAAwD;IACzE,OAAO,EAAE,0BAA0B;IACnC,SAAS,EAAE,mDAAmD;IAC9D,MAAM,EAAE,0BAA0B;IAClC,uFAAuF;IACvF,kEAAkE;IAClE,KAAK,EAAE,kCAAkC;CAC1C,CAAC;AAEF,MAAM,UAAU,GAAqD;IACnE,EAAE,EAAE,+CAA+C;IACnD,EAAE,EAAE,qDAAqD;CAC1D,CAAC;AAEF,wFAAwF;AACxF,uFAAuF;AACvF,0FAA0F;AAC1F,6FAA6F;AAC7F,mDAAmD;AACnD,MAAM,UAAU,GAAG,yEAAyE,eAAe,EAAE,CAAC;AAE9G,MAAM,UAAU,MAAM,CAAC,EACrB,OAAO,GAAG,SAAS,EACnB,IAAI,GAAG,IAAI,EACX,QAAQ,EACR,IAAI,GAAG,QAAQ,EACf,SAAS,EACT,GAAG,IAAI,EACK;IACZ,OAAO,CACL,iBACE,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,KAC1E,IAAI,YAEP,QAAQ,GACF,CACV,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"Button.js","sourceRoot":"","sources":["../../src/primitives/Button.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAcnD,MAAM,aAAa,GAAwD;IACzE,OAAO,EAAE,2DAA2D;IACpE,SAAS,EACP,qGAAqG;IACvG,MAAM,EAAE,yDAAyD;IACjE,uFAAuF;IACvF,kEAAkE;IAClE,KAAK,EAAE,4CAA4C;CACpD,CAAC;AAEF,MAAM,UAAU,GAAqD;IACnE,EAAE,EAAE,+CAA+C;IACnD,EAAE,EAAE,qDAAqD;CAC1D,CAAC;AAEF,wFAAwF;AACxF,uFAAuF;AACvF,0FAA0F;AAC1F,6FAA6F;AAC7F,mDAAmD;AACnD,2FAA2F;AAC3F,6FAA6F;AAC7F,4FAA4F;AAC5F,yDAAyD;AACzD,EAAE;AACF,2FAA2F;AAC3F,0FAA0F;AAC1F,yFAAyF;AACzF,yFAAyF;AACzF,yCAAyC;AACzC,MAAM,SAAS,GAAG,mEAAmE,CAAC;AAEtF,MAAM,UAAU,GAAG,wGAAwG,SAAS,IAAI,eAAe,EAAE,CAAC;AAE1J,MAAM,UAAU,MAAM,CAAC,EACrB,OAAO,GAAG,SAAS,EACnB,IAAI,GAAG,IAAI,EACX,QAAQ,EACR,IAAI,GAAG,QAAQ,EACf,SAAS,EACT,GAAG,IAAI,EACK;IACZ,OAAO,CACL,iBACE,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,EAAE,CAAC,UAAU,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,aAAa,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,KAC1E,IAAI,YAEP,QAAQ,GACF,CACV,CAAC;AACJ,CAAC"}
@@ -2,6 +2,11 @@ import { type InputHTMLAttributes, type ReactNode } from 'react';
2
2
  export interface CheckboxProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {
3
3
  /** Localized label. Rendered inside the control's own `<label>`. */
4
4
  label: ReactNode;
5
+ /**
6
+ * Classes for the `<input>` itself. `className` goes to the `<label>`, which is this
7
+ * part's root — see the note below.
8
+ */
9
+ inputClassName?: string;
5
10
  }
6
11
  /**
7
12
  * A checkbox and its label, as one part.
@@ -11,11 +16,21 @@ export interface CheckboxProps extends Omit<InputHTMLAttributes<HTMLInputElement
11
16
  * visible, and loses the ability to click the text to toggle the box, plus the name the
12
17
  * control is announced by. Making the label a prop means it cannot be forgotten.
13
18
  *
14
- * 🔴 `cursor-pointer` and the gap live here rather than being left to the caller, because
15
- * the caller cannot reach them: `className` is forwarded to the `<input>`, and both belong
16
- * to the `<label>` that wraps it. nene-vault carries them on the label in its own
17
- * implementation (measured 2026-08-23, checking Tailwind classes and CSS both), so a
18
- * migration that could not set them would lose the pointer cursor on every choice in the
19
- * product — visible to a mouse user, invisible in a diff.
19
+ * 🔴 `className` lands on the `<label>`, which is this part's root the same place it
20
+ * lands in every other component the kit ships. Until 0.10.0 it went to the `<input>`
21
+ * instead, so nothing the caller wrote could reach the root: `self-start` inside a flex
22
+ * row, a width, a margin. nene-vault had to wrap each choice in a `<div>` to say them
23
+ * (found while migrating, 2026-08-23). Use `inputClassName` for the box itself.
24
+ *
25
+ * 🔑 This is the cause behind a symptom the kit already answered once. In wave 2 the
26
+ * report was that `cursor-pointer` could not be set, because it belongs to the label; the
27
+ * kit took `cursor-pointer` and the gap on itself. That was right as far as it went, and
28
+ * it left the reason intact — every other label-level property stayed unreachable.
29
+ * Fixing what a report names is not the same as fixing what it is about.
30
+ *
31
+ * `cursor-pointer` and the gap still live here: they are not decisions a product should
32
+ * have to repeat at every call site. nene-vault carries them on the label in its own
33
+ * implementation (measured 2026-08-23), so a migration that could not set them would lose
34
+ * the pointer cursor on every choice — visible to a mouse user, invisible in a diff.
20
35
  */
21
36
  export declare const Checkbox: import("react").ForwardRefExoticComponent<CheckboxProps & import("react").RefAttributes<HTMLInputElement>>;
@@ -3,7 +3,7 @@ import { forwardRef } from 'react';
3
3
  import { cx } from '../lib/cx.js';
4
4
  import { CONTROL_CLASS } from '../lib/states.js';
5
5
  import { useFieldWiring } from '../forms/field-context.js';
6
- const BOX_CLASS = `size-x-slot-choice-box shrink-0 rounded-x-slot-control border border-border accent-x-slot-choice-accent ${CONTROL_CLASS}`;
6
+ const BOX_CLASS = `size-x-slot-choice-box shrink-0 rounded-x-slot-control border border-x-slot-choice-border accent-x-slot-choice-accent ${CONTROL_CLASS}`;
7
7
  /**
8
8
  * A checkbox and its label, as one part.
9
9
  *
@@ -12,15 +12,25 @@ const BOX_CLASS = `size-x-slot-choice-box shrink-0 rounded-x-slot-control border
12
12
  * visible, and loses the ability to click the text to toggle the box, plus the name the
13
13
  * control is announced by. Making the label a prop means it cannot be forgotten.
14
14
  *
15
- * 🔴 `cursor-pointer` and the gap live here rather than being left to the caller, because
16
- * the caller cannot reach them: `className` is forwarded to the `<input>`, and both belong
17
- * to the `<label>` that wraps it. nene-vault carries them on the label in its own
18
- * implementation (measured 2026-08-23, checking Tailwind classes and CSS both), so a
19
- * migration that could not set them would lose the pointer cursor on every choice in the
20
- * product — visible to a mouse user, invisible in a diff.
15
+ * 🔴 `className` lands on the `<label>`, which is this part's root the same place it
16
+ * lands in every other component the kit ships. Until 0.10.0 it went to the `<input>`
17
+ * instead, so nothing the caller wrote could reach the root: `self-start` inside a flex
18
+ * row, a width, a margin. nene-vault had to wrap each choice in a `<div>` to say them
19
+ * (found while migrating, 2026-08-23). Use `inputClassName` for the box itself.
20
+ *
21
+ * 🔑 This is the cause behind a symptom the kit already answered once. In wave 2 the
22
+ * report was that `cursor-pointer` could not be set, because it belongs to the label; the
23
+ * kit took `cursor-pointer` and the gap on itself. That was right as far as it went, and
24
+ * it left the reason intact — every other label-level property stayed unreachable.
25
+ * Fixing what a report names is not the same as fixing what it is about.
26
+ *
27
+ * `cursor-pointer` and the gap still live here: they are not decisions a product should
28
+ * have to repeat at every call site. nene-vault carries them on the label in its own
29
+ * implementation (measured 2026-08-23), so a migration that could not set them would lose
30
+ * the pointer cursor on every choice — visible to a mouse user, invisible in a diff.
21
31
  */
22
- export const Checkbox = forwardRef(function Checkbox({ label, className, id, 'aria-invalid': ariaInvalid, 'aria-describedby': ariaDescribedBy, 'aria-required': ariaRequired, ...rest }, ref) {
32
+ export const Checkbox = forwardRef(function Checkbox({ label, className, inputClassName, id, 'aria-invalid': ariaInvalid, 'aria-describedby': ariaDescribedBy, 'aria-required': ariaRequired, ...rest }, ref) {
23
33
  const wiring = useFieldWiring({ id, ariaInvalid, ariaDescribedBy, ariaRequired });
24
- return (_jsxs("label", { className: "inline-flex cursor-pointer items-center gap-x-slot-choice-gap font-sans text-text-primary", children: [_jsx("input", { ref: ref, type: "checkbox", className: cx(BOX_CLASS, className), ...wiring, ...rest }), label] }));
34
+ return (_jsxs("label", { className: cx('inline-flex cursor-pointer items-center gap-x-slot-choice-gap font-sans text-x-slot-choice-size text-x-slot-choice-fg', className), children: [_jsx("input", { ref: ref, type: "checkbox", className: cx(BOX_CLASS, inputClassName), ...wiring, ...rest }), label] }));
25
35
  });
26
36
  //# sourceMappingURL=Checkbox.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Checkbox.js","sourceRoot":"","sources":["../../src/primitives/Checkbox.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAA4C,MAAM,OAAO,CAAC;AAC7E,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAO3D,MAAM,SAAS,GAAG,2GAA2G,aAAa,EAAE,CAAC;AAE7I;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,UAAU,CAAkC,SAAS,QAAQ,CACnF,EACE,KAAK,EACL,SAAS,EACT,EAAE,EACF,cAAc,EAAE,WAAW,EAC3B,kBAAkB,EAAE,eAAe,EACnC,eAAe,EAAE,YAAY,EAC7B,GAAG,IAAI,EACR,EACD,GAAG;IAEH,MAAM,MAAM,GAAG,cAAc,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC,CAAC;IAElF,OAAO,CACL,iBAAO,SAAS,EAAC,2FAA2F,aAC1G,gBAAO,GAAG,EAAE,GAAG,EAAE,IAAI,EAAC,UAAU,EAAC,SAAS,EAAE,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,KAAM,MAAM,KAAM,IAAI,GAAI,EAC7F,KAAK,IACA,CACT,CAAC;AACJ,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"Checkbox.js","sourceRoot":"","sources":["../../src/primitives/Checkbox.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAA4C,MAAM,OAAO,CAAC;AAC7E,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAY3D,MAAM,SAAS,GAAG,yHAAyH,aAAa,EAAE,CAAC;AAE3J;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,UAAU,CAAkC,SAAS,QAAQ,CACnF,EACE,KAAK,EACL,SAAS,EACT,cAAc,EACd,EAAE,EACF,cAAc,EAAE,WAAW,EAC3B,kBAAkB,EAAE,eAAe,EACnC,eAAe,EAAE,YAAY,EAC7B,GAAG,IAAI,EACR,EACD,GAAG;IAEH,MAAM,MAAM,GAAG,cAAc,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC,CAAC;IAElF,OAAO,CACL,iBACE,SAAS,EAAE,EAAE,CACX,uHAAuH,EACvH,SAAS,CACV,aAED,gBACE,GAAG,EAAE,GAAG,EACR,IAAI,EAAC,UAAU,EACf,SAAS,EAAE,EAAE,CAAC,SAAS,EAAE,cAAc,CAAC,KACpC,MAAM,KACN,IAAI,GACR,EACD,KAAK,IACA,CACT,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -3,7 +3,7 @@ import { forwardRef } from 'react';
3
3
  import { cx } from '../lib/cx.js';
4
4
  import { CONTROL_CLASS } from '../lib/states.js';
5
5
  import { useFieldWiring } from '../forms/field-context.js';
6
- const BASE_CLASS = `w-full rounded-x-slot-control border border-border bg-surface-raised px-x-slot-control-pad-x py-x-slot-control-pad-y font-sans text-x-slot-control-size pointer-coarse:text-x-slot-control-touch-size text-text-primary placeholder:text-text-muted ${CONTROL_CLASS}`;
6
+ const BASE_CLASS = `w-full rounded-x-slot-control border border-x-slot-control-border bg-x-slot-control-bg px-x-slot-control-pad-x py-x-slot-control-pad-y font-sans text-x-slot-control-size pointer-coarse:text-x-slot-control-touch-size text-x-slot-control-fg placeholder:text-x-slot-control-placeholder ${CONTROL_CLASS}`;
7
7
  /**
8
8
  * Text input primitive. forwardRef so it works directly with react-hook-form `register`.
9
9
  * Visual values come from theme tokens only.
@@ -1 +1 @@
1
- {"version":3,"file":"Input.js","sourceRoot":"","sources":["../../src/primitives/Input.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAA4B,MAAM,OAAO,CAAC;AAC7D,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAI3D,MAAM,UAAU,GAAG,uPAAuP,aAAa,EAAE,CAAC;AAE1R;;;GAGG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,UAAU,CAA+B,SAAS,KAAK,CAC1E,EACE,SAAS,EACT,EAAE,EACF,cAAc,EAAE,WAAW,EAC3B,kBAAkB,EAAE,eAAe,EACnC,eAAe,EAAE,YAAY,EAC7B,GAAG,IAAI,EACR,EACD,GAAG;IAEH,MAAM,MAAM,GAAG,cAAc,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC,CAAC;IAElF,OAAO,gBAAO,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,KAAM,MAAM,KAAM,IAAI,GAAI,CAAC;AACzF,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"Input.js","sourceRoot":"","sources":["../../src/primitives/Input.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAA4B,MAAM,OAAO,CAAC;AAC7D,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAI3D,MAAM,UAAU,GAAG,8RAA8R,aAAa,EAAE,CAAC;AAEjU;;;GAGG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,UAAU,CAA+B,SAAS,KAAK,CAC1E,EACE,SAAS,EACT,EAAE,EACF,cAAc,EAAE,WAAW,EAC3B,kBAAkB,EAAE,eAAe,EACnC,eAAe,EAAE,YAAY,EAC7B,GAAG,IAAI,EACR,EACD,GAAG;IAEH,MAAM,MAAM,GAAG,cAAc,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC,CAAC;IAElF,OAAO,gBAAO,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,KAAM,MAAM,KAAM,IAAI,GAAI,CAAC;AACzF,CAAC,CAAC,CAAC"}
@@ -2,6 +2,11 @@ import { type InputHTMLAttributes, type ReactNode } from 'react';
2
2
  export interface RadioProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {
3
3
  /** Localized label. Rendered inside the control's own `<label>`. */
4
4
  label: ReactNode;
5
+ /**
6
+ * Classes for the `<input>` itself. `className` goes to the `<label>`, which is this
7
+ * part's root — see the note below.
8
+ */
9
+ inputClassName?: string;
5
10
  /** Radios only mean anything in a group; `name` is what makes them one. */
6
11
  name: string;
7
12
  }
@@ -12,12 +17,21 @@ export interface RadioProps extends Omit<InputHTMLAttributes<HTMLInputElement>,
12
17
  * its own group of one: it can be checked but never unchecked, and arrow keys do not move
13
18
  * between the options. Nothing about the rendered page shows this, so it survives review.
14
19
  *
15
- * 🔴 `cursor-pointer`, the gap and the box size are the component's, for the same reason as
16
- * on `Checkbox`: `className` reaches the `<input>`, and those belong to the `<label>`.
17
- * nene-vault's radios share one label style with its checkboxes, so the same hole was here.
20
+ * 🔴 `className` lands on the `<label>`, which is this part's root the same place it
21
+ * lands in every other component the kit ships. Until 0.10.0 it went to the `<input>`
22
+ * instead, so nothing the caller wrote could reach the root: `self-start` inside a flex
23
+ * row, a width, a margin. nene-vault had to wrap each choice in a `<div>` to say them
24
+ * (found while migrating, 2026-08-23). Use `inputClassName` for the box itself.
18
25
  *
19
- * 🔴 This does not take the `FormField` wiring. A group of radios shares one label and one
20
- * error, so the id and `aria-describedby` belong on a `<fieldset>` around the group, not on
21
- * each option putting them here would give every option the same id.
26
+ * 🔑 This is the cause behind a symptom the kit already answered once. In wave 2 the
27
+ * report was that `cursor-pointer` could not be set, because it belongs to the label; the
28
+ * kit took `cursor-pointer` and the gap on itself. That was right as far as it went, and
29
+ * it left the reason intact — every other label-level property stayed unreachable.
30
+ * Fixing what a report names is not the same as fixing what it is about.
31
+ *
32
+ * `cursor-pointer` and the gap still live here: they are not decisions a product should
33
+ * have to repeat at every call site. nene-vault carries them on the label in its own
34
+ * implementation (measured 2026-08-23), so a migration that could not set them would lose
35
+ * the pointer cursor on every choice — visible to a mouse user, invisible in a diff.
22
36
  */
23
37
  export declare const Radio: import("react").ForwardRefExoticComponent<RadioProps & import("react").RefAttributes<HTMLInputElement>>;
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { forwardRef } from 'react';
3
3
  import { cx } from '../lib/cx.js';
4
4
  import { CONTROL_CLASS } from '../lib/states.js';
5
- const DOT_CLASS = `size-x-slot-choice-box shrink-0 border border-border accent-x-slot-choice-accent ${CONTROL_CLASS}`;
5
+ const DOT_CLASS = `size-x-slot-choice-box shrink-0 border border-x-slot-choice-border accent-x-slot-choice-accent ${CONTROL_CLASS}`;
6
6
  /**
7
7
  * One option in a radio group, with its label.
8
8
  *
@@ -10,15 +10,24 @@ const DOT_CLASS = `size-x-slot-choice-box shrink-0 border border-border accent-x
10
10
  * its own group of one: it can be checked but never unchecked, and arrow keys do not move
11
11
  * between the options. Nothing about the rendered page shows this, so it survives review.
12
12
  *
13
- * 🔴 `cursor-pointer`, the gap and the box size are the component's, for the same reason as
14
- * on `Checkbox`: `className` reaches the `<input>`, and those belong to the `<label>`.
15
- * nene-vault's radios share one label style with its checkboxes, so the same hole was here.
13
+ * 🔴 `className` lands on the `<label>`, which is this part's root the same place it
14
+ * lands in every other component the kit ships. Until 0.10.0 it went to the `<input>`
15
+ * instead, so nothing the caller wrote could reach the root: `self-start` inside a flex
16
+ * row, a width, a margin. nene-vault had to wrap each choice in a `<div>` to say them
17
+ * (found while migrating, 2026-08-23). Use `inputClassName` for the box itself.
16
18
  *
17
- * 🔴 This does not take the `FormField` wiring. A group of radios shares one label and one
18
- * error, so the id and `aria-describedby` belong on a `<fieldset>` around the group, not on
19
- * each option putting them here would give every option the same id.
19
+ * 🔑 This is the cause behind a symptom the kit already answered once. In wave 2 the
20
+ * report was that `cursor-pointer` could not be set, because it belongs to the label; the
21
+ * kit took `cursor-pointer` and the gap on itself. That was right as far as it went, and
22
+ * it left the reason intact — every other label-level property stayed unreachable.
23
+ * Fixing what a report names is not the same as fixing what it is about.
24
+ *
25
+ * `cursor-pointer` and the gap still live here: they are not decisions a product should
26
+ * have to repeat at every call site. nene-vault carries them on the label in its own
27
+ * implementation (measured 2026-08-23), so a migration that could not set them would lose
28
+ * the pointer cursor on every choice — visible to a mouse user, invisible in a diff.
20
29
  */
21
- export const Radio = forwardRef(function Radio({ label, name, className, ...rest }, ref) {
22
- return (_jsxs("label", { className: "inline-flex cursor-pointer items-center gap-x-slot-choice-gap font-sans text-text-primary", children: [_jsx("input", { ref: ref, type: "radio", name: name, className: cx(DOT_CLASS, className), ...rest }), label] }));
30
+ export const Radio = forwardRef(function Radio({ label, name, className, inputClassName, ...rest }, ref) {
31
+ return (_jsxs("label", { className: cx('inline-flex cursor-pointer items-center gap-x-slot-choice-gap font-sans text-x-slot-choice-size text-x-slot-choice-fg', className), children: [_jsx("input", { ref: ref, type: "radio", name: name, className: cx(DOT_CLASS, inputClassName), ...rest }), label] }));
23
32
  });
24
33
  //# sourceMappingURL=Radio.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Radio.js","sourceRoot":"","sources":["../../src/primitives/Radio.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAA4C,MAAM,OAAO,CAAC;AAC7E,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AASjD,MAAM,SAAS,GAAG,oFAAoF,aAAa,EAAE,CAAC;AAEtH;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,UAAU,CAA+B,SAAS,KAAK,CAC1E,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,EACnC,GAAG;IAEH,OAAO,CACL,iBAAO,SAAS,EAAC,2FAA2F,aAC1G,gBAAO,GAAG,EAAE,GAAG,EAAE,IAAI,EAAC,OAAO,EAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,KAAM,IAAI,GAAI,EAC1F,KAAK,IACA,CACT,CAAC;AACJ,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"Radio.js","sourceRoot":"","sources":["../../src/primitives/Radio.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAA4C,MAAM,OAAO,CAAC;AAC7E,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAcjD,MAAM,SAAS,GAAG,kGAAkG,aAAa,EAAE,CAAC;AAEpI;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,UAAU,CAA+B,SAAS,KAAK,CAC1E,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,cAAc,EAAE,GAAG,IAAI,EAAE,EACnD,GAAG;IAEH,OAAO,CACL,iBACE,SAAS,EAAE,EAAE,CACX,uHAAuH,EACvH,SAAS,CACV,aAED,gBACE,GAAG,EAAE,GAAG,EACR,IAAI,EAAC,OAAO,EACZ,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,EAAE,CAAC,SAAS,EAAE,cAAc,CAAC,KACpC,IAAI,GACR,EACD,KAAK,IACA,CACT,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -3,7 +3,7 @@ import { forwardRef } from 'react';
3
3
  import { cx } from '../lib/cx.js';
4
4
  import { CONTROL_CLASS } from '../lib/states.js';
5
5
  import { useFieldWiring } from '../forms/field-context.js';
6
- const BASE_CLASS = `w-full rounded-x-slot-control border border-border bg-surface-raised px-x-slot-control-pad-x py-x-slot-control-pad-y font-sans text-x-slot-control-size pointer-coarse:text-x-slot-control-touch-size text-text-primary ${CONTROL_CLASS}`;
6
+ const BASE_CLASS = `w-full rounded-x-slot-control border border-x-slot-control-border bg-x-slot-control-bg px-x-slot-control-pad-x py-x-slot-control-pad-y font-sans text-x-slot-control-size pointer-coarse:text-x-slot-control-touch-size text-x-slot-control-fg ${CONTROL_CLASS}`;
7
7
  /**
8
8
  * Select primitive. forwardRef so it works directly with react-hook-form `register`.
9
9
  * Visual values come from theme tokens only.
@@ -1 +1 @@
1
- {"version":3,"file":"Select.js","sourceRoot":"","sources":["../../src/primitives/Select.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAA6C,MAAM,OAAO,CAAC;AAC9E,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAM3D,MAAM,UAAU,GAAG,2NAA2N,aAAa,EAAE,CAAC;AAE9P;;;GAGG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,UAAU,CAAiC,SAAS,MAAM,CAC9E,EACE,QAAQ,EACR,SAAS,EACT,EAAE,EACF,cAAc,EAAE,WAAW,EAC3B,kBAAkB,EAAE,eAAe,EACnC,eAAe,EAAE,YAAY,EAC7B,GAAG,IAAI,EACR,EACD,GAAG;IAEH,MAAM,MAAM,GAAG,cAAc,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC,CAAC;IAElF,OAAO,CACL,iBAAQ,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,KAAM,MAAM,KAAM,IAAI,YACzE,QAAQ,GACF,CACV,CAAC;AACJ,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"Select.js","sourceRoot":"","sources":["../../src/primitives/Select.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAA6C,MAAM,OAAO,CAAC;AAC9E,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAM3D,MAAM,UAAU,GAAG,kPAAkP,aAAa,EAAE,CAAC;AAErR;;;GAGG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,UAAU,CAAiC,SAAS,MAAM,CAC9E,EACE,QAAQ,EACR,SAAS,EACT,EAAE,EACF,cAAc,EAAE,WAAW,EAC3B,kBAAkB,EAAE,eAAe,EACnC,eAAe,EAAE,YAAY,EAC7B,GAAG,IAAI,EACR,EACD,GAAG;IAEH,MAAM,MAAM,GAAG,cAAc,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC,CAAC;IAElF,OAAO,CACL,iBAAQ,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,KAAM,MAAM,KAAM,IAAI,YACzE,QAAQ,GACF,CACV,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { cx } from '../lib/cx.js';
3
3
  export function Spinner({ label, className }) {
4
- return (_jsx("output", { className: cx('font-sans text-text-muted', className), "aria-live": "polite", children: label }));
4
+ return (_jsx("output", { className: cx('font-sans text-x-slot-spinner-fg', className), "aria-live": "polite", children: label }));
5
5
  }
6
6
  //# sourceMappingURL=Spinner.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Spinner.js","sourceRoot":"","sources":["../../src/primitives/Spinner.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAQlC,MAAM,UAAU,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAgB;IACxD,OAAO,CACL,iBAAQ,SAAS,EAAE,EAAE,CAAC,2BAA2B,EAAE,SAAS,CAAC,eAAY,QAAQ,YAC9E,KAAK,GACC,CACV,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"Spinner.js","sourceRoot":"","sources":["../../src/primitives/Spinner.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAQlC,MAAM,UAAU,OAAO,CAAC,EAAE,KAAK,EAAE,SAAS,EAAgB;IACxD,OAAO,CACL,iBAAQ,SAAS,EAAE,EAAE,CAAC,kCAAkC,EAAE,SAAS,CAAC,eAAY,QAAQ,YACrF,KAAK,GACC,CACV,CAAC;AACJ,CAAC"}
@@ -14,6 +14,8 @@ import { CLICKABLE_CLASS } from '../lib/states.js';
14
14
  * `aria-checked` carries the state; the visible track is decoration on top of it.
15
15
  */
16
16
  export const Switch = forwardRef(function Switch({ checked, onCheckedChange, label, className, ...rest }, ref) {
17
- return (_jsx("button", { ref: ref, type: "button", role: "switch", "aria-checked": checked, "aria-label": label, onClick: () => onCheckedChange(!checked), className: cx('inline-flex items-center rounded-x-slot-switch border border-border px-x-slot-switch-pad-x py-x-slot-switch-pad-y font-sans', checked ? 'bg-accent text-on-accent' : 'bg-surface text-text-muted', CLICKABLE_CLASS, className), ...rest, children: label }));
17
+ return (_jsx("button", { ref: ref, type: "button", role: "switch", "aria-checked": checked, "aria-label": label, onClick: () => onCheckedChange(!checked), className: cx('inline-flex items-center rounded-x-slot-switch border border-x-slot-switch-border px-x-slot-switch-pad-x py-x-slot-switch-pad-y font-sans', checked
18
+ ? 'bg-x-slot-switch-on-bg text-x-slot-switch-on-fg'
19
+ : 'bg-x-slot-switch-off-bg text-x-slot-switch-off-fg', CLICKABLE_CLASS, className), ...rest, children: label }));
18
20
  });
19
21
  //# sourceMappingURL=Switch.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Switch.js","sourceRoot":"","sources":["../../src/primitives/Switch.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAA6B,MAAM,OAAO,CAAC;AAC9D,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAUnD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,UAAU,CAAiC,SAAS,MAAM,CAC9E,EAAE,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,EACvD,GAAG;IAEH,OAAO,CACL,iBACE,GAAG,EAAE,GAAG,EACR,IAAI,EAAC,QAAQ,EACb,IAAI,EAAC,QAAQ,kBACC,OAAO,gBACT,KAAK,EACjB,OAAO,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC,EACxC,SAAS,EAAE,EAAE,CACX,6HAA6H,EAC7H,OAAO,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,4BAA4B,EACnE,eAAe,EACf,SAAS,CACV,KACG,IAAI,YAEP,KAAK,GACC,CACV,CAAC;AACJ,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"Switch.js","sourceRoot":"","sources":["../../src/primitives/Switch.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAA6B,MAAM,OAAO,CAAC;AAC9D,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAUnD;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,MAAM,GAAG,UAAU,CAAiC,SAAS,MAAM,CAC9E,EAAE,OAAO,EAAE,eAAe,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,IAAI,EAAE,EACvD,GAAG;IAEH,OAAO,CACL,iBACE,GAAG,EAAE,GAAG,EACR,IAAI,EAAC,QAAQ,EACb,IAAI,EAAC,QAAQ,kBACC,OAAO,gBACT,KAAK,EACjB,OAAO,EAAE,GAAG,EAAE,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC,EACxC,SAAS,EAAE,EAAE,CACX,2IAA2I,EAC3I,OAAO;YACL,CAAC,CAAC,iDAAiD;YACnD,CAAC,CAAC,mDAAmD,EACvD,eAAe,EACf,SAAS,CACV,KACG,IAAI,YAEP,KAAK,GACC,CACV,CAAC;AACJ,CAAC,CAAC,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { cx } from '../lib/cx.js';
3
3
  export function Text({ as = 'p', tone = 'primary', children, className }) {
4
- const merged = cx('font-sans', tone === 'muted' ? 'text-text-muted' : 'text-text-primary', className);
4
+ const merged = cx('font-sans', tone === 'muted' ? 'text-x-slot-text-muted-fg' : 'text-x-slot-text-fg', className);
5
5
  return as === 'span' ? (_jsx("span", { className: merged, children: children })) : (_jsx("p", { className: merged, children: children }));
6
6
  }
7
7
  //# sourceMappingURL=Text.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Text.js","sourceRoot":"","sources":["../../src/primitives/Text.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAUlC,MAAM,UAAU,IAAI,CAAC,EAAE,EAAE,GAAG,GAAG,EAAE,IAAI,GAAG,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAa;IACjF,MAAM,MAAM,GAAG,EAAE,CACf,WAAW,EACX,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,mBAAmB,EAC1D,SAAS,CACV,CAAC;IAEF,OAAO,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,CACrB,eAAM,SAAS,EAAE,MAAM,YAAG,QAAQ,GAAQ,CAC3C,CAAC,CAAC,CAAC,CACF,YAAG,SAAS,EAAE,MAAM,YAAG,QAAQ,GAAK,CACrC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"Text.js","sourceRoot":"","sources":["../../src/primitives/Text.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAUlC,MAAM,UAAU,IAAI,CAAC,EAAE,EAAE,GAAG,GAAG,EAAE,IAAI,GAAG,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAa;IACjF,MAAM,MAAM,GAAG,EAAE,CACf,WAAW,EACX,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,qBAAqB,EACtE,SAAS,CACV,CAAC;IAEF,OAAO,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,CACrB,eAAM,SAAS,EAAE,MAAM,YAAG,QAAQ,GAAQ,CAC3C,CAAC,CAAC,CAAC,CACF,YAAG,SAAS,EAAE,MAAM,YAAG,QAAQ,GAAK,CACrC,CAAC;AACJ,CAAC"}
@@ -3,7 +3,7 @@ import { forwardRef } from 'react';
3
3
  import { cx } from '../lib/cx.js';
4
4
  import { CONTROL_CLASS } from '../lib/states.js';
5
5
  import { useFieldWiring } from '../forms/field-context.js';
6
- const BASE_CLASS = `w-full rounded-x-slot-control border border-border bg-surface-raised px-x-slot-control-pad-x py-x-slot-control-pad-y font-sans text-x-slot-control-size pointer-coarse:text-x-slot-control-touch-size text-text-primary placeholder:text-text-muted ${CONTROL_CLASS}`;
6
+ const BASE_CLASS = `w-full rounded-x-slot-control border border-x-slot-control-border bg-x-slot-control-bg px-x-slot-control-pad-x py-x-slot-control-pad-y font-sans text-x-slot-control-size pointer-coarse:text-x-slot-control-touch-size text-x-slot-control-fg placeholder:text-x-slot-control-placeholder ${CONTROL_CLASS}`;
7
7
  /**
8
8
  * Multi-line text input. Deliberately identical to `Input` apart from the element, so the
9
9
  * two never drift: five ships wrote their own `Textarea.tsx` and the kit shipped without
@@ -1 +1 @@
1
- {"version":3,"file":"Textarea.js","sourceRoot":"","sources":["../../src/primitives/Textarea.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAA+B,MAAM,OAAO,CAAC;AAChE,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAI3D,MAAM,UAAU,GAAG,uPAAuP,aAAa,EAAE,CAAC;AAE1R;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,UAAU,CAAqC,SAAS,QAAQ,CACtF,EACE,SAAS,EACT,EAAE,EACF,cAAc,EAAE,WAAW,EAC3B,kBAAkB,EAAE,eAAe,EACnC,eAAe,EAAE,YAAY,EAC7B,GAAG,IAAI,EACR,EACD,GAAG;IAEH,MAAM,MAAM,GAAG,cAAc,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC,CAAC;IAElF,OAAO,mBAAU,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,KAAM,MAAM,KAAM,IAAI,GAAI,CAAC;AAC5F,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"Textarea.js","sourceRoot":"","sources":["../../src/primitives/Textarea.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAA+B,MAAM,OAAO,CAAC;AAChE,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAI3D,MAAM,UAAU,GAAG,8RAA8R,aAAa,EAAE,CAAC;AAEjU;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,UAAU,CAAqC,SAAS,QAAQ,CACtF,EACE,SAAS,EACT,EAAE,EACF,cAAc,EAAE,WAAW,EAC3B,kBAAkB,EAAE,eAAe,EACnC,eAAe,EAAE,YAAY,EAC7B,GAAG,IAAI,EACR,EACD,GAAG;IAEH,MAAM,MAAM,GAAG,cAAc,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,CAAC,CAAC;IAElF,OAAO,mBAAU,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,CAAC,UAAU,EAAE,SAAS,CAAC,KAAM,MAAM,KAAM,IAAI,GAAI,CAAC;AAC5F,CAAC,CAAC,CAAC"}
@@ -1,6 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { cx } from '../lib/cx.js';
3
3
  export function EmptyState({ message, align = 'center', className }) {
4
- return (_jsx("div", { className: cx('py-x-slot-state-pad-y font-sans text-text-muted', align === 'center' && 'text-center', className), role: "status", children: message }));
4
+ return (_jsx("div", { className: cx('py-x-slot-state-pad-y font-sans text-x-slot-empty-state-fg', align === 'center' && 'text-center', className), role: "status", children: message }));
5
5
  }
6
6
  //# sourceMappingURL=EmptyState.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"EmptyState.js","sourceRoot":"","sources":["../../src/states/EmptyState.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAgBlC,MAAM,UAAU,UAAU,CAAC,EAAE,OAAO,EAAE,KAAK,GAAG,QAAQ,EAAE,SAAS,EAAmB;IAClF,OAAO,CACL,cACE,SAAS,EAAE,EAAE,CACX,iDAAiD,EACjD,KAAK,KAAK,QAAQ,IAAI,aAAa,EACnC,SAAS,CACV,EACD,IAAI,EAAC,QAAQ,YAEZ,OAAO,GACJ,CACP,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"EmptyState.js","sourceRoot":"","sources":["../../src/states/EmptyState.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAgBlC,MAAM,UAAU,UAAU,CAAC,EAAE,OAAO,EAAE,KAAK,GAAG,QAAQ,EAAE,SAAS,EAAmB;IAClF,OAAO,CACL,cACE,SAAS,EAAE,EAAE,CACX,4DAA4D,EAC5D,KAAK,KAAK,QAAQ,IAAI,aAAa,EACnC,SAAS,CACV,EACD,IAAI,EAAC,QAAQ,YAEZ,OAAO,GACJ,CACP,CAAC;AACJ,CAAC"}
@@ -2,6 +2,6 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Button } from '../primitives/Button.js';
3
3
  import { cx } from '../lib/cx.js';
4
4
  export function ErrorState({ message, retryLabel, onRetry, className }) {
5
- return (_jsxs("div", { className: cx('py-x-slot-state-pad-y', className), role: "alert", children: [_jsx("p", { className: "font-sans text-danger", children: message }), _jsx("div", { className: "py-x-slot-state-action-pad-y", children: _jsx(Button, { variant: "secondary", onClick: onRetry, children: retryLabel }) })] }));
5
+ return (_jsxs("div", { className: cx('py-x-slot-state-pad-y', className), role: "alert", children: [_jsx("p", { className: "font-sans text-x-slot-error-state-fg", children: message }), _jsx("div", { className: "py-x-slot-state-action-pad-y", children: _jsx(Button, { variant: "secondary", onClick: onRetry, children: retryLabel }) })] }));
6
6
  }
7
7
  //# sourceMappingURL=ErrorState.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ErrorState.js","sourceRoot":"","sources":["../../src/states/ErrorState.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAYlC,MAAM,UAAU,UAAU,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAmB;IACrF,OAAO,CACL,eAAK,SAAS,EAAE,EAAE,CAAC,uBAAuB,EAAE,SAAS,CAAC,EAAE,IAAI,EAAC,OAAO,aAClE,YAAG,SAAS,EAAC,uBAAuB,YAAE,OAAO,GAAK,EAClD,cAAK,SAAS,EAAC,8BAA8B,YAC3C,KAAC,MAAM,IAAC,OAAO,EAAC,WAAW,EAAC,OAAO,EAAE,OAAO,YACzC,UAAU,GACJ,GACL,IACF,CACP,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"ErrorState.js","sourceRoot":"","sources":["../../src/states/ErrorState.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AACjD,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAYlC,MAAM,UAAU,UAAU,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAmB;IACrF,OAAO,CACL,eAAK,SAAS,EAAE,EAAE,CAAC,uBAAuB,EAAE,SAAS,CAAC,EAAE,IAAI,EAAC,OAAO,aAClE,YAAG,SAAS,EAAC,sCAAsC,YAAE,OAAO,GAAK,EACjE,cAAK,SAAS,EAAC,8BAA8B,YAC3C,KAAC,MAAM,IAAC,OAAO,EAAC,WAAW,EAAC,OAAO,EAAE,OAAO,YACzC,UAAU,GACJ,GACL,IACF,CACP,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hideyukimori/nene2-ui",
3
- "version": "0.7.0",
3
+ "version": "0.11.0",
4
4
  "description": "NeNe fleet shared React UI kit — token-driven primitives on Tailwind v4 @theme. Components carry no design of their own; themes do.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -138,7 +138,12 @@
138
138
  --color-x-slot-field-error: var(--color-danger);
139
139
  --text-x-slot-field-error-size: var(--text-x-2xs);
140
140
  --text-x-slot-field-label-size: var(--text-x-xs);
141
- --font-weight-x-slot-field-label: 500;
141
+ /* 🔴 `var(--font-weight-medium)`, not `500`. Identical output — Tailwind defines that
142
+ * step as 500 — but a literal here is a weight the kit invented, and the namespace has a
143
+ * nine-step scale already (thin…black). This one escaped the "slot defaults are scale
144
+ * references only" check because that check listed the namespaces it knew about; found
145
+ * while adding the radius scale (#348). */
146
+ --font-weight-x-slot-field-label: var(--font-weight-medium);
142
147
  /* Control text. Two slots, because one value cannot answer "how is this being pointed at".
143
148
  *
144
149
  * 0.6.0 used `max(var(--text-x-md), var(--text-x-ios-floor))`, which raised every control
@@ -152,6 +157,133 @@
152
157
  --text-x-slot-control-size: var(--text-x-md);
153
158
  --text-x-slot-control-touch-size: var(--text-x-ios-floor);
154
159
 
160
+ /* ── Colour slots ─────────────────────────────────────────────────────────────
161
+ * Every colour a component paints comes from here.
162
+ *
163
+ * 🔴 Until 0.9.0 only `FormField` and `InlineAlert` had any, and the other 26 components
164
+ * reached straight into the palette (`text-text-primary`, `bg-surface-raised`) — 59 places
165
+ * in 20 files. The README said "every design value a component uses comes from a slot"
166
+ * the whole time. The check that was supposed to enforce it listed the utility prefixes
167
+ * it knew about — `p px py … rounded` — so colour and weight were never inspected at all.
168
+ *
169
+ * Found by nene-vault comparing its production screens against the migrated build in a
170
+ * real browser (Playwright, computed styles, element by element, 2026-08-23): 73 elements
171
+ * matched, 21 differed, and every difference was inside a kit component. Its own markup —
172
+ * side nav, tables, headings — matched on every property. A product cannot make a control
173
+ * darker than its body text while the kit writes the colour itself.
174
+ *
175
+ * Defaults are palette references, so nothing renders differently. What changes is that
176
+ * there is now an opening. */
177
+ --color-x-slot-focus-ring: var(--color-text-primary);
178
+
179
+ --color-x-slot-button-primary-bg: var(--color-accent);
180
+ --color-x-slot-button-primary-fg: var(--color-on-accent);
181
+ --color-x-slot-button-secondary-bg: var(--color-surface-raised);
182
+ --color-x-slot-button-secondary-fg: var(--color-text-primary);
183
+ --color-x-slot-button-secondary-border: var(--color-border);
184
+ --color-x-slot-button-danger-bg: var(--color-danger);
185
+ --color-x-slot-button-danger-fg: var(--color-on-accent);
186
+ --color-x-slot-button-ghost-fg: var(--color-text-primary);
187
+
188
+ /* Shared by Input, Select and Textarea — they are one control with three shapes, and a
189
+ * product that darkens one and not the others has a bug, not a design. */
190
+ --color-x-slot-control-fg: var(--color-text-primary);
191
+ --color-x-slot-control-bg: var(--color-surface-raised);
192
+ --color-x-slot-control-border: var(--color-border);
193
+ --color-x-slot-control-placeholder: var(--color-text-muted);
194
+
195
+ --color-x-slot-choice-fg: var(--color-text-primary);
196
+ --color-x-slot-choice-border: var(--color-border);
197
+
198
+ --color-x-slot-switch-on-bg: var(--color-accent);
199
+ --color-x-slot-switch-on-fg: var(--color-on-accent);
200
+ --color-x-slot-switch-off-bg: var(--color-surface);
201
+ --color-x-slot-switch-off-fg: var(--color-text-muted);
202
+ --color-x-slot-switch-border: var(--color-border);
203
+
204
+ --color-x-slot-badge-neutral-bg: var(--color-surface);
205
+ --color-x-slot-badge-neutral-fg: var(--color-text-muted);
206
+ --color-x-slot-badge-neutral-border: var(--color-border);
207
+ --color-x-slot-badge-accent-bg: var(--color-accent);
208
+ --color-x-slot-badge-accent-fg: var(--color-on-accent);
209
+ --color-x-slot-badge-accent-border: var(--color-accent);
210
+ --color-x-slot-badge-danger-bg: var(--color-danger);
211
+ --color-x-slot-badge-danger-fg: var(--color-on-accent);
212
+ --color-x-slot-badge-danger-border: var(--color-danger);
213
+
214
+ --color-x-slot-toast-bg: var(--color-surface-raised);
215
+ --color-x-slot-toast-fg: var(--color-text-primary);
216
+ --color-x-slot-toast-border: var(--color-border);
217
+ --color-x-slot-toast-danger-fg: var(--color-danger);
218
+ --color-x-slot-toast-danger-border: var(--color-danger);
219
+
220
+ --color-x-slot-card-bg: var(--color-surface-raised);
221
+ --color-x-slot-card-border: var(--color-border);
222
+
223
+ --color-x-slot-modal-bg: var(--color-surface-raised);
224
+ --color-x-slot-modal-fg: var(--color-text-primary);
225
+ --color-x-slot-modal-border: var(--color-border);
226
+ /* The dim behind a modal. A colour, so it belongs here — the opacity that goes with it is
227
+ * applied by the component, since it is not a palette entry. */
228
+ --color-x-slot-modal-scrim: var(--color-text-primary);
229
+
230
+ --color-x-slot-table-fg: var(--color-text-primary);
231
+ --color-x-slot-table-header-fg: var(--color-text-muted);
232
+ --color-x-slot-table-border: var(--color-border);
233
+
234
+ --color-x-slot-detail-term-fg: var(--color-text-muted);
235
+ --color-x-slot-detail-description-fg: var(--color-text-primary);
236
+ --color-x-slot-detail-border: var(--color-border);
237
+
238
+ --color-x-slot-pagination-fg: var(--color-text-muted);
239
+ --color-x-slot-page-header-fg: var(--color-text-primary);
240
+ --color-x-slot-text-fg: var(--color-text-primary);
241
+ --color-x-slot-text-muted-fg: var(--color-text-muted);
242
+ --color-x-slot-spinner-fg: var(--color-text-muted);
243
+ --color-x-slot-empty-state-fg: var(--color-text-muted);
244
+ --color-x-slot-error-state-fg: var(--color-danger);
245
+ --color-x-slot-field-error-fg: var(--color-danger);
246
+
247
+ /* An upper bound for an `<svg>` written directly inside a `Button`.
248
+ *
249
+ * 🔴 `max-*`, deliberately not `size-*`. An `<svg>` with no width/height attributes and no
250
+ * CSS size is a replaced element with no intrinsic size, so it lays out at 300x150 — which
251
+ * is how a nene-vault upload button became a 230px-tall rectangle the moment its wrapper
252
+ * changed from a `<div>` to a `<Stack>` (2026-08-23).
253
+ *
254
+ * Sizing it outright would fix that and break something else: a class produced by an
255
+ * arbitrary variant (`[&_svg]:size-6`) outranks the plain `h-6 w-6` that `Icon` puts on
256
+ * itself, so `<Icon size="sm">` inside a button would silently render at the button's
257
+ * size. A maximum has no such conflict — it constrains nothing that is already smaller,
258
+ * and there is no specificity contest because the two properties are different.
259
+ *
260
+ * The bound is `--spacing-x-lg`, which is 1.5rem — `Icon size="lg"` exactly — so no icon
261
+ * the kit ships is clamped by it. */
262
+ --spacing-x-slot-button-icon: var(--spacing-x-lg);
263
+
264
+ /* ── Weight slots ─────────────────────────────────────────────────────────────
265
+ * `font-medium` appeared inline in four components. Same rule, same reason as colour. */
266
+ --font-weight-x-slot-button: var(--font-weight-medium);
267
+ --font-weight-x-slot-table-header: var(--font-weight-medium);
268
+ --font-weight-x-slot-detail-term: var(--font-weight-medium);
269
+ --font-weight-x-slot-page-header: var(--font-weight-medium);
270
+
271
+ /* ── Size slots that decline to choose ────────────────────────────────────────
272
+ * 🔴 `inherit`, not a step. Button and the choice controls set no font-size today, so
273
+ * they take the page's — and picking a step here would change how every product already
274
+ * renders, which is the one thing this release must not do. `inherit` is not a design
275
+ * value the kit invented; it is the kit saying it has no opinion, in a place a product
276
+ * can now answer. nene-vault's production buttons are 13px against a 14px body, which is
277
+ * exactly the distinction that had nowhere to live.
278
+ *
279
+ * ⚠️ 13px is not on the type scale (0.6875 / 0.75 / 0.875 / 1 / 1.125 / 1.5rem). The
280
+ * scale was measured from what the fleet writes in Tailwind classes, which cannot express
281
+ * a value it has no step for — so that measurement could not have seen it. Recorded here
282
+ * rather than acted on: changing the type scale is its own decision, with its own
283
+ * measurement, and it is not this release's. */
284
+ --text-x-slot-button-size: inherit;
285
+ --text-x-slot-choice-size: inherit;
286
+
155
287
  /* Sentinel for the consumer's build (#316). Zero-width, so applying it does nothing.
156
288
  * Its only job is to exist: `p-x-source-probe` appears nowhere except this kit's `dist`,
157
289
  * so a build that generates it has the kit in its `@source`, and a build that does not
@@ -163,7 +295,50 @@
163
295
  * gave them nothing (50 x10, 40 x4, 30 x6, measured 2026-08-23 across 20 uses). */
164
296
  --opacity-x-disabled: 50%;
165
297
 
298
+ /* The radius scale. Nine steps plus pill, chosen the same way the spacing scale was —
299
+ * by measuring the fleet, not by taste. Snapping the 266 radius values the fleet actually
300
+ * applies (`border-radius` declarations and `--radius-*` theme tokens across ten products,
301
+ * 2026-08-23, #348) onto these nine puts 69.9% exactly on a step and 97.7% within 2px.
302
+ *
303
+ * 🔴 This replaces a scale that had ONE step. Eight slots all pointed at `--radius-x-md`,
304
+ * so a product following the rules could only ever render 8px — and a slot whose value set
305
+ * has one member is not a slot. The cause is recorded because it generalizes: the kit's
306
+ * theme was promoted verbatim from nene-payout, and payout is the fleet's only product
307
+ * with a single radius. Promoting from the product with the fewest conformance violations
308
+ * exported its poverty as the norm — having no choices is not the same as choosing well.
309
+ * A component implementation may come from one ship; the SET OF CHOICES may not.
310
+ *
311
+ * 🔴 `2px` is its own step because it is the single most common radius in the fleet
312
+ * (56 of 266). nene-records ships 9 themes at 0px and 3 at 2-3px as separate product
313
+ * themes — so folding 2px into 0 would not be a rounding error, it would delete a
314
+ * distinction somebody drew on purpose. Candidate scales were therefore scored on a
315
+ * second axis besides average error: whether two values that exist by design collapse
316
+ * onto one step (vault's proposal). The steps kept apart here are 0/2, 6/8 and 10/12;
317
+ * what still collapses (3-4, 5-6, 9-10) is 1px apart, below a scale's resolution.
318
+ *
319
+ * `--radius-x-md` keeps the value it had. Every slot points at it, so changing it would
320
+ * move every product's appearance silently — the scale gains steps, the default does not
321
+ * move. */
322
+ --radius-x-none: 0;
323
+ --radius-x-2xs: 2px;
324
+ --radius-x-xs: 4px;
325
+ --radius-x-sm: 6px;
166
326
  --radius-x-md: 0.5rem;
327
+ --radius-x-lg: 10px;
328
+ --radius-x-xl: 12px;
329
+ --radius-x-2xl: 16px;
330
+ --radius-x-3xl: 24px;
331
+
332
+ /* Fully round. A step, not a footnote: `rounded-x-pill` is the most-used radius in
333
+ * nene-field (48 uses) and appears in five products (64 uses total).
334
+ *
335
+ * 🔴 A product whose design language has no rounding does NOT redefine this step — it
336
+ * points its slots at `--radius-x-none`. nene-records reaches the same end today by
337
+ * setting its own `--radius-full: 0px`, which works only because its components hard-code
338
+ * `rounded-full`. Overriding a scale step changes what a name means fleet-wide; overriding
339
+ * a slot changes one product's choice. The second is the mechanism; the first is the drift
340
+ * the scale exists to prevent. */
341
+ --radius-x-pill: 9999px;
167
342
 
168
343
  /* The spacing scale. Nine steps, chosen by measurement rather than taste: snapping the
169
344
  * 944 spacing utilities the fleet writes by hand onto these nine moves 98.2% of them by