@crewlethq/ui 0.38.0 → 0.40.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 (157) hide show
  1. package/README.md +79 -3
  2. package/dist/AgentHandoffPanel/index.js +3 -3
  3. package/dist/AppShell/AppShell.d.ts +13 -2
  4. package/dist/AppShell/index.js +1 -1
  5. package/dist/{AppShell-NDU4XMGF.css → AppShell-NPSWZ3XW.css} +45 -4
  6. package/dist/ArtifactBar/index.js +6 -5
  7. package/dist/{ArtifactBar-FWPBBKQ5.css → ArtifactBar-6PGWGKN2.css} +13 -1
  8. package/dist/ArtifactCard/index.js +2 -2
  9. package/dist/AuthLayout/index.js +2 -2
  10. package/dist/AvatarPicker/index.js +10 -6
  11. package/dist/Card/Card.d.ts +14 -2
  12. package/dist/Card/index.js +1 -1
  13. package/dist/{Card-G2ZGT5Z6.css → Card-JR2UPQH7.css} +20 -0
  14. package/dist/CatalogTile/CatalogTile.d.ts +47 -0
  15. package/dist/CatalogTile/index.d.ts +3 -0
  16. package/dist/CatalogTile/index.js +3 -0
  17. package/dist/CatalogTile-XL4XLFUH.css +135 -0
  18. package/dist/CharacterPicker/index.js +2 -2
  19. package/dist/Charts/Histogram.d.ts +71 -0
  20. package/dist/Charts/index.d.ts +2 -0
  21. package/dist/Charts/index.js +1 -1
  22. package/dist/{Charts-MBJG72BS.css → Charts-TZ744HT6.css} +118 -0
  23. package/dist/CodeBlock/index.js +1 -1
  24. package/dist/{CodeBlock-GYNJ2HI6.css → CodeBlock-N5ETJF24.css} +13 -0
  25. package/dist/CommandPalette/index.js +3 -3
  26. package/dist/CommentThread/index.js +3 -3
  27. package/dist/Composer/index.js +2 -2
  28. package/dist/DataGrid/DataGrid.d.ts +267 -0
  29. package/dist/DataGrid/index.d.ts +3 -0
  30. package/dist/DataGrid/index.js +7 -0
  31. package/dist/DataGrid-AQKPJD7W.css +482 -0
  32. package/dist/DataTable/index.js +2 -2
  33. package/dist/DataView/index.js +4 -4
  34. package/dist/DatasetSource/DatasetSource.d.ts +7 -1
  35. package/dist/DatasetSource/index.js +1 -1
  36. package/dist/HuePicker/index.js +11 -4
  37. package/dist/LayersList/index.js +2 -2
  38. package/dist/LinkInterstitial/index.js +2 -2
  39. package/dist/List/List.d.ts +8 -0
  40. package/dist/List/index.js +1 -1
  41. package/dist/{List-MYJIV6MP.css → List-YHLIZFK4.css} +46 -0
  42. package/dist/ListInput/ListInput.d.ts +9 -1
  43. package/dist/ListInput/index.js +2 -2
  44. package/dist/LockedLabel/LockedLabel.d.ts +34 -0
  45. package/dist/LockedLabel/index.d.ts +3 -0
  46. package/dist/LockedLabel/index.js +3 -0
  47. package/dist/LockedLabel-VQEGEB7G.css +16 -0
  48. package/dist/MarkdownEditor/index.js +8 -5
  49. package/dist/MergeConflicts/index.js +11 -5
  50. package/dist/Modal/index.js +1 -1
  51. package/dist/{Modal-7MWRCWAI.css → Modal-TOEWHDCQ.css} +5 -0
  52. package/dist/ObjectHeader/index.js +1 -1
  53. package/dist/{ObjectHeader-D7GU7QNI.css → ObjectHeader-ZOS22FKX.css} +7 -8
  54. package/dist/PageNote/PageNote.d.ts +14 -0
  55. package/dist/PageNote/index.d.ts +3 -0
  56. package/dist/PageNote/index.js +2 -0
  57. package/dist/PageNote-RHLXH3ML.css +12 -0
  58. package/dist/PropertyList/PropertyList.d.ts +88 -0
  59. package/dist/PropertyList/index.d.ts +3 -0
  60. package/dist/PropertyList/index.js +7 -0
  61. package/dist/PropertyList-SCYM66LL.css +96 -0
  62. package/dist/RelatedRow/RelatedRow.d.ts +27 -0
  63. package/dist/RelatedRow/index.d.ts +3 -0
  64. package/dist/RelatedRow/index.js +9 -0
  65. package/dist/RelatedRow-2FVS6QQA.css +6 -0
  66. package/dist/RichEditor/index.js +1 -1
  67. package/dist/SectionFrame/SectionFrame.d.ts +76 -0
  68. package/dist/SectionFrame/index.d.ts +3 -0
  69. package/dist/SectionFrame/index.js +7 -0
  70. package/dist/SectionFrame-M62UUVFQ.css +164 -0
  71. package/dist/SegmentedControl/index.js +11 -4
  72. package/dist/SettingsTable/SettingsTable.d.ts +66 -0
  73. package/dist/SettingsTable/index.d.ts +3 -0
  74. package/dist/SettingsTable/index.js +3 -0
  75. package/dist/SettingsTable-6DUFAFXG.css +160 -0
  76. package/dist/ShareDialog/index.js +2 -2
  77. package/dist/SheetColumnEditor/index.js +7 -6
  78. package/dist/SheetGrid/index.js +3 -3
  79. package/dist/SidebarNav/SidebarNav.d.ts +35 -2
  80. package/dist/SidebarNav/index.js +2 -1
  81. package/dist/{SidebarNav-7SGUZYKK.css → SidebarNav-YI74SPDC.css} +10 -0
  82. package/dist/StatCard/index.js +1 -1
  83. package/dist/{StatCard-4T7TMWMN.css → StatCard-HAA3F5GX.css} +8 -3
  84. package/dist/StatGroup/index.js +1 -1
  85. package/dist/{StatGroup-DOFHX5QJ.css → StatGroup-ZMW7VQWP.css} +27 -0
  86. package/dist/Switcher/index.js +2 -2
  87. package/dist/Tabs/Tabs.d.ts +55 -1
  88. package/dist/Tabs/fold.d.ts +54 -0
  89. package/dist/Tabs/index.d.ts +1 -1
  90. package/dist/Tabs/index.js +9 -2
  91. package/dist/Tabs/roving.d.ts +3 -3
  92. package/dist/{Tabs-WIF7457H.css → Tabs-S7F4RWAN.css} +77 -0
  93. package/dist/TagsInput/index.js +1 -1
  94. package/dist/ThemeGallery/index.js +2 -2
  95. package/dist/ThemeSwitcher/index.js +12 -5
  96. package/dist/TileGrid/TileGrid.d.ts +33 -0
  97. package/dist/TileGrid/index.d.ts +3 -0
  98. package/dist/TileGrid/index.js +2 -0
  99. package/dist/TileGrid-I6LNYD2H.css +52 -0
  100. package/dist/VersionCompare/index.js +12 -5
  101. package/dist/{chunk-B5J23C73.js → chunk-2PEXZ7L4.js} +1 -1
  102. package/dist/{chunk-S27UBCVX.js → chunk-2VOHUGUA.js} +2 -2
  103. package/dist/{chunk-XBURIXHO.js → chunk-3TXY3PJZ.js} +1 -1
  104. package/dist/{chunk-2QZ2VPHR.js → chunk-4OK4DX3V.js} +2 -2
  105. package/dist/chunk-4RKTZSEW.js +64 -0
  106. package/dist/{chunk-ECGGQX2H.js → chunk-A44YHLCQ.js} +2 -2
  107. package/dist/{chunk-F4LPQA4E.js → chunk-BA32AVKS.js} +1 -1
  108. package/dist/chunk-CV4NES3P.js +9 -0
  109. package/dist/{chunk-PPHTIKZO.js → chunk-E4BOVKNJ.js} +1 -1
  110. package/dist/{chunk-W7PAIVAP.js → chunk-E7QLG3PG.js} +30 -9
  111. package/dist/{chunk-RKKO7QHH.js → chunk-EGMQURBR.js} +5 -4
  112. package/dist/{chunk-GMW4ZHST.js → chunk-EX22Q5SH.js} +2 -2
  113. package/dist/{chunk-A23KDROH.js → chunk-FXBGEANQ.js} +1 -1
  114. package/dist/{chunk-4L2BWSHR.js → chunk-GFYQKMQZ.js} +2 -2
  115. package/dist/{chunk-HG5VF3TZ.js → chunk-HMVQQEHW.js} +91 -2
  116. package/dist/{chunk-IPWU6ERC.js → chunk-HQJ24WPM.js} +4 -2
  117. package/dist/{chunk-SVGARBDY.js → chunk-IAGYPTEJ.js} +2 -2
  118. package/dist/{chunk-ZK3VYY7L.js → chunk-INHXF2CL.js} +24 -11
  119. package/dist/chunk-INVSUFJK.js +71 -0
  120. package/dist/{chunk-6NNY5WBF.js → chunk-JKAGN4V4.js} +1 -1
  121. package/dist/{chunk-4LRAJXHL.js → chunk-JSWOXRRE.js} +1 -1
  122. package/dist/{chunk-DYB66CNM.js → chunk-KKNHMXTE.js} +6 -3
  123. package/dist/{chunk-UWRBD2YO.js → chunk-KNHUBHFX.js} +1 -1
  124. package/dist/{chunk-ZMDYQ2HH.js → chunk-KWWP3D7M.js} +1 -1
  125. package/dist/{chunk-46RL3E54.js → chunk-M6NQ4XGK.js} +1 -1
  126. package/dist/{chunk-PT6WKXKW.js → chunk-MMPKN7WV.js} +1 -1
  127. package/dist/{chunk-NRBAXRWE.js → chunk-N3TFYBN3.js} +1 -1
  128. package/dist/chunk-NNTO3TNC.js +9 -0
  129. package/dist/{chunk-DS2C73RJ.js → chunk-NZWX27J7.js} +2 -2
  130. package/dist/{chunk-VGE3G3T4.js → chunk-ODOJJGXH.js} +1 -1
  131. package/dist/chunk-OHGH7O6T.js +19 -0
  132. package/dist/{chunk-4ISUIS6F.js → chunk-OOC7Q67K.js} +1 -1
  133. package/dist/{chunk-BT5H2THK.js → chunk-OUD75UB2.js} +1 -1
  134. package/dist/chunk-PCT47E7O.js +48 -0
  135. package/dist/{chunk-X3UYTAOG.js → chunk-PFZOFAQ6.js} +1 -1
  136. package/dist/{chunk-YQG4PZGC.js → chunk-QRKT4XTT.js} +2 -2
  137. package/dist/{chunk-BJI3RFXG.js → chunk-S4DREXGM.js} +1 -1
  138. package/dist/{chunk-GDDE4UM7.js → chunk-SEC2GR2V.js} +1 -1
  139. package/dist/{chunk-YEVG2X5R.js → chunk-SNQRGH4A.js} +1 -1
  140. package/dist/chunk-T6MXORP5.js +116 -0
  141. package/dist/{chunk-OTCXRJ7D.js → chunk-U2XAJONO.js} +1 -1
  142. package/dist/{chunk-3ZUINC7C.js → chunk-WYYCPV46.js} +6 -1
  143. package/dist/chunk-X4IXXLWM.js +306 -0
  144. package/dist/{chunk-PAQXOP2M.js → chunk-XGBUUQDU.js} +2 -2
  145. package/dist/chunk-XIDD7PJO.js +416 -0
  146. package/dist/{chunk-XO7PUL4F.js → chunk-YPTTSJPM.js} +1 -1
  147. package/dist/chunk-ZUTUI27P.js +21 -0
  148. package/dist/generated/index.d.ts +9 -0
  149. package/dist/generated/index.js +83 -74
  150. package/dist/index.js +83 -74
  151. package/dist/styles.css +1627 -104
  152. package/package.json +3 -3
  153. package/dist/chunk-7SDUKCNW.js +0 -141
  154. package/dist/{Editor-QV4JP242.js → Editor-IRDQ3JDZ.js} +1 -1
  155. package/dist/{chunk-JZPK4IXR.js → chunk-3PR65I3H.js} +2 -2
  156. package/dist/{chunk-ETVEGR2Y.js → chunk-ISA2O2BK.js} +1 -1
  157. /package/dist/{chunk-4QQ3MND5.js → chunk-S3QTFUJX.js} +0 -0
@@ -0,0 +1,416 @@
1
+ import { EmptyState } from './chunk-RA2ULG6H.js';
2
+ import { useMediaMatch } from './chunk-RTPQDNW3.js';
3
+ import { Button } from './chunk-OG6CL3EB.js';
4
+ import { VisuallyHidden } from './chunk-BZFWDIV6.js';
5
+ import { cx } from './chunk-ODEQTPFM.js';
6
+ import './DataGrid-AQKPJD7W.css';
7
+ import { useId, useRef, useState, useMemo, useCallback, useLayoutEffect, useImperativeHandle } from 'react';
8
+ import { breakpoint } from '@crewlethq/tokens';
9
+ import { ChevronDownGlyph, ChevronUpGlyph } from '@crewlethq/icons/glyphs';
10
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
11
+
12
+ function columnChoicesOf(columns) {
13
+ return columns.map((column) => ({
14
+ key: column.key,
15
+ label: headerWord(column) || column.label || column.key,
16
+ optional: column.optional
17
+ }));
18
+ }
19
+ function ChooserList({ label, items, onToggle }) {
20
+ const headingId = useId();
21
+ if (items.length === 0) return null;
22
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
23
+ /* @__PURE__ */ jsx("div", { className: "crewlet-column-chooser__label", id: headingId, children: label }),
24
+ /* @__PURE__ */ jsx("div", { className: "crewlet-column-chooser__choices", role: "group", "aria-labelledby": headingId, children: items.map((item) => /* @__PURE__ */ jsxs("label", { className: "crewlet-column-chooser__choice", children: [
25
+ /* @__PURE__ */ jsx("input", { type: "checkbox", checked: item.checked, onChange: () => onToggle(item.key) }),
26
+ /* @__PURE__ */ jsx("span", { children: item.label })
27
+ ] }, item.key)) })
28
+ ] });
29
+ }
30
+ function ColumnChooser({ choices, value, onChange, label = "Columns" }) {
31
+ const chosen = new Set(value ? value.split(",").filter(Boolean) : []);
32
+ const isOn = (choice) => chosen.size === 0 ? !choice.optional : chosen.has(choice.key);
33
+ return /* @__PURE__ */ jsx(
34
+ ChooserList,
35
+ {
36
+ label,
37
+ items: choices.map((choice) => ({ key: choice.key, label: choice.label, checked: isOn(choice) })),
38
+ onToggle: (key) => {
39
+ const next = new Set(choices.filter(isOn).map((c) => c.key));
40
+ if (next.has(key)) next.delete(key);
41
+ else next.add(key);
42
+ onChange(
43
+ choices.filter((c) => next.has(c.key)).map((c) => c.key).join(",")
44
+ );
45
+ }
46
+ }
47
+ );
48
+ }
49
+ var LABELS = {
50
+ hiddenToFit: (names) => `Hidden to fit: ${names}`,
51
+ loadMore: "Load more",
52
+ showEveryColumn: "Show every column",
53
+ and: "and"
54
+ };
55
+ function parseGridSort(raw) {
56
+ if (!raw) return null;
57
+ return raw.startsWith("-") ? { key: raw.slice(1), desc: true } : { key: raw, desc: false };
58
+ }
59
+ function headerWord(column) {
60
+ return typeof column.header === "string" ? column.header : "";
61
+ }
62
+ function bandRows(band) {
63
+ return band.bands ? band.bands.flatMap(bandRows) : band.rows;
64
+ }
65
+ function compare(a, b) {
66
+ if (typeof a === "number" && typeof b === "number") {
67
+ if (Number.isNaN(a)) return Number.isNaN(b) ? 0 : 1;
68
+ if (Number.isNaN(b)) return -1;
69
+ return a < b ? -1 : a > b ? 1 : 0;
70
+ }
71
+ return String(a).localeCompare(String(b), void 0, { numeric: true, sensitivity: "base" });
72
+ }
73
+ var SHRINK_CAP = "20%";
74
+ var SHRINK_SHARE = 0.2;
75
+ var SQUEEZE_SAMPLE_ROWS = 12;
76
+ var NO_DROPS = [];
77
+ var NO_FIT = { set: "", width: 0, dropped: NO_DROPS };
78
+ function fitGridColumns({
79
+ fit,
80
+ width,
81
+ overflows,
82
+ visible
83
+ }) {
84
+ if (fit.dropped.length > 0 && width > fit.width) {
85
+ return { set: fit.set, width, dropped: NO_DROPS };
86
+ }
87
+ if (overflows) {
88
+ let next;
89
+ for (const c of visible) {
90
+ if (c.drop === void 0) continue;
91
+ if (!next || c.drop < next.drop) next = c;
92
+ }
93
+ if (next) return { set: fit.set, width, dropped: [...fit.dropped, next.key] };
94
+ }
95
+ if (width !== fit.width && (fit.dropped.length > 0 || fit.width === 0)) {
96
+ return { ...fit, width };
97
+ }
98
+ return null;
99
+ }
100
+ function overflowing(wrap) {
101
+ const last = wrap.querySelector(":scope > .crewlet-data-grid__head")?.lastElementChild;
102
+ if (!last) return false;
103
+ const inner = wrap.getBoundingClientRect().left + wrap.clientLeft + wrap.clientWidth;
104
+ return last.getBoundingClientRect().right > inner + 0.5;
105
+ }
106
+ function squeezed(wrap, visible) {
107
+ const heads = wrap.querySelector(":scope > .crewlet-data-grid__head")?.children;
108
+ if (!heads) return false;
109
+ const cap = wrap.clientWidth * SHRINK_SHARE - 1;
110
+ const rows = [...wrap.querySelectorAll(":scope > .crewlet-data-grid__body .crewlet-data-grid__row")].slice(
111
+ 0,
112
+ SQUEEZE_SAMPLE_ROWS
113
+ );
114
+ for (let i = 0; i < visible.length; i++) {
115
+ const column = visible[i];
116
+ if (!column.shrink || column.width) continue;
117
+ const head = heads[i];
118
+ if (!head || head.getBoundingClientRect().width >= cap) continue;
119
+ for (const row of rows) {
120
+ const cell = row.querySelectorAll(":scope > .crewlet-data-grid__cell")[i];
121
+ if (cell && cutShort(cell)) return true;
122
+ }
123
+ }
124
+ return false;
125
+ }
126
+ function cutShort(el) {
127
+ for (const node of [el, ...el.querySelectorAll("*")]) {
128
+ const box = node;
129
+ if (box.clientWidth > 1 && box.scrollWidth > box.clientWidth + 1) return true;
130
+ }
131
+ return false;
132
+ }
133
+ function droppedNames(columns, dropped, and) {
134
+ const names = dropped.map((key) => {
135
+ const c = columns.find((col) => col.key === key);
136
+ return c && (headerWord(c) || c.label) || key;
137
+ });
138
+ return names.length <= 1 ? names[0] ?? "" : `${names.slice(0, -1).join(", ")} ${and} ${names[names.length - 1]}`;
139
+ }
140
+ function DataGrid({
141
+ rows,
142
+ bands,
143
+ columns,
144
+ rowKey,
145
+ onRowActivate,
146
+ rowHref,
147
+ isSelected,
148
+ isFailed,
149
+ sort: sortRaw = "",
150
+ onSortChange,
151
+ serverSorted = false,
152
+ cols: colsRaw = "",
153
+ onColsChange,
154
+ empty,
155
+ footer,
156
+ onLoadMore,
157
+ loadedNote,
158
+ phoneRows = "labelled",
159
+ flush = false,
160
+ handleRef,
161
+ onPointerDown,
162
+ labels,
163
+ "aria-label": ariaLabel,
164
+ "aria-labelledby": ariaLabelledby,
165
+ className
166
+ }) {
167
+ const text = { ...LABELS, ...labels };
168
+ const sort = parseGridSort(sortRaw);
169
+ const body = useRef(null);
170
+ const [cursor, setCursor] = useState(-1);
171
+ const gridId = useId();
172
+ const shownColumns = useMemo(() => {
173
+ const asked = colsRaw.split(",").map((c) => c.trim()).filter(Boolean);
174
+ if (asked.length === 0) return columns.filter((c) => !c.optional);
175
+ const byKey = new Map(columns.map((c) => [c.key, c]));
176
+ const picked = asked.map((key) => byKey.get(key)).filter((c) => !!c);
177
+ return picked.length > 0 ? picked : columns.filter((c) => !c.optional);
178
+ }, [columns, colsRaw]);
179
+ const [wrap, setWrap] = useState(null);
180
+ const phone = useMediaMatch(`(width < ${breakpoint.phone})`);
181
+ const shownKeys = shownColumns.map((c) => c.key).join(",");
182
+ const [fit, setFit] = useState(NO_FIT);
183
+ const dropped = !phone && fit.set === shownKeys ? fit.dropped : NO_DROPS;
184
+ const visibleColumns = useMemo(
185
+ () => dropped.length === 0 ? shownColumns : shownColumns.filter((c) => !dropped.includes(c.key)),
186
+ [shownColumns, dropped]
187
+ );
188
+ const sortRows = useCallback(
189
+ (input) => {
190
+ if (!sort || serverSorted) return input;
191
+ const column = columns.find((c) => c.key === sort.key);
192
+ if (!column?.sortValue) return input;
193
+ const get = column.sortValue;
194
+ return [...input].sort((a, b) => {
195
+ const av = get(a);
196
+ const bv = get(b);
197
+ if (av == null && bv == null) return 0;
198
+ if (av == null) return 1;
199
+ if (bv == null) return -1;
200
+ const cmp = compare(av, bv);
201
+ return sort.desc ? -cmp : cmp;
202
+ });
203
+ },
204
+ [columns, sort, serverSorted]
205
+ );
206
+ const flat = useMemo(() => {
207
+ const walk = (band) => band.bands ? band.bands.flatMap(walk) : sortRows(band.rows);
208
+ if (bands) return bands.flatMap(walk);
209
+ return sortRows(rows ?? []);
210
+ }, [bands, rows, sortRows]);
211
+ const [boxWidth, setBoxWidth] = useState(0);
212
+ useLayoutEffect(() => {
213
+ if (!wrap || typeof ResizeObserver !== "function") return;
214
+ const watch = new ResizeObserver(() => setBoxWidth(wrap.clientWidth));
215
+ watch.observe(wrap);
216
+ return () => watch.disconnect();
217
+ }, [wrap]);
218
+ useLayoutEffect(() => {
219
+ const el = wrap;
220
+ if (!el || phone) return;
221
+ const next = fitGridColumns({
222
+ fit: fit.set === shownKeys ? fit : { ...NO_FIT, set: shownKeys },
223
+ width: el.clientWidth,
224
+ overflows: overflowing(el) || squeezed(el, visibleColumns),
225
+ visible: visibleColumns
226
+ });
227
+ if (next !== null) setFit(next);
228
+ }, [wrap, phone, fit, shownKeys, visibleColumns, flat, boxWidth]);
229
+ useImperativeHandle(
230
+ handleRef,
231
+ () => ({
232
+ step: (by) => setCursor((at) => {
233
+ const next = Math.max(0, Math.min(flat.length - 1, at + by));
234
+ body.current?.querySelector(`[data-row-index="${next}"]`)?.scrollIntoView({ block: "nearest" });
235
+ return next;
236
+ }),
237
+ activate: (event) => {
238
+ const row = flat[cursor];
239
+ if (row === void 0 || !onRowActivate) return false;
240
+ onRowActivate(row, event);
241
+ return true;
242
+ },
243
+ rowCount: () => flat.length
244
+ }),
245
+ [flat, cursor, onRowActivate]
246
+ );
247
+ function headerClick(column) {
248
+ if (!column.sortValue || !onSortChange) return;
249
+ if (sort?.key === column.key && !sort.desc) onSortChange(`-${column.key}`);
250
+ else if (sort?.key === column.key && sort.desc) onSortChange("");
251
+ else onSortChange(column.key);
252
+ }
253
+ const template = visibleColumns.map((c) => c.width ?? (c.shrink ? `fit-content(${SHRINK_CAP})` : `minmax(${c.floor ?? 0}, 1fr)`)).join(" ");
254
+ if (flat.length === 0 && !bands?.length && empty) {
255
+ return /* @__PURE__ */ jsx("div", { className: cx("crewlet-data-grid", className), "data-flush": flush || void 0, children: /* @__PURE__ */ jsx(
256
+ EmptyState,
257
+ {
258
+ size: "compact",
259
+ icon: empty.icon,
260
+ title: empty.title,
261
+ description: empty.hint,
262
+ action: empty.action
263
+ }
264
+ ) });
265
+ }
266
+ let index = -1;
267
+ function renderRow(row) {
268
+ index += 1;
269
+ const at = index;
270
+ const link = rowHref?.(row);
271
+ const marked = Boolean(isSelected?.(row));
272
+ const rowId = `${gridId}-row-${at}`;
273
+ const overlay = link !== void 0 ? (
274
+ // eslint-disable-next-line jsx-a11y/anchor-has-content
275
+ /* @__PURE__ */ jsx(
276
+ "a",
277
+ {
278
+ className: "crewlet-data-grid__row-link",
279
+ href: link,
280
+ "aria-labelledby": rowId,
281
+ "aria-current": marked ? "true" : void 0,
282
+ onClick: (e) => onRowActivate?.(row, e)
283
+ }
284
+ )
285
+ ) : onRowActivate ? /* @__PURE__ */ jsx(
286
+ "button",
287
+ {
288
+ type: "button",
289
+ className: "crewlet-data-grid__row-link",
290
+ "aria-labelledby": rowId,
291
+ "aria-current": marked ? "true" : void 0,
292
+ onClick: (e) => onRowActivate(row, e)
293
+ }
294
+ ) : null;
295
+ const inner = visibleColumns.map((column, i) => /* @__PURE__ */ jsxs(
296
+ "span",
297
+ {
298
+ role: "cell",
299
+ className: cx(
300
+ "crewlet-data-grid__cell",
301
+ column.align === "right" && "crewlet-data-grid__cell--right",
302
+ column.shrink && "crewlet-data-grid__cell--shrink"
303
+ ),
304
+ "data-lead": column.phoneLead || void 0,
305
+ "data-phone-omit": column.phoneOmit || void 0,
306
+ "data-label": column.action ? void 0 : headerWord(column) || column.label || void 0,
307
+ children: [
308
+ i === 0 ? overlay : null,
309
+ column.cell(row)
310
+ ]
311
+ },
312
+ column.key
313
+ ));
314
+ return /* @__PURE__ */ jsx(
315
+ "div",
316
+ {
317
+ id: rowId,
318
+ role: "row",
319
+ className: cx(
320
+ "crewlet-data-grid__row",
321
+ marked && "crewlet-data-grid__row--selected",
322
+ isFailed?.(row) && "crewlet-data-grid__row--failed",
323
+ cursor === at && "crewlet-data-grid__row--cursor"
324
+ ),
325
+ "data-row-index": at,
326
+ "aria-current": overlay === null && marked ? "true" : void 0,
327
+ children: inner
328
+ },
329
+ rowKey(row)
330
+ );
331
+ }
332
+ function renderBand(band) {
333
+ const loaded = bandRows(band).length;
334
+ return (
335
+ // A BAND IS ROWS OF THE TABLE: its head and its foot are rows of one
336
+ // cell each across every column, and its own box is layout alone.
337
+ /* @__PURE__ */ jsxs("div", { className: "crewlet-data-grid__band", role: "none", children: [
338
+ /* @__PURE__ */ jsx("div", { className: "crewlet-data-grid__band-head", role: "row", children: /* @__PURE__ */ jsxs("span", { className: "crewlet-data-grid__band-cell", role: "rowheader", "aria-colspan": visibleColumns.length, children: [
339
+ band.mark,
340
+ /* @__PURE__ */ jsx("span", { className: "crewlet-data-grid__truncate", children: band.label }),
341
+ /* @__PURE__ */ jsx("span", { className: "crewlet-data-grid__band-count", children: band.total != null && band.total !== loaded ? `${loaded} of ${band.total}` : loaded })
342
+ ] }) }),
343
+ band.bands ? band.bands.map((sub) => renderBand(sub)) : sortRows(band.rows).map(renderRow),
344
+ band.footer && /* @__PURE__ */ jsx("div", { className: "crewlet-data-grid__band-foot", role: "row", children: /* @__PURE__ */ jsx("span", { className: "crewlet-data-grid__band-cell", role: "cell", "aria-colspan": visibleColumns.length, children: band.footer }) })
345
+ ] }, band.key)
346
+ );
347
+ }
348
+ return /* @__PURE__ */ jsxs(
349
+ "div",
350
+ {
351
+ ref: setWrap,
352
+ role: "table",
353
+ "aria-label": ariaLabel,
354
+ "aria-labelledby": ariaLabelledby,
355
+ className: cx("crewlet-data-grid", className),
356
+ "data-phone-rows": phoneRows === "compact" ? "compact" : void 0,
357
+ "data-flush": flush || void 0,
358
+ style: { gridTemplateColumns: template },
359
+ onPointerDown,
360
+ children: [
361
+ /* @__PURE__ */ jsx("div", { className: "crewlet-data-grid__head", role: "row", children: visibleColumns.map((column) => {
362
+ const sorted = sort?.key === column.key;
363
+ const sortable = Boolean(column.sortValue && onSortChange);
364
+ const headClass = cx(
365
+ "crewlet-data-grid__th",
366
+ column.align === "right" && "crewlet-data-grid__th--right",
367
+ column.shrink && "crewlet-data-grid__th--shrink",
368
+ sorted && "crewlet-data-grid__th--sorted",
369
+ !sortable && "crewlet-data-grid__th--plain"
370
+ );
371
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
372
+ /* @__PURE__ */ jsx("span", { className: "crewlet-data-grid__truncate", children: column.header }),
373
+ sorted && (sort?.desc ? /* @__PURE__ */ jsx(ChevronDownGlyph, { size: "xs" }) : /* @__PURE__ */ jsx(ChevronUpGlyph, { size: "xs" }))
374
+ ] });
375
+ if (!sortable) {
376
+ const named = !headerWord(column) && !column.action ? column.label : void 0;
377
+ return /* @__PURE__ */ jsxs("div", { className: headClass, role: "columnheader", title: named, children: [
378
+ content,
379
+ named && /* @__PURE__ */ jsx(VisuallyHidden, { children: named })
380
+ ] }, column.key);
381
+ }
382
+ return /* @__PURE__ */ jsx(
383
+ "div",
384
+ {
385
+ className: headClass,
386
+ role: "columnheader",
387
+ "aria-sort": sorted ? sort?.desc ? "descending" : "ascending" : void 0,
388
+ children: /* @__PURE__ */ jsx(
389
+ "button",
390
+ {
391
+ type: "button",
392
+ className: "crewlet-data-grid__sort",
393
+ onClick: () => headerClick(column),
394
+ "aria-label": headerWord(column) ? void 0 : column.label,
395
+ children: content
396
+ }
397
+ )
398
+ },
399
+ column.key
400
+ );
401
+ }) }),
402
+ /* @__PURE__ */ jsx("div", { className: "crewlet-data-grid__body", role: "rowgroup", ref: body, children: bands ? bands.map((band) => renderBand(band)) : sortRows(rows ?? []).map(renderRow) }),
403
+ (footer || onLoadMore || loadedNote || dropped.length > 0) && /* @__PURE__ */ jsxs("div", { className: "crewlet-data-grid__foot", children: [
404
+ footer,
405
+ /* @__PURE__ */ jsx("span", { className: "crewlet-data-grid__foot-spacer", "aria-hidden": "true" }),
406
+ dropped.length > 0 && /* @__PURE__ */ jsx("span", { className: "crewlet-data-grid__note", children: text.hiddenToFit(droppedNames(shownColumns, dropped, text.and)) }),
407
+ loadedNote && /* @__PURE__ */ jsx("span", { className: "crewlet-data-grid__note", children: loadedNote }),
408
+ onLoadMore && /* @__PURE__ */ jsx(Button, { size: "small", variant: "secondary", onClick: onLoadMore, children: text.loadMore })
409
+ ] }),
410
+ colsRaw && onColsChange && /* @__PURE__ */ jsx("button", { type: "button", className: "crewlet-data-grid__cols-reset", onClick: () => onColsChange(""), children: text.showEveryColumn })
411
+ ]
412
+ }
413
+ );
414
+ }
415
+
416
+ export { ChooserList, ColumnChooser, DataGrid, columnChoicesOf, fitGridColumns, parseGridSort };
@@ -1,6 +1,6 @@
1
1
  import { VisuallyHidden } from './chunk-BZFWDIV6.js';
2
2
  import { cx } from './chunk-ODEQTPFM.js';
3
- import './StatCard-4T7TMWMN.css';
3
+ import './StatCard-HAA3F5GX.css';
4
4
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
5
5
 
6
6
  var StatCard = ({
@@ -0,0 +1,21 @@
1
+ import { Text } from './chunk-IKBK4A5O.js';
2
+ import { Inline, Stack, Spacer } from './chunk-ZAC7SKUN.js';
3
+ import { Card } from './chunk-INHXF2CL.js';
4
+ import { cx } from './chunk-ODEQTPFM.js';
5
+ import './RelatedRow-2FVS6QQA.css';
6
+ import { ChevronRightGlyph } from '@crewlethq/icons/glyphs';
7
+ import { jsx, jsxs } from 'react/jsx-runtime';
8
+
9
+ function RelatedRow({ href, icon, title, description, label = "Related", className }) {
10
+ return /* @__PURE__ */ jsx("nav", { "aria-label": label, className: cx("crewlet-related-row", className), children: /* @__PURE__ */ jsx(Card, { href, interactive: true, padding: "sm", children: /* @__PURE__ */ jsxs(Inline, { gap: 3, children: [
11
+ /* @__PURE__ */ jsx("span", { className: "crewlet-related-row__glyph", "aria-hidden": "true", children: icon }),
12
+ /* @__PURE__ */ jsxs(Stack, { gap: 1, children: [
13
+ /* @__PURE__ */ jsx(Text, { variant: "cell", children: title }),
14
+ /* @__PURE__ */ jsx(Text, { variant: "caption", children: description })
15
+ ] }),
16
+ /* @__PURE__ */ jsx(Spacer, {}),
17
+ /* @__PURE__ */ jsx("span", { className: "crewlet-related-row__glyph", "aria-hidden": "true", children: /* @__PURE__ */ jsx(ChevronRightGlyph, { size: "sm" }) })
18
+ ] }) }) });
19
+ }
20
+
21
+ export { RelatedRow };
@@ -32,6 +32,7 @@ export * from '../CanvasBoard/index.js';
32
32
  export * from '../CanvasSchematic/index.js';
33
33
  export * from '../CanvasToolbar/index.js';
34
34
  export * from '../Card/index.js';
35
+ export * from '../CatalogTile/index.js';
35
36
  export * from '../ChangeMark/index.js';
36
37
  export * from '../CharacterPicker/index.js';
37
38
  export * from '../Charts/index.js';
@@ -49,6 +50,7 @@ export * from '../Container/index.js';
49
50
  export * from '../Copyable/index.js';
50
51
  export * from '../Count/index.js';
51
52
  export * from '../CursorFlag/index.js';
53
+ export * from '../DataGrid/index.js';
52
54
  export * from '../DataTable/index.js';
53
55
  export * from '../DataView/index.js';
54
56
  export * from '../DatasetSource/index.js';
@@ -95,6 +97,7 @@ export * from '../ListInput/index.js';
95
97
  export * from '../Listbox/index.js';
96
98
  export * from '../LiveCursor/index.js';
97
99
  export * from '../LivePreview/index.js';
100
+ export * from '../LockedLabel/index.js';
98
101
  export * from '../Markdown/index.js';
99
102
  export * from '../MarkdownEditor/index.js';
100
103
  export * from '../MediaMatch/index.js';
@@ -110,6 +113,7 @@ export * from '../OrgNode/index.js';
110
113
  export * from '../OrgTable/index.js';
111
114
  export * from '../Outline/index.js';
112
115
  export * from '../PageHeader/index.js';
116
+ export * from '../PageNote/index.js';
113
117
  export * from '../PeopleRail/index.js';
114
118
  export * from '../PinTile/index.js';
115
119
  export * from '../Popover/index.js';
@@ -120,9 +124,11 @@ export * from '../PresenterView/index.js';
120
124
  export * from '../PricingCard/index.js';
121
125
  export * from '../Principal/index.js';
122
126
  export * from '../PrincipalPicker/index.js';
127
+ export * from '../PropertyList/index.js';
123
128
  export * from '../Prose/index.js';
124
129
  export * from '../QrCode/index.js';
125
130
  export * from '../ReadingPane/index.js';
131
+ export * from '../RelatedRow/index.js';
126
132
  export * from '../RelativeTime/index.js';
127
133
  export * from '../Reorder/index.js';
128
134
  export * from '../RichEditor/index.js';
@@ -130,9 +136,11 @@ export * from '../RichEditorMarkdown/index.js';
130
136
  export * from '../SandboxedFrame/index.js';
131
137
  export * from '../SearchTrigger/index.js';
132
138
  export * from '../Section/index.js';
139
+ export * from '../SectionFrame/index.js';
133
140
  export * from '../SegmentedControl/index.js';
134
141
  export * from '../SegmentedMeter/index.js';
135
142
  export * from '../Select/index.js';
143
+ export * from '../SettingsTable/index.js';
136
144
  export * from '../ShareDialog/index.js';
137
145
  export * from '../SheetColumnEditor/index.js';
138
146
  export * from '../SheetGrid/index.js';
@@ -163,6 +171,7 @@ export * from '../ThemeGallery/index.js';
163
171
  export * from '../ThemeSwatch/index.js';
164
172
  export * from '../ThemeSwitcher/index.js';
165
173
  export * from '../ThemeToggle/index.js';
174
+ export * from '../TileGrid/index.js';
166
175
  export * from '../TimeWindowPicker/index.js';
167
176
  export * from '../Timeline/index.js';
168
177
  export * from '../Toaster/index.js';