@crewlethq/ui 0.69.0 → 0.70.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 (152) hide show
  1. package/README.md +19 -1
  2. package/dist/AgentHandoffPanel/index.js +4 -4
  3. package/dist/AppShell/index.js +3 -3
  4. package/dist/ArtifactBar/index.js +5 -5
  5. package/dist/AvatarPicker/index.js +8 -8
  6. package/dist/BriefCard/index.js +3 -3
  7. package/dist/Button/Button.d.ts +10 -0
  8. package/dist/Button/index.js +1 -1
  9. package/dist/{Button-VRRYSXFN.css → Button-GDEBGBX6.css} +30 -3
  10. package/dist/Canvas/index.js +2 -2
  11. package/dist/CanvasBoard/index.js +4 -4
  12. package/dist/CanvasToolbar/index.js +3 -3
  13. package/dist/CharacterPicker/index.js +2 -2
  14. package/dist/ChatThread/index.js +2 -2
  15. package/dist/CodeBlock/index.js +3 -3
  16. package/dist/ColorSwatch/index.js +3 -3
  17. package/dist/CommandPalette/index.js +4 -4
  18. package/dist/CommentThread/index.js +4 -4
  19. package/dist/Composer/index.js +2 -2
  20. package/dist/ConflictNote/index.js +2 -2
  21. package/dist/Copyable/index.js +2 -2
  22. package/dist/DataGrid/DataGrid.d.ts +50 -4
  23. package/dist/DataGrid/index.d.ts +2 -2
  24. package/dist/DataGrid/index.js +2 -2
  25. package/dist/{DataGrid-NHIN2I42.css → DataGrid-Q26F2V5Q.css} +145 -24
  26. package/dist/DataTable/index.js +4 -4
  27. package/dist/DataView/index.js +8 -7
  28. package/dist/{DataView-RH5UDA5F.css → DataView-L7HLNW7C.css} +1 -112
  29. package/dist/DatasetSource/index.js +1 -1
  30. package/dist/DateTimePicker/index.js +2 -2
  31. package/dist/DeepWorkCard/index.js +4 -4
  32. package/dist/DocTabsEditor/index.js +3 -3
  33. package/dist/DownloadButton/index.js +2 -2
  34. package/dist/EditingStatus/index.js +2 -2
  35. package/dist/{Editor-NZRUKWB4.js → Editor-NNQEALNT.js} +3 -3
  36. package/dist/EntityList/index.js +1 -1
  37. package/dist/ErrorBoundary/index.js +2 -2
  38. package/dist/FileDrop/index.js +2 -2
  39. package/dist/FilterPill/FilterPill.d.ts +63 -0
  40. package/dist/FilterPill/index.d.ts +3 -0
  41. package/dist/FilterPill/index.js +4 -0
  42. package/dist/FilterPill-4GMNFZND.css +134 -0
  43. package/dist/FollowBanner/index.js +2 -2
  44. package/dist/HuePicker/index.js +5 -5
  45. package/dist/InlineEditor/index.js +4 -4
  46. package/dist/LinkInterstitial/index.js +3 -3
  47. package/dist/ListInput/index.js +3 -3
  48. package/dist/LogoSlot/index.js +3 -3
  49. package/dist/MarkdownEditor/index.js +5 -5
  50. package/dist/Menu/Menu.d.ts +10 -1
  51. package/dist/Menu/index.js +2 -2
  52. package/dist/{Menu-OLUGHX56.css → Menu-I4SNXHOT.css} +12 -0
  53. package/dist/MergeConflicts/index.js +5 -5
  54. package/dist/Modal/index.js +2 -2
  55. package/dist/OpenInAppCard/index.js +4 -4
  56. package/dist/PeekRail/index.js +2 -2
  57. package/dist/PeopleRail/index.js +2 -2
  58. package/dist/PresenterView/index.js +2 -2
  59. package/dist/ProposalCard/index.js +4 -4
  60. package/dist/ReceiptStrip/index.js +2 -2
  61. package/dist/RefusalCard/index.js +1 -1
  62. package/dist/ResultTableCard/index.js +4 -4
  63. package/dist/RichEditor/index.js +2 -2
  64. package/dist/SandboxedFrame/index.js +2 -2
  65. package/dist/SegmentedControl/index.js +4 -4
  66. package/dist/SelectionBar/index.js +2 -2
  67. package/dist/ShareDialog/index.js +4 -4
  68. package/dist/SheetColumnEditor/index.js +8 -8
  69. package/dist/SheetGrid/index.js +5 -5
  70. package/dist/SlideCompare/index.js +2 -2
  71. package/dist/SlideFilmstrip/index.js +3 -3
  72. package/dist/StatusCard/index.js +1 -1
  73. package/dist/Switcher/index.js +3 -3
  74. package/dist/TableCells/index.js +2 -2
  75. package/dist/{TableCells-F6MUV572.css → TableCells-TKSNLRK3.css} +1 -0
  76. package/dist/Tabs/index.js +3 -3
  77. package/dist/ThemeSwitcher/index.js +5 -5
  78. package/dist/TimeRangePicker/index.js +6 -6
  79. package/dist/TimeWindowPicker/index.js +2 -2
  80. package/dist/TreeCanvas/index.js +3 -3
  81. package/dist/VersionCompare/index.js +5 -5
  82. package/dist/VersionTimeline/index.js +2 -2
  83. package/dist/{chunk-HXJHRQDR.js → chunk-3EY5SEGH.js} +2 -2
  84. package/dist/{chunk-DS5NBENV.js → chunk-3LP3VPLT.js} +2 -2
  85. package/dist/{chunk-6MI2GMYG.js → chunk-3WN5HUAK.js} +2 -2
  86. package/dist/{chunk-4E3CE2UK.js → chunk-4DL2BQJE.js} +2 -2
  87. package/dist/{chunk-PQWNK3N7.js → chunk-4MVLED6E.js} +3 -3
  88. package/dist/{chunk-BXEKD5NU.js → chunk-6C6YK75K.js} +2 -2
  89. package/dist/{chunk-2A6DL3K5.js → chunk-6FBPFG3C.js} +1 -1
  90. package/dist/{chunk-L4UO57YP.js → chunk-73SAOOR5.js} +3 -3
  91. package/dist/{chunk-WXLQJUGO.js → chunk-ADSOY7UM.js} +1 -1
  92. package/dist/{chunk-GNDKUSCG.js → chunk-AGLONIVV.js} +1 -1
  93. package/dist/{chunk-2EA2GSA2.js → chunk-AQIFKLXY.js} +1 -1
  94. package/dist/{chunk-SUJO3AHN.js → chunk-B3PK2LND.js} +1 -1
  95. package/dist/{chunk-UYK3SGZI.js → chunk-BWFJB5JD.js} +3 -3
  96. package/dist/{chunk-I24FI46B.js → chunk-C667GCU7.js} +1 -1
  97. package/dist/{chunk-CWYU7DNT.js → chunk-CDNZTCP2.js} +1 -1
  98. package/dist/{chunk-NJYB4VJI.js → chunk-DB7UVFOY.js} +2 -2
  99. package/dist/{chunk-OJGI4XJH.js → chunk-DGSK4LLS.js} +1 -1
  100. package/dist/{chunk-7QTPJDRF.js → chunk-DGXZ635L.js} +7 -4
  101. package/dist/{chunk-2SU735S3.js → chunk-DV5L2GRY.js} +1 -1
  102. package/dist/{chunk-NSCYGUDG.js → chunk-EHFQMY3B.js} +1 -1
  103. package/dist/{chunk-S2UHV52X.js → chunk-EN4UJQ63.js} +3 -3
  104. package/dist/{chunk-6ID4DVML.js → chunk-EOXI3CRG.js} +1 -1
  105. package/dist/{chunk-VTGIDEI5.js → chunk-ERFXYGRF.js} +2 -2
  106. package/dist/{chunk-JEA5OX54.js → chunk-FQI62PIZ.js} +2 -2
  107. package/dist/{chunk-ELLRZ5XR.js → chunk-FURJVZCT.js} +72 -26
  108. package/dist/{chunk-5K7GGQNX.js → chunk-G4QZWVAB.js} +2 -2
  109. package/dist/{chunk-IABWA76I.js → chunk-H32JW6CZ.js} +2 -2
  110. package/dist/{chunk-PX54PALQ.js → chunk-HPI5J6AR.js} +1 -1
  111. package/dist/{chunk-ZEPUKRO7.js → chunk-IJ7KLXUZ.js} +1 -1
  112. package/dist/{chunk-PVZOP3QK.js → chunk-IPUEVTRJ.js} +1 -1
  113. package/dist/{chunk-RLBGU35B.js → chunk-J5WWMC35.js} +45 -46
  114. package/dist/{chunk-O3BNL4TV.js → chunk-JD7P2GJP.js} +1 -1
  115. package/dist/{chunk-KIJJD4YD.js → chunk-JQEXAH7G.js} +1 -1
  116. package/dist/{chunk-K4IVKHKU.js → chunk-JT7WRPZ6.js} +1 -1
  117. package/dist/chunk-K4LZXSKZ.js +62 -0
  118. package/dist/{chunk-ZHVLDRAT.js → chunk-KAA3GFTP.js} +4 -4
  119. package/dist/{chunk-WDNURPXU.js → chunk-KL6A7JGH.js} +1 -1
  120. package/dist/{chunk-2JHGPXYG.js → chunk-KQWJWTED.js} +1 -1
  121. package/dist/{chunk-WU5JDEEY.js → chunk-L4HHWG4V.js} +1 -1
  122. package/dist/{chunk-GDDVI4US.js → chunk-LQWORB5B.js} +1 -1
  123. package/dist/{chunk-EHB4TSP2.js → chunk-NXNLAZPK.js} +2 -2
  124. package/dist/{chunk-WPMZKZUH.js → chunk-O3HCFM3D.js} +1 -1
  125. package/dist/{chunk-F32FFE6I.js → chunk-OBPINJNO.js} +1 -1
  126. package/dist/{chunk-T73DMDU4.js → chunk-OQG4P5KU.js} +17 -3
  127. package/dist/{chunk-UWOYDHVW.js → chunk-P64MIA7C.js} +1 -1
  128. package/dist/{chunk-KHHDCNYM.js → chunk-PRN5IP2R.js} +1 -1
  129. package/dist/{chunk-DMK2A4IK.js → chunk-QSWQJX27.js} +1 -1
  130. package/dist/{chunk-D2ZXIQ23.js → chunk-R5OATXWU.js} +1 -1
  131. package/dist/{chunk-OFABBAUR.js → chunk-SMZPUHBL.js} +1 -1
  132. package/dist/{chunk-7QTJO3PV.js → chunk-SO5SXSTP.js} +1 -1
  133. package/dist/{chunk-IYG4ETAQ.js → chunk-T5GBTXNC.js} +1 -1
  134. package/dist/{chunk-DXVJSBEW.js → chunk-TKBFRGUV.js} +3 -3
  135. package/dist/{chunk-U7J52N67.js → chunk-TPCBPGSB.js} +1 -1
  136. package/dist/{chunk-W6UVBBNH.js → chunk-TYIHFDMP.js} +1 -1
  137. package/dist/{chunk-GJ7VIQWL.js → chunk-UY3FWQWG.js} +1 -1
  138. package/dist/{chunk-NTFVEOYY.js → chunk-VBA5FSWV.js} +1 -1
  139. package/dist/{chunk-7EOUVWGQ.js → chunk-VWMB3CJN.js} +1 -1
  140. package/dist/{chunk-CX6QT4CH.js → chunk-W5AXJWOW.js} +1 -1
  141. package/dist/{chunk-OWQATZGW.js → chunk-YGWIWDXE.js} +2 -2
  142. package/dist/{chunk-2T32N2WD.js → chunk-YUHKRRWO.js} +2 -2
  143. package/dist/{chunk-M25IV5MH.js → chunk-ZWCK4N4L.js} +1 -1
  144. package/dist/generated/index.d.ts +1 -0
  145. package/dist/generated/index.js +92 -91
  146. package/dist/index.js +92 -91
  147. package/dist/styles.css +333 -146
  148. package/package.json +3 -3
  149. package/dist/{chunk-XWOH3UPZ.js → chunk-5OFRDX66.js} +1 -1
  150. package/dist/{chunk-KBXSOBLD.js → chunk-ABZC3NLM.js} +0 -0
  151. package/dist/{chunk-VZICPYGR.js → chunk-SNQRGH4A.js} +1 -1
  152. package/dist/{chunk-AIMMHN5J.js → chunk-VLGGLLKH.js} +1 -1
@@ -1,15 +1,19 @@
1
1
  import { Checkbox } from './chunk-PBCNINMB.js';
2
2
  import { EmptyState } from './chunk-PPUR46MK.js';
3
3
  import { useMediaMatch } from './chunk-RTPQDNW3.js';
4
- import { Button } from './chunk-7QTPJDRF.js';
4
+ import { Button } from './chunk-DGXZ635L.js';
5
5
  import { VisuallyHidden } from './chunk-UT6CW3C7.js';
6
6
  import { cx } from './chunk-ODEQTPFM.js';
7
- import './DataGrid-NHIN2I42.css';
7
+ import './DataGrid-Q26F2V5Q.css';
8
8
  import { useId, useRef, useState, useMemo, useCallback, useLayoutEffect, useImperativeHandle, useSyncExternalStore, useEffect } from 'react';
9
9
  import { breakpoint } from '@crewlethq/tokens';
10
- import { ChevronDownGlyph, ChevronUpGlyph } from '@crewlethq/icons/glyphs';
10
+ import { ArrowDownGlyph, ArrowUpGlyph, ArrowUpDownGlyph } from '@crewlethq/icons/glyphs';
11
11
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
12
12
 
13
+ var DATA_GRID_ICON_TRACK = "calc(var(--size-target-min) + var(--spacing-3) * 2)";
14
+ function alignOf(column) {
15
+ return column.align ?? (column.icon ? "center" : "left");
16
+ }
13
17
  function columnChoicesOf(columns) {
14
18
  return columns.map((column) => ({
15
19
  key: column.key,
@@ -59,6 +63,15 @@ function parseGridSort(raw) {
59
63
  if (!raw) return null;
60
64
  return raw.startsWith("-") ? { key: raw.slice(1), desc: true } : { key: raw, desc: false };
61
65
  }
66
+ function nextGridSort(column, sort, defaultSort = "") {
67
+ const chosen = sort === defaultSort ? "" : sort;
68
+ const current2 = parseGridSort(chosen || defaultSort);
69
+ let next;
70
+ if (current2?.key !== column) next = column;
71
+ else if (!current2.desc) next = `-${column}`;
72
+ else next = chosen ? "" : column;
73
+ return next === defaultSort ? "" : next;
74
+ }
62
75
  function headerWord(column) {
63
76
  return typeof column.header === "string" ? column.header : "";
64
77
  }
@@ -120,7 +133,7 @@ function squeezed(wrap, visible, leading = 0) {
120
133
  let headCut = false;
121
134
  for (let i = 0; i < visible.length; i++) {
122
135
  const column = visible[i];
123
- if (!column.shrink || column.width) continue;
136
+ if (!column.shrink || column.width || column.icon) continue;
124
137
  const head = heads[i + leading];
125
138
  if (!head || head.getBoundingClientRect().width >= cap) continue;
126
139
  if (cutShort(head)) headCut = true;
@@ -156,6 +169,7 @@ function DataGrid({
156
169
  selection,
157
170
  isFailed,
158
171
  sort: sortRaw = "",
172
+ defaultSort = "",
159
173
  onSortChange,
160
174
  serverSorted = false,
161
175
  cols: colsRaw = "",
@@ -174,7 +188,7 @@ function DataGrid({
174
188
  className
175
189
  }) {
176
190
  const text = { ...LABELS, ...labels };
177
- const sort = parseGridSort(sortRaw);
191
+ const sort = parseGridSort(sortRaw || defaultSort);
178
192
  const body = useRef(null);
179
193
  const [cursor, setCursor] = useState(-1);
180
194
  const gridId = useId();
@@ -278,7 +292,7 @@ function DataGrid({
278
292
  ),
279
293
  action: true,
280
294
  phoneLead: true,
281
- width: "calc(var(--size-target-min) + var(--spacing-3) * 2)"
295
+ width: DATA_GRID_ICON_TRACK
282
296
  } : null;
283
297
  const drawnColumns = selectColumn ? [selectColumn, ...visibleColumns] : visibleColumns;
284
298
  const leading = drawnColumns.length - visibleColumns.length;
@@ -312,10 +326,31 @@ function DataGrid({
312
326
  body.current?.querySelector(`[data-row-index="${next}"]`)?.scrollIntoView({ block: "nearest" });
313
327
  return next;
314
328
  }),
329
+ // THE ROW'S OWN WAY IN, from the keyboard: its handler where it has
330
+ // one, else its link, followed as a click on it would be (with the
331
+ // keys held, so a modified Enter opens it elsewhere as a modified
332
+ // click does). A grid of links only had no Enter at all.
315
333
  activate: (event) => {
316
334
  const row = flat[cursor];
317
- if (row === void 0 || !onRowActivate) return false;
318
- onRowActivate(row, event);
335
+ if (row === void 0) return false;
336
+ if (onRowActivate) {
337
+ onRowActivate(row, event);
338
+ return true;
339
+ }
340
+ const link = body.current?.querySelector(
341
+ `[data-row-index="${cursor}"] > .crewlet-data-grid__cell > a.crewlet-data-grid__row-link`
342
+ );
343
+ if (!link) return false;
344
+ link.dispatchEvent(
345
+ new MouseEvent("click", {
346
+ bubbles: true,
347
+ cancelable: true,
348
+ metaKey: event.metaKey,
349
+ ctrlKey: event.ctrlKey,
350
+ shiftKey: event.shiftKey,
351
+ altKey: event.altKey
352
+ })
353
+ );
319
354
  return true;
320
355
  },
321
356
  rowCount: () => flat.length
@@ -324,11 +359,11 @@ function DataGrid({
324
359
  );
325
360
  function headerClick(column) {
326
361
  if (!column.sortValue || !onSortChange) return;
327
- if (sort?.key === column.key && !sort.desc) onSortChange(`-${column.key}`);
328
- else if (sort?.key === column.key && sort.desc) onSortChange("");
329
- else onSortChange(column.key);
362
+ onSortChange(nextGridSort(column.key, sortRaw, defaultSort));
330
363
  }
331
- const template = drawnColumns.map((c) => c.width ?? (c.shrink ? `fit-content(${SHRINK_CAP})` : `minmax(${c.floor ?? 0}, 1fr)`)).join(" ");
364
+ const template = drawnColumns.map(
365
+ (c) => c.width ?? (c.icon ? DATA_GRID_ICON_TRACK : c.shrink ? `fit-content(${SHRINK_CAP})` : `minmax(${c.floor ?? 0}, 1fr)`)
366
+ ).join(" ");
332
367
  if (flat.length === 0 && !bands?.length && empty) {
333
368
  return /* @__PURE__ */ jsx("div", { className: cx("crewlet-data-grid", className), "data-flush": flush || void 0, children: /* @__PURE__ */ jsx(
334
369
  EmptyState,
@@ -377,7 +412,8 @@ function DataGrid({
377
412
  role: "cell",
378
413
  className: cx(
379
414
  "crewlet-data-grid__cell",
380
- column.align === "right" && "crewlet-data-grid__cell--right",
415
+ alignOf(column) !== "left" && `crewlet-data-grid__cell--${alignOf(column)}`,
416
+ column.icon && "crewlet-data-grid__cell--icon",
381
417
  column.shrink && "crewlet-data-grid__cell--shrink"
382
418
  ),
383
419
  "data-lead": column.phoneLead || void 0,
@@ -444,36 +480,46 @@ function DataGrid({
444
480
  const sortable = Boolean(column.sortValue && onSortChange);
445
481
  const headClass = cx(
446
482
  "crewlet-data-grid__th",
447
- column.align === "right" && "crewlet-data-grid__th--right",
483
+ alignOf(column) !== "left" && `crewlet-data-grid__th--${alignOf(column)}`,
484
+ column.icon && "crewlet-data-grid__th--icon",
448
485
  column.shrink && "crewlet-data-grid__th--shrink",
449
486
  sorted && "crewlet-data-grid__th--sorted",
450
487
  !sortable && "crewlet-data-grid__th--plain"
451
488
  );
452
- const content = /* @__PURE__ */ jsxs(Fragment, { children: [
453
- /* @__PURE__ */ jsx("span", { className: "crewlet-data-grid__truncate", children: column.header }),
454
- sorted && (sort?.desc ? /* @__PURE__ */ jsx(ChevronDownGlyph, { size: "xs" }) : /* @__PURE__ */ jsx(ChevronUpGlyph, { size: "xs" }))
455
- ] });
489
+ const worded = column.header !== "" && column.header !== null && column.header !== void 0;
490
+ const label = worded ? /* @__PURE__ */ jsx("span", { className: "crewlet-data-grid__truncate", children: column.header }) : null;
491
+ const arrow = sorted ? sort?.desc ? /* @__PURE__ */ jsx(ArrowDownGlyph, { size: "xs" }) : /* @__PURE__ */ jsx(ArrowUpGlyph, { size: "xs" }) : sortable ? /* @__PURE__ */ jsx(ArrowUpDownGlyph, { size: "xs" }) : null;
492
+ const ariaSort = sorted ? sort?.desc ? "descending" : "ascending" : void 0;
493
+ const mark = arrow && /* @__PURE__ */ jsx("span", { className: "crewlet-data-grid__sort-mark", "aria-hidden": "true", children: arrow });
456
494
  if (!sortable) {
457
495
  const named = !headerWord(column) && !column.action ? column.label : void 0;
458
- return /* @__PURE__ */ jsxs("div", { className: headClass, role: "columnheader", title: named, children: [
459
- content,
460
- named && /* @__PURE__ */ jsx(VisuallyHidden, { children: named })
461
- ] }, column.key);
496
+ return (
497
+ // THE ORDER IN FORCE IS SAID on a head that cannot change it too:
498
+ // a grid sorted by its default, with nothing to press.
499
+ /* @__PURE__ */ jsxs("div", { className: headClass, role: "columnheader", title: named, "aria-sort": ariaSort, children: [
500
+ label,
501
+ mark,
502
+ named && /* @__PURE__ */ jsx(VisuallyHidden, { children: named })
503
+ ] }, column.key)
504
+ );
462
505
  }
463
506
  return /* @__PURE__ */ jsx(
464
507
  "div",
465
508
  {
466
509
  className: headClass,
467
510
  role: "columnheader",
468
- "aria-sort": sorted ? sort?.desc ? "descending" : "ascending" : void 0,
469
- children: /* @__PURE__ */ jsx(
511
+ "aria-sort": ariaSort,
512
+ children: /* @__PURE__ */ jsxs(
470
513
  "button",
471
514
  {
472
515
  type: "button",
473
516
  className: "crewlet-data-grid__sort",
474
517
  onClick: () => headerClick(column),
475
518
  "aria-label": headerWord(column) ? void 0 : column.label,
476
- children: content
519
+ children: [
520
+ label,
521
+ mark
522
+ ]
477
523
  }
478
524
  )
479
525
  },
@@ -544,4 +590,4 @@ function useAnyDataGridDriving() {
544
590
  return drivable.length > 0;
545
591
  }
546
592
 
547
- export { ChooserList, ColumnChooser, DataGrid, columnChoicesOf, countDataGridRows, fitGridColumns, parseGridSort, useAnyDataGridDriving, useDataGridDriving };
593
+ export { ChooserList, ColumnChooser, DATA_GRID_ICON_TRACK, DataGrid, columnChoicesOf, countDataGridRows, fitGridColumns, nextGridSort, parseGridSort, useAnyDataGridDriving, useDataGridDriving };
@@ -1,8 +1,8 @@
1
1
  import { safeHref } from './chunk-BAKPMH3S.js';
2
2
  import { IconTile } from './chunk-3LI4TRUR.js';
3
- import { ReceiptStrip } from './chunk-M25IV5MH.js';
3
+ import { ReceiptStrip } from './chunk-ZWCK4N4L.js';
4
4
  import { StatusCard } from './chunk-NTQPJJAN.js';
5
- import { ButtonLink, Button } from './chunk-7QTPJDRF.js';
5
+ import { ButtonLink, Button } from './chunk-DGXZ635L.js';
6
6
  import { cx } from './chunk-ODEQTPFM.js';
7
7
  import './OpenInAppCard-CKHCK7DO.css';
8
8
  import { CircleCheckGlyph } from '@crewlethq/icons/glyphs';
@@ -1,9 +1,9 @@
1
1
  import { useReorder } from './chunk-MPVMB2DV.js';
2
+ import { Kbd } from './chunk-ANTAQAR4.js';
2
3
  import { FormField, Textarea } from './chunk-ETSF7SU6.js';
3
4
  import { characterCountState, CharacterCount, countCharacters } from './chunk-PGCLHYVP.js';
4
- import { Kbd } from './chunk-ANTAQAR4.js';
5
5
  import { announce } from './chunk-2G355KDJ.js';
6
- import { Button } from './chunk-7QTPJDRF.js';
6
+ import { Button } from './chunk-DGXZ635L.js';
7
7
  import { isComposing } from './chunk-H5XTJ7GJ.js';
8
8
  import { IconButton } from './chunk-UAUP6XGK.js';
9
9
  import { cx } from './chunk-ODEQTPFM.js';
@@ -1,6 +1,6 @@
1
1
  import { today, CalendarGrid, shiftMonth, compareDays } from './chunk-EE3DJMSQ.js';
2
2
  import { Popover } from './chunk-KHJIEPZV.js';
3
- import { Button } from './chunk-7QTPJDRF.js';
3
+ import { Button } from './chunk-DGXZ635L.js';
4
4
  import { IconButton } from './chunk-UAUP6XGK.js';
5
5
  import { useFocusModality } from './chunk-NUZHC6MM.js';
6
6
  import { cx } from './chunk-ODEQTPFM.js';
@@ -1,4 +1,4 @@
1
- import { Button } from './chunk-7QTPJDRF.js';
1
+ import { Button } from './chunk-DGXZ635L.js';
2
2
  import './ErrorBoundary-U2PA3LY2.css';
3
3
  import { Component } from 'react';
4
4
  import { jsxs, jsx } from 'react/jsx-runtime';
@@ -1,7 +1,7 @@
1
1
  import { useRoving, tabStop } from './chunk-EGMQURBR.js';
2
2
  import { StatusDot } from './chunk-WIATRXEJ.js';
3
3
  import { Count } from './chunk-MLDTLZAO.js';
4
- import { Menu } from './chunk-T73DMDU4.js';
4
+ import { Menu } from './chunk-OQG4P5KU.js';
5
5
  import { HIT_AREA_CLASS } from './chunk-2YTOOH3A.js';
6
6
  import { VisuallyHidden } from './chunk-UT6CW3C7.js';
7
7
  import { cx } from './chunk-ODEQTPFM.js';
@@ -1,19 +1,20 @@
1
1
  import { PageHeader } from './chunk-FPDIHEM4.js';
2
- import { DataTable } from './chunk-UYK3SGZI.js';
3
- import { DateTimePicker } from './chunk-PX54PALQ.js';
2
+ import { FilterPill } from './chunk-K4LZXSKZ.js';
3
+ import { DataTable } from './chunk-BWFJB5JD.js';
4
+ import { DateTimePicker } from './chunk-HPI5J6AR.js';
4
5
  import { useListbox, useOptionKeys } from './chunk-7KHM2FZH.js';
5
6
  import { Toolbar } from './chunk-NR4CPM4T.js';
6
7
  import { Popover } from './chunk-KHJIEPZV.js';
7
8
  import { RelativeTime } from './chunk-EJNJMHQG.js';
8
- import { Input } from './chunk-ETSF7SU6.js';
9
9
  import { Kbd } from './chunk-ANTAQAR4.js';
10
+ import { Input } from './chunk-ETSF7SU6.js';
10
11
  import { Count } from './chunk-MLDTLZAO.js';
11
- import { Menu } from './chunk-T73DMDU4.js';
12
- import { Button } from './chunk-7QTPJDRF.js';
12
+ import { Menu } from './chunk-OQG4P5KU.js';
13
+ import { Button } from './chunk-DGXZ635L.js';
13
14
  import { IconButton } from './chunk-UAUP6XGK.js';
14
15
  import { VisuallyHidden } from './chunk-UT6CW3C7.js';
15
16
  import { cx } from './chunk-ODEQTPFM.js';
16
- import './DataView-RH5UDA5F.css';
17
+ import './DataView-L7HLNW7C.css';
17
18
  import { useMemo, useState, useEffect, useCallback, useRef, useId } from 'react';
18
19
  import { SearchGlyph, ChevronDownGlyph, SlidersVerticalGlyph, ArrowUpGlyph, ArrowDownGlyph, XGlyph, ArrowUpDownGlyph, EyeGlyph, EyeOffGlyph, HashGlyph, ClockGlyph, ListGlyph, CheckGlyph } from '@crewlethq/icons/glyphs';
19
20
  import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
@@ -362,31 +363,34 @@ var isMultiple = (def) => def.kind === "select" && def.multiple === true;
362
363
  var chosenValues = (value) => Array.isArray(value) ? [...value] : [];
363
364
  var sameValue = (a, b) => String(a) === String(b);
364
365
  function formatFilterValue(def, value, labels) {
365
- const operator = operatorOf(def);
366
+ const { operator, answer } = filterAnswer(def, value, labels);
367
+ return operator ? `${operator} ${answer}` : answer;
368
+ }
369
+ function filterAnswer(def, value, labels) {
366
370
  const unusual = def.operator !== void 0 && def.operator !== defaultOperator(def);
367
- const prefix = unusual ? `${labels.operator[operator]} ` : "";
371
+ const compared = (answer) => unusual ? { operator: labels.operator[operatorOf(def)], answer } : { answer };
368
372
  if (isMultiple(def)) {
369
373
  const held = chosenValues(value);
370
- if (held.length === 0) return labels.any;
374
+ if (held.length === 0) return { answer: labels.any };
371
375
  if (held.length === 1) {
372
376
  const option = def.options?.find((candidate) => sameValue(candidate.value, held[0]));
373
- return `${prefix}${option ? option.label : String(held[0])}`;
377
+ return compared(option ? option.label : String(held[0]));
374
378
  }
375
- return labels.selected(held.length);
379
+ return { answer: labels.selected(held.length) };
376
380
  }
377
381
  if (value === void 0 || value === null || value === "") {
378
382
  const option = def.options?.find((candidate) => String(candidate.value) === "");
379
- return option ? option.label : labels.any;
383
+ return { answer: option ? option.label : labels.any };
380
384
  }
381
385
  if (def.kind === "select") {
382
386
  const option = def.options?.find((candidate) => sameValue(candidate.value, value));
383
- return `${prefix}${option ? option.label : String(value)}`;
387
+ return compared(option ? option.label : String(value));
384
388
  }
385
389
  if (def.kind === "datetime") {
386
390
  const at = new Date(String(value));
387
- if (!Number.isNaN(at.getTime())) return `${prefix}${at.toLocaleString()}`;
391
+ if (!Number.isNaN(at.getTime())) return compared(at.toLocaleString());
388
392
  }
389
- return `${prefix}${String(value)}`;
393
+ return compared(String(value));
390
394
  }
391
395
  function OptionListEditor({ def, value, labels, onCommit }) {
392
396
  const id = useId();
@@ -563,38 +567,33 @@ function FilterAxisChip({
563
567
  if (def.kind === "datetime") return /* @__PURE__ */ jsx(MomentEditor, { ...props });
564
568
  return /* @__PURE__ */ jsx(TextEditor, { ...props });
565
569
  };
566
- return /* @__PURE__ */ jsxs("div", { className: cx("crewlet-filter-axis-chip", className), children: [
567
- /* @__PURE__ */ jsx(
568
- Popover,
569
- {
570
- align: "start",
571
- role: "dialog",
572
- label: labels.editor(def.label),
573
- defaultOpen: autoOpen,
574
- className: "crewlet-filter-axis__popover",
575
- trigger: (open, toggle) => /* @__PURE__ */ jsxs("button", { type: "button", className: cx("crewlet-filter-axis-chip__trigger", open && "is-open"), onClick: toggle, children: [
576
- /* @__PURE__ */ jsxs("span", { className: "crewlet-filter-axis-chip__label", children: [
577
- def.label,
578
- ":"
570
+ const { operator, answer } = filterAnswer(def, value, labels);
571
+ return /* @__PURE__ */ jsx(
572
+ FilterPill,
573
+ {
574
+ className: cx("crewlet-filter-axis-chip", className),
575
+ field: def.label,
576
+ operator,
577
+ value: answer,
578
+ onRemove,
579
+ removeLabel: labels.remove(def.label),
580
+ renderWords: (words, wordsClass) => /* @__PURE__ */ jsx(
581
+ Popover,
582
+ {
583
+ align: "start",
584
+ role: "dialog",
585
+ label: labels.editor(def.label),
586
+ defaultOpen: autoOpen,
587
+ className: "crewlet-filter-axis__popover",
588
+ trigger: (open, toggle) => /* @__PURE__ */ jsxs("button", { type: "button", className: cx(wordsClass, open && "is-open"), onClick: toggle, children: [
589
+ words,
590
+ /* @__PURE__ */ jsx(ChevronDownGlyph, { size: "xs" })
579
591
  ] }),
580
- /* @__PURE__ */ jsx("span", { className: "crewlet-filter-axis-chip__value", children: formatFilterValue(def, value, labels) }),
581
- /* @__PURE__ */ jsx(ChevronDownGlyph, { className: "crewlet-filter-axis-chip__chevron", size: "xs" })
582
- ] }),
583
- children: editor
584
- }
585
- ),
586
- onRemove ? /* @__PURE__ */ jsx(
587
- IconButton,
588
- {
589
- className: "crewlet-filter-axis-chip__remove",
590
- size: "sm",
591
- variant: "ghost",
592
- label: labels.remove(def.label),
593
- icon: /* @__PURE__ */ jsx(XGlyph, { size: "xs" }),
594
- onClick: onRemove
595
- }
596
- ) : null
597
- ] });
592
+ children: editor
593
+ }
594
+ )
595
+ }
596
+ );
598
597
  }
599
598
  function FilterAxisBar({
600
599
  filters,
@@ -1,4 +1,4 @@
1
- import { ConfirmModal } from './chunk-I24FI46B.js';
1
+ import { ConfirmModal } from './chunk-C667GCU7.js';
2
2
  import { InlineCode } from './chunk-PLL7ZJHY.js';
3
3
  import { Callout } from './chunk-BPCY7ZID.js';
4
4
  import './LinkInterstitial-ET4MSVSV.css';
@@ -1,5 +1,5 @@
1
1
  import { useTreeState, useMeasuredSizes, layoutForest, treeAncestors, useLayoutAnchor, treeExpandable, layoutConnectors, treeItemAction, treeStep, treePosInSet, treeSetSize, treeLevel, placeGroups } from './chunk-MY374UUD.js';
2
- import { CANVAS_COMPOSE_CONTEXT, CANVAS_FIT_MAX_ZOOM, Canvas } from './chunk-F32FFE6I.js';
2
+ import { CANVAS_COMPOSE_CONTEXT, CANVAS_FIT_MAX_ZOOM, Canvas } from './chunk-OBPINJNO.js';
3
3
  import { focusables } from './chunk-H5XTJ7GJ.js';
4
4
  import { cx } from './chunk-ODEQTPFM.js';
5
5
  import './TreeCanvas-5FPK4CII.css';
@@ -1,5 +1,5 @@
1
1
  import { Callout } from './chunk-BPCY7ZID.js';
2
- import { Button } from './chunk-7QTPJDRF.js';
2
+ import { Button } from './chunk-DGXZ635L.js';
3
3
  import { isComposing } from './chunk-H5XTJ7GJ.js';
4
4
  import { cx } from './chunk-ODEQTPFM.js';
5
5
  import { useEffect } from 'react';
@@ -0,0 +1,62 @@
1
+ import { IconButton } from './chunk-UAUP6XGK.js';
2
+ import { cx } from './chunk-ODEQTPFM.js';
3
+ import './FilterPill-4GMNFZND.css';
4
+ import { XGlyph } from '@crewlethq/icons/glyphs';
5
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
6
+
7
+ var FILTER_PILL_LABELS = {
8
+ remove: (sentence) => `Remove the ${sentence} filter`,
9
+ removeUnnamed: "Remove this filter",
10
+ fieldEnd: ":"
11
+ };
12
+ var FILTER_PILL_WORDS_CLASS = "crewlet-filter-pill__words";
13
+ function filterPillSentence(field, operator, value) {
14
+ const parts = [field, operator, value].filter((part) => part !== void 0 && part !== null && part !== "");
15
+ if (!parts.every((part) => typeof part === "string" || typeof part === "number")) return void 0;
16
+ return parts.join(" ");
17
+ }
18
+ function FilterPill({
19
+ field,
20
+ operator,
21
+ value,
22
+ onRemove,
23
+ removeLabel,
24
+ renderWords,
25
+ labels,
26
+ className
27
+ }) {
28
+ const text = { ...FILTER_PILL_LABELS, ...labels };
29
+ const hasValue = value !== void 0 && value !== null && value !== "";
30
+ const hasOperator = operator !== void 0 && operator !== null && operator !== "";
31
+ const words = /* @__PURE__ */ jsxs(Fragment, { children: [
32
+ /* @__PURE__ */ jsxs("span", { className: "crewlet-filter-pill__field", children: [
33
+ field,
34
+ hasValue && !hasOperator ? text.fieldEnd : null
35
+ ] }),
36
+ hasOperator ? /* @__PURE__ */ jsxs(Fragment, { children: [
37
+ " ",
38
+ /* @__PURE__ */ jsx("span", { className: "crewlet-filter-pill__operator", children: operator })
39
+ ] }) : null,
40
+ hasValue ? /* @__PURE__ */ jsxs(Fragment, { children: [
41
+ " ",
42
+ /* @__PURE__ */ jsx("span", { className: "crewlet-filter-pill__value", children: value })
43
+ ] }) : null
44
+ ] });
45
+ const sentence = filterPillSentence(field, hasOperator ? operator : void 0, hasValue ? value : void 0);
46
+ return /* @__PURE__ */ jsxs("div", { className: cx("crewlet-filter-pill", className), children: [
47
+ renderWords ? renderWords(words, FILTER_PILL_WORDS_CLASS) : /* @__PURE__ */ jsx("span", { className: FILTER_PILL_WORDS_CLASS, children: words }),
48
+ onRemove ? /* @__PURE__ */ jsx(
49
+ IconButton,
50
+ {
51
+ className: "crewlet-filter-pill__remove",
52
+ size: "sm",
53
+ variant: "ghost",
54
+ label: removeLabel ?? (sentence ? text.remove(sentence) : text.removeUnnamed),
55
+ icon: /* @__PURE__ */ jsx(XGlyph, { size: "xs" }),
56
+ onClick: onRemove
57
+ }
58
+ ) : null
59
+ ] });
60
+ }
61
+
62
+ export { FILTER_PILL_LABELS, FILTER_PILL_WORDS_CLASS, FilterPill, filterPillSentence };
@@ -1,12 +1,12 @@
1
1
  import { Select } from './chunk-VK45YJLH.js';
2
2
  import { SHEET_LABELS, SHEET_COLUMN_TYPES, optionHue, retypeColumn } from './chunk-LFSIKGRQ.js';
3
- import { HueSwatch } from './chunk-2EA2GSA2.js';
3
+ import { HueSwatch } from './chunk-AQIFKLXY.js';
4
4
  import { NODE_HUES, NODE_HUE_NAMES } from './chunk-AYKXMIOR.js';
5
5
  import { Checkbox } from './chunk-PBCNINMB.js';
6
- import { FormField, Input } from './chunk-ETSF7SU6.js';
7
6
  import { Kbd } from './chunk-ANTAQAR4.js';
8
- import { Menu } from './chunk-T73DMDU4.js';
9
- import { Button } from './chunk-7QTPJDRF.js';
7
+ import { FormField, Input } from './chunk-ETSF7SU6.js';
8
+ import { Menu } from './chunk-OQG4P5KU.js';
9
+ import { Button } from './chunk-DGXZ635L.js';
10
10
  import { IconButton } from './chunk-UAUP6XGK.js';
11
11
  import { VisuallyHidden } from './chunk-UT6CW3C7.js';
12
12
  import { cx } from './chunk-ODEQTPFM.js';
@@ -1,5 +1,5 @@
1
1
  import { Toolbar } from './chunk-NR4CPM4T.js';
2
- import { ShortcutTip } from './chunk-F32FFE6I.js';
2
+ import { ShortcutTip } from './chunk-OBPINJNO.js';
3
3
  import { IconButton } from './chunk-UAUP6XGK.js';
4
4
  import { cx } from './chunk-ODEQTPFM.js';
5
5
  import './CanvasToolbar-EM5EVZED.css';
@@ -1,4 +1,4 @@
1
- import { Button } from './chunk-7QTPJDRF.js';
1
+ import { Button } from './chunk-DGXZ635L.js';
2
2
  import { cx } from './chunk-ODEQTPFM.js';
3
3
  import './FileDrop-WE7BNZGV.css';
4
4
  import { forwardRef, useRef, useState } from 'react';
@@ -1,6 +1,6 @@
1
1
  import { Toolbar } from './chunk-NR4CPM4T.js';
2
2
  import { announce } from './chunk-2G355KDJ.js';
3
- import { Button } from './chunk-7QTPJDRF.js';
3
+ import { Button } from './chunk-DGXZ635L.js';
4
4
  import { returnFocus } from './chunk-NUZHC6MM.js';
5
5
  import { cx } from './chunk-ODEQTPFM.js';
6
6
  import './SelectionBar-SCAU6EBY.css';
@@ -1,4 +1,4 @@
1
- import { Modal } from './chunk-I24FI46B.js';
1
+ import { Modal } from './chunk-C667GCU7.js';
2
2
  import { useListbox, useOptionKeys } from './chunk-7KHM2FZH.js';
3
3
  import { Popover } from './chunk-KHJIEPZV.js';
4
4
  import { KeyChip, highlightMatch } from './chunk-HBDA76EZ.js';
@@ -1,7 +1,7 @@
1
- import { Modal } from './chunk-I24FI46B.js';
1
+ import { Modal } from './chunk-C667GCU7.js';
2
2
  import { useListbox, useHighlightRest } from './chunk-7KHM2FZH.js';
3
- import { Input } from './chunk-ETSF7SU6.js';
4
3
  import { Kbd } from './chunk-ANTAQAR4.js';
4
+ import { Input } from './chunk-ETSF7SU6.js';
5
5
  import { Count } from './chunk-MLDTLZAO.js';
6
6
  import { HIT_AREA_CLASS } from './chunk-2YTOOH3A.js';
7
7
  import { isComposing } from './chunk-H5XTJ7GJ.js';
@@ -1,7 +1,7 @@
1
1
  import { PrincipalAvatar } from './chunk-CI3VPIJN.js';
2
2
  import { RelativeTime } from './chunk-EJNJMHQG.js';
3
3
  import { Timeline } from './chunk-4MJN2KN6.js';
4
- import { Button } from './chunk-7QTPJDRF.js';
4
+ import { Button } from './chunk-DGXZ635L.js';
5
5
  import { cx } from './chunk-ODEQTPFM.js';
6
6
  import './VersionTimeline-DEAQ7CJG.css';
7
7
  import { RotateCcwClockGlyph, PencilGlyph, ShieldGlyph, DatabaseGlyph, UploadGlyph } from '@crewlethq/icons/glyphs';
@@ -1,7 +1,7 @@
1
1
  import { LayerNodeBridge } from './chunk-LM3ISVJA.js';
2
2
  import { Tooltip } from './chunk-I33UIUZD.js';
3
3
  import { Kbd } from './chunk-ANTAQAR4.js';
4
- import { Button } from './chunk-7QTPJDRF.js';
4
+ import { Button } from './chunk-DGXZ635L.js';
5
5
  import { LAYER_REPOSITION_EVENT, LayerHost } from './chunk-OMV5W53A.js';
6
6
  import { IconButton } from './chunk-UAUP6XGK.js';
7
7
  import { returnFocus } from './chunk-NUZHC6MM.js';
@@ -1,10 +1,10 @@
1
- import { Button } from './chunk-7QTPJDRF.js';
1
+ import { Button } from './chunk-DGXZ635L.js';
2
2
  import { useLayerContainer, viewportBounds, LAYER_GAP, anchorGone, placePopup, LAYER_REPOSITION_EVENT } from './chunk-OMV5W53A.js';
3
3
  import { usePopupLayer } from './chunk-H5XTJ7GJ.js';
4
4
  import { IconButton } from './chunk-UAUP6XGK.js';
5
5
  import { returnFocus } from './chunk-NUZHC6MM.js';
6
6
  import { cx } from './chunk-ODEQTPFM.js';
7
- import './Menu-OLUGHX56.css';
7
+ import './Menu-I4SNXHOT.css';
8
8
  import { useId, useState, useRef, useCallback, useLayoutEffect, useEffect } from 'react';
9
9
  import { createPortal } from 'react-dom';
10
10
  import { EllipsisVerticalGlyph, CheckGlyph } from '@crewlethq/icons/glyphs';
@@ -32,6 +32,7 @@ function Menu({
32
32
  trigger,
33
33
  trailingIcon,
34
34
  triggerVariant = "ghost",
35
+ valueTrigger = false,
35
36
  triggerTabIndex,
36
37
  open: controlled,
37
38
  onOpenChange,
@@ -280,7 +281,20 @@ function Menu({
280
281
  onKeyDown: onTriggerKeyDown
281
282
  };
282
283
  return /* @__PURE__ */ jsxs("span", { className: "crewlet-menu-anchor", children: [
283
- renderTrigger ? renderTrigger(shared) : trigger === void 0 ? /* @__PURE__ */ jsx(IconButton, { ...shared, label, icon: icon ?? /* @__PURE__ */ jsx(EllipsisVerticalGlyph, {}), size: "sm" }) : /* @__PURE__ */ jsx(Button, { ...shared, "aria-label": label, variant: triggerVariant, size: "small", leadingIcon: icon, trailingIcon, children: trigger }),
284
+ renderTrigger ? renderTrigger(shared) : trigger === void 0 ? /* @__PURE__ */ jsx(IconButton, { ...shared, label, icon: icon ?? /* @__PURE__ */ jsx(EllipsisVerticalGlyph, {}), size: "sm" }) : /* @__PURE__ */ jsx(
285
+ Button,
286
+ {
287
+ ...shared,
288
+ "aria-label": label,
289
+ variant: triggerVariant,
290
+ size: "small",
291
+ flush: valueTrigger,
292
+ className: valueTrigger ? "crewlet-menu__value-trigger" : void 0,
293
+ leadingIcon: icon,
294
+ trailingIcon,
295
+ children: trigger
296
+ }
297
+ ),
284
298
  list && container ? createPortal(list, container) : null
285
299
  ] });
286
300
  }
@@ -1,6 +1,6 @@
1
1
  import { StepList } from './chunk-HJBHP66O.js';
2
+ import { ReceiptStrip } from './chunk-ZWCK4N4L.js';
2
3
  import { Meter } from './chunk-RQFRRPV6.js';
3
- import { ReceiptStrip } from './chunk-M25IV5MH.js';
4
4
  import { StatusCard } from './chunk-NTQPJJAN.js';
5
5
  import { Disclosure } from './chunk-222VILSP.js';
6
6
  import { Spinner } from './chunk-XSPCITPN.js';
@@ -1,7 +1,7 @@
1
1
  import { SlideNav } from './chunk-5AJR6X75.js';
2
2
  import { SlideStage, SLIDE_WIDTH, SLIDE_HEIGHT } from './chunk-RMEBFYL7.js';
3
3
  import { Eyebrow } from './chunk-RK4XPHVG.js';
4
- import { Button } from './chunk-7QTPJDRF.js';
4
+ import { Button } from './chunk-DGXZ635L.js';
5
5
  import { cx } from './chunk-ODEQTPFM.js';
6
6
  import './PresenterView-RKYEK27N.css';
7
7
  import { useRef, useState, useEffect } from 'react';
@@ -1,4 +1,4 @@
1
- import { CopyButton } from './chunk-IYG4ETAQ.js';
1
+ import { CopyButton } from './chunk-T5GBTXNC.js';
2
2
  import { cx } from './chunk-ODEQTPFM.js';
3
3
  import './CodeBlock-T47UA5GM.css';
4
4
  import { forwardRef, useRef, useState, useLayoutEffect } from 'react';
@@ -1,5 +1,5 @@
1
1
  import { useMediaMatch } from './chunk-RTPQDNW3.js';
2
- import { Button } from './chunk-7QTPJDRF.js';
2
+ import { Button } from './chunk-DGXZ635L.js';
3
3
  import { VisuallyHidden } from './chunk-UT6CW3C7.js';
4
4
  import { cx } from './chunk-ODEQTPFM.js';
5
5
  import './ChatThread-2KO3FZKQ.css';