@charcuterie/ui 0.1.1 → 0.2.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 (105) hide show
  1. package/README.md +9 -0
  2. package/dist/Accordion/Accordion.d.ts +82 -0
  3. package/dist/Accordion/Accordion.d.ts.map +1 -0
  4. package/dist/Accordion/Accordion.js +108 -0
  5. package/dist/Accordion/Accordion.js.map +1 -0
  6. package/dist/Accordion/AccordionSection.d.ts +28 -0
  7. package/dist/Accordion/AccordionSection.d.ts.map +1 -0
  8. package/dist/Accordion/AccordionSection.js +53 -0
  9. package/dist/Accordion/AccordionSection.js.map +1 -0
  10. package/dist/Field/Field.d.ts +69 -0
  11. package/dist/Field/Field.d.ts.map +1 -0
  12. package/dist/Field/Field.js +73 -0
  13. package/dist/Field/Field.js.map +1 -0
  14. package/dist/FileDropZone/FileDropZone.d.ts +63 -0
  15. package/dist/FileDropZone/FileDropZone.d.ts.map +1 -0
  16. package/dist/FileDropZone/FileDropZone.js +122 -0
  17. package/dist/FileDropZone/FileDropZone.js.map +1 -0
  18. package/dist/LogViewer/LogViewer.d.ts +88 -0
  19. package/dist/LogViewer/LogViewer.d.ts.map +1 -0
  20. package/dist/LogViewer/LogViewer.js +104 -0
  21. package/dist/LogViewer/LogViewer.js.map +1 -0
  22. package/dist/Menu/Menu.d.ts +81 -0
  23. package/dist/Menu/Menu.d.ts.map +1 -0
  24. package/dist/Menu/Menu.js +199 -0
  25. package/dist/Menu/Menu.js.map +1 -0
  26. package/dist/Menu/MenuAction.d.ts +24 -0
  27. package/dist/Menu/MenuAction.d.ts.map +1 -0
  28. package/dist/Menu/MenuAction.js +37 -0
  29. package/dist/Menu/MenuAction.js.map +1 -0
  30. package/dist/Select/Select.d.ts +87 -0
  31. package/dist/Select/Select.d.ts.map +1 -0
  32. package/dist/Select/Select.js +51 -0
  33. package/dist/Select/Select.js.map +1 -0
  34. package/dist/SortableTableHeader/SortableTableHeader.d.ts +61 -0
  35. package/dist/SortableTableHeader/SortableTableHeader.d.ts.map +1 -0
  36. package/dist/SortableTableHeader/SortableTableHeader.js +56 -0
  37. package/dist/SortableTableHeader/SortableTableHeader.js.map +1 -0
  38. package/dist/Toast/Toast.d.ts +54 -0
  39. package/dist/Toast/Toast.d.ts.map +1 -0
  40. package/dist/Toast/Toast.js +121 -0
  41. package/dist/Toast/Toast.js.map +1 -0
  42. package/dist/Toast/ToastRegion.d.ts +57 -0
  43. package/dist/Toast/ToastRegion.d.ts.map +1 -0
  44. package/dist/Toast/ToastRegion.js +41 -0
  45. package/dist/Toast/ToastRegion.js.map +1 -0
  46. package/dist/Toast/toastLifecycle.d.ts +34 -0
  47. package/dist/Toast/toastLifecycle.d.ts.map +1 -0
  48. package/dist/Toast/toastLifecycle.js +25 -0
  49. package/dist/Toast/toastLifecycle.js.map +1 -0
  50. package/dist/Tooltip/Tooltip.d.ts +68 -0
  51. package/dist/Tooltip/Tooltip.d.ts.map +1 -0
  52. package/dist/Tooltip/Tooltip.js +104 -0
  53. package/dist/Tooltip/Tooltip.js.map +1 -0
  54. package/dist/index.d.ts +22 -0
  55. package/dist/index.d.ts.map +1 -1
  56. package/dist/index.js +11 -0
  57. package/dist/index.js.map +1 -1
  58. package/dist/mountStory.testHelpers.d.ts +0 -11
  59. package/dist/mountStory.testHelpers.d.ts.map +1 -1
  60. package/dist/mountStory.testHelpers.js +27 -0
  61. package/dist/mountStory.testHelpers.js.map +1 -1
  62. package/package.json +1 -1
  63. package/src/Accordion/Accordion.mdx +83 -0
  64. package/src/Accordion/Accordion.stories.tsx +146 -0
  65. package/src/Accordion/Accordion.test.tsx +163 -0
  66. package/src/Accordion/Accordion.tsx +182 -0
  67. package/src/Accordion/AccordionSection.tsx +163 -0
  68. package/src/Field/Field.mdx +74 -0
  69. package/src/Field/Field.stories.tsx +144 -0
  70. package/src/Field/Field.test.tsx +142 -0
  71. package/src/Field/Field.tsx +163 -0
  72. package/src/FileDropZone/FileDropZone.mdx +78 -0
  73. package/src/FileDropZone/FileDropZone.stories.tsx +136 -0
  74. package/src/FileDropZone/FileDropZone.test.tsx +230 -0
  75. package/src/FileDropZone/FileDropZone.tsx +234 -0
  76. package/src/LogViewer/LogViewer.mdx +88 -0
  77. package/src/LogViewer/LogViewer.stories.tsx +135 -0
  78. package/src/LogViewer/LogViewer.test.tsx +173 -0
  79. package/src/LogViewer/LogViewer.tsx +195 -0
  80. package/src/Menu/Menu.mdx +103 -0
  81. package/src/Menu/Menu.stories.tsx +161 -0
  82. package/src/Menu/Menu.test.tsx +202 -0
  83. package/src/Menu/Menu.tsx +300 -0
  84. package/src/Menu/MenuAction.tsx +95 -0
  85. package/src/Select/Select.mdx +74 -0
  86. package/src/Select/Select.stories.tsx +126 -0
  87. package/src/Select/Select.test.tsx +129 -0
  88. package/src/Select/Select.tsx +200 -0
  89. package/src/SortableTableHeader/SortableTableHeader.mdx +67 -0
  90. package/src/SortableTableHeader/SortableTableHeader.stories.tsx +207 -0
  91. package/src/SortableTableHeader/SortableTableHeader.test.tsx +180 -0
  92. package/src/SortableTableHeader/SortableTableHeader.tsx +131 -0
  93. package/src/Toast/Toast.mdx +84 -0
  94. package/src/Toast/Toast.stories.tsx +192 -0
  95. package/src/Toast/Toast.test.tsx +217 -0
  96. package/src/Toast/Toast.tsx +224 -0
  97. package/src/Toast/ToastRegion.tsx +98 -0
  98. package/src/Toast/toastLifecycle.ts +45 -0
  99. package/src/Tooltip/Tooltip.mdx +69 -0
  100. package/src/Tooltip/Tooltip.stories.tsx +104 -0
  101. package/src/Tooltip/Tooltip.test.tsx +138 -0
  102. package/src/Tooltip/Tooltip.tsx +169 -0
  103. package/src/index.ts +43 -0
  104. package/src/mountStory.testHelpers.ts +30 -0
  105. package/src/sourceRules.test.ts +221 -30
@@ -0,0 +1,34 @@
1
+ import type { StatusTransitions } from "@charcuterie/logic";
2
+ /**
3
+ * The one machine the plan wrote down and M2 did not build:
4
+ *
5
+ * > | Toast lifecycle | entering → visible → exiting → removed |
6
+ *
7
+ * It is here rather than in `@charcuterie/logic/core` beside
8
+ * `asyncTransitions` and `connectionTransitions` on purpose. Those
9
+ * two describe *data* — a fetch, a socket — and a Preact app with no
10
+ * components at all still wants them. This one describes an
11
+ * **animation**, which only exists because something is being
12
+ * painted, so it belongs to the component layer.
13
+ */
14
+ export type ToastStatus = "entering" | "exiting" | "removed" | "visible";
15
+ /**
16
+ * `visible → removed` is deliberately **not** a legal transition,
17
+ * and neither is anything out of `removed`.
18
+ *
19
+ * The first means a toast cannot skip its exit — a dismissal that
20
+ * unmounts the node immediately is the flicker every hand-rolled
21
+ * toast stack has, and making it illegal turns that into a thrown
22
+ * error in a test rather than a jump nobody files.
23
+ *
24
+ * The second makes `removed` terminal, which is what lets the region
25
+ * call `onDismiss` exactly once. `createStatus` throws on an illegal
26
+ * transition, so a second timer firing after the first is a loud
27
+ * failure instead of a duplicate removal.
28
+ *
29
+ * `exiting → visible` **is** legal: pointing at a toast that is
30
+ * already sliding away has to bring it back, or the user is chasing
31
+ * a disappearing message with the cursor.
32
+ */
33
+ export declare const toastTransitions: StatusTransitions<ToastStatus>;
34
+ //# sourceMappingURL=toastLifecycle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toastLifecycle.d.ts","sourceRoot":"","sources":["../../src/Toast/toastLifecycle.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAE3D;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,WAAW,GACnB,UAAU,GACV,SAAS,GACT,SAAS,GACT,SAAS,CAAA;AAEb;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,gBAAgB,EAAE,iBAAiB,CAAC,WAAW,CAMzD,CAAA"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * `visible → removed` is deliberately **not** a legal transition,
3
+ * and neither is anything out of `removed`.
4
+ *
5
+ * The first means a toast cannot skip its exit — a dismissal that
6
+ * unmounts the node immediately is the flicker every hand-rolled
7
+ * toast stack has, and making it illegal turns that into a thrown
8
+ * error in a test rather than a jump nobody files.
9
+ *
10
+ * The second makes `removed` terminal, which is what lets the region
11
+ * call `onDismiss` exactly once. `createStatus` throws on an illegal
12
+ * transition, so a second timer firing after the first is a loud
13
+ * failure instead of a duplicate removal.
14
+ *
15
+ * `exiting → visible` **is** legal: pointing at a toast that is
16
+ * already sliding away has to bring it back, or the user is chasing
17
+ * a disappearing message with the cursor.
18
+ */
19
+ export const toastTransitions = {
20
+ entering: ["visible", "exiting"],
21
+ exiting: ["removed", "visible"],
22
+ removed: [],
23
+ visible: ["exiting"],
24
+ };
25
+ //# sourceMappingURL=toastLifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toastLifecycle.js","sourceRoot":"","sources":["../../src/Toast/toastLifecycle.ts"],"names":[],"mappings":"AAoBA;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAC3B;IACE,QAAQ,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;IAChC,OAAO,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC;IAC/B,OAAO,EAAE,EAAE;IACX,OAAO,EAAE,CAAC,SAAS,CAAC;CACrB,CAAA"}
@@ -0,0 +1,68 @@
1
+ import type { Placement } from "@floating-ui/react";
2
+ import type { ReactElement, ReactNode } from "react";
3
+ export type TooltipProps = {
4
+ /**
5
+ * The control the tip describes. **Cloned, not wrapped** — the
6
+ * same slot contract as `Popover`'s trigger.
7
+ *
8
+ * It has to be something focusable. A tooltip on a `<span>` is
9
+ * pointer-only, which is the state mux-magic's is in today.
10
+ */
11
+ children: ReactElement;
12
+ className?: string;
13
+ /** Milliseconds of hover before it opens. */
14
+ delay?: number;
15
+ /**
16
+ * Text, and text only. `role="tooltip"` has no way to move focus
17
+ * into itself, so a link or a button inside one is unreachable by
18
+ * keyboard and unreadable by touch — if it needs a control, it is
19
+ * a `Popover`.
20
+ */
21
+ label: string;
22
+ placement?: Placement;
23
+ };
24
+ /**
25
+ * Replaces mux-magic's `FieldTooltip`, which is 130 lines of
26
+ * hand-rolled positioning — a `computePosition` that reimplements
27
+ * `flip` and `shift` against `window.innerHeight` — and has three
28
+ * defects that all render perfectly:
29
+ *
30
+ * 1. **Nothing references the tip.** It sets `role="tooltip"` and
31
+ * no `aria-describedby` anywhere, so the control it belongs to
32
+ * never mentions it. A screen reader reads the button, says
33
+ * nothing about the tip, and the tip itself is a floating node
34
+ * nobody is pointed at. `role="tooltip"` is not a live region;
35
+ * it does nothing on its own.
36
+ * 2. **Pointer only.** `onPointerEnter`/`onPointerLeave` with no
37
+ * `onFocus`/`onBlur`, so a keyboard user cannot open it at all.
38
+ * 3. **No dismiss.** Escape does nothing, which WCAG 1.4.13
39
+ * requires of any content shown on hover.
40
+ *
41
+ * All three come from the same place: the ARIA is written by hand
42
+ * beside the behaviour instead of falling out of it. Here `useRole`
43
+ * writes `aria-describedby` on the trigger and `role` + `id` on the
44
+ * tip from one source, `useFocus` is what makes it keyboard-openable,
45
+ * and `useDismiss` is Escape.
46
+ *
47
+ * ### Not a `title`, and not a substitute for a name
48
+ *
49
+ * A `title` attribute is unstyleable, has a ~1s delay nobody can
50
+ * change, and does not exist on touch. `Badge` still uses one — for
51
+ * a *truncation* readout, where the full text is already in
52
+ * `textContent` and the tip is a convenience
53
+ * ([decision](../../../docs/decisions/2026-07-30-a-badge-truncates-with-text-overflow.md)).
54
+ * That is the line: a `title` may repeat something already
55
+ * available, and a `Tooltip` may add something, but **neither may be
56
+ * the only place a control's name exists**. An icon button still
57
+ * needs its `aria-label`; the tip is extra.
58
+ *
59
+ * ### Touch has no hover, and this component does not pretend
60
+ *
61
+ * There is no long-press fallback here. A tooltip is supplementary
62
+ * by construction, so on the kiosk it simply never appears, and
63
+ * anything a touch user *must* read belongs in a `Field`'s
64
+ * `description` instead. Building a long-press would make the tip
65
+ * load-bearing on exactly the surface where it is least reliable.
66
+ */
67
+ export declare const Tooltip: ({ children, className, delay, label, placement, }: TooltipProps) => ReactNode;
68
+ //# sourceMappingURL=Tooltip.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Tooltip.d.ts","sourceRoot":"","sources":["../../src/Tooltip/Tooltip.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAanD,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAIpD,MAAM,MAAM,YAAY,GAAG;IACzB;;;;;;OAMG;IACH,QAAQ,EAAE,YAAY,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;;OAKG;IACH,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,SAAS,CAAA;CACtB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,eAAO,MAAM,OAAO,GAAI,mDAMrB,YAAY,KAAG,SA4EjB,CAAA"}
@@ -0,0 +1,104 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useClonedChild, useVisibility, } from "@charcuterie/logic";
3
+ import { autoUpdate, flip, offset, shift, useDismiss, useFloating, useFocus, useHover, useInteractions, useRole, } from "@floating-ui/react";
4
+ import { toClassName } from "../toClassName.js";
5
+ /**
6
+ * Replaces mux-magic's `FieldTooltip`, which is 130 lines of
7
+ * hand-rolled positioning — a `computePosition` that reimplements
8
+ * `flip` and `shift` against `window.innerHeight` — and has three
9
+ * defects that all render perfectly:
10
+ *
11
+ * 1. **Nothing references the tip.** It sets `role="tooltip"` and
12
+ * no `aria-describedby` anywhere, so the control it belongs to
13
+ * never mentions it. A screen reader reads the button, says
14
+ * nothing about the tip, and the tip itself is a floating node
15
+ * nobody is pointed at. `role="tooltip"` is not a live region;
16
+ * it does nothing on its own.
17
+ * 2. **Pointer only.** `onPointerEnter`/`onPointerLeave` with no
18
+ * `onFocus`/`onBlur`, so a keyboard user cannot open it at all.
19
+ * 3. **No dismiss.** Escape does nothing, which WCAG 1.4.13
20
+ * requires of any content shown on hover.
21
+ *
22
+ * All three come from the same place: the ARIA is written by hand
23
+ * beside the behaviour instead of falling out of it. Here `useRole`
24
+ * writes `aria-describedby` on the trigger and `role` + `id` on the
25
+ * tip from one source, `useFocus` is what makes it keyboard-openable,
26
+ * and `useDismiss` is Escape.
27
+ *
28
+ * ### Not a `title`, and not a substitute for a name
29
+ *
30
+ * A `title` attribute is unstyleable, has a ~1s delay nobody can
31
+ * change, and does not exist on touch. `Badge` still uses one — for
32
+ * a *truncation* readout, where the full text is already in
33
+ * `textContent` and the tip is a convenience
34
+ * ([decision](../../../docs/decisions/2026-07-30-a-badge-truncates-with-text-overflow.md)).
35
+ * That is the line: a `title` may repeat something already
36
+ * available, and a `Tooltip` may add something, but **neither may be
37
+ * the only place a control's name exists**. An icon button still
38
+ * needs its `aria-label`; the tip is extra.
39
+ *
40
+ * ### Touch has no hover, and this component does not pretend
41
+ *
42
+ * There is no long-press fallback here. A tooltip is supplementary
43
+ * by construction, so on the kiosk it simply never appears, and
44
+ * anything a touch user *must* read belongs in a `Field`'s
45
+ * `description` instead. Building a long-press would make the tip
46
+ * load-bearing on exactly the surface where it is least reliable.
47
+ */
48
+ export const Tooltip = ({ children, className, delay = 200, label, placement = "top", }) => {
49
+ const { isVisible, setIsVisible } = useVisibility();
50
+ const { context, floatingStyles, refs } = useFloating({
51
+ // Read-only, as everywhere: floating-ui is told what is true and
52
+ // never decides it.
53
+ open: isVisible,
54
+ onOpenChange: setIsVisible,
55
+ placement,
56
+ middleware: [offset(6), flip(), shift({ padding: 8 })],
57
+ strategy: "fixed",
58
+ whileElementsMounted: autoUpdate,
59
+ });
60
+ const { getFloatingProps, getReferenceProps } = useInteractions([
61
+ useHover(context, {
62
+ // `move: false` — a tooltip that re-opens because the
63
+ // pointer twitched inside the trigger is the flicker every
64
+ // hand-rolled one has.
65
+ move: false,
66
+ restMs: delay,
67
+ }),
68
+ // The line mux-magic is missing. Without it the tip is
69
+ // pointer-only, which is a WCAG 2.1.1 failure on a control
70
+ // whose explanation lives there.
71
+ useFocus(context),
72
+ useDismiss(context, { referencePress: false }),
73
+ useRole(context, { role: "tooltip" }),
74
+ ]);
75
+ const clonedTrigger = useClonedChild(children, {
76
+ ...getReferenceProps(),
77
+ ref: refs.setReference,
78
+ });
79
+ return (_jsxs(_Fragment, { children: [clonedTrigger, isVisible ? (_jsx("div", { ...getFloatingProps(), className: toClassName(
80
+ // `intent-neutral-solid` + its own `on-solid`, rather
81
+ // than `surface-inverse` + `content-on-accent`. The
82
+ // second pair looks like the obvious one and is not a
83
+ // *pair* at all — nothing in the token set promises those
84
+ // two contrast, and in `daylight` dark they land at
85
+ // 2.9:1. The `solid`/`on-solid` roles exist precisely to
86
+ // be a guaranteed couple, and the contrast gate checks
87
+ // them as one.
88
+ "inset-auto m-0 max-w-xs rounded-md bg-intent-neutral-solid px-2 py-1 text-intent-neutral-on-solid text-xs shadow-medium", className),
89
+ // No `popover="manual"` and no `FloatingFocusManager`,
90
+ // unlike `Popover`. Both exist to manage focus, and focus
91
+ // never enters a tooltip — moving it here is what makes
92
+ // one unescapable. The trade is that a tooltip is not in
93
+ // the top layer, so it can be clipped by an
94
+ // `overflow: hidden` ancestor; `strategy: "fixed"` keeps
95
+ // that to ancestors that actually clip fixed descendants.
96
+ ref: refs.setFloating,
97
+ // Duplicated from `getFloatingProps()` deliberately, and
98
+ // the two cannot differ — `useRole(context, { role:
99
+ // "tooltip" })` above is where it comes from. Stated here
100
+ // because a linter cannot see a role through a spread, and
101
+ // neither can the next reader.
102
+ role: "tooltip", style: floatingStyles, children: label })) : null] }));
103
+ };
104
+ //# sourceMappingURL=Tooltip.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Tooltip.js","sourceRoot":"","sources":["../../src/Tooltip/Tooltip.tsx"],"names":[],"mappings":";AAAA,OAAO,EACL,cAAc,EACd,aAAa,GACd,MAAM,oBAAoB,CAAA;AAE3B,OAAO,EACL,UAAU,EACV,IAAI,EACJ,MAAM,EACN,KAAK,EACL,UAAU,EACV,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,eAAe,EACf,OAAO,GACR,MAAM,oBAAoB,CAAA;AAG3B,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAwB/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,EACtB,QAAQ,EACR,SAAS,EACT,KAAK,GAAG,GAAG,EACX,KAAK,EACL,SAAS,GAAG,KAAK,GACJ,EAAa,EAAE;IAC5B,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,aAAa,EAAE,CAAA;IAEnD,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,GAAG,WAAW,CAAC;QACpD,iEAAiE;QACjE,oBAAoB;QACpB,IAAI,EAAE,SAAS;QACf,YAAY,EAAE,YAAY;QAC1B,SAAS;QACT,UAAU,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC;QACtD,QAAQ,EAAE,OAAO;QACjB,oBAAoB,EAAE,UAAU;KACjC,CAAC,CAAA;IAEF,MAAM,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,GAC3C,eAAe,CAAC;QACd,QAAQ,CAAC,OAAO,EAAE;YAChB,sDAAsD;YACtD,2DAA2D;YAC3D,uBAAuB;YACvB,IAAI,EAAE,KAAK;YACX,MAAM,EAAE,KAAK;SACd,CAAC;QACF,uDAAuD;QACvD,2DAA2D;QAC3D,iCAAiC;QACjC,QAAQ,CAAC,OAAO,CAAC;QACjB,UAAU,CAAC,OAAO,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC;QAC9C,OAAO,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;KACtC,CAAC,CAAA;IAEJ,MAAM,aAAa,GAAG,cAAc,CAAC,QAAQ,EAAE;QAC7C,GAAG,iBAAiB,EAAE;QACtB,GAAG,EAAE,IAAI,CAAC,YAAY;KACvB,CAAC,CAAA;IAEF,OAAO,CACL,8BACG,aAAa,EAEb,SAAS,CAAC,CAAC,CAAC,CACX,iBACM,gBAAgB,EAAE,EACtB,SAAS,EAAE,WAAW;gBACpB,sDAAsD;gBACtD,oDAAoD;gBACpD,sDAAsD;gBACtD,0DAA0D;gBAC1D,oDAAoD;gBACpD,yDAAyD;gBACzD,uDAAuD;gBACvD,eAAe;gBACf,yHAAyH,EACzH,SAAS,CACV;gBACD,uDAAuD;gBACvD,0DAA0D;gBAC1D,wDAAwD;gBACxD,yDAAyD;gBACzD,4CAA4C;gBAC5C,yDAAyD;gBACzD,0DAA0D;gBAC1D,GAAG,EAAE,IAAI,CAAC,WAAW;gBACrB,yDAAyD;gBACzD,oDAAoD;gBACpD,0DAA0D;gBAC1D,2DAA2D;gBAC3D,+BAA+B;gBAC/B,IAAI,EAAC,SAAS,EACd,KAAK,EAAE,cAAc,YAEpB,KAAK,GACF,CACP,CAAC,CAAC,CAAC,IAAI,IACP,CACJ,CAAA;AACH,CAAC,CAAA"}
package/dist/index.d.ts CHANGED
@@ -30,6 +30,8 @@
30
30
  * `@charcuterie/tokens/theme.css` by its own name, which is what
31
31
  * this package's README has always told it to do.
32
32
  */
33
+ export type { AccordionHeadingLevel, AccordionItem, AccordionProps, } from "./Accordion/Accordion.tsx";
34
+ export { Accordion } from "./Accordion/Accordion.tsx";
33
35
  export type { AlertProps, AlertSize, } from "./Alert/Alert.tsx";
34
36
  export { Alert } from "./Alert/Alert.tsx";
35
37
  export type { BadgeProps } from "./Badge/Badge.tsx";
@@ -42,16 +44,24 @@ export type { BadgeSize } from "./controlStyles.ts";
42
44
  export { BADGE_SIZE_CLASS, CONTROL_SIZE_CLASS, DOT_SIZE_CLASS, ICON_CONTROL_SIZE_CLASS, MIN_TOUCH_TARGET_CLASS, SPINNER_SIZE_CLASS, } from "./controlStyles.ts";
43
45
  export type { EmptyStateProps, EmptyStateSize, } from "./EmptyState/EmptyState.tsx";
44
46
  export { EmptyState } from "./EmptyState/EmptyState.tsx";
47
+ export type { FieldProps } from "./Field/Field.tsx";
48
+ export { Field } from "./Field/Field.tsx";
49
+ export type { FileDropZoneProps } from "./FileDropZone/FileDropZone.tsx";
50
+ export { FileDropZone } from "./FileDropZone/FileDropZone.tsx";
45
51
  export type { IconButtonProps } from "./IconButton/IconButton.tsx";
46
52
  export { IconButton } from "./IconButton/IconButton.tsx";
47
53
  export type { IntentAppearance } from "./intentStyles.ts";
48
54
  export { DISABLED_CLASS, FOCUS_RING_CLASS, INTENT_APPEARANCE_CLASS, INTENT_CONTENT_CLASS, INTENT_HOVER_CLASS, INTENT_SOLID_FILL_CLASS, } from "./intentStyles.ts";
49
55
  export type { LiveStatusIndicatorProps, LiveStatusIndicatorSize, } from "./LiveStatusIndicator/LiveStatusIndicator.tsx";
50
56
  export { LiveStatusIndicator } from "./LiveStatusIndicator/LiveStatusIndicator.tsx";
57
+ export type { LogLine, LogViewerProps, } from "./LogViewer/LogViewer.tsx";
58
+ export { LogViewer } from "./LogViewer/LogViewer.tsx";
51
59
  export type { MediaTileProps, MediaTileRatio, } from "./MediaTile/MediaTile.tsx";
52
60
  export { MediaTile } from "./MediaTile/MediaTile.tsx";
53
61
  export type { MediaStatus } from "./MediaTile/mediaStatus.ts";
54
62
  export { mediaTransitions } from "./MediaTile/mediaStatus.ts";
63
+ export type { MenuItem, MenuProps, } from "./Menu/Menu.tsx";
64
+ export { Menu } from "./Menu/Menu.tsx";
55
65
  export type { ModalProps, ModalSize, } from "./Modal/Modal.tsx";
56
66
  export { Modal } from "./Modal/Modal.tsx";
57
67
  export type { PopoverProps } from "./Popover/Popover.tsx";
@@ -62,13 +72,25 @@ export type { ProgressThreshold } from "./ProgressBar/progressValue.ts";
62
72
  export { getProgressIntent, toProgressPercent, toProgressValue, } from "./ProgressBar/progressValue.ts";
63
73
  export type { SegmentedControlProps, SegmentedItem, } from "./SegmentedControl/SegmentedControl.tsx";
64
74
  export { SegmentedControl } from "./SegmentedControl/SegmentedControl.tsx";
75
+ export type { SelectItem, SelectOption, SelectOptionGroup, SelectProps, } from "./Select/Select.tsx";
76
+ export { Select } from "./Select/Select.tsx";
65
77
  export type { SkeletonProps, SkeletonShape, } from "./Skeleton/Skeleton.tsx";
66
78
  export { Skeleton } from "./Skeleton/Skeleton.tsx";
79
+ export type { SortableTableHeaderProps, SortDirection, } from "./SortableTableHeader/SortableTableHeader.tsx";
80
+ export { SortableTableHeader } from "./SortableTableHeader/SortableTableHeader.tsx";
67
81
  export type { SpinnerProps } from "./Spinner/Spinner.tsx";
68
82
  export { Spinner } from "./Spinner/Spinner.tsx";
69
83
  export { getAsyncIntent, getAsyncLabel, getConnectionIntent, getConnectionLabel, getIsConnectionBusy, } from "./statusIntent.ts";
70
84
  export type { TabItem, TabsActivation, TabsOrientation, TabsProps, } from "./Tabs/Tabs.tsx";
71
85
  export { Tabs } from "./Tabs/Tabs.tsx";
86
+ export type { ToastProps } from "./Toast/Toast.tsx";
87
+ export { Toast } from "./Toast/Toast.tsx";
88
+ export type { ToastRecord, ToastRegionProps, } from "./Toast/ToastRegion.tsx";
89
+ export { ToastRegion } from "./Toast/ToastRegion.tsx";
90
+ export type { ToastStatus } from "./Toast/toastLifecycle.ts";
91
+ export { toastTransitions } from "./Toast/toastLifecycle.ts";
92
+ export type { TooltipProps } from "./Tooltip/Tooltip.tsx";
93
+ export { Tooltip } from "./Tooltip/Tooltip.tsx";
72
94
  export { toClassName } from "./toClassName.ts";
73
95
  export type { VisuallyHiddenProps } from "./VisuallyHidden/VisuallyHidden.tsx";
74
96
  export { VisuallyHidden } from "./VisuallyHidden/VisuallyHidden.tsx";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -30,26 +30,37 @@
30
30
  * `@charcuterie/tokens/theme.css` by its own name, which is what
31
31
  * this package's README has always told it to do.
32
32
  */
33
+ export { Accordion } from "./Accordion/Accordion.js";
33
34
  export { Alert } from "./Alert/Alert.js";
34
35
  export { Badge } from "./Badge/Badge.js";
35
36
  export { Button } from "./Button/Button.js";
36
37
  export { Card } from "./Card/Card.js";
37
38
  export { BADGE_SIZE_CLASS, CONTROL_SIZE_CLASS, DOT_SIZE_CLASS, ICON_CONTROL_SIZE_CLASS, MIN_TOUCH_TARGET_CLASS, SPINNER_SIZE_CLASS, } from "./controlStyles.js";
38
39
  export { EmptyState } from "./EmptyState/EmptyState.js";
40
+ export { Field } from "./Field/Field.js";
41
+ export { FileDropZone } from "./FileDropZone/FileDropZone.js";
39
42
  export { IconButton } from "./IconButton/IconButton.js";
40
43
  export { DISABLED_CLASS, FOCUS_RING_CLASS, INTENT_APPEARANCE_CLASS, INTENT_CONTENT_CLASS, INTENT_HOVER_CLASS, INTENT_SOLID_FILL_CLASS, } from "./intentStyles.js";
41
44
  export { LiveStatusIndicator } from "./LiveStatusIndicator/LiveStatusIndicator.js";
45
+ export { LogViewer } from "./LogViewer/LogViewer.js";
42
46
  export { MediaTile } from "./MediaTile/MediaTile.js";
43
47
  export { mediaTransitions } from "./MediaTile/mediaStatus.js";
48
+ export { Menu } from "./Menu/Menu.js";
44
49
  export { Modal } from "./Modal/Modal.js";
45
50
  export { Popover } from "./Popover/Popover.js";
46
51
  export { ProgressBar } from "./ProgressBar/ProgressBar.js";
47
52
  export { getProgressIntent, toProgressPercent, toProgressValue, } from "./ProgressBar/progressValue.js";
48
53
  export { SegmentedControl } from "./SegmentedControl/SegmentedControl.js";
54
+ export { Select } from "./Select/Select.js";
49
55
  export { Skeleton } from "./Skeleton/Skeleton.js";
56
+ export { SortableTableHeader } from "./SortableTableHeader/SortableTableHeader.js";
50
57
  export { Spinner } from "./Spinner/Spinner.js";
51
58
  export { getAsyncIntent, getAsyncLabel, getConnectionIntent, getConnectionLabel, getIsConnectionBusy, } from "./statusIntent.js";
52
59
  export { Tabs } from "./Tabs/Tabs.js";
60
+ export { Toast } from "./Toast/Toast.js";
61
+ export { ToastRegion } from "./Toast/ToastRegion.js";
62
+ export { toastTransitions } from "./Toast/toastLifecycle.js";
63
+ export { Tooltip } from "./Tooltip/Tooltip.js";
53
64
  export { toClassName } from "./toClassName.js";
54
65
  export { VisuallyHidden } from "./VisuallyHidden/VisuallyHidden.js";
55
66
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAMH,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAmB,CAAA;AAEzC,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAmB,CAAA;AAEzC,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAqB,CAAA;AAM5C,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAiB,CAAA;AAEtC,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,EACd,uBAAuB,EACvB,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,oBAAoB,CAAA;AAK3B,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA6B,CAAA;AAExD,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA6B,CAAA;AAExD,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,uBAAuB,EACvB,oBAAoB,EACpB,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,mBAAmB,CAAA;AAK1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,8CAA+C,CAAA;AAKnF,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA2B,CAAA;AAErD,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAA;AAK7D,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAmB,CAAA;AAEzC,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAuB,CAAA;AAK/C,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA+B,CAAA;AAE3D,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,GAChB,MAAM,gCAAgC,CAAA;AAKvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,wCAAyC,CAAA;AAK1E,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAyB,CAAA;AAElD,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAuB,CAAA;AAC/C,OAAO,EACL,cAAc,EACd,aAAa,EACb,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,mBAAmB,CAAA;AAO1B,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAiB,CAAA;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAE9C,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAqC,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAOH,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA2B,CAAA;AAKrD,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAmB,CAAA;AAEzC,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAmB,CAAA;AAEzC,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAqB,CAAA;AAM5C,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAiB,CAAA;AAEtC,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,EACd,uBAAuB,EACvB,sBAAsB,EACtB,kBAAkB,GACnB,MAAM,oBAAoB,CAAA;AAK3B,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA6B,CAAA;AAExD,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAmB,CAAA;AAEzC,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAiC,CAAA;AAE9D,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA6B,CAAA;AAExD,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,uBAAuB,EACvB,oBAAoB,EACpB,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,mBAAmB,CAAA;AAK1B,OAAO,EAAE,mBAAmB,EAAE,MAAM,8CAA+C,CAAA;AAKnF,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA2B,CAAA;AAKrD,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA2B,CAAA;AAErD,OAAO,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAA;AAK7D,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAiB,CAAA;AAKtC,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAmB,CAAA;AAEzC,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAuB,CAAA;AAK/C,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA+B,CAAA;AAE3D,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,GAChB,MAAM,gCAAgC,CAAA;AAKvC,OAAO,EAAE,gBAAgB,EAAE,MAAM,wCAAyC,CAAA;AAO1E,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAqB,CAAA;AAK5C,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAyB,CAAA;AAKlD,OAAO,EAAE,mBAAmB,EAAE,MAAM,8CAA+C,CAAA;AAEnF,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAuB,CAAA;AAC/C,OAAO,EACL,cAAc,EACd,aAAa,EACb,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,GACpB,MAAM,mBAAmB,CAAA;AAO1B,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAiB,CAAA;AAEtC,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAmB,CAAA;AAKzC,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAyB,CAAA;AAErD,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAE5D,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAuB,CAAA;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAE9C,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAqC,CAAA"}
@@ -11,17 +11,6 @@ type MountableStory = {
11
11
  canvasElement: HTMLElement;
12
12
  }) => Promise<void>;
13
13
  };
14
- /**
15
- * Mount a composed story into a fresh canvas and hand back the same
16
- * two things a `play` function used to receive.
17
- *
18
- * `run()` — rather than rendering the component directly — is what
19
- * keeps these tests honest after the story/test split: the subject
20
- * is the story a reader sees, with its args, its decorators, and its
21
- * loaders, not a second assembly of the same component that can
22
- * drift from it. It is also what triggers the a11y addon's
23
- * `afterEach`, so every mount here is an axe run.
24
- */
25
14
  export declare const mountStory: (story: MountableStory) => Promise<{
26
15
  canvas: Canvas;
27
16
  canvasElement: HTMLElement;
@@ -1 +1 @@
1
- {"version":3,"file":"mountStory.testHelpers.d.ts","sourceRoot":"","sources":["../src/mountStory.testHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAEvC,KAAK,MAAM,GAAG,UAAU,CAAC,OAAO,MAAM,CAAC,CAAA;AAEvC;;;;;GAKG;AACH,KAAK,cAAc,GAAG;IACpB,GAAG,EAAE,CAAC,OAAO,EAAE;QACb,aAAa,EAAE,WAAW,CAAA;KAC3B,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACpB,CAAA;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,GACrB,OAAO,cAAc,KACpB,OAAO,CAAC;IACT,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,WAAW,CAAA;CAC3B,CAQA,CAAA"}
1
+ {"version":3,"file":"mountStory.testHelpers.d.ts","sourceRoot":"","sources":["../src/mountStory.testHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAEvC,KAAK,MAAM,GAAG,UAAU,CAAC,OAAO,MAAM,CAAC,CAAA;AAEvC;;;;;GAKG;AACH,KAAK,cAAc,GAAG;IACpB,GAAG,EAAE,CAAC,OAAO,EAAE;QACb,aAAa,EAAE,WAAW,CAAA;KAC3B,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACpB,CAAA;AAqCD,eAAO,MAAM,UAAU,GACrB,OAAO,cAAc,KACpB,OAAO,CAAC;IACT,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,WAAW,CAAA;CAC3B,CAcA,CAAA"}
@@ -10,9 +10,36 @@ import { within } from "storybook/test";
10
10
  * drift from it. It is also what triggers the a11y addon's
11
11
  * `afterEach`, so every mount here is an axe run.
12
12
  */
13
+ /**
14
+ * Every canvas this helper has created, so the next mount can take
15
+ * the previous ones out of the document.
16
+ *
17
+ * They used to accumulate — one detached-but-attached `<div>` per
18
+ * test, for the whole file — and nothing noticed for three
19
+ * milestones, because every component up to M6 lays out **in
20
+ * flow**: a stale copy sits harmlessly below the live one and every
21
+ * query is scoped to its own canvas anyway.
22
+ *
23
+ * `ToastRegion` is the first `position: fixed` component in the
24
+ * library, and it broke that immediately. A previous test's toast
25
+ * stack is pinned to the same corner of the viewport as the live
26
+ * one, so `userEvent.click` — which clicks by **coordinates** —
27
+ * drove the wrong element while every query still returned the
28
+ * right one. The test failed with "the toast did not go away", one
29
+ * test after the toast it was actually clicking.
30
+ *
31
+ * The stale tree is removed rather than unmounted because portable
32
+ * stories expose no unmount. Detaching is enough: it takes the node
33
+ * out of the layout, which is the entire problem.
34
+ */
35
+ const mountedCanvases = [];
13
36
  export const mountStory = async (story) => {
37
+ for (const previous of mountedCanvases.splice(0)) {
38
+ previous.remove();
39
+ }
14
40
  const canvasElement = document.createElement("div");
15
41
  document.body.append(canvasElement);
42
+ mountedCanvases.push(canvasElement);
16
43
  await story.run({ canvasElement });
17
44
  return { canvas: within(canvasElement), canvasElement };
18
45
  };
@@ -1 +1 @@
1
- {"version":3,"file":"mountStory.testHelpers.js","sourceRoot":"","sources":["../src/mountStory.testHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAgBvC;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,EAC7B,KAAqB,EAIpB,EAAE;IACH,MAAM,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;IAEnD,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAA;IAEnC,MAAM,KAAK,CAAC,GAAG,CAAC,EAAE,aAAa,EAAE,CAAC,CAAA;IAElC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,aAAa,CAAC,EAAE,aAAa,EAAE,CAAA;AACzD,CAAC,CAAA"}
1
+ {"version":3,"file":"mountStory.testHelpers.js","sourceRoot":"","sources":["../src/mountStory.testHelpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAgBvC;;;;;;;;;;GAUG;AACH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,eAAe,GAAkB,EAAE,CAAA;AAEzC,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,EAC7B,KAAqB,EAIpB,EAAE;IACH,KAAK,MAAM,QAAQ,IAAI,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;QACjD,QAAQ,CAAC,MAAM,EAAE,CAAA;IACnB,CAAC;IAED,MAAM,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;IAEnD,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAA;IAEnC,eAAe,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;IAEnC,MAAM,KAAK,CAAC,GAAG,CAAC,EAAE,aAAa,EAAE,CAAC,CAAA;IAElC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,aAAa,CAAC,EAAE,aAAa,EAAE,CAAA;AACzD,CAAC,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@charcuterie/ui",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "The Charcuterie components. Tokens for look, @charcuterie/logic for state, ARIA that agents can actually drive.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -0,0 +1,83 @@
1
+ import { Canvas, Controls, Meta } from "@storybook/addon-docs/blocks";
2
+
3
+ import * as AccordionStories from "./Accordion.stories";
4
+
5
+ <Meta of={AccordionStories} />
6
+
7
+ # Accordion
8
+
9
+ Eleven sites in the fleet. The plan called it "nearly free once `Tabs` exists" — it is, the
10
+ exclusive mode is `VisibilityGroup` and nothing else — but the saving is not why it ships.
11
+
12
+ <Canvas of={AccordionStories.Default} />
13
+
14
+ ## Props
15
+
16
+ <Controls />
17
+
18
+ ## The two-owners bug, live, in the app this milestone migrates
19
+
20
+ mux-magic's `JobStepsDisclosure` is built on `<details>`, and `<details>` **owns `open`**. It
21
+ also wants the state in a Jotai atom so a job can be expanded from elsewhere. Reconciling
22
+ the two takes three separate mechanisms:
23
+
24
+ ```tsx
25
+ const detailsRef = useRef<HTMLDetailsElement>(null)
26
+ const skipNextToggleRef = useRef(isOpen)
27
+
28
+ useEffect(() => {
29
+ if (detailsRef.current) detailsRef.current.open = isOpen
30
+ }, [isOpen])
31
+
32
+ const handleToggle = (event) => {
33
+ if (skipNextToggleRef.current) {
34
+ skipNextToggleRef.current = false
35
+ return // ← swallow the toggle our own write just fired
36
+ }
37
+ setStepsOpen(…)
38
+ }
39
+ ```
40
+
41
+ A ref to reach past React, an effect to push state into the DOM, and a guard to stop the
42
+ DOM's echo coming back. Every one of the three exists only because **two things hold one
43
+ fact** — the Radix argument from `Popover`, aimed at the platform this time.
44
+
45
+ So this is a `<button aria-expanded>` and a `role="region"`, with `VisibilityGroup` holding
46
+ the state alone.
47
+
48
+ ## Why not `<details name="…">`
49
+
50
+ The platform *does* now ship an exclusive accordion, and it was still rejected:
51
+
52
+ | | `<details name>` | This |
53
+ | --- | --- | --- |
54
+ | Who owns `open` | the DOM | `VisibilityGroup` |
55
+ | Disabled section | **impossible** — a `<summary>` cannot be disabled | not registered, so not a member |
56
+ | Driven from elsewhere | ref + effect + echo guard | pass `expandedKeys` |
57
+ | Panel keeps scroll/subscriptions | yes | yes (`hidden`, not unmounted) |
58
+
59
+ The second row is the one that settles it: four of the eleven sites have a section that is
60
+ unreachable until a job produces it.
61
+
62
+ <Canvas of={AccordionStories.AllVariants} />
63
+
64
+ ## Two kinds, one component
65
+
66
+ `isMultiple` picks between `VisibilityGroup` and `MultiplePicker`. Hooks cannot be
67
+ conditional, so **both are created and one is consulted** — two empty stores and no DOM.
68
+
69
+ The alternative is reimplementing exclusivity on top of `MultiplePicker` by deselecting the
70
+ others, which is precisely the logic `VisibilityGroup` exists to own once.
71
+
72
+ ## Registration is membership
73
+
74
+ A disabled section never registers, so nothing can expand it — including a consumer passing
75
+ its key in `expandedKeys`. `AllStates` does exactly that, on purpose.
76
+
77
+ <Canvas of={AccordionStories.AllStates} />
78
+
79
+ ## The heading level is the caller's
80
+
81
+ An accordion inside a `Card` that already has an `<h2>` needs `headingLevel={3}`. Getting it
82
+ wrong is a document-outline break that **no gate in this repo can see** — it depends
83
+ entirely on the page the accordion lands on, so it is a prop rather than a constant.