@charcuterie/ui 3.0.0 → 3.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 (130) hide show
  1. package/README.md +10 -0
  2. package/dist/Badge/Badge.d.ts +33 -3
  3. package/dist/Badge/Badge.d.ts.map +1 -1
  4. package/dist/Badge/Badge.js +20 -2
  5. package/dist/Badge/Badge.js.map +1 -1
  6. package/dist/Board/Board.d.ts +119 -0
  7. package/dist/Board/Board.d.ts.map +1 -0
  8. package/dist/Board/Board.js +165 -0
  9. package/dist/Board/Board.js.map +1 -0
  10. package/dist/Board/BoardCard.d.ts +120 -0
  11. package/dist/Board/BoardCard.d.ts.map +1 -0
  12. package/dist/Board/BoardCard.js +77 -0
  13. package/dist/Board/BoardCard.js.map +1 -0
  14. package/dist/Board/BoardLaneList.d.ts +103 -0
  15. package/dist/Board/BoardLaneList.d.ts.map +1 -0
  16. package/dist/Board/BoardLaneList.js +69 -0
  17. package/dist/Board/BoardLaneList.js.map +1 -0
  18. package/dist/Board/boardMove.d.ts +116 -0
  19. package/dist/Board/boardMove.d.ts.map +1 -0
  20. package/dist/Board/boardMove.js +116 -0
  21. package/dist/Board/boardMove.js.map +1 -0
  22. package/dist/Board/useBoardDrag.d.ts +44 -0
  23. package/dist/Board/useBoardDrag.d.ts.map +1 -0
  24. package/dist/Board/useBoardDrag.js +237 -0
  25. package/dist/Board/useBoardDrag.js.map +1 -0
  26. package/dist/Checkbox/Checkbox.d.ts.map +1 -1
  27. package/dist/Checkbox/Checkbox.js +15 -4
  28. package/dist/Checkbox/Checkbox.js.map +1 -1
  29. package/dist/DataTable/DataTable.d.ts +159 -0
  30. package/dist/DataTable/DataTable.d.ts.map +1 -0
  31. package/dist/DataTable/DataTable.js +197 -0
  32. package/dist/DataTable/DataTable.js.map +1 -0
  33. package/dist/DatePicker/DateGrid.d.ts +79 -0
  34. package/dist/DatePicker/DateGrid.d.ts.map +1 -0
  35. package/dist/DatePicker/DateGrid.js +220 -0
  36. package/dist/DatePicker/DateGrid.js.map +1 -0
  37. package/dist/DatePicker/DatePicker.d.ts +138 -0
  38. package/dist/DatePicker/DatePicker.d.ts.map +1 -0
  39. package/dist/DatePicker/DatePicker.js +384 -0
  40. package/dist/DatePicker/DatePicker.js.map +1 -0
  41. package/dist/DatePicker/datePresets.d.ts +29 -0
  42. package/dist/DatePicker/datePresets.d.ts.map +1 -0
  43. package/dist/DatePicker/datePresets.js +28 -0
  44. package/dist/DatePicker/datePresets.js.map +1 -0
  45. package/dist/DatePicker/parseDateInput.d.ts +106 -0
  46. package/dist/DatePicker/parseDateInput.d.ts.map +1 -0
  47. package/dist/DatePicker/parseDateInput.js +419 -0
  48. package/dist/DatePicker/parseDateInput.js.map +1 -0
  49. package/dist/DatePicker/plainDate.d.ts +167 -0
  50. package/dist/DatePicker/plainDate.d.ts.map +1 -0
  51. package/dist/DatePicker/plainDate.js +272 -0
  52. package/dist/DatePicker/plainDate.js.map +1 -0
  53. package/dist/Dialog/Dialog.d.ts +12 -2
  54. package/dist/Dialog/Dialog.d.ts.map +1 -1
  55. package/dist/Dialog/Dialog.js +2 -2
  56. package/dist/Dialog/Dialog.js.map +1 -1
  57. package/dist/MarkdownEditor/MarkdownEditor.d.ts +147 -0
  58. package/dist/MarkdownEditor/MarkdownEditor.d.ts.map +1 -0
  59. package/dist/MarkdownEditor/MarkdownEditor.js +492 -0
  60. package/dist/MarkdownEditor/MarkdownEditor.js.map +1 -0
  61. package/dist/MarkdownEditor/markdownCommands.d.ts +202 -0
  62. package/dist/MarkdownEditor/markdownCommands.d.ts.map +1 -0
  63. package/dist/MarkdownEditor/markdownCommands.js +379 -0
  64. package/dist/MarkdownEditor/markdownCommands.js.map +1 -0
  65. package/dist/MarkdownEditor/markdownSpans.d.ts +92 -0
  66. package/dist/MarkdownEditor/markdownSpans.d.ts.map +1 -0
  67. package/dist/MarkdownEditor/markdownSpans.js +303 -0
  68. package/dist/MarkdownEditor/markdownSpans.js.map +1 -0
  69. package/dist/Modal/Modal.d.ts +6 -2
  70. package/dist/Modal/Modal.d.ts.map +1 -1
  71. package/dist/Modal/Modal.js +1 -1
  72. package/dist/Modal/Modal.js.map +1 -1
  73. package/dist/Overlay/OverlayPanel.d.ts +13 -2
  74. package/dist/Overlay/OverlayPanel.d.ts.map +1 -1
  75. package/dist/Overlay/OverlayPanel.js +5 -1
  76. package/dist/Overlay/OverlayPanel.js.map +1 -1
  77. package/dist/categoricalStyles.d.ts +53 -0
  78. package/dist/categoricalStyles.d.ts.map +1 -0
  79. package/dist/categoricalStyles.js +195 -0
  80. package/dist/categoricalStyles.js.map +1 -0
  81. package/dist/index.d.ts +22 -0
  82. package/dist/index.d.ts.map +1 -1
  83. package/dist/index.js +11 -0
  84. package/dist/index.js.map +1 -1
  85. package/package.json +2 -2
  86. package/src/Badge/Badge.mdx +46 -0
  87. package/src/Badge/Badge.stories.tsx +98 -4
  88. package/src/Badge/Badge.test.tsx +157 -2
  89. package/src/Badge/Badge.tsx +49 -3
  90. package/src/Board/Board.mdx +199 -0
  91. package/src/Board/Board.stories.tsx +707 -0
  92. package/src/Board/Board.test.tsx +310 -0
  93. package/src/Board/Board.tsx +333 -0
  94. package/src/Board/BoardCard.tsx +290 -0
  95. package/src/Board/BoardLaneList.tsx +275 -0
  96. package/src/Board/boardMove.test.ts +213 -0
  97. package/src/Board/boardMove.ts +225 -0
  98. package/src/Board/useBoardDrag.ts +413 -0
  99. package/src/Checkbox/Checkbox.tsx +34 -3
  100. package/src/DataTable/DataTable.mdx +123 -0
  101. package/src/DataTable/DataTable.stories.tsx +411 -0
  102. package/src/DataTable/DataTable.test.tsx +386 -0
  103. package/src/DataTable/DataTable.tsx +497 -0
  104. package/src/DatePicker/DateGrid.tsx +467 -0
  105. package/src/DatePicker/DatePicker.mdx +170 -0
  106. package/src/DatePicker/DatePicker.stories.tsx +268 -0
  107. package/src/DatePicker/DatePicker.test.tsx +455 -0
  108. package/src/DatePicker/DatePicker.tsx +852 -0
  109. package/src/DatePicker/datePresets.ts +34 -0
  110. package/src/DatePicker/parseDateInput.test.ts +187 -0
  111. package/src/DatePicker/parseDateInput.ts +629 -0
  112. package/src/DatePicker/plainDate.test.ts +375 -0
  113. package/src/DatePicker/plainDate.ts +465 -0
  114. package/src/Dialog/Dialog.stories.tsx +48 -0
  115. package/src/Dialog/Dialog.test.tsx +30 -0
  116. package/src/Dialog/Dialog.tsx +13 -1
  117. package/src/MarkdownEditor/MarkdownEditor.mdx +189 -0
  118. package/src/MarkdownEditor/MarkdownEditor.stories.tsx +267 -0
  119. package/src/MarkdownEditor/MarkdownEditor.test.tsx +627 -0
  120. package/src/MarkdownEditor/MarkdownEditor.tsx +862 -0
  121. package/src/MarkdownEditor/markdownCommands.test.ts +384 -0
  122. package/src/MarkdownEditor/markdownCommands.ts +566 -0
  123. package/src/MarkdownEditor/markdownSpans.test.ts +217 -0
  124. package/src/MarkdownEditor/markdownSpans.ts +458 -0
  125. package/src/Modal/Modal.tsx +7 -1
  126. package/src/Overlay/OverlayPanel.tsx +17 -1
  127. package/src/argTypes.storyHelpers.ts +39 -0
  128. package/src/categoricalStyles.ts +244 -0
  129. package/src/index.ts +89 -0
  130. package/src/sourceRules.test.ts +52 -1
@@ -0,0 +1,237 @@
1
+ import { useCallback, useEffect, useRef, useState, } from "react";
2
+ import { chooseDropTarget } from "./boardMove.js";
3
+ /**
4
+ * Pointer dragging for the board — **on Pointer Events, with no
5
+ * drag-and-drop dependency**, and the reasoning is written down in
6
+ * `docs/decisions/2026-08-19-the-board-owns-the-move-and-takes-no-drag-and-drop-dependency.md`.
7
+ *
8
+ * The short version: a published design system's dependency list is
9
+ * inherited by every consumer, `castkit/packages/slatecast` has 60 KB
10
+ * gzipped to spend in total, and the two candidates cost 12–30 KB
11
+ * before a card has been drawn. What they buy is sensors, collision
12
+ * strategies, and sortable animation — a general solution to a
13
+ * problem this component has a specific version of: one card, from
14
+ * one lane, into one other lane.
15
+ *
16
+ * ### Pointer Events rather than HTML5 drag-and-drop
17
+ *
18
+ * `draggable="true"` is the zero-dependency instinct and it is the
19
+ * wrong one. It does not fire on touch at all — so the Narrow View,
20
+ * the kiosk density, and the tablet the owner actually reads this on
21
+ * get nothing — its drag image is a browser-drawn ghost with no
22
+ * styling hook worth using, and `dataTransfer` is readable only
23
+ * inside a real `drop`, which makes a live drop indicator awkward.
24
+ * Pointer Events are one code path for mouse, touch and pen, and
25
+ * `setPointerCapture` means the drag survives the pointer leaving the
26
+ * card, the lane, and the window.
27
+ *
28
+ * ### Every rectangle is measured once, at grab
29
+ *
30
+ * Re-measuring on each `pointermove` reads more correct and is
31
+ * worse. The drop indicator is a real element; inserting it moves
32
+ * the cards below it; the next move measures the moved cards and
33
+ * computes a different index; the indicator jumps back. That
34
+ * feedback loop is why the indicator here is `position: absolute`
35
+ * against a snapshot taken at grab — the layout under the pointer
36
+ * is frozen for the length of the drag, so the number the person
37
+ * sees and the number that gets committed are the same number.
38
+ *
39
+ * The cost is honest and small: a lane that reflows mid-drag (a live
40
+ * agent-run line wrapping to two lines) is measured stale. A board
41
+ * where that matters wants a re-snapshot on `ResizeObserver`, which
42
+ * is a change to this file and to nothing else.
43
+ */
44
+ /**
45
+ * How far the pointer has to travel before a press becomes a drag.
46
+ *
47
+ * Without it the handle is a button that cannot be clicked: every
48
+ * mouse-down/up pair carries a pixel or two of movement, and a
49
+ * "drag" of one pixel would commit a move and swallow the click that
50
+ * was meant to open the move menu. Four device-independent pixels is
51
+ * the usual figure and it is comfortably below a deliberate drag.
52
+ */
53
+ const DRAG_THRESHOLD_PX = 4;
54
+ const toRect = (element) => {
55
+ const rect = element.getBoundingClientRect();
56
+ return {
57
+ height: rect.height,
58
+ left: rect.left,
59
+ top: rect.top,
60
+ width: rect.width,
61
+ };
62
+ };
63
+ /**
64
+ * Where the line goes for a given insertion index — the midpoint of
65
+ * the gap the card would be dropped into, in the list's own
66
+ * coordinates.
67
+ *
68
+ * Split out and exported because it is the one piece of this file
69
+ * that is pure arithmetic over the snapshot, and the three cases
70
+ * (before everything, between two, after everything) are exactly
71
+ * where an off-by-one lives.
72
+ */
73
+ export const getIndicatorOffset = (lane, index) => {
74
+ const { cardRects, gap, listTop } = lane;
75
+ if (cardRects.length === 0) {
76
+ return 0;
77
+ }
78
+ const previous = cardRects[index - 1];
79
+ const next = cardRects[index];
80
+ if (!previous) {
81
+ return ((cardRects[0]?.top ?? listTop) - listTop - gap / 2);
82
+ }
83
+ if (!next) {
84
+ return (previous.top + previous.height - listTop + gap / 2);
85
+ }
86
+ return ((previous.top + previous.height + next.top) / 2 -
87
+ listTop);
88
+ };
89
+ export const useBoardDrag = ({ onDrop, }) => {
90
+ const laneElements = useRef(new Map());
91
+ const snapshot = useRef([]);
92
+ const [drag, setDrag] = useState(null);
93
+ /**
94
+ * The live drag, readable from a listener that was registered
95
+ * once. The listeners below are attached for the whole life of the
96
+ * component rather than added and removed per drag — re-attaching
97
+ * on every state change is how a `pointerup` gets missed — so they
98
+ * cannot close over `drag` itself.
99
+ */
100
+ const dragRef = useRef(null);
101
+ const setDragState = useCallback((next) => {
102
+ dragRef.current = next;
103
+ setDrag(next);
104
+ }, []);
105
+ const registerLane = useCallback((laneKey) => (element) => {
106
+ if (element) {
107
+ laneElements.current.set(laneKey, element);
108
+ return;
109
+ }
110
+ laneElements.current.delete(laneKey);
111
+ }, []);
112
+ const takeSnapshot = useCallback(() => {
113
+ snapshot.current = Array.from(laneElements.current, ([key, element]) => {
114
+ const cardElements = Array.from(element.querySelectorAll("[data-board-card]"));
115
+ return {
116
+ cardRects: cardElements.map(toRect),
117
+ gap: Number.parseFloat(globalThis.getComputedStyle(element).rowGap) || 0,
118
+ key,
119
+ listTop: element.getBoundingClientRect().top,
120
+ rect: toRect(element),
121
+ };
122
+ });
123
+ }, []);
124
+ const moveTo = useCallback((point) => {
125
+ const origin = dragRef.current;
126
+ if (!origin) {
127
+ return;
128
+ }
129
+ const target = chooseDropTarget(snapshot.current, point);
130
+ const lane = snapshot.current.find((one) => one.key === target?.laneKey);
131
+ setDragState({
132
+ ...origin,
133
+ indicatorOffset: lane && target
134
+ ? getIndicatorOffset(lane, target.index)
135
+ : null,
136
+ target,
137
+ });
138
+ }, [setDragState]);
139
+ const startDrag = useCallback((pointerEvent, origin) => {
140
+ const handle = pointerEvent.currentTarget;
141
+ const startX = pointerEvent.clientX;
142
+ const startY = pointerEvent.clientY;
143
+ // The capture goes on the handle, so `pointermove` keeps
144
+ // arriving after the pointer has left it — which it does
145
+ // immediately, because the card it is dragging moves out from
146
+ // under it.
147
+ if (handle instanceof HTMLElement) {
148
+ handle.setPointerCapture?.(pointerEvent.pointerId);
149
+ }
150
+ const onPointerMove = (moveEvent) => {
151
+ if (moveEvent.pointerId !== pointerEvent.pointerId) {
152
+ return;
153
+ }
154
+ if (!dragRef.current &&
155
+ Math.hypot(moveEvent.clientX - startX, moveEvent.clientY - startY) < DRAG_THRESHOLD_PX) {
156
+ return;
157
+ }
158
+ if (!dragRef.current) {
159
+ takeSnapshot();
160
+ setDragState({
161
+ ...origin,
162
+ indicatorOffset: null,
163
+ target: null,
164
+ });
165
+ }
166
+ // A touch drag scrolls the page unless something says
167
+ // otherwise, and `touch-action: none` on the handle only
168
+ // covers the handle. This covers the rest of the gesture.
169
+ moveEvent.preventDefault();
170
+ moveTo({
171
+ x: moveEvent.clientX,
172
+ y: moveEvent.clientY,
173
+ });
174
+ };
175
+ const finish = (isCommitted) => {
176
+ globalThis.removeEventListener("pointermove", onPointerMove);
177
+ globalThis.removeEventListener("pointerup", onUp);
178
+ globalThis.removeEventListener("pointercancel", onCancel);
179
+ const live = dragRef.current;
180
+ setDragState(null);
181
+ if (!live) {
182
+ return;
183
+ }
184
+ /**
185
+ * A pointer sequence that ends on the element it started
186
+ * from still fires a `click`, and the element it started
187
+ * from is a button that opens the move menu. Without this,
188
+ * every completed drag lands the card and then opens a menu
189
+ * on top of it.
190
+ *
191
+ * Swallowed in the **capture** phase and `once`, so it
192
+ * consumes exactly the synthetic click this gesture
193
+ * produced and nothing after it. A `hasDragged` flag on the
194
+ * card would be the same idea with a lifetime nobody owns.
195
+ */
196
+ globalThis.addEventListener("click", (clickEvent) => {
197
+ clickEvent.preventDefault();
198
+ clickEvent.stopPropagation();
199
+ }, { capture: true, once: true });
200
+ if (isCommitted && live.target) {
201
+ onDrop(origin, live.target);
202
+ }
203
+ };
204
+ const onUp = (upEvent) => {
205
+ if (upEvent.pointerId === pointerEvent.pointerId) {
206
+ finish(true);
207
+ }
208
+ };
209
+ const onCancel = () => {
210
+ finish(false);
211
+ };
212
+ globalThis.addEventListener("pointermove", onPointerMove, { passive: false });
213
+ globalThis.addEventListener("pointerup", onUp);
214
+ globalThis.addEventListener("pointercancel", onCancel);
215
+ }, [moveTo, onDrop, setDragState, takeSnapshot]);
216
+ /**
217
+ * Escape abandons the drag, and it is registered for the life of
218
+ * the component rather than for the life of a drag. A listener
219
+ * added when a drag starts is a listener that leaks when the
220
+ * component unmounts mid-drag — which is exactly what a route
221
+ * change during a drag does.
222
+ */
223
+ useEffect(() => {
224
+ const onKeyDown = (keyEvent) => {
225
+ if (keyEvent.key === "Escape" && dragRef.current) {
226
+ keyEvent.preventDefault();
227
+ setDragState(null);
228
+ }
229
+ };
230
+ globalThis.addEventListener("keydown", onKeyDown);
231
+ return () => {
232
+ globalThis.removeEventListener("keydown", onKeyDown);
233
+ };
234
+ }, [setDragState]);
235
+ return { drag, registerLane, startDrag };
236
+ };
237
+ //# sourceMappingURL=useBoardDrag.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useBoardDrag.js","sourceRoot":"","sources":["../../src/Board/useBoardDrag.ts"],"names":[],"mappings":"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"}
@@ -1 +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;IAClB;;;;;;;;;;;;;;;;;OAiBG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAoBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,QAAQ,GAAI,qFAUtB,aAAa,KAAG,SA2GlB,CAAA"}
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;IAClB;;;;;;;;;;;;;;;;;OAiBG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,CAAA;AAoBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,QAAQ,GAAI,qFAUtB,aAAa,KAAG,SA0IlB,CAAA"}
@@ -75,9 +75,18 @@ export const Checkbox = ({ className, id, isChecked = false, isDisabled = false,
75
75
  // No `disabled:` colour override; the wrapper's `opacity-60`
76
76
  // does the dimming, and doubling it on the box is what made a
77
77
  // disabled checkbox vanish.
78
+ // `indeterminate:` wears the same fill as `checked:`. It is
79
+ // the state a *group* box is in when some of its members are
80
+ // ticked, and it cannot be written in markup at all —
81
+ // `indeterminate` is a DOM property with no HTML attribute —
82
+ // so the only way to reach it is a consumer writing to the
83
+ // input. `DataTable`'s select-all box does exactly that, and
84
+ // before this line it painted **nothing**: the property was
85
+ // set, screen readers announced "mixed", and the box on
86
+ // screen was indistinguishable from empty.
78
87
  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
88
+ ? "border-border-default checked:border-intent-neutral-solid checked:bg-intent-neutral-solid indeterminate:border-intent-neutral-solid indeterminate:bg-intent-neutral-solid"
89
+ : "border-border-strong checked:border-intent-accent-solid checked:bg-intent-accent-solid indeterminate:border-intent-accent-solid indeterminate:bg-intent-accent-solid", isDisabled
81
90
  ? "cursor-not-allowed"
82
91
  : isReadOnly
83
92
  ? "cursor-default"
@@ -99,10 +108,12 @@ export const Checkbox = ({ className, id, isChecked = false, isDisabled = false,
99
108
  if (isReadOnly && keyEvent.key === " ") {
100
109
  keyEvent.preventDefault();
101
110
  }
102
- }, type: "checkbox", value: value }), _jsx("svg", { "aria-hidden": "true", className: toClassName("pointer-events-none invisible absolute peer-checked:visible",
111
+ }, type: "checkbox", value: value }), _jsx("svg", { "aria-hidden": "true", className: toClassName("pointer-events-none invisible absolute peer-checked:visible peer-indeterminate:invisible",
103
112
  // Matches whichever fill the box wears, so the tick keeps its
104
113
  // guaranteed on-solid contrast in either intent.
105
114
  isReadOnly
106
115
  ? "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 })] }));
116
+ : "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("svg", { "aria-hidden": "true", className: toClassName("pointer-events-none invisible absolute peer-indeterminate:visible", isReadOnly
117
+ ? "text-intent-neutral-on-solid"
118
+ : "text-intent-accent-on-solid", CHECK_SIZE_CLASS[size]), fill: "none", stroke: "currentColor", strokeLinecap: "round", strokeWidth: 3, viewBox: "0 0 24 24", children: _jsx("path", { d: "M6 12h12" }) })] }), _jsx("span", { children: label })] }));
108
119
  //# sourceMappingURL=Checkbox.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Checkbox.js","sourceRoot":"","sources":["../../src/Checkbox/Checkbox.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Checkbox.js","sourceRoot":"","sources":["../../src/Checkbox/Checkbox.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAyD/C,MAAM,cAAc,GAAgC;IAClD,EAAE,EAAE,UAAU;IACd,EAAE,EAAE,QAAQ;IACZ,EAAE,EAAE,QAAQ;CACb,CAAA;AAED,MAAM,gBAAgB,GAAgC;IACpD,EAAE,EAAE,UAAU;IACd,EAAE,EAAE,QAAQ;IACZ,EAAE,EAAE,UAAU;CACf,CAAA;AAED,MAAM,eAAe,GAAgC;IACnD,EAAE,EAAE,SAAS;IACb,EAAE,EAAE,SAAS;IACb,EAAE,EAAE,SAAS;CACd,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,EACvB,SAAS,EACT,EAAE,EACF,SAAS,GAAG,KAAK,EACjB,UAAU,GAAG,KAAK,EAClB,UAAU,GAAG,KAAK,EAClB,KAAK,EACL,QAAQ,EACR,IAAI,GAAG,IAAI,EACX,KAAK,GACS,EAAa,EAAE,CAAC,CAC9B,iBACE,SAAS,EAAE,WAAW,CACpB,mEAAmE,EACnE,eAAe,CAAC,IAAI,CAAC;IACrB,iEAAiE;IACjE,kDAAkD;IAClD,UAAU;QACR,CAAC,CAAC,oBAAoB;QACtB,CAAC,CAAC,UAAU;YACV,CAAC,CAAC,gBAAgB;YAClB,CAAC,CAAC,gBAAgB;IACtB,kEAAkE;IAClE,kEAAkE;IAClE,+DAA+D;IAC/D,mEAAmE;IACnE,kEAAkE;IAClE,kEAAkE;IAClE,mEAAmE;IACnE,sDAAsD;IACtD,UAAU,IAAI,YAAY,EAC1B,SAAS,CACV,aAED,gBAAM,SAAS,EAAC,2CAA2C,aACzD,iCACiB,UAAU,IAAI,SAAS,EACtC,SAAS,EAAE,WAAW;oBACpB,0DAA0D;oBAC1D,8DAA8D;oBAC9D,8DAA8D;oBAC9D,mDAAmD;oBACnD,uHAAuH;oBACvH,+DAA+D;oBAC/D,8DAA8D;oBAC9D,+DAA+D;oBAC/D,0DAA0D;oBAC1D,iEAAiE;oBACjE,6DAA6D;oBAC7D,8DAA8D;oBAC9D,4BAA4B;oBAC5B,4DAA4D;oBAC5D,6DAA6D;oBAC7D,sDAAsD;oBACtD,6DAA6D;oBAC7D,2DAA2D;oBAC3D,6DAA6D;oBAC7D,4DAA4D;oBAC5D,wDAAwD;oBACxD,2CAA2C;oBAC3C,UAAU;wBACR,CAAC,CAAC,2KAA2K;wBAC7K,CAAC,CAAC,sKAAsK,EAC1K,UAAU;wBACR,CAAC,CAAC,oBAAoB;wBACtB,CAAC,CAAC,UAAU;4BACV,CAAC,CAAC,gBAAgB;4BAClB,CAAC,CAAC,gBAAgB,EACtB,cAAc,CAAC,IAAI,CAAC,EACpB,gBAAgB,CACjB,EACD,cAAc,EAAE,SAAS,EACzB,QAAQ,EAAE,UAAU,EACpB,EAAE,EAAE,EAAE,EACN,QAAQ,EAAE,CACR,KAAoC,EACpC,EAAE;wBACF,IAAI,UAAU,EAAE,CAAC;4BACf,OAAM;wBACR,CAAC;wBAED,QAAQ,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;oBAClC,CAAC,EACD,OAAO,EAAE,CAAC,UAAU,EAAE,EAAE;wBACtB,yDAAyD;wBACzD,yDAAyD;wBACzD,qCAAqC;wBACrC,IAAI,UAAU,EAAE,CAAC;4BACf,UAAU,CAAC,cAAc,EAAE,CAAA;wBAC7B,CAAC;oBACH,CAAC,EACD,SAAS,EAAE,CAAC,QAAQ,EAAE,EAAE;wBACtB,yDAAyD;wBACzD,SAAS;wBACT,IAAI,UAAU,IAAI,QAAQ,CAAC,GAAG,KAAK,GAAG,EAAE,CAAC;4BACvC,QAAQ,CAAC,cAAc,EAAE,CAAA;wBAC3B,CAAC;oBACH,CAAC,EACD,IAAI,EAAC,UAAU,EACf,KAAK,EAAE,KAAK,GACZ,EAEF,6BACc,MAAM,EAClB,SAAS,EAAE,WAAW,CACpB,0FAA0F;oBAC1F,8DAA8D;oBAC9D,iDAAiD;oBACjD,UAAU;wBACR,CAAC,CAAC,8BAA8B;wBAChC,CAAC,CAAC,6BAA6B,EACjC,gBAAgB,CAAC,IAAI,CAAC,CACvB,EACD,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,EACtB,WAAW,EAAE,CAAC,EACd,OAAO,EAAC,WAAW,YAEnB,eAAM,CAAC,EAAC,iBAAiB,GAAG,GACxB,EAMN,6BACc,MAAM,EAClB,SAAS,EAAE,WAAW,CACpB,mEAAmE,EACnE,UAAU;wBACR,CAAC,CAAC,8BAA8B;wBAChC,CAAC,CAAC,6BAA6B,EACjC,gBAAgB,CAAC,IAAI,CAAC,CACvB,EACD,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,aAAa,EAAC,OAAO,EACrB,WAAW,EAAE,CAAC,EACd,OAAO,EAAC,WAAW,YAEnB,eAAM,CAAC,EAAC,UAAU,GAAG,GACjB,IACD,EAEP,yBAAO,KAAK,GAAQ,IACd,CACT,CAAA"}
@@ -0,0 +1,159 @@
1
+ import type { ReactNode } from "react";
2
+ import type { SortDirection } from "../SortableTableHeader/SortableTableHeader.tsx";
3
+ export type DataTableColumn<Row> = {
4
+ /**
5
+ * Lands on this column's `<th>` **and** on every `<td>` under it,
6
+ * which is what makes it the place a width goes: `w-32` on one
7
+ * column is the only sizing this component has, and it is
8
+ * deliberately the consumer's to write.
9
+ */
10
+ className?: string;
11
+ /**
12
+ * The column's name. Rendered twice on purpose — once in the
13
+ * header row, and once inside each cell as the label the stacked
14
+ * layout needs — so it has to be a node that can be rendered more
15
+ * than once. The in-cell copy is `aria-hidden`, because the
16
+ * `columnheader` association already says it to assistive
17
+ * technology.
18
+ */
19
+ header: ReactNode;
20
+ /**
21
+ * Whether this column offers a sort control. A column without one
22
+ * renders a plain `<th>` with **no** `aria-sort` at all, which is
23
+ * the attribute's way of saying "this column cannot be sorted" —
24
+ * `"none"` would claim the opposite.
25
+ */
26
+ isSortable?: boolean;
27
+ /** Stable id. Also the `columnKey` a sort request comes back with. */
28
+ key: string;
29
+ renderCell: (row: Row) => ReactNode;
30
+ };
31
+ export type DataTableSort = {
32
+ columnKey: string;
33
+ direction: SortDirection;
34
+ };
35
+ export type DataTableSelection<Row> = {
36
+ /**
37
+ * The accessible name of a row's checkbox. A tick box called
38
+ * "Select row" seven times over is seven identical controls in a
39
+ * screen reader's forms list, so this is required rather than
40
+ * defaulted — it is normally the same value the first column
41
+ * renders.
42
+ */
43
+ getRowLabel: (row: Row) => string;
44
+ /** The whole next set, never a delta. */
45
+ onSelectionChange: (selectedRowKeys: string[]) => void;
46
+ selectAllLabel?: string;
47
+ selectedRowKeys: readonly string[];
48
+ };
49
+ export type DataTableProps<Row> = {
50
+ className?: string;
51
+ columns: readonly DataTableColumn<Row>[];
52
+ /**
53
+ * What fills the table when `rows` is empty — an `EmptyState`,
54
+ * normally. Rendered in a `colSpan` cell **inside** the table, so
55
+ * the header row and the sort the reader just performed are still
56
+ * there. Swapping the whole table out for a message is how a
57
+ * filter that matches nothing takes the controls away with it.
58
+ */
59
+ emptyState?: ReactNode;
60
+ getRowKey: (row: Row) => string;
61
+ /**
62
+ * Shows the `<caption>`. Off by default: most tables sit under a
63
+ * heading the page already renders, and printing the name twice is
64
+ * how a table ends up with two titles.
65
+ */
66
+ isLabelVisible?: boolean;
67
+ /**
68
+ * The table's accessible name, as a real `<caption>`. Required,
69
+ * because a screen reader listing "table with 6 columns, 40 rows"
70
+ * and no name is a table nobody can choose to enter.
71
+ */
72
+ label: string;
73
+ onSortChange?: (sort: DataTableSort) => void;
74
+ rows: readonly Row[];
75
+ selection?: DataTableSelection<Row>;
76
+ /**
77
+ * Which column is sorted and which way — **the fact, not the
78
+ * doing.** The rows arrive already ordered; this only says which
79
+ * header lights up and what `aria-sort` announces.
80
+ */
81
+ sort?: DataTableSort;
82
+ };
83
+ /**
84
+ * **A table that reflows instead of scrolling, sized by its
85
+ * container.**
86
+ *
87
+ * ### It composes `SortableTableHeader`; it does not replace it
88
+ *
89
+ * The header cell shipped first, on its own, and stays on its own:
90
+ * it is already in a published 1.0.0 with a consumer of its own
91
+ * (mux-magic's `FileExplorerModal`), and subsuming it would be a
92
+ * breaking change bought for nothing. Every sortable column here
93
+ * renders that component, so there is exactly one place in the fleet
94
+ * that knows `aria-sort` belongs on the `<th>` while the click
95
+ * target is a `<button>` inside it, and one place to fix if that is
96
+ * ever wrong.
97
+ *
98
+ * That composition is also why this is a **real `<table>`**. A grid
99
+ * of `<div role="row">`s is the other reasonable choice, and it
100
+ * cannot host a `<th>` at all — so it would have meant either
101
+ * duplicating the header or breaking it.
102
+ *
103
+ * ### The narrow layout reflows; it never scrolls sideways
104
+ *
105
+ * Below `--cq-md` (32rem) each row stops being a row and becomes a
106
+ * labelled block — the column name beside its value, one pair per
107
+ * line — while the header row wraps into a strip of sort controls
108
+ * that stays reachable. Above it, a normal table.
109
+ *
110
+ * The two rejected alternatives are worth naming because both are
111
+ * common:
112
+ *
113
+ * - **Horizontal scroll.** WCAG 2.2 SC 1.4.10 (Reflow) exists
114
+ * because of it, and the consumer this was built for bans it
115
+ * outright ("No horizontal scroll, ever"). A pan surface also
116
+ * hides the *existence* of the columns off-screen.
117
+ * - **Dropping low-priority columns.** Cheapest to build and the
118
+ * only one that loses data: the assignee column does not come
119
+ * back, and there is no gesture that asks for it.
120
+ *
121
+ * ### Container queries, never a media query
122
+ *
123
+ * The width that matters is the element's, not the window's. A table
124
+ * in a three-up board lane is narrow on a 4K monitor, and the owner
125
+ * of this fleet browses zoomed in — a 1500px window at 175% zoom is
126
+ * ~860 effective pixels, so a `@media (max-width: …)` is measuring
127
+ * something that is not the question. The `@container` is declared
128
+ * on the wrapper and queried by its descendants, because a container
129
+ * query never matches the element that declares it.
130
+ *
131
+ * ### What it does not own
132
+ *
133
+ * **Sorting the data.** `sort` says which column is sorted;
134
+ * `onSortChange` asks for a different one. Comparing two values is
135
+ * per-column app logic — a date, a title, a priority enum with an
136
+ * order that is not alphabetical — and a table that sorted its own
137
+ * rows would have to be handed a comparator per column to do it,
138
+ * which is the same code in a worse place. The rows arrive ordered.
139
+ *
140
+ * **The selected set.** `selection.selectedRowKeys` is authoritative
141
+ * and lives with the consumer, because every use of a selection —
142
+ * the count in a toolbar, the bulk action, the undo — is outside
143
+ * this component. That is the opposite of `Checkbox`, and for a
144
+ * stated reason: the platform owns one checkbox's checkedness, and
145
+ * nothing at all owns "these five rows".
146
+ *
147
+ * **Column widths.** No drag handle, no measured layout. The browser's
148
+ * own auto table layout sizes columns to their content, which is a
149
+ * better algorithm than anything worth reimplementing, and
150
+ * `column.className` overrides it. Drag-to-resize is a *persistence*
151
+ * question (whose widths, stored where, keyed on what) that a
152
+ * component cannot answer for its consumer.
153
+ *
154
+ * **Virtualisation.** Deliberately absent; see the decision record.
155
+ * Every row is in the DOM, which is what keeps the accessibility
156
+ * tree honest and the auto column layout possible.
157
+ */
158
+ export declare const DataTable: <Row>({ className, columns, emptyState, getRowKey, isLabelVisible, label, onSortChange, rows, selection, sort, }: DataTableProps<Row>) => ReactNode;
159
+ //# sourceMappingURL=DataTable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataTable.d.ts","sourceRoot":"","sources":["../../src/DataTable/DataTable.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAItC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gDAAgD,CAAA;AAKnF,MAAM,MAAM,eAAe,CAAC,GAAG,IAAI;IACjC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;;;;OAOG;IACH,MAAM,EAAE,SAAS,CAAA;IACjB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,sEAAsE;IACtE,GAAG,EAAE,MAAM,CAAA;IACX,UAAU,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,SAAS,CAAA;CACpC,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAC1B,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,aAAa,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,kBAAkB,CAAC,GAAG,IAAI;IACpC;;;;;;OAMG;IACH,WAAW,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,MAAM,CAAA;IACjC,yCAAyC;IACzC,iBAAiB,EAAE,CAAC,eAAe,EAAE,MAAM,EAAE,KAAK,IAAI,CAAA;IACtD,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,eAAe,EAAE,SAAS,MAAM,EAAE,CAAA;CACnC,CAAA;AAED,MAAM,MAAM,cAAc,CAAC,GAAG,IAAI;IAChC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,SAAS,eAAe,CAAC,GAAG,CAAC,EAAE,CAAA;IACxC;;;;;;OAMG;IACH,UAAU,CAAC,EAAE,SAAS,CAAA;IACtB,SAAS,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,MAAM,CAAA;IAC/B;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAA;IACb,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,IAAI,CAAA;IAC5C,IAAI,EAAE,SAAS,GAAG,EAAE,CAAA;IACpB,SAAS,CAAC,EAAE,kBAAkB,CAAC,GAAG,CAAC,CAAA;IACnC;;;;OAIG;IACH,IAAI,CAAC,EAAE,aAAa,CAAA;CACrB,CAAA;AAiCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0EG;AACH,eAAO,MAAM,SAAS,GAAI,GAAG,EAAG,4GAW7B,cAAc,CAAC,GAAG,CAAC,KAAG,SA4RxB,CAAA"}