@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,197 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useRef } from "react";
3
+ import { Checkbox } from "../Checkbox/Checkbox.js";
4
+ import { SortableTableHeader } from "../SortableTableHeader/SortableTableHeader.js";
5
+ import { toClassName } from "../toClassName.js";
6
+ import { VisuallyHidden } from "../VisuallyHidden/VisuallyHidden.js";
7
+ /**
8
+ * The cell padding, in one place because four elements have to agree
9
+ * on it: the sortable header's button (which brings its own, inside
10
+ * `SortableTableHeader`), the plain header, the body cell, and the
11
+ * empty-state cell.
12
+ */
13
+ const CELL_PADDING_CLASS = "px-3 py-2";
14
+ /**
15
+ * `role` on every part, and it is not belt-and-braces.
16
+ *
17
+ * The narrow layout takes `display` away from the table elements —
18
+ * `block` on the table, `grid` on the row, `flex` on the cell — and
19
+ * a table's semantics have historically travelled with its
20
+ * `display`. Measured in this sandbox's chromium via CDP
21
+ * (`Accessibility.getFullAXTree`), that engine now keeps
22
+ * `table` / `row` / `columnheader` / `cell` intact through
23
+ * `display: block`; the roles below are therefore a **no-op here**
24
+ * and insurance for the engines this sandbox cannot run. The one
25
+ * measured difference is `<tbody>`: chromium ignores it entirely
26
+ * until it is given `role="rowgroup"`, at which point it joins the
27
+ * tree as a rowgroup beside `<thead>`'s — which is what a table
28
+ * with two rowgroups is supposed to look like.
29
+ *
30
+ * The cost of being wrong in each direction is what settles it. A
31
+ * redundant role changes nothing anywhere. A dropped one turns the
32
+ * whole table into a stack of unrelated text in exactly the layout
33
+ * where the column headers are no longer on screen to read.
34
+ */
35
+ const ROW_GROUP_ROLE = "rowgroup";
36
+ /**
37
+ * **A table that reflows instead of scrolling, sized by its
38
+ * container.**
39
+ *
40
+ * ### It composes `SortableTableHeader`; it does not replace it
41
+ *
42
+ * The header cell shipped first, on its own, and stays on its own:
43
+ * it is already in a published 1.0.0 with a consumer of its own
44
+ * (mux-magic's `FileExplorerModal`), and subsuming it would be a
45
+ * breaking change bought for nothing. Every sortable column here
46
+ * renders that component, so there is exactly one place in the fleet
47
+ * that knows `aria-sort` belongs on the `<th>` while the click
48
+ * target is a `<button>` inside it, and one place to fix if that is
49
+ * ever wrong.
50
+ *
51
+ * That composition is also why this is a **real `<table>`**. A grid
52
+ * of `<div role="row">`s is the other reasonable choice, and it
53
+ * cannot host a `<th>` at all — so it would have meant either
54
+ * duplicating the header or breaking it.
55
+ *
56
+ * ### The narrow layout reflows; it never scrolls sideways
57
+ *
58
+ * Below `--cq-md` (32rem) each row stops being a row and becomes a
59
+ * labelled block — the column name beside its value, one pair per
60
+ * line — while the header row wraps into a strip of sort controls
61
+ * that stays reachable. Above it, a normal table.
62
+ *
63
+ * The two rejected alternatives are worth naming because both are
64
+ * common:
65
+ *
66
+ * - **Horizontal scroll.** WCAG 2.2 SC 1.4.10 (Reflow) exists
67
+ * because of it, and the consumer this was built for bans it
68
+ * outright ("No horizontal scroll, ever"). A pan surface also
69
+ * hides the *existence* of the columns off-screen.
70
+ * - **Dropping low-priority columns.** Cheapest to build and the
71
+ * only one that loses data: the assignee column does not come
72
+ * back, and there is no gesture that asks for it.
73
+ *
74
+ * ### Container queries, never a media query
75
+ *
76
+ * The width that matters is the element's, not the window's. A table
77
+ * in a three-up board lane is narrow on a 4K monitor, and the owner
78
+ * of this fleet browses zoomed in — a 1500px window at 175% zoom is
79
+ * ~860 effective pixels, so a `@media (max-width: …)` is measuring
80
+ * something that is not the question. The `@container` is declared
81
+ * on the wrapper and queried by its descendants, because a container
82
+ * query never matches the element that declares it.
83
+ *
84
+ * ### What it does not own
85
+ *
86
+ * **Sorting the data.** `sort` says which column is sorted;
87
+ * `onSortChange` asks for a different one. Comparing two values is
88
+ * per-column app logic — a date, a title, a priority enum with an
89
+ * order that is not alphabetical — and a table that sorted its own
90
+ * rows would have to be handed a comparator per column to do it,
91
+ * which is the same code in a worse place. The rows arrive ordered.
92
+ *
93
+ * **The selected set.** `selection.selectedRowKeys` is authoritative
94
+ * and lives with the consumer, because every use of a selection —
95
+ * the count in a toolbar, the bulk action, the undo — is outside
96
+ * this component. That is the opposite of `Checkbox`, and for a
97
+ * stated reason: the platform owns one checkbox's checkedness, and
98
+ * nothing at all owns "these five rows".
99
+ *
100
+ * **Column widths.** No drag handle, no measured layout. The browser's
101
+ * own auto table layout sizes columns to their content, which is a
102
+ * better algorithm than anything worth reimplementing, and
103
+ * `column.className` overrides it. Drag-to-resize is a *persistence*
104
+ * question (whose widths, stored where, keyed on what) that a
105
+ * component cannot answer for its consumer.
106
+ *
107
+ * **Virtualisation.** Deliberately absent; see the decision record.
108
+ * Every row is in the DOM, which is what keeps the accessibility
109
+ * tree honest and the auto column layout possible.
110
+ */
111
+ export const DataTable = ({ className, columns, emptyState, getRowKey, isLabelVisible = false, label, onSortChange, rows, selection, sort, }) => {
112
+ const tableRef = useRef(null);
113
+ const selectedRowKeys = selection?.selectedRowKeys;
114
+ /**
115
+ * The checkboxes are **written to**, not re-mounted.
116
+ *
117
+ * `Checkbox` is uncontrolled by design — `isChecked` seeds the
118
+ * first paint and the `<input>` is the store from then on — so a
119
+ * consumer changing `selectedRowKeys` out from under it (a "clear
120
+ * selection" button, a filter that drops a selected row) would
121
+ * otherwise leave the tick behind. Re-mounting with a
122
+ * state-bearing `key` fixes the tick and throws the focus away
123
+ * mid-keyboard, one row into a `Space`-through-the-list.
124
+ *
125
+ * So the store gets written instead, which is also the only way to
126
+ * express the header box's third state: `indeterminate` is a DOM
127
+ * property with no HTML attribute at all, so there is no markup
128
+ * that could have set it.
129
+ *
130
+ * No dependency array: this has to run after every render that
131
+ * could have changed a row, and it is a `querySelectorAll` over
132
+ * the rows already on screen.
133
+ */
134
+ useEffect(() => {
135
+ const table = tableRef.current;
136
+ if (!table || !selectedRowKeys) {
137
+ return;
138
+ }
139
+ const selectedKeys = new Set(selectedRowKeys);
140
+ for (const input of table.querySelectorAll('tbody input[type="checkbox"]')) {
141
+ input.checked = selectedKeys.has(input.value);
142
+ }
143
+ const selectAllInput = table.querySelector('thead input[type="checkbox"]');
144
+ if (selectAllInput) {
145
+ const selectedRowCount = rows.filter((row) => selectedKeys.has(getRowKey(row))).length;
146
+ selectAllInput.checked =
147
+ rows.length > 0 && selectedRowCount === rows.length;
148
+ selectAllInput.indeterminate =
149
+ selectedRowCount > 0 &&
150
+ selectedRowCount < rows.length;
151
+ }
152
+ });
153
+ const selectedKeys = new Set(selectedRowKeys ?? []);
154
+ const columnCount = columns.length + (selection ? 1 : 0);
155
+ return (_jsx("div", { className: toClassName("@container", className), children: _jsxs("table", { className: "block w-full border-collapse text-start text-content-primary text-md cq-md:table", ref: tableRef, role: "table", children: [_jsx("caption", { className: toClassName("text-start", isLabelVisible
156
+ ? "pb-2 font-medium text-content-secondary text-sm"
157
+ : "sr-only"), children: label }), _jsx("thead", { className: "block cq-md:table-header-group", role: ROW_GROUP_ROLE, children: _jsxs("tr", { className: "flex flex-wrap items-center gap-x-1 border-border-subtle border-b cq-md:table-row cq-md:border-b-0", role: "row", children: [selection ? (_jsx("th", { className: toClassName("border-border-subtle p-2 text-start cq-md:table-cell cq-md:border-b"), role: "columnheader", scope: "col", children: _jsx(Checkbox, { label: _jsx(VisuallyHidden, { children: selection.selectAllLabel ??
158
+ "Select all rows" }), onChange: (isChecked) => {
159
+ selection.onSelectionChange(isChecked ? rows.map(getRowKey) : []);
160
+ } }) })) : null, columns.map((column) => column.isSortable ? (_jsx(SortableTableHeader
161
+ // The header keeps its own `border-b` for the
162
+ // wide layout and loses it in the strip, where
163
+ // one underline per chip reads as five separate
164
+ // rules rather than one header edge.
165
+ , {
166
+ // The header keeps its own `border-b` for the
167
+ // wide layout and loses it in the strip, where
168
+ // one underline per chip reads as five separate
169
+ // rules rather than one header edge.
170
+ className: toClassName("border-b-0 cq-md:border-b", column.className), direction: sort?.columnKey === column.key
171
+ ? sort.direction
172
+ : undefined, onSort: (direction) => {
173
+ onSortChange?.({
174
+ columnKey: column.key,
175
+ direction,
176
+ });
177
+ }, children: column.header }, column.key)) : (_jsx("th", { className: toClassName("border-border-subtle text-start font-medium text-content-secondary text-sm uppercase tracking-wide cq-md:table-cell cq-md:border-b", CELL_PADDING_CLASS, column.className), role: "columnheader", scope: "col", children: column.header }, column.key)))] }) }), _jsx("tbody", { className: "flex flex-col gap-2 pt-2 cq-md:table-row-group cq-md:gap-0 cq-md:pt-0", role: ROW_GROUP_ROLE, children: rows.length === 0 ? (_jsx("tr", { className: "block cq-md:table-row", role: "row", children: _jsx("td", { className: "block p-0 cq-md:table-cell", colSpan: columnCount, role: "cell", children: emptyState }) })) : (rows.map((row) => {
178
+ const rowKey = getRowKey(row);
179
+ const isSelected = selectedKeys.has(rowKey);
180
+ return (_jsxs("tr", { className: toClassName(
181
+ // Narrow: a card. Wide: a row with a hairline
182
+ // under it. Both states are written here rather
183
+ // than in a stylesheet so a reader can see the
184
+ // whole of a row's shape in one place.
185
+ "flex flex-col gap-1 rounded-lg border border-border-subtle p-3 transition-colors duration-(--duration-fast) ease-standard", "cq-md:table-row cq-md:gap-0 cq-md:rounded-none cq-md:border-0 cq-md:border-border-subtle cq-md:border-b cq-md:p-0", isSelected
186
+ ? "bg-intent-accent-surface"
187
+ : "bg-surface-raised hover:bg-intent-neutral-surface cq-md:bg-transparent"), "data-is-selected": isSelected, role: "row", children: [selection ? (_jsx("td", { className: "block p-2 cq-md:table-cell cq-md:align-middle", role: "cell", children: _jsx(Checkbox, { isChecked: isSelected, label: _jsx(VisuallyHidden, { children: selection.getRowLabel(row) }), onChange: (isChecked) => {
188
+ selection.onSelectionChange(isChecked
189
+ ? [
190
+ ...selection.selectedRowKeys,
191
+ rowKey,
192
+ ]
193
+ : selection.selectedRowKeys.filter((one) => one !== rowKey));
194
+ }, value: rowKey }) })) : null, columns.map((column) => (_jsxs("td", { className: toClassName("flex items-baseline gap-3 py-0.5 cq-md:table-cell cq-md:align-middle", CELL_PADDING_CLASS, "cq-md:py-2", column.className), role: "cell", children: [_jsx("span", { "aria-hidden": "true", className: "w-20 shrink-0 truncate text-content-secondary text-xs uppercase tracking-wide cq-sm:w-24 cq-md:hidden", children: column.header }), _jsx("span", { className: "min-w-0 flex-1 wrap-anywhere cq-md:wrap-normal", children: column.renderCell(row) })] }, column.key)))] }, rowKey));
195
+ })) })] }) }));
196
+ };
197
+ //# sourceMappingURL=DataTable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataTable.js","sourceRoot":"","sources":["../../src/DataTable/DataTable.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,79 @@
1
+ import type { ReactNode } from "react";
2
+ import type { PlainDate } from "./plainDate.ts";
3
+ export type DateGridProps = {
4
+ firstDayOfWeek: number;
5
+ focusedDate: PlainDate;
6
+ /**
7
+ * The month this grid draws — any date inside it. `DatePicker`
8
+ * renders two of these in range mode, so the month is a prop
9
+ * rather than derived from the focus.
10
+ */
11
+ gridMonth: PlainDate;
12
+ /**
13
+ * Whether the keyboard is *in* the grid. Only the grid that owns
14
+ * focus pulls it onto its focused cell; the other one would rip
15
+ * focus back and forth between the two months on every arrow key.
16
+ */
17
+ isGridFocused: boolean;
18
+ isRange: boolean;
19
+ label: string;
20
+ locale?: string;
21
+ maximum?: PlainDate;
22
+ minimum?: PlainDate;
23
+ onFocusDate: (date: PlainDate) => void;
24
+ onHoverDate: (date: null | PlainDate) => void;
25
+ onSelectDate: (date: PlainDate) => void;
26
+ /**
27
+ * The end of the band being drawn *right now* — the committed end,
28
+ * or the hovered/keyboard-focused day while the second click is
29
+ * still outstanding. Painting the pending half is the difference
30
+ * between a range picker you can aim and one you have to guess at.
31
+ */
32
+ previewEnd: null | PlainDate;
33
+ rangeStart: null | PlainDate;
34
+ selectedDates: readonly PlainDate[];
35
+ today: PlainDate;
36
+ };
37
+ /**
38
+ * One month, as a real `<table role="grid">`.
39
+ *
40
+ * ### Why the roving focus is arithmetic and not `useRovingFocus`
41
+ *
42
+ * `@charcuterie/logic`'s `RovingFocus` is a **registration** kind:
43
+ * members register from an effect and `next`/`previous`/`first`/
44
+ * `last` walk that list. `SegmentedControl` and `Tabs` are exactly
45
+ * that shape, and a calendar is not, for two reasons that are worth
46
+ * stating rather than discovering:
47
+ *
48
+ * - The movement is two-dimensional and it is *date* arithmetic, not
49
+ * list traversal. ArrowDown is "+7 days", which is a different
50
+ * thing from "the seventh next registered member" the moment a
51
+ * month does not start on the first column.
52
+ * - The move can leave the rendered set entirely. ArrowRight on 31
53
+ * August lands on 1 September, which is a day this grid has not
54
+ * rendered and no member has registered. A registration list
55
+ * cannot express a move to something that does not exist yet; a
56
+ * day number can, and re-rendering the grid around it is the
57
+ * correct response.
58
+ *
59
+ * So the focused *date* is the state and the DOM follows it. This is
60
+ * the same conclusion `Field` reached about `createLinkedIds` — the
61
+ * state kind is real and this is not its shape.
62
+ *
63
+ * ### The cell is the gridcell
64
+ *
65
+ * `<td tabindex>` rather than `<td><button>`. It is the APG date
66
+ * picker's own structure, it keeps exactly one tab stop in the grid
67
+ * (which `expectAgentDrivable` checks), and it avoids a focusable
68
+ * button inside a focusable cell — two tab stops per day, which is
69
+ * what the naive build produces.
70
+ *
71
+ * Each cell's accessible name is the **whole date**, formatted in
72
+ * the active locale: "Wednesday, August 19, 2026", not "19". A
73
+ * screen reader reading a bare number in a grid with no row or
74
+ * column headers announced is a user counting cells, and
75
+ * `getByRole("gridcell", { name: … })` becomes unusable the moment
76
+ * two months are on screen.
77
+ */
78
+ export declare const DateGrid: ({ firstDayOfWeek, focusedDate, gridMonth, isGridFocused, isRange, label, locale, maximum, minimum, onFocusDate, onHoverDate, onSelectDate, previewEnd, rangeStart, selectedDates, today, }: DateGridProps) => ReactNode;
79
+ //# sourceMappingURL=DateGrid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DateGrid.d.ts","sourceRoot":"","sources":["../../src/DatePicker/DateGrid.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAA;AAMrD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAe/C,MAAM,MAAM,aAAa,GAAG;IAC1B,cAAc,EAAE,MAAM,CAAA;IACtB,WAAW,EAAE,SAAS,CAAA;IACtB;;;;OAIG;IACH,SAAS,EAAE,SAAS,CAAA;IACpB;;;;OAIG;IACH,aAAa,EAAE,OAAO,CAAA;IACtB,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,WAAW,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACtC,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,SAAS,KAAK,IAAI,CAAA;IAC7C,YAAY,EAAE,CAAC,IAAI,EAAE,SAAS,KAAK,IAAI,CAAA;IACvC;;;;;OAKG;IACH,UAAU,EAAE,IAAI,GAAG,SAAS,CAAA;IAC5B,UAAU,EAAE,IAAI,GAAG,SAAS,CAAA;IAC5B,aAAa,EAAE,SAAS,SAAS,EAAE,CAAA;IACnC,KAAK,EAAE,SAAS,CAAA;CACjB,CAAA;AAQD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,eAAO,MAAM,QAAQ,GAAI,4LAiBtB,aAAa,KAAG,SA0VlB,CAAA"}
@@ -0,0 +1,220 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useRef } from "react";
3
+ import { FOCUS_RING_CLASS } from "../intentStyles.js";
4
+ import { toClassName } from "../toClassName.js";
5
+ import { VisuallyHidden } from "../VisuallyHidden/VisuallyHidden.js";
6
+ import { addDays, addMonths, clampPlainDate, comparePlainDates, formatPlainDate, getDaysInMonth, getIsSameDay, getIsWithinRange, getWeekday, getWeekdayNames, toIsoDate, } from "./plainDate.js";
7
+ const CELL_BASE_CLASS = "cursor-pointer rounded-md p-0 text-center";
8
+ const DAY_BASE_CLASS = "mx-auto flex size-8 items-center justify-center rounded-md border border-transparent text-xs transition-colors duration-(--duration-fast) ease-standard cq-xs:size-9 cq-xs:text-sm cq-sm:size-10";
9
+ /**
10
+ * One month, as a real `<table role="grid">`.
11
+ *
12
+ * ### Why the roving focus is arithmetic and not `useRovingFocus`
13
+ *
14
+ * `@charcuterie/logic`'s `RovingFocus` is a **registration** kind:
15
+ * members register from an effect and `next`/`previous`/`first`/
16
+ * `last` walk that list. `SegmentedControl` and `Tabs` are exactly
17
+ * that shape, and a calendar is not, for two reasons that are worth
18
+ * stating rather than discovering:
19
+ *
20
+ * - The movement is two-dimensional and it is *date* arithmetic, not
21
+ * list traversal. ArrowDown is "+7 days", which is a different
22
+ * thing from "the seventh next registered member" the moment a
23
+ * month does not start on the first column.
24
+ * - The move can leave the rendered set entirely. ArrowRight on 31
25
+ * August lands on 1 September, which is a day this grid has not
26
+ * rendered and no member has registered. A registration list
27
+ * cannot express a move to something that does not exist yet; a
28
+ * day number can, and re-rendering the grid around it is the
29
+ * correct response.
30
+ *
31
+ * So the focused *date* is the state and the DOM follows it. This is
32
+ * the same conclusion `Field` reached about `createLinkedIds` — the
33
+ * state kind is real and this is not its shape.
34
+ *
35
+ * ### The cell is the gridcell
36
+ *
37
+ * `<td tabindex>` rather than `<td><button>`. It is the APG date
38
+ * picker's own structure, it keeps exactly one tab stop in the grid
39
+ * (which `expectAgentDrivable` checks), and it avoids a focusable
40
+ * button inside a focusable cell — two tab stops per day, which is
41
+ * what the naive build produces.
42
+ *
43
+ * Each cell's accessible name is the **whole date**, formatted in
44
+ * the active locale: "Wednesday, August 19, 2026", not "19". A
45
+ * screen reader reading a bare number in a grid with no row or
46
+ * column headers announced is a user counting cells, and
47
+ * `getByRole("gridcell", { name: … })` becomes unusable the moment
48
+ * two months are on screen.
49
+ */
50
+ export const DateGrid = ({ firstDayOfWeek, focusedDate, gridMonth, isGridFocused, isRange, label, locale, maximum, minimum, onFocusDate, onHoverDate, onSelectDate, previewEnd, rangeStart, selectedDates, today, }) => {
51
+ const cellElements = useRef(new Map());
52
+ const daysInMonth = getDaysInMonth(gridMonth.year, gridMonth.month);
53
+ const firstOfMonth = {
54
+ day: 1,
55
+ month: gridMonth.month,
56
+ year: gridMonth.year,
57
+ };
58
+ const leadingBlanks = (getWeekday(firstOfMonth) - firstDayOfWeek + 7) % 7;
59
+ const days = Array.from({ length: daysInMonth }, (_unused, index) => ({
60
+ day: index + 1,
61
+ month: gridMonth.month,
62
+ year: gridMonth.year,
63
+ }));
64
+ const getIsEnabled = (date) => getIsWithinRange(date, minimum, maximum);
65
+ const isFocusInThisMonth = focusedDate.month === gridMonth.month &&
66
+ focusedDate.year === gridMonth.year;
67
+ /**
68
+ * Exactly one cell in this grid is in the tab order. When the
69
+ * focused date is in another month — the second grid of a range
70
+ * picker — the tab stop falls to the first day this grid *can*
71
+ * offer, because a grid with zero tab stops strands the widget and
72
+ * a grid where every cell is tabbable is the pattern not being
73
+ * implemented at all.
74
+ */
75
+ const tabStopDate = isFocusInThisMonth
76
+ ? focusedDate
77
+ : (days.find(getIsEnabled) ?? firstOfMonth);
78
+ useEffect(() => {
79
+ if (!isGridFocused || !isFocusInThisMonth) {
80
+ return;
81
+ }
82
+ cellElements.current
83
+ .get(toIsoDate(focusedDate))
84
+ ?.focus();
85
+ }, [focusedDate, isFocusInThisMonth, isGridFocused]);
86
+ const moveFocus = (date) => {
87
+ onFocusDate(clampPlainDate(date, minimum, maximum));
88
+ };
89
+ const handleKeyDown = (keyEvent) => {
90
+ const moves = {
91
+ ArrowDown: () => addDays(focusedDate, 7),
92
+ ArrowLeft: () => addDays(focusedDate, -1),
93
+ ArrowRight: () => addDays(focusedDate, 1),
94
+ ArrowUp: () => addDays(focusedDate, -7),
95
+ End: () => addDays(focusedDate, 6 -
96
+ ((getWeekday(focusedDate) -
97
+ firstDayOfWeek +
98
+ 7) %
99
+ 7)),
100
+ Home: () => addDays(focusedDate, -((getWeekday(focusedDate) - firstDayOfWeek + 7) %
101
+ 7)),
102
+ PageDown: () => addMonths(focusedDate, keyEvent.shiftKey ? 12 : 1),
103
+ PageUp: () => addMonths(focusedDate, keyEvent.shiftKey ? -12 : -1),
104
+ };
105
+ const move = moves[keyEvent.key];
106
+ if (move) {
107
+ // Arrows scroll the page by default, and PageUp/PageDown scroll
108
+ // it a long way. A calendar that pages the document while it
109
+ // pages the month is the hand-rolled version of this component.
110
+ keyEvent.preventDefault();
111
+ moveFocus(move());
112
+ return;
113
+ }
114
+ if (keyEvent.key === "Enter" || keyEvent.key === " ") {
115
+ keyEvent.preventDefault();
116
+ if (getIsEnabled(focusedDate)) {
117
+ onSelectDate(focusedDate);
118
+ }
119
+ }
120
+ };
121
+ const weekdayNames = {
122
+ long: getWeekdayNames({
123
+ firstDayOfWeek,
124
+ locale,
125
+ weekday: "long",
126
+ }),
127
+ narrow: getWeekdayNames({
128
+ firstDayOfWeek,
129
+ locale,
130
+ weekday: "narrow",
131
+ }),
132
+ short: getWeekdayNames({
133
+ firstDayOfWeek,
134
+ locale,
135
+ weekday: "short",
136
+ }),
137
+ };
138
+ /**
139
+ * The band being painted right now: the committed pair, or the
140
+ * committed start plus whatever the pointer or the keyboard is
141
+ * currently over. Ordered, so a backwards drag paints forwards.
142
+ */
143
+ const bandFrom = previewEnd && rangeStart
144
+ ? comparePlainDates(previewEnd, rangeStart) < 0
145
+ ? previewEnd
146
+ : rangeStart
147
+ : null;
148
+ const bandTo = previewEnd && rangeStart
149
+ ? comparePlainDates(previewEnd, rangeStart) < 0
150
+ ? rangeStart
151
+ : previewEnd
152
+ : null;
153
+ const isBandWiderThanADay = bandFrom !== null &&
154
+ bandTo !== null &&
155
+ !getIsSameDay(bandFrom, bandTo);
156
+ /**
157
+ * Every cell of every week, including the neighbouring months'
158
+ * days, each keyed by its own real date.
159
+ *
160
+ * Keying a blank cell by its position in the array is the obvious
161
+ * thing and it is wrong twice over: React reuses the wrong node
162
+ * when the month changes length, and the lint rule that says so is
163
+ * right. A leading blank in August *is* a day in July; it has an
164
+ * ISO date whether or not it is drawn.
165
+ */
166
+ const weeks = Array.from({
167
+ length: Math.ceil((leadingBlanks + daysInMonth) / 7),
168
+ }, (_unused, weekIndex) => Array.from({ length: 7 }, (_blank, dayIndex) => addDays(firstOfMonth, weekIndex * 7 + dayIndex - leadingBlanks)));
169
+ return (_jsxs("table", { "aria-label": label, className: "w-full border-collapse", onMouseLeave: () => {
170
+ onHoverDate(null);
171
+ },
172
+ // biome-ignore lint/a11y/noNoninteractiveElementToInteractiveRole: a calendar IS the ARIA spec's own worked example of `role="grid"` on a `<table>` — an interactive grid whose cells take roving focus. Biome's advice ("replace table with a div") trades correct table semantics for five more suppressions on the div rebuild. It has to sit on the line immediately above the attribute: a biome suppression covers the NEXT LINE, not the next node, so one placed above a multi-line `<table` covers only the tag name — and `yarn lint` runs `--write --unsafe`, so a misplaced one deletes the role silently and the widget degrades to a static `role="table"`.
173
+ role: "grid", children: [_jsx("thead", { children: _jsx("tr", { children: weekdayNames.long.map((longName, index) => (_jsxs("th", { className: "pb-1 font-medium text-content-secondary text-xs", scope: "col", children: [_jsx("span", { "aria-hidden": "true", className: "cq-xs:hidden", children: weekdayNames.narrow[index] }), _jsx("span", { "aria-hidden": "true", className: "hidden cq-xs:inline", children: weekdayNames.short[index] }), _jsx(VisuallyHidden, { children: longName })] }, longName))) }) }), _jsx("tbody", { children: weeks.map((week) => (_jsx("tr", { children: week.map((date) => {
174
+ const isoDate = toIsoDate(date);
175
+ if (date.month !== gridMonth.month) {
176
+ return (_jsx("td", { "aria-hidden": "true", className: "p-0", children: _jsx("span", { className: "block size-8 cq-xs:size-9 cq-sm:size-10" }) }, isoDate));
177
+ }
178
+ const isEnabled = getIsEnabled(date);
179
+ const isSelected = selectedDates.some((one) => getIsSameDay(one, date));
180
+ const isInBand = isRange &&
181
+ isBandWiderThanADay &&
182
+ bandFrom !== null &&
183
+ bandTo !== null &&
184
+ comparePlainDates(date, bandFrom) >= 0 &&
185
+ comparePlainDates(date, bandTo) <= 0;
186
+ return (_jsx("td", { "aria-current": getIsSameDay(today, date)
187
+ ? "date"
188
+ : undefined, "aria-disabled": isEnabled ? undefined : true, "aria-label": formatPlainDate(date, {
189
+ dateStyle: "full",
190
+ locale,
191
+ }), "aria-selected": isSelected, className: toClassName(CELL_BASE_CLASS, FOCUS_RING_CLASS, !isEnabled && "cursor-not-allowed", isInBand && "bg-intent-accent-surface", isInBand &&
192
+ bandFrom !== null &&
193
+ getIsSameDay(bandFrom, date) &&
194
+ "rounded-s-md", isInBand &&
195
+ bandTo !== null &&
196
+ getIsSameDay(bandTo, date) &&
197
+ "rounded-e-md"), onClick: () => {
198
+ if (isEnabled) {
199
+ onSelectDate(date);
200
+ }
201
+ }, onKeyDown: handleKeyDown, onMouseEnter: () => {
202
+ onHoverDate(date);
203
+ }, ref: (element) => {
204
+ if (element) {
205
+ cellElements.current.set(isoDate, element);
206
+ }
207
+ else {
208
+ cellElements.current.delete(isoDate);
209
+ }
210
+ },
211
+ // biome-ignore lint/a11y/noNoninteractiveElementToInteractiveRole: the APG date-picker's own structure — the `<td>` IS the gridcell and carries the roving tabindex, rather than wrapping a `<button>` and putting 31 tab stops in one month. A `<td>`'s implicit role is `cell`, so `gridcell` is the one role the platform does not already imply, and `aria-selected` is not supported without it.
212
+ role: "gridcell", tabIndex: getIsSameDay(tabStopDate, date) ? 0 : -1, children: _jsx("span", { "aria-hidden": "true", className: toClassName(DAY_BASE_CLASS, isSelected &&
213
+ "bg-intent-accent-solid text-intent-accent-on-solid", !isSelected &&
214
+ getIsSameDay(today, date) &&
215
+ "border-intent-accent-border font-semibold", !isSelected &&
216
+ isEnabled &&
217
+ "hover:bg-intent-neutral-surface-hover", !isEnabled && "text-content-disabled"), children: date.day }) }, isoDate));
218
+ }) }, toIsoDate(week[0] ?? firstOfMonth)))) })] }));
219
+ };
220
+ //# sourceMappingURL=DateGrid.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DateGrid.js","sourceRoot":"","sources":["../../src/DatePicker/DateGrid.tsx"],"names":[],"mappings":"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"}