@charcuterie/ui 2.4.1 → 2.6.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 (56) hide show
  1. package/dist/Checkbox/Checkbox.d.ts +68 -0
  2. package/dist/Checkbox/Checkbox.d.ts.map +1 -0
  3. package/dist/Checkbox/Checkbox.js +108 -0
  4. package/dist/Checkbox/Checkbox.js.map +1 -0
  5. package/dist/Field/Field.d.ts.map +1 -1
  6. package/dist/Field/Field.js +12 -1
  7. package/dist/Field/Field.js.map +1 -1
  8. package/dist/Menu/Menu.d.ts +60 -2
  9. package/dist/Menu/Menu.d.ts.map +1 -1
  10. package/dist/Menu/Menu.js +58 -11
  11. package/dist/Menu/Menu.js.map +1 -1
  12. package/dist/RadioGroup/RadioGroup.d.ts +54 -0
  13. package/dist/RadioGroup/RadioGroup.d.ts.map +1 -0
  14. package/dist/RadioGroup/RadioGroup.js +121 -0
  15. package/dist/RadioGroup/RadioGroup.js.map +1 -0
  16. package/dist/RadioGroup/RadioGroupOption.d.ts +27 -0
  17. package/dist/RadioGroup/RadioGroupOption.d.ts.map +1 -0
  18. package/dist/RadioGroup/RadioGroupOption.js +75 -0
  19. package/dist/RadioGroup/RadioGroupOption.js.map +1 -0
  20. package/dist/Switch/Switch.d.ts +60 -0
  21. package/dist/Switch/Switch.d.ts.map +1 -0
  22. package/dist/Switch/Switch.js +106 -0
  23. package/dist/Switch/Switch.js.map +1 -0
  24. package/dist/index.d.ts +6 -0
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +3 -0
  27. package/dist/index.js.map +1 -1
  28. package/dist/slotWiring.d.ts +9 -7
  29. package/dist/slotWiring.d.ts.map +1 -1
  30. package/dist/slotWiring.js +10 -70
  31. package/dist/slotWiring.js.map +1 -1
  32. package/package.json +2 -2
  33. package/src/Checkbox/Checkbox.mdx +71 -0
  34. package/src/Checkbox/Checkbox.stories.tsx +122 -0
  35. package/src/Checkbox/Checkbox.test.tsx +109 -0
  36. package/src/Checkbox/Checkbox.tsx +205 -0
  37. package/src/Combobox/Combobox.stories.tsx +19 -4
  38. package/src/Field/Field.stories.tsx +19 -0
  39. package/src/Field/Field.test.tsx +30 -2
  40. package/src/Field/Field.tsx +13 -1
  41. package/src/Menu/Menu.stories.tsx +80 -2
  42. package/src/Menu/Menu.test.tsx +102 -0
  43. package/src/Menu/Menu.tsx +156 -17
  44. package/src/RadioGroup/RadioGroup.mdx +67 -0
  45. package/src/RadioGroup/RadioGroup.stories.tsx +140 -0
  46. package/src/RadioGroup/RadioGroup.test.tsx +232 -0
  47. package/src/RadioGroup/RadioGroup.tsx +223 -0
  48. package/src/RadioGroup/RadioGroupOption.tsx +148 -0
  49. package/src/Switch/Switch.mdx +55 -0
  50. package/src/Switch/Switch.stories.tsx +116 -0
  51. package/src/Switch/Switch.test.tsx +115 -0
  52. package/src/Switch/Switch.tsx +183 -0
  53. package/src/index.ts +9 -0
  54. package/src/slotWiring.ts +15 -107
  55. package/src/sourceRules.test.ts +11 -1
  56. package/src/tailwindCandidates.test.ts +9 -7
@@ -0,0 +1,68 @@
1
+ import type { ControlSize } from "@charcuterie/tokens";
2
+ import type { ReactNode } from "react";
3
+ export type CheckboxProps = {
4
+ className?: string;
5
+ /**
6
+ * The caller's own id, when it has one — a stable target for an
7
+ * autofill hint or a deep link. Left to React's `useId` on the
8
+ * `<input>` otherwise, which is enough for the wrapping `<label>`.
9
+ */
10
+ id?: string;
11
+ /**
12
+ * **Initial** only. The `<input>` is the store from then on — the
13
+ * DOM owns a checkbox's checkedness, and a controlled `checked`
14
+ * prop is the thing this library refuses to have
15
+ * (`SegmentedControl` says the same about `selectedValue`).
16
+ */
17
+ isChecked?: boolean;
18
+ isDisabled?: boolean;
19
+ /**
20
+ * Shows the value at full contrast but refuses to change it — a
21
+ * setting you may read here and edit elsewhere. Distinct from
22
+ * `isDisabled`, which dims: a read-only box is not turned down,
23
+ * because the whole point is that you can still read it. Announced
24
+ * as `aria-readonly`, and the toggle is blocked on both pointer and
25
+ * `Space`.
26
+ */
27
+ isReadOnly?: boolean;
28
+ /**
29
+ * The visible text beside the box, and the checkbox's accessible
30
+ * name — the `<label>` wraps the control, so there is no `for` to
31
+ * get wrong. A box with no label is a control a screen reader
32
+ * cannot announce, which is why this is required.
33
+ */
34
+ label: ReactNode;
35
+ onChange?: (isChecked: boolean) => void;
36
+ size?: ControlSize;
37
+ };
38
+ /**
39
+ * A single boolean, on or off, that owns nothing but itself.
40
+ *
41
+ * This is the primitive mux-magic's `BooleanField` hand-rolled in
42
+ * `bg-slate-700 accent-blue-500` because the library had no checkbox
43
+ * to reach for — palette colours with no light mode, the exact M6
44
+ * defect the token layer exists to delete. Here the box is
45
+ * `bg-surface-sunken` and the fill is `bg-intent-accent-solid`, so
46
+ * one control reads correctly in `daylight`, `midnight`, and on the
47
+ * kiosk with no per-app override.
48
+ *
49
+ * ### The `<label>` wraps the control
50
+ *
51
+ * A checkbox reads to the *left* of its text, which is why it is not
52
+ * a `Field` — `Field` stacks label above control in a `flex-col`,
53
+ * right for a text input and wrong for a boolean, and stacking every
54
+ * checkbox in a step card would double the card's height. Wrapping is
55
+ * also the one label association that needs no `for` at all, so there
56
+ * is no minted-then-dropped id to get wrong.
57
+ *
58
+ * ### The `<input>` is the store
59
+ *
60
+ * `defaultChecked`, not `checked`. The DOM owns a checkbox's state
61
+ * natively, so there is no second copy to keep in step and no
62
+ * controlled-prop round-trip — `onChange` reports the new state to a
63
+ * consumer that wants to persist it, and reading it back is the
64
+ * `<input>`'s job. `isChecked` seeds the first paint and nothing
65
+ * after.
66
+ */
67
+ export declare const Checkbox: ({ className, id, isChecked, isDisabled, isReadOnly, label, onChange, size, }: CheckboxProps) => ReactNode;
68
+ //# sourceMappingURL=Checkbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Checkbox.d.ts","sourceRoot":"","sources":["../../src/Checkbox/Checkbox.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,KAAK,EAAe,SAAS,EAAE,MAAM,OAAO,CAAA;AAKnD,MAAM,MAAM,aAAa,GAAG;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,EAAE,CAAC,EAAE,MAAM,CAAA;IACX;;;;;OAKG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;;;;OAOG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;;OAKG;IACH,KAAK,EAAE,SAAS,CAAA;IAChB,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAA;IACvC,IAAI,CAAC,EAAE,WAAW,CAAA;CACnB,CAAA;AAoBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,QAAQ,GAAI,8EAStB,aAAa,KAAG,SA0GlB,CAAA"}
@@ -0,0 +1,108 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { FOCUS_RING_CLASS } from "../intentStyles.js";
3
+ import { toClassName } from "../toClassName.js";
4
+ const BOX_SIZE_CLASS = {
5
+ sm: "size-3.5",
6
+ md: "size-4",
7
+ lg: "size-5",
8
+ };
9
+ const CHECK_SIZE_CLASS = {
10
+ sm: "size-2.5",
11
+ md: "size-3",
12
+ lg: "size-3.5",
13
+ };
14
+ const TEXT_SIZE_CLASS = {
15
+ sm: "text-sm",
16
+ md: "text-md",
17
+ lg: "text-lg",
18
+ };
19
+ /**
20
+ * A single boolean, on or off, that owns nothing but itself.
21
+ *
22
+ * This is the primitive mux-magic's `BooleanField` hand-rolled in
23
+ * `bg-slate-700 accent-blue-500` because the library had no checkbox
24
+ * to reach for — palette colours with no light mode, the exact M6
25
+ * defect the token layer exists to delete. Here the box is
26
+ * `bg-surface-sunken` and the fill is `bg-intent-accent-solid`, so
27
+ * one control reads correctly in `daylight`, `midnight`, and on the
28
+ * kiosk with no per-app override.
29
+ *
30
+ * ### The `<label>` wraps the control
31
+ *
32
+ * A checkbox reads to the *left* of its text, which is why it is not
33
+ * a `Field` — `Field` stacks label above control in a `flex-col`,
34
+ * right for a text input and wrong for a boolean, and stacking every
35
+ * checkbox in a step card would double the card's height. Wrapping is
36
+ * also the one label association that needs no `for` at all, so there
37
+ * is no minted-then-dropped id to get wrong.
38
+ *
39
+ * ### The `<input>` is the store
40
+ *
41
+ * `defaultChecked`, not `checked`. The DOM owns a checkbox's state
42
+ * natively, so there is no second copy to keep in step and no
43
+ * controlled-prop round-trip — `onChange` reports the new state to a
44
+ * consumer that wants to persist it, and reading it back is the
45
+ * `<input>`'s job. `isChecked` seeds the first paint and nothing
46
+ * after.
47
+ */
48
+ export const Checkbox = ({ className, id, isChecked = false, isDisabled = false, isReadOnly = false, label, onChange, size = "md", }) => (_jsxs("label", { className: toClassName("inline-flex items-center gap-2 text-content-secondary select-none", TEXT_SIZE_CLASS[size],
49
+ // One cursor, chosen by state — two cursor utilities of the same
50
+ // specificity do not resolve by class-list order.
51
+ isDisabled
52
+ ? "cursor-not-allowed"
53
+ : isReadOnly
54
+ ? "cursor-default"
55
+ : "cursor-pointer",
56
+ // Disabled dims the whole control with opacity rather than fading
57
+ // the box to a quieter token. The token scale has no step between
58
+ // `border-default` and `border-strong`, so a muted outline was
59
+ // either invisible or indistinguishable from enabled; `opacity-60`
60
+ // keeps the full shape and colour and just turns them down, which
61
+ // is the "present but inactive" the box actually is. Read-only is
62
+ // *not* dimmed — its whole point is that the value stays readable.
63
+ // The same treatment is on `Switch` and `RadioGroup`.
64
+ isDisabled && "opacity-60", className), children: [_jsxs("span", { className: "relative grid shrink-0 place-items-center", children: [_jsx("input", { "aria-readonly": isReadOnly || undefined, className: toClassName(
65
+ // `border-2` is the family's shared weight — the `Switch`
66
+ // track's `ring-2` and the `RadioGroup` ring match it, so the
67
+ // three read as one set — and a 2px edge is also what keeps a
68
+ // disabled box visible where a 1px one washed out.
69
+ "peer appearance-none rounded-sm border-2 bg-surface-sunken transition-colors duration-(--duration-fast) ease-standard",
70
+ // Read-only wears the **neutral** intent, not the accent: full
71
+ // contrast (so the value reads) but plainly not an actionable
72
+ // accent control, with a softer `border-default` resting edge.
73
+ // Three distinct states result — enabled (accent, crisp),
74
+ // disabled (accent, dimmed by the wrapper), read-only (neutral).
75
+ // No `disabled:` colour override; the wrapper's `opacity-60`
76
+ // does the dimming, and doubling it on the box is what made a
77
+ // disabled checkbox vanish.
78
+ isReadOnly
79
+ ? "border-border-default checked:border-intent-neutral-solid checked:bg-intent-neutral-solid"
80
+ : "border-border-strong checked:border-intent-accent-solid checked:bg-intent-accent-solid", isDisabled
81
+ ? "cursor-not-allowed"
82
+ : isReadOnly
83
+ ? "cursor-default"
84
+ : "cursor-pointer", BOX_SIZE_CLASS[size], FOCUS_RING_CLASS), defaultChecked: isChecked, disabled: isDisabled, id: id, onChange: (event) => {
85
+ if (isReadOnly) {
86
+ return;
87
+ }
88
+ onChange?.(event.target.checked);
89
+ }, onClick: (clickEvent) => {
90
+ // Native checkboxes have no `readonly`, so the toggle is
91
+ // blocked here — `preventDefault` on the click stops the
92
+ // checked flip a pointer would make.
93
+ if (isReadOnly) {
94
+ clickEvent.preventDefault();
95
+ }
96
+ }, onKeyDown: (keyEvent) => {
97
+ // …and Space, the keyboard toggle a click block does not
98
+ // cover.
99
+ if (isReadOnly && keyEvent.key === " ") {
100
+ keyEvent.preventDefault();
101
+ }
102
+ }, type: "checkbox" }), _jsx("svg", { "aria-hidden": "true", className: toClassName("pointer-events-none invisible absolute peer-checked:visible",
103
+ // Matches whichever fill the box wears, so the tick keeps its
104
+ // guaranteed on-solid contrast in either intent.
105
+ isReadOnly
106
+ ? "text-intent-neutral-on-solid"
107
+ : "text-intent-accent-on-solid", CHECK_SIZE_CLASS[size]), fill: "none", stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 3, viewBox: "0 0 24 24", children: _jsx("path", { d: "M20 6 9 17l-5-5" }) })] }), _jsx("span", { children: label })] }));
108
+ //# sourceMappingURL=Checkbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Checkbox.js","sourceRoot":"","sources":["../../src/Checkbox/Checkbox.tsx"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Field.d.ts","sourceRoot":"","sources":["../../src/Field/Field.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAIhD,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG;IACnC;;;;;OAKG;IACH,QAAQ,EAAE,YAAY,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;OAGG;IACH,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,KAAK,EAAE,SAAS,CAAA;CACjB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2EG;AACH,eAAO,MAAM,KAAK,GAAI,sFAQnB,UAAU,KAAG,SA4Ff,CAAA"}
1
+ {"version":3,"file":"Field.d.ts","sourceRoot":"","sources":["../../src/Field/Field.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAIhD,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG;IACnC;;;;;OAKG;IACH,QAAQ,EAAE,YAAY,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;OAGG;IACH,WAAW,CAAC,EAAE,SAAS,CAAA;IACvB;;;;;OAKG;IACH,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,KAAK,EAAE,SAAS,CAAA;CACjB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2EG;AACH,eAAO,MAAM,KAAK,GAAI,sFAQnB,UAAU,KAAG,SAwGf,CAAA"}
@@ -86,8 +86,19 @@ export const Field = ({ children, className, description, error, isRequired = fa
86
86
  * link, a server-rendered error summary linking to the control.
87
87
  * `useUniqueId` is still called: hooks are unconditional, and it
88
88
  * costs one counter read.
89
+ *
90
+ * Precedence is `Field` prop → **the child's own `id`** →
91
+ * generated. The child's is read because a control written as
92
+ * `<input id="rename-pattern" />` puts the id where the author can
93
+ * see it, not on the `Field`; overwriting it with a minted
94
+ * `-control` id used to break exactly the outside-in references the
95
+ * `Field` prop exists to keep — a deep link, an autofill hint, a
96
+ * consumer's own selector. The `Field` prop still wins when both
97
+ * are set: it is the outer, later declaration, and last-writer-wins
98
+ * is the slot's rule for a value.
89
99
  */
90
- const controlId = receivedSlotProps.id ?? `${baseId}-control`;
100
+ const childId = children.props.id;
101
+ const controlId = receivedSlotProps.id ?? childId ?? `${baseId}-control`;
91
102
  const descriptionId = `${baseId}-description`;
92
103
  const errorId = `${baseId}-error`;
93
104
  const describedBy = [
@@ -1 +1 @@
1
- {"version":3,"file":"Field.js","sourceRoot":"","sources":["../../src/Field/Field.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,cAAc,EACd,WAAW,GACZ,MAAM,oBAAoB,CAAA;AAI3B,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AA2B/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2EG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,EACpB,QAAQ,EACR,SAAS,EACT,WAAW,EACX,KAAK,EACL,UAAU,GAAG,KAAK,EAClB,KAAK,EACL,GAAG,iBAAiB,EACT,EAAa,EAAE;IAC1B,MAAM,MAAM,GAAG,WAAW,EAAE,CAAA;IAE5B;;;;;;OAMG;IACH,MAAM,SAAS,GACb,iBAAiB,CAAC,EAAE,IAAI,GAAG,MAAM,UAAU,CAAA;IAE7C,MAAM,aAAa,GAAG,GAAG,MAAM,cAAc,CAAA;IAE7C,MAAM,OAAO,GAAG,GAAG,MAAM,QAAQ,CAAA;IAEjC,MAAM,WAAW,GAAG;QAClB,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa;QAChD,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO;KACrC;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAA;IAEZ,MAAM,aAAa,GAAG,cAAc,CAClC,QAAQ,EACR,cAAc,CAAC,iBAAiB,EAAE;QAChC,kBAAkB,EAChB,WAAW,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW;QAC9C,6DAA6D;QAC7D,+DAA+D;QAC/D,iDAAiD;QACjD,cAAc,EACZ,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI;QACxC,sDAAsD;QACtD,8DAA8D;QAC9D,8DAA8D;QAC9D,gDAAgD;QAChD,eAAe,EAAE,UAAU,IAAI,SAAS;QACxC,EAAE,EAAE,SAAS;QACb,QAAQ,EAAE,UAAU,IAAI,SAAS;KAClC,CAAC,CACH,CAAA;IAED,OAAO,CACL,eACE,SAAS,EAAE,WAAW,CACpB,uBAAuB,EACvB,SAAS,CACV,aAED,iBACE,SAAS,EAAC,0CAA0C,EACpD,OAAO,EAAE,SAAS,aAEjB,KAAK,EAEL,UAAU,CAAC,CAAC,CAAC,CACZ,8BAKc,MAAM,EAClB,SAAS,EAAC,iCAAiC,kBAGtC,CACR,CAAC,CAAC,CAAC,IAAI,IACF,EAEP,aAAa,EAEb,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAClC,YACE,SAAS,EAAC,gCAAgC,EAC1C,EAAE,EAAE,aAAa,YAEhB,WAAW,GACV,CACL,EAEA,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAC5B,YACE,SAAS,EAAC,oCAAoC,EAC9C,EAAE,EAAE,OAAO,YAEV,KAAK,GACJ,CACL,IACG,CACP,CAAA;AACH,CAAC,CAAA"}
1
+ {"version":3,"file":"Field.js","sourceRoot":"","sources":["../../src/Field/Field.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,cAAc,EACd,WAAW,GACZ,MAAM,oBAAoB,CAAA;AAI3B,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AA2B/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2EG;AACH,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,EACpB,QAAQ,EACR,SAAS,EACT,WAAW,EACX,KAAK,EACL,UAAU,GAAG,KAAK,EAClB,KAAK,EACL,GAAG,iBAAiB,EACT,EAAa,EAAE;IAC1B,MAAM,MAAM,GAAG,WAAW,EAAE,CAAA;IAE5B;;;;;;;;;;;;;;;;OAgBG;IACH,MAAM,OAAO,GAAI,QAAQ,CAAC,KAAyB,CAAC,EAAE,CAAA;IAEtD,MAAM,SAAS,GACb,iBAAiB,CAAC,EAAE,IAAI,OAAO,IAAI,GAAG,MAAM,UAAU,CAAA;IAExD,MAAM,aAAa,GAAG,GAAG,MAAM,cAAc,CAAA;IAE7C,MAAM,OAAO,GAAG,GAAG,MAAM,QAAQ,CAAA;IAEjC,MAAM,WAAW,GAAG;QAClB,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa;QAChD,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO;KACrC;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAA;IAEZ,MAAM,aAAa,GAAG,cAAc,CAClC,QAAQ,EACR,cAAc,CAAC,iBAAiB,EAAE;QAChC,kBAAkB,EAChB,WAAW,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW;QAC9C,6DAA6D;QAC7D,+DAA+D;QAC/D,iDAAiD;QACjD,cAAc,EACZ,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI;QACxC,sDAAsD;QACtD,8DAA8D;QAC9D,8DAA8D;QAC9D,gDAAgD;QAChD,eAAe,EAAE,UAAU,IAAI,SAAS;QACxC,EAAE,EAAE,SAAS;QACb,QAAQ,EAAE,UAAU,IAAI,SAAS;KAClC,CAAC,CACH,CAAA;IAED,OAAO,CACL,eACE,SAAS,EAAE,WAAW,CACpB,uBAAuB,EACvB,SAAS,CACV,aAED,iBACE,SAAS,EAAC,0CAA0C,EACpD,OAAO,EAAE,SAAS,aAEjB,KAAK,EAEL,UAAU,CAAC,CAAC,CAAC,CACZ,8BAKc,MAAM,EAClB,SAAS,EAAC,iCAAiC,kBAGtC,CACR,CAAC,CAAC,CAAC,IAAI,IACF,EAEP,aAAa,EAEb,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAClC,YACE,SAAS,EAAC,gCAAgC,EAC1C,EAAE,EAAE,aAAa,YAEhB,WAAW,GACV,CACL,EAEA,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAC5B,YACE,SAAS,EAAC,oCAAoC,EAC9C,EAAE,EAAE,OAAO,YAEV,KAAK,GACJ,CACL,IACG,CACP,CAAA;AACH,CAAC,CAAA"}
@@ -6,11 +6,53 @@ export type MenuItem = {
6
6
  key: string;
7
7
  label: ReactNode;
8
8
  onSelect: () => void;
9
+ /**
10
+ * The default kind, and optional so the common `{ key, label,
11
+ * onSelect }` still type-checks. Present only to discriminate this
12
+ * from a `separator` or a `group`.
13
+ */
14
+ type?: "item";
9
15
  };
16
+ /**
17
+ * A rule between groups of items — `role="separator"`, and nothing a
18
+ * keyboard user lands on. It never registers with the roving group,
19
+ * so the arrow keys pass straight over it, the same mechanism a
20
+ * disabled item uses.
21
+ */
22
+ export type MenuSeparator = {
23
+ key: string;
24
+ type: "separator";
25
+ };
26
+ /**
27
+ * A named set of items — `role="group"` with the `label` as its
28
+ * accessible name (a screen reader announces "Danger, group" before
29
+ * its members). The heading itself is not focusable; only the items
30
+ * inside it register.
31
+ */
32
+ export type MenuGroup = {
33
+ items: MenuItem[];
34
+ key: string;
35
+ label: ReactNode;
36
+ type: "group";
37
+ };
38
+ /**
39
+ * What a menu is made of. A bare `MenuItem` is still valid on its
40
+ * own, so existing `items` arrays need no change; a `separator` or a
41
+ * `group` opts in by its `type`.
42
+ */
43
+ export type MenuEntry = MenuGroup | MenuItem | MenuSeparator;
10
44
  export type MenuProps = {
11
45
  className?: string;
46
+ /**
47
+ * Shown when there is no item to show — a `group` with no members
48
+ * and a bare separator list both count as empty. Rendered as a
49
+ * **disabled** `menuitem` (a `role="menu"` must own one), so it is
50
+ * announced but never focused. Without it an empty menu renders
51
+ * nothing.
52
+ */
53
+ emptyState?: ReactNode;
12
54
  isVisible: boolean;
13
- items: MenuItem[];
55
+ items: MenuEntry[];
14
56
  /** Outside press, Escape, and choosing an item all land here. */
15
57
  onDismiss: () => void;
16
58
  placement?: Placement;
@@ -69,6 +111,22 @@ export type MenuProps = {
69
111
  * focus is whichever one `RovingFocus` says is active, and that is
70
112
  * not known until the items have registered.
71
113
  *
114
+ * ### Separators, groups, and an empty state
115
+ *
116
+ * `items` is a union, not a flat `MenuItem[]`: a `separator`
117
+ * (`role="separator"`) and a `group` (`role="group"`, named by its
118
+ * `label`) opt in by their `type`, and a bare item still type-checks
119
+ * unchanged. The keyboard model needs no new code for them — a
120
+ * separator and a group heading register nothing, so the roving
121
+ * group never sees them and the arrow keys skip straight over, the
122
+ * same mechanism a disabled item already used. A `group`'s items
123
+ * register normally, so focus moves through them in DOM order as if
124
+ * the heading were not there. When there is nothing to show, the
125
+ * `emptyState` renders as a **disabled** `menuitem` — a `role="menu"`
126
+ * with no `menuitem` child fails `aria-required-children`, so the
127
+ * note has to be one, `aria-disabled` and out of the roving group:
128
+ * announced as "No actions available, dimmed", focusable by nothing.
129
+ *
72
130
  * ### No type-ahead, deliberately
73
131
  *
74
132
  * The APG lists type-ahead as optional for a menu and required for a
@@ -77,5 +135,5 @@ export type MenuProps = {
77
135
  * buffer and a timer in a component that currently has neither, for
78
136
  * a menu you can cross in three arrow presses.
79
137
  */
80
- export declare const Menu: ({ className, isVisible, items, onDismiss, placement, trigger, }: MenuProps) => ReactNode;
138
+ export declare const Menu: ({ className, emptyState, isVisible, items, onDismiss, placement, trigger, }: MenuProps) => ReactNode;
81
139
  //# sourceMappingURL=Menu.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Menu.d.ts","sourceRoot":"","sources":["../../src/Menu/Menu.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAKnD,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAQpD,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,SAAS,CAAA;IAChB,QAAQ,EAAE,MAAM,IAAI,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,SAAS,GAAG;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,OAAO,CAAA;IAClB,KAAK,EAAE,QAAQ,EAAE,CAAA;IACjB,iEAAiE;IACjE,SAAS,EAAE,MAAM,IAAI,CAAA;IACrB,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,+DAA+D;IAC/D,OAAO,EAAE,YAAY,CAAA;CACtB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2DG;AACH,eAAO,MAAM,IAAI,GAAI,iEAOlB,SAAS,KAAG,SAuId,CAAA"}
1
+ {"version":3,"file":"Menu.d.ts","sourceRoot":"","sources":["../../src/Menu/Menu.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAKnD,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAQpD,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,SAAS,CAAA;IAChB,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,WAAW,CAAA;CAClB,CAAA;AAED;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,QAAQ,EAAE,CAAA;IACjB,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,SAAS,CAAA;IAChB,IAAI,EAAE,OAAO,CAAA;CACd,CAAA;AAED;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,aAAa,CAAA;AAE5D,MAAM,MAAM,SAAS,GAAG;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,SAAS,CAAA;IACtB,SAAS,EAAE,OAAO,CAAA;IAClB,KAAK,EAAE,SAAS,EAAE,CAAA;IAClB,iEAAiE;IACjE,SAAS,EAAE,MAAM,IAAI,CAAA;IACrB,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,+DAA+D;IAC/D,OAAO,EAAE,YAAY,CAAA;CACtB,CAAA;AAYD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2EG;AACH,eAAO,MAAM,IAAI,GAAI,6EAQlB,SAAS,KAAG,SAyMd,CAAA"}
package/dist/Menu/Menu.js CHANGED
@@ -1,11 +1,14 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { selectTabIndex, useRovingFocus, } from "@charcuterie/logic";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { selectTabIndex, useRovingFocus, useUniqueId, } from "@charcuterie/logic";
3
3
  import { FloatingFocusManager, FloatingPortal, } from "@floating-ui/react";
4
4
  import { useEffect, useRef } from "react";
5
5
  import { PANEL_SURFACE_CLASS } from "../Overlay/overlayPanelClass.js";
6
6
  import { useAnchoredOverlay } from "../Overlay/useAnchoredOverlay.js";
7
7
  import { toClassName } from "../toClassName.js";
8
8
  import { MenuAction } from "./MenuAction.js";
9
+ const isMenuItem = (entry) => entry.type === undefined || entry.type === "item";
10
+ const hasAnyItem = (items) => items.some((entry) => isMenuItem(entry) ||
11
+ (entry.type === "group" && entry.items.length > 0));
9
12
  /**
10
13
  * A menu is **not** a listbox, and mux-magic's `TypePicker` is the
11
14
  * fleet's one attempt at telling them apart — it renders
@@ -58,6 +61,22 @@ import { MenuAction } from "./MenuAction.js";
58
61
  * focus is whichever one `RovingFocus` says is active, and that is
59
62
  * not known until the items have registered.
60
63
  *
64
+ * ### Separators, groups, and an empty state
65
+ *
66
+ * `items` is a union, not a flat `MenuItem[]`: a `separator`
67
+ * (`role="separator"`) and a `group` (`role="group"`, named by its
68
+ * `label`) opt in by their `type`, and a bare item still type-checks
69
+ * unchanged. The keyboard model needs no new code for them — a
70
+ * separator and a group heading register nothing, so the roving
71
+ * group never sees them and the arrow keys skip straight over, the
72
+ * same mechanism a disabled item already used. A `group`'s items
73
+ * register normally, so focus moves through them in DOM order as if
74
+ * the heading were not there. When there is nothing to show, the
75
+ * `emptyState` renders as a **disabled** `menuitem` — a `role="menu"`
76
+ * with no `menuitem` child fails `aria-required-children`, so the
77
+ * note has to be one, `aria-disabled` and out of the roving group:
78
+ * announced as "No actions available, dimmed", focusable by nothing.
79
+ *
61
80
  * ### No type-ahead, deliberately
62
81
  *
63
82
  * The APG lists type-ahead as optional for a menu and required for a
@@ -66,7 +85,8 @@ import { MenuAction } from "./MenuAction.js";
66
85
  * buffer and a timer in a component that currently has neither, for
67
86
  * a menu you can cross in three arrow presses.
68
87
  */
69
- export const Menu = ({ className, isVisible, items, onDismiss, placement = "bottom-start", trigger, }) => {
88
+ export const Menu = ({ className, emptyState, isVisible, items, onDismiss, placement = "bottom-start", trigger, }) => {
89
+ const menuId = useUniqueId();
70
90
  const itemElements = useRef(new Map());
71
91
  const focus = useRovingFocus();
72
92
  const { activeValue, registeredValues, setActiveValue } = focus;
@@ -107,6 +127,38 @@ export const Menu = ({ className, isVisible, items, onDismiss, placement = "bott
107
127
  }
108
128
  itemElements.current.get(activeValue)?.focus();
109
129
  }, [activeValue, isVisible]);
130
+ // One member of the roving group, whether it sits at the top level
131
+ // or inside a `group`. The registration lives in `MenuAction`'s
132
+ // effect, so an item nested in a group joins the same arrow-key
133
+ // sequence in DOM order — the heading above it registers nothing.
134
+ const renderItem = (item) => (_jsx(MenuAction, { item: item, onDismiss: onDismiss, register: focus.register, tabIndex: selectTabIndex(focus, item.key), trackElement: (key, element) => {
135
+ if (element) {
136
+ itemElements.current.set(key, element);
137
+ }
138
+ else {
139
+ itemElements.current.delete(key);
140
+ }
141
+ } }, item.key));
142
+ const renderEntry = (entry) => {
143
+ if (entry.type === "separator") {
144
+ // A native `<hr>` — implicit `role="separator"`, and the one
145
+ // that does *not* need `aria-valuenow` (that is the focusable
146
+ // splitter kind, not a static rule between menu groups).
147
+ return (_jsx("hr", { className: "-mx-1 my-1 h-px border-0 bg-border-subtle" }, entry.key));
148
+ }
149
+ if (entry.type === "group") {
150
+ const headingId = `${menuId}-${entry.key}`;
151
+ return (_jsxs("div", { "aria-labelledby": headingId, role: "group", children: [_jsx("div", { className: "px-2 pt-1.5 pb-0.5 font-medium text-content-secondary text-xs", id: headingId, children: entry.label }), entry.items.map(renderItem)] }, entry.key));
152
+ }
153
+ return renderItem(entry);
154
+ };
155
+ // A **disabled** `menuitem`, not inert text: a `role="menu"` with
156
+ // no `menuitem` child fails `aria-required-children`, so the empty
157
+ // note has to be one — `aria-disabled` and `tabindex="-1"`, so it
158
+ // is announced ("No actions available, dimmed") but takes no tab
159
+ // stop and never joins the roving group. `null` when the consumer
160
+ // gave no `emptyState`, so an empty menu renders nothing.
161
+ const emptyElement = emptyState === undefined ? null : (_jsx("div", { "aria-disabled": "true", className: "px-2 py-1.5 text-content-disabled text-sm", role: "menuitem", tabIndex: -1, children: emptyState }));
110
162
  return (_jsxs(_Fragment, { children: [clonedTrigger, isVisible ? (_jsx(FloatingPortal, { children: _jsx(FloatingFocusManager, { context: context,
111
163
  // `false`, so Tab leaves the menu and lands on the next
112
164
  // control in the page — which is what closes it, through
@@ -137,13 +189,8 @@ export const Menu = ({ className, isVisible, items, onDismiss, placement = "bott
137
189
  // "menu" })` in the hook is where it comes from. Stated
138
190
  // here because a linter cannot see a role through a
139
191
  // spread.
140
- role: "menu", style: floatingStyles, children: items.map((item) => (_jsx(MenuAction, { item: item, onDismiss: onDismiss, register: focus.register, tabIndex: selectTabIndex(focus, item.key), trackElement: (key, element) => {
141
- if (element) {
142
- itemElements.current.set(key, element);
143
- }
144
- else {
145
- itemElements.current.delete(key);
146
- }
147
- } }, item.key))) }) }) })) : null] }));
192
+ role: "menu", style: floatingStyles, children: hasAnyItem(items)
193
+ ? items.map(renderEntry)
194
+ : emptyElement }) }) })) : null] }));
148
195
  };
149
196
  //# sourceMappingURL=Menu.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Menu.js","sourceRoot":"","sources":["../../src/Menu/Menu.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Menu.js","sourceRoot":"","sources":["../../src/Menu/Menu.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ import type { ControlSize } from "@charcuterie/tokens";
2
+ import type { ReactNode } from "react";
3
+ export type RadioItem = {
4
+ /**
5
+ * A disabled option is simply **not registered** with the roving
6
+ * group, so the arrow keys skip it without any command in
7
+ * `RovingFocus` having to know what "disabled" means. It stays
8
+ * registered with the picker: it is still one of the options.
9
+ */
10
+ isDisabled?: boolean;
11
+ label: ReactNode;
12
+ value: string;
13
+ };
14
+ export type RadioGroupProps = {
15
+ className?: string;
16
+ items: readonly RadioItem[];
17
+ /**
18
+ * Shows which option is chosen at full contrast but refuses to move
19
+ * the choice — the arrow keys and clicks no longer select, and the
20
+ * group announces `aria-readonly`. Focus can still travel the
21
+ * options so a keyboard user can read them.
22
+ */
23
+ isReadOnly?: boolean;
24
+ /** The group's accessible name. Required. */
25
+ label: string;
26
+ onChange?: (selectedValue: string | null) => void;
27
+ /** **Initial** only. Charcuterie owns it from then on. */
28
+ selectedValue?: string;
29
+ size?: ControlSize;
30
+ };
31
+ /**
32
+ * One choice out of many, each on its own row with a label the size
33
+ * of prose — the stacked sibling of `SegmentedControl`.
34
+ *
35
+ * The two are the *same* composition — `SinglePicker` + `RovingFocus`,
36
+ * a `radiogroup` of `radio`s where selection follows focus — and a
37
+ * different shape. `SegmentedControl` is a compact strip for a
38
+ * handful of short options that share a control row; `RadioGroup` is
39
+ * the form-length list where each option carries a real sentence and
40
+ * an in-line strip would wrap. Picking between them is layout, not
41
+ * behaviour, which is why the keyboard model here is identical and
42
+ * lives in the same two hooks.
43
+ *
44
+ * ### `radiogroup`, not a stack of checkboxes
45
+ *
46
+ * A column of `<input type="checkbox">` is the **independent
47
+ * toggles** pattern: nothing says the options are mutually
48
+ * exclusive, and a screen reader never announces "1 of 4". A single
49
+ * choice from a named set is a radio group, and its arrow keys both
50
+ * move focus and check — APG's one activation mode, the same reason
51
+ * `SegmentedControl` has no `manual` prop.
52
+ */
53
+ export declare const RadioGroup: ({ className, items, isReadOnly, label, onChange, selectedValue, size, }: RadioGroupProps) => ReactNode;
54
+ //# sourceMappingURL=RadioGroup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RadioGroup.d.ts","sourceRoot":"","sources":["../../src/RadioGroup/RadioGroup.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAMtC,MAAM,MAAM,SAAS,GAAG;IACtB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,KAAK,EAAE,SAAS,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,SAAS,SAAS,EAAE,CAAA;IAC3B;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,6CAA6C;IAC7C,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAA;IACjD,0DAA0D;IAC1D,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,IAAI,CAAC,EAAE,WAAW,CAAA;CACnB,CAAA;AAQD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,UAAU,GAAI,yEAQxB,eAAe,KAAG,SAgJpB,CAAA"}
@@ -0,0 +1,121 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { selectTabIndex, useRovingFocus, useSinglePicker, } from "@charcuterie/logic";
3
+ import { useCallback, useEffect, useRef } from "react";
4
+ import { toClassName } from "../toClassName.js";
5
+ import { RadioGroupOption } from "./RadioGroupOption.js";
6
+ const GAP_CLASS = {
7
+ sm: "gap-1",
8
+ md: "gap-1.5",
9
+ lg: "gap-2",
10
+ };
11
+ /**
12
+ * One choice out of many, each on its own row with a label the size
13
+ * of prose — the stacked sibling of `SegmentedControl`.
14
+ *
15
+ * The two are the *same* composition — `SinglePicker` + `RovingFocus`,
16
+ * a `radiogroup` of `radio`s where selection follows focus — and a
17
+ * different shape. `SegmentedControl` is a compact strip for a
18
+ * handful of short options that share a control row; `RadioGroup` is
19
+ * the form-length list where each option carries a real sentence and
20
+ * an in-line strip would wrap. Picking between them is layout, not
21
+ * behaviour, which is why the keyboard model here is identical and
22
+ * lives in the same two hooks.
23
+ *
24
+ * ### `radiogroup`, not a stack of checkboxes
25
+ *
26
+ * A column of `<input type="checkbox">` is the **independent
27
+ * toggles** pattern: nothing says the options are mutually
28
+ * exclusive, and a screen reader never announces "1 of 4". A single
29
+ * choice from a named set is a radio group, and its arrow keys both
30
+ * move focus and check — APG's one activation mode, the same reason
31
+ * `SegmentedControl` has no `manual` prop.
32
+ */
33
+ export const RadioGroup = ({ className, items, isReadOnly = false, label, onChange, selectedValue, size = "md", }) => {
34
+ const groupRef = useRef(null);
35
+ const optionElements = useRef(new Map());
36
+ const initialValue = selectedValue ??
37
+ items.find((one) => !one.isDisabled)?.value ??
38
+ null;
39
+ const selection = useSinglePicker({
40
+ onChange,
41
+ selectedValue: initialValue,
42
+ });
43
+ const focus = useRovingFocus({
44
+ activeValue: initialValue,
45
+ });
46
+ const { select } = selection;
47
+ const { activeValue, setActiveValue } = focus;
48
+ /**
49
+ * Selected **or** pending. Members register from an effect, so on
50
+ * the first paint `selectedValue` is still null and the intent
51
+ * lives in `pendingValue` — reading only the former renders a
52
+ * group with nothing checked, then corrects itself a frame later.
53
+ */
54
+ const checkedValue = selection.selectedValue ?? selection.pendingValue;
55
+ const chooseOption = useCallback((value) => {
56
+ // Focus may still land on the option so it can be read; only the
57
+ // choice is frozen when read-only.
58
+ setActiveValue(value);
59
+ if (!isReadOnly) {
60
+ select(value);
61
+ }
62
+ }, [isReadOnly, select, setActiveValue]);
63
+ useEffect(() => {
64
+ // Selection follows focus — the radio-group rule, and the one
65
+ // line a `manual` mode this component deliberately lacks would
66
+ // remove. Read-only severs exactly this link: focus still travels
67
+ // for reading, but moving it no longer moves the choice.
68
+ if (activeValue !== null && !isReadOnly) {
69
+ select(activeValue);
70
+ }
71
+ }, [activeValue, isReadOnly, select]);
72
+ useEffect(() => {
73
+ const group = groupRef.current;
74
+ if (!group ||
75
+ activeValue === null ||
76
+ !group.contains(document.activeElement)) {
77
+ return;
78
+ }
79
+ optionElements.current.get(activeValue)?.focus();
80
+ }, [activeValue]);
81
+ return (_jsx("div", { "aria-label": label, "aria-readonly": isReadOnly || undefined, className: toClassName("flex flex-col", GAP_CLASS[size], className), onKeyDown: (keyEvent) => {
82
+ const commands = {
83
+ ArrowDown: focus.next,
84
+ ArrowLeft: focus.previous,
85
+ ArrowRight: focus.next,
86
+ ArrowUp: focus.previous,
87
+ End: focus.last,
88
+ Home: focus.first,
89
+ };
90
+ const command = commands[keyEvent.key];
91
+ if (command) {
92
+ // Arrow keys scroll the page by default, and a control
93
+ // that scrolls the window while it moves focus is the
94
+ // hand-rolled version of this component.
95
+ keyEvent.preventDefault();
96
+ command();
97
+ return;
98
+ }
99
+ // Space checks the focused option. Selection already follows
100
+ // focus, so this is almost always a no-op — one idempotent
101
+ // command, not a second code path — and read-only skips it.
102
+ if (keyEvent.key === " " &&
103
+ activeValue !== null &&
104
+ !isReadOnly) {
105
+ keyEvent.preventDefault();
106
+ select(activeValue);
107
+ }
108
+ }, ref: groupRef, role: "radiogroup", children: items.map((item) => (_jsx(RadioGroupOption, { isChecked: checkedValue === item.value, isReadOnly: isReadOnly, item: item, onChoose: chooseOption, registerFocus: focus.register, registerSelection: selection.register, size: size,
109
+ // The roving-tabindex rule read from the core rather than
110
+ // restated here: exactly one option is in the tab order, so
111
+ // Tab enters and leaves the group once.
112
+ tabIndex: selectTabIndex(focus, item.value), trackElement: (value, element) => {
113
+ if (element) {
114
+ optionElements.current.set(value, element);
115
+ }
116
+ else {
117
+ optionElements.current.delete(value);
118
+ }
119
+ } }, item.value))) }));
120
+ };
121
+ //# sourceMappingURL=RadioGroup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RadioGroup.js","sourceRoot":"","sources":["../../src/RadioGroup/RadioGroup.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,cAAc,EACd,cAAc,EACd,eAAe,GAChB,MAAM,oBAAoB,CAAA;AAG3B,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAEtD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAwB,CAAA;AAgCzD,MAAM,SAAS,GAAgC;IAC7C,EAAE,EAAE,OAAO;IACX,EAAE,EAAE,SAAS;IACb,EAAE,EAAE,OAAO;CACZ,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,EACzB,SAAS,EACT,KAAK,EACL,UAAU,GAAG,KAAK,EAClB,KAAK,EACL,QAAQ,EACR,aAAa,EACb,IAAI,GAAG,IAAI,GACK,EAAa,EAAE;IAC/B,MAAM,QAAQ,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAA;IAE7C,MAAM,cAAc,GAAG,MAAM,CAC3B,IAAI,GAAG,EAA6B,CACrC,CAAA;IAED,MAAM,YAAY,GAChB,aAAa;QACb,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,KAAK;QAC3C,IAAI,CAAA;IAEN,MAAM,SAAS,GAAG,eAAe,CAAS;QACxC,QAAQ;QACR,aAAa,EAAE,YAAY;KAC5B,CAAC,CAAA;IAEF,MAAM,KAAK,GAAG,cAAc,CAAS;QACnC,WAAW,EAAE,YAAY;KAC1B,CAAC,CAAA;IAEF,MAAM,EAAE,MAAM,EAAE,GAAG,SAAS,CAAA;IAE5B,MAAM,EAAE,WAAW,EAAE,cAAc,EAAE,GAAG,KAAK,CAAA;IAE7C;;;;;OAKG;IACH,MAAM,YAAY,GAChB,SAAS,CAAC,aAAa,IAAI,SAAS,CAAC,YAAY,CAAA;IAEnD,MAAM,YAAY,GAAG,WAAW,CAC9B,CAAC,KAAa,EAAE,EAAE;QAChB,iEAAiE;QACjE,mCAAmC;QACnC,cAAc,CAAC,KAAK,CAAC,CAAA;QAErB,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,CAAC,KAAK,CAAC,CAAA;QACf,CAAC;IACH,CAAC,EACD,CAAC,UAAU,EAAE,MAAM,EAAE,cAAc,CAAC,CACrC,CAAA;IAED,SAAS,CAAC,GAAG,EAAE;QACb,8DAA8D;QAC9D,+DAA+D;QAC/D,kEAAkE;QAClE,yDAAyD;QACzD,IAAI,WAAW,KAAK,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACxC,MAAM,CAAC,WAAW,CAAC,CAAA;QACrB,CAAC;IACH,CAAC,EAAE,CAAC,WAAW,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC,CAAA;IAErC,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAA;QAE9B,IACE,CAAC,KAAK;YACN,WAAW,KAAK,IAAI;YACpB,CAAC,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC,EACvC,CAAC;YACD,OAAM;QACR,CAAC;QAED,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,KAAK,EAAE,CAAA;IAClD,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAA;IAEjB,OAAO,CACL,4BACc,KAAK,mBACF,UAAU,IAAI,SAAS,EACtC,SAAS,EAAE,WAAW,CACpB,eAAe,EACf,SAAS,CAAC,IAAI,CAAC,EACf,SAAS,CACV,EACD,SAAS,EAAE,CAAC,QAAQ,EAAE,EAAE;YACtB,MAAM,QAAQ,GAA+B;gBAC3C,SAAS,EAAE,KAAK,CAAC,IAAI;gBACrB,SAAS,EAAE,KAAK,CAAC,QAAQ;gBACzB,UAAU,EAAE,KAAK,CAAC,IAAI;gBACtB,OAAO,EAAE,KAAK,CAAC,QAAQ;gBACvB,GAAG,EAAE,KAAK,CAAC,IAAI;gBACf,IAAI,EAAE,KAAK,CAAC,KAAK;aAClB,CAAA;YAED,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAA;YAEtC,IAAI,OAAO,EAAE,CAAC;gBACZ,uDAAuD;gBACvD,sDAAsD;gBACtD,yCAAyC;gBACzC,QAAQ,CAAC,cAAc,EAAE,CAAA;gBAEzB,OAAO,EAAE,CAAA;gBAET,OAAM;YACR,CAAC;YAED,6DAA6D;YAC7D,2DAA2D;YAC3D,4DAA4D;YAC5D,IACE,QAAQ,CAAC,GAAG,KAAK,GAAG;gBACpB,WAAW,KAAK,IAAI;gBACpB,CAAC,UAAU,EACX,CAAC;gBACD,QAAQ,CAAC,cAAc,EAAE,CAAA;gBAEzB,MAAM,CAAC,WAAW,CAAC,CAAA;YACrB,CAAC;QACH,CAAC,EACD,GAAG,EAAE,QAAQ,EACb,IAAI,EAAC,YAAY,YAEhB,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACnB,KAAC,gBAAgB,IACf,SAAS,EAAE,YAAY,KAAK,IAAI,CAAC,KAAK,EACtC,UAAU,EAAE,UAAU,EACtB,IAAI,EAAE,IAAI,EAEV,QAAQ,EAAE,YAAY,EACtB,aAAa,EAAE,KAAK,CAAC,QAAQ,EAC7B,iBAAiB,EAAE,SAAS,CAAC,QAAQ,EACrC,IAAI,EAAE,IAAI;YACV,0DAA0D;YAC1D,4DAA4D;YAC5D,wCAAwC;YACxC,QAAQ,EAAE,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,EAC3C,YAAY,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;gBAC/B,IAAI,OAAO,EAAE,CAAC;oBACZ,cAAc,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;gBAC5C,CAAC;qBAAM,CAAC;oBACN,cAAc,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;gBACtC,CAAC;YACH,CAAC,IAfI,IAAI,CAAC,KAAK,CAgBf,CACH,CAAC,GACE,CACP,CAAA;AACH,CAAC,CAAA"}