@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.
- package/README.md +10 -0
- package/dist/Badge/Badge.d.ts +33 -3
- package/dist/Badge/Badge.d.ts.map +1 -1
- package/dist/Badge/Badge.js +20 -2
- package/dist/Badge/Badge.js.map +1 -1
- package/dist/Board/Board.d.ts +119 -0
- package/dist/Board/Board.d.ts.map +1 -0
- package/dist/Board/Board.js +165 -0
- package/dist/Board/Board.js.map +1 -0
- package/dist/Board/BoardCard.d.ts +120 -0
- package/dist/Board/BoardCard.d.ts.map +1 -0
- package/dist/Board/BoardCard.js +77 -0
- package/dist/Board/BoardCard.js.map +1 -0
- package/dist/Board/BoardLaneList.d.ts +103 -0
- package/dist/Board/BoardLaneList.d.ts.map +1 -0
- package/dist/Board/BoardLaneList.js +69 -0
- package/dist/Board/BoardLaneList.js.map +1 -0
- package/dist/Board/boardMove.d.ts +116 -0
- package/dist/Board/boardMove.d.ts.map +1 -0
- package/dist/Board/boardMove.js +116 -0
- package/dist/Board/boardMove.js.map +1 -0
- package/dist/Board/useBoardDrag.d.ts +44 -0
- package/dist/Board/useBoardDrag.d.ts.map +1 -0
- package/dist/Board/useBoardDrag.js +237 -0
- package/dist/Board/useBoardDrag.js.map +1 -0
- package/dist/Checkbox/Checkbox.d.ts.map +1 -1
- package/dist/Checkbox/Checkbox.js +15 -4
- package/dist/Checkbox/Checkbox.js.map +1 -1
- package/dist/DataTable/DataTable.d.ts +159 -0
- package/dist/DataTable/DataTable.d.ts.map +1 -0
- package/dist/DataTable/DataTable.js +197 -0
- package/dist/DataTable/DataTable.js.map +1 -0
- package/dist/DatePicker/DateGrid.d.ts +79 -0
- package/dist/DatePicker/DateGrid.d.ts.map +1 -0
- package/dist/DatePicker/DateGrid.js +220 -0
- package/dist/DatePicker/DateGrid.js.map +1 -0
- package/dist/DatePicker/DatePicker.d.ts +138 -0
- package/dist/DatePicker/DatePicker.d.ts.map +1 -0
- package/dist/DatePicker/DatePicker.js +384 -0
- package/dist/DatePicker/DatePicker.js.map +1 -0
- package/dist/DatePicker/datePresets.d.ts +29 -0
- package/dist/DatePicker/datePresets.d.ts.map +1 -0
- package/dist/DatePicker/datePresets.js +28 -0
- package/dist/DatePicker/datePresets.js.map +1 -0
- package/dist/DatePicker/parseDateInput.d.ts +106 -0
- package/dist/DatePicker/parseDateInput.d.ts.map +1 -0
- package/dist/DatePicker/parseDateInput.js +419 -0
- package/dist/DatePicker/parseDateInput.js.map +1 -0
- package/dist/DatePicker/plainDate.d.ts +167 -0
- package/dist/DatePicker/plainDate.d.ts.map +1 -0
- package/dist/DatePicker/plainDate.js +272 -0
- package/dist/DatePicker/plainDate.js.map +1 -0
- package/dist/Dialog/Dialog.d.ts +12 -2
- package/dist/Dialog/Dialog.d.ts.map +1 -1
- package/dist/Dialog/Dialog.js +2 -2
- package/dist/Dialog/Dialog.js.map +1 -1
- package/dist/MarkdownEditor/MarkdownEditor.d.ts +147 -0
- package/dist/MarkdownEditor/MarkdownEditor.d.ts.map +1 -0
- package/dist/MarkdownEditor/MarkdownEditor.js +492 -0
- package/dist/MarkdownEditor/MarkdownEditor.js.map +1 -0
- package/dist/MarkdownEditor/markdownCommands.d.ts +202 -0
- package/dist/MarkdownEditor/markdownCommands.d.ts.map +1 -0
- package/dist/MarkdownEditor/markdownCommands.js +379 -0
- package/dist/MarkdownEditor/markdownCommands.js.map +1 -0
- package/dist/MarkdownEditor/markdownSpans.d.ts +92 -0
- package/dist/MarkdownEditor/markdownSpans.d.ts.map +1 -0
- package/dist/MarkdownEditor/markdownSpans.js +303 -0
- package/dist/MarkdownEditor/markdownSpans.js.map +1 -0
- package/dist/Modal/Modal.d.ts +6 -2
- package/dist/Modal/Modal.d.ts.map +1 -1
- package/dist/Modal/Modal.js +1 -1
- package/dist/Modal/Modal.js.map +1 -1
- package/dist/Overlay/OverlayPanel.d.ts +13 -2
- package/dist/Overlay/OverlayPanel.d.ts.map +1 -1
- package/dist/Overlay/OverlayPanel.js +5 -1
- package/dist/Overlay/OverlayPanel.js.map +1 -1
- package/dist/categoricalStyles.d.ts +53 -0
- package/dist/categoricalStyles.d.ts.map +1 -0
- package/dist/categoricalStyles.js +195 -0
- package/dist/categoricalStyles.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/Badge/Badge.mdx +46 -0
- package/src/Badge/Badge.stories.tsx +98 -4
- package/src/Badge/Badge.test.tsx +157 -2
- package/src/Badge/Badge.tsx +49 -3
- package/src/Board/Board.mdx +199 -0
- package/src/Board/Board.stories.tsx +707 -0
- package/src/Board/Board.test.tsx +310 -0
- package/src/Board/Board.tsx +333 -0
- package/src/Board/BoardCard.tsx +290 -0
- package/src/Board/BoardLaneList.tsx +275 -0
- package/src/Board/boardMove.test.ts +213 -0
- package/src/Board/boardMove.ts +225 -0
- package/src/Board/useBoardDrag.ts +413 -0
- package/src/Checkbox/Checkbox.tsx +34 -3
- package/src/DataTable/DataTable.mdx +123 -0
- package/src/DataTable/DataTable.stories.tsx +411 -0
- package/src/DataTable/DataTable.test.tsx +386 -0
- package/src/DataTable/DataTable.tsx +497 -0
- package/src/DatePicker/DateGrid.tsx +467 -0
- package/src/DatePicker/DatePicker.mdx +170 -0
- package/src/DatePicker/DatePicker.stories.tsx +268 -0
- package/src/DatePicker/DatePicker.test.tsx +455 -0
- package/src/DatePicker/DatePicker.tsx +852 -0
- package/src/DatePicker/datePresets.ts +34 -0
- package/src/DatePicker/parseDateInput.test.ts +187 -0
- package/src/DatePicker/parseDateInput.ts +629 -0
- package/src/DatePicker/plainDate.test.ts +375 -0
- package/src/DatePicker/plainDate.ts +465 -0
- package/src/Dialog/Dialog.stories.tsx +48 -0
- package/src/Dialog/Dialog.test.tsx +30 -0
- package/src/Dialog/Dialog.tsx +13 -1
- package/src/MarkdownEditor/MarkdownEditor.mdx +189 -0
- package/src/MarkdownEditor/MarkdownEditor.stories.tsx +267 -0
- package/src/MarkdownEditor/MarkdownEditor.test.tsx +627 -0
- package/src/MarkdownEditor/MarkdownEditor.tsx +862 -0
- package/src/MarkdownEditor/markdownCommands.test.ts +384 -0
- package/src/MarkdownEditor/markdownCommands.ts +566 -0
- package/src/MarkdownEditor/markdownSpans.test.ts +217 -0
- package/src/MarkdownEditor/markdownSpans.ts +458 -0
- package/src/Modal/Modal.tsx +7 -1
- package/src/Overlay/OverlayPanel.tsx +17 -1
- package/src/argTypes.storyHelpers.ts +39 -0
- package/src/categoricalStyles.ts +244 -0
- package/src/index.ts +89 -0
- 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,
|
|
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" }) })
|
|
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":";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,UAAU;wBACR,CAAC,CAAC,
|
|
1
|
+
{"version":3,"file":"Checkbox.js","sourceRoot":"","sources":["../../src/Checkbox/Checkbox.tsx"],"names":[],"mappings":"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"}
|
|
@@ -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"}
|