@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
@@ -1,24 +1,48 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { cx } from '../lib/cx.js';
3
- import { CLICKABLE_CLASS } from '../lib/states.js';
3
+ import { CLICKABLE_CLASS, TOUCH_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
- md: 'px-x-slot-button-pad-x py-x-slot-button-pad-y',
14
- sm: 'px-x-slot-button-sm-pad-x py-x-slot-button-sm-pad-y',
13
+ md: 'px-x-slot-button-pad-x py-x-slot-button-pad-y text-x-slot-button-size',
14
+ sm: 'px-x-slot-button-sm-pad-x py-x-slot-button-sm-pad-y text-x-slot-button-sm-size',
15
15
  };
16
+ // 🔴 `inline-flex`, so the button places what is inside it. A `<button>` is `inline-block`
17
+ // by default, which leaves an icon and its label on a shared baseline rather than centred —
18
+ // visible as a half-pixel of drift on every icon button, and invisible in a diff. The kit
19
+ // already takes responsibility for the size of an `<svg>` in here (`SVG_BOUND`); taking
20
+ // responsibility for where it sits is the other half of the same job, and leaving one to the
21
+ // caller while doing the other is the asymmetry nene-vault had to work around by writing
22
+ // `inline-flex` at the call site.
23
+ //
24
+ // ⚠️ This changes rendering. A text-only button is laid out by flex rather than by inline
25
+ // flow, so it no longer sits on the surrounding text's baseline the way an inline-block does.
26
+ // Inside a paragraph that is visible; in the button rows and toolbars these are actually used
27
+ // in, it is not. `inline-flex` rather than `flex` keeps the element from claiming a line.
28
+ //
16
29
  // 🔴 `border border-transparent` is load-bearing. Height comes from the padding, so the
17
30
  // `secondary` variant — the only one with a visible border — would otherwise stand 2px
18
31
  // taller than the others. nene-vault puts a primary and a secondary side by side in seven
19
32
  // modal footers, where that shows up as a step (measured 2026-08-23); its own Button carries
20
33
  // 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}`;
34
+ // 🔴 `[&_svg]:max-*` bounds a raw `<svg>` child without sizing it. An svg with no width or
35
+ // height attribute lays out at the replaced-element default of 300x150; a `max-height` pulls
36
+ // it back and, because a `viewBox` gives the element an intrinsic ratio, the width follows.
37
+ // `max-width` covers the svg that has no viewBox either.
38
+ //
39
+ // 🔴 Not `[&_svg]:size-*`. That would outrank the plain `h-5 w-5` an `Icon` sets on itself
40
+ // — an arbitrary variant compiles to a descendant selector, which is more specific than a
41
+ // single class — so `<Icon size="sm">` inside a button would render at the button's size
42
+ // instead of its own. A maximum cannot collide with a height: different property, and it
43
+ // leaves anything already smaller alone.
44
+ const SVG_BOUND = '[&_svg]:max-h-x-slot-button-icon [&_svg]:max-w-x-slot-button-icon';
45
+ const BASE_CLASS = `rounded-x-slot-button border border-transparent inline-flex items-center justify-center gap-x-slot-button-gap font-sans font-x-slot-button ${SVG_BOUND} ${TOUCH_CLASS} ${CLICKABLE_CLASS}`;
22
46
  export function Button({ variant = 'primary', size = 'md', children, type = 'button', className, ...rest }) {
23
47
  return (_jsx("button", { type: type, className: cx(BASE_CLASS, SIZE_CLASS[size], VARIANT_CLASS[variant], className), ...rest, children: children }));
24
48
  }
@@ -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,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAchE,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,uEAAuE;IAC3E,EAAE,EAAE,gFAAgF;CACrF,CAAC;AAEF,2FAA2F;AAC3F,4FAA4F;AAC5F,0FAA0F;AAC1F,wFAAwF;AACxF,6FAA6F;AAC7F,yFAAyF;AACzF,kCAAkC;AAClC,EAAE;AACF,0FAA0F;AAC1F,8FAA8F;AAC9F,8FAA8F;AAC9F,0FAA0F;AAC1F,EAAE;AACF,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,8IAA8I,SAAS,IAAI,WAAW,IAAI,eAAe,EAAE,CAAC;AAE/M,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>>;
@@ -1,9 +1,9 @@
1
1
  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
- import { CONTROL_CLASS } from '../lib/states.js';
4
+ import { CONTROL_CLASS, TOUCH_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(TOUCH_CLASS, '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,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC9D,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,WAAW,EACX,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"}
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { forwardRef } from 'react';
3
3
  import { cx } from '../lib/cx.js';
4
- import { CONTROL_CLASS } from '../lib/states.js';
4
+ import { CONTROL_CLASS, TOUCH_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} ${TOUCH_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,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAI3D,MAAM,UAAU,GAAG,8RAA8R,aAAa,IAAI,WAAW,EAAE,CAAC;AAEhV;;;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>>;
@@ -1,8 +1,8 @@
1
1
  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
- 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}`;
4
+ import { CONTROL_CLASS, TOUCH_CLASS } from '../lib/states.js';
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(TOUCH_CLASS, '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,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAc9D,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,WAAW,EACX,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"}
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { forwardRef } from 'react';
3
3
  import { cx } from '../lib/cx.js';
4
- import { CONTROL_CLASS } from '../lib/states.js';
4
+ import { CONTROL_CLASS, TOUCH_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} ${TOUCH_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,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAM3D,MAAM,UAAU,GAAG,kPAAkP,aAAa,IAAI,WAAW,EAAE,CAAC;AAEpS;;;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"}
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { forwardRef } from 'react';
3
3
  import { cx } from '../lib/cx.js';
4
- import { CLICKABLE_CLASS } from '../lib/states.js';
4
+ import { CLICKABLE_CLASS, TOUCH_CLASS } from '../lib/states.js';
5
5
  /**
6
6
  * An on/off control that takes effect immediately.
7
7
  *
@@ -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(TOUCH_CLASS, '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,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAUhE;;;;;;;;;;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,WAAW,EACX,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"}
@@ -1,9 +1,9 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { forwardRef } from 'react';
3
3
  import { cx } from '../lib/cx.js';
4
- import { CONTROL_CLASS } from '../lib/states.js';
4
+ import { CONTROL_CLASS, TOUCH_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} ${TOUCH_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,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAI3D,MAAM,UAAU,GAAG,8RAA8R,aAAa,IAAI,WAAW,EAAE,CAAC;AAEhV;;;;;;;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.8.0",
3
+ "version": "0.14.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",