@crewlethq/ui 0.69.0 → 0.71.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 (156) hide show
  1. package/README.md +25 -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 +3 -3
  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/Toaster/Toaster.d.ts +14 -2
  81. package/dist/Toaster/index.d.ts +1 -1
  82. package/dist/Toaster/index.js +1 -1
  83. package/dist/TreeCanvas/index.js +3 -3
  84. package/dist/VersionCompare/index.js +5 -5
  85. package/dist/VersionTimeline/index.js +2 -2
  86. package/dist/{chunk-HXJHRQDR.js → chunk-3EY5SEGH.js} +2 -2
  87. package/dist/{chunk-DS5NBENV.js → chunk-3LP3VPLT.js} +2 -2
  88. package/dist/{chunk-6MI2GMYG.js → chunk-3WN5HUAK.js} +2 -2
  89. package/dist/{chunk-4E3CE2UK.js → chunk-4DL2BQJE.js} +2 -2
  90. package/dist/{chunk-PQWNK3N7.js → chunk-4MVLED6E.js} +3 -3
  91. package/dist/{chunk-BXEKD5NU.js → chunk-6C6YK75K.js} +2 -2
  92. package/dist/{chunk-2A6DL3K5.js → chunk-6FBPFG3C.js} +1 -1
  93. package/dist/{chunk-L4UO57YP.js → chunk-73SAOOR5.js} +3 -3
  94. package/dist/{chunk-WXLQJUGO.js → chunk-ADSOY7UM.js} +1 -1
  95. package/dist/{chunk-GNDKUSCG.js → chunk-AGLONIVV.js} +1 -1
  96. package/dist/{chunk-2EA2GSA2.js → chunk-AQIFKLXY.js} +1 -1
  97. package/dist/{chunk-SUJO3AHN.js → chunk-B3PK2LND.js} +1 -1
  98. package/dist/{chunk-UYK3SGZI.js → chunk-BWFJB5JD.js} +3 -3
  99. package/dist/{chunk-I24FI46B.js → chunk-C667GCU7.js} +1 -1
  100. package/dist/{chunk-CWYU7DNT.js → chunk-CDNZTCP2.js} +1 -1
  101. package/dist/{chunk-NJYB4VJI.js → chunk-DB7UVFOY.js} +2 -2
  102. package/dist/{chunk-OJGI4XJH.js → chunk-DGSK4LLS.js} +1 -1
  103. package/dist/{chunk-7QTPJDRF.js → chunk-DGXZ635L.js} +7 -4
  104. package/dist/{chunk-2SU735S3.js → chunk-DV5L2GRY.js} +1 -1
  105. package/dist/{chunk-NSCYGUDG.js → chunk-EHFQMY3B.js} +1 -1
  106. package/dist/{chunk-S2UHV52X.js → chunk-EN4UJQ63.js} +3 -3
  107. package/dist/{chunk-6ID4DVML.js → chunk-EOXI3CRG.js} +1 -1
  108. package/dist/{chunk-VTGIDEI5.js → chunk-ERFXYGRF.js} +2 -2
  109. package/dist/{chunk-JEA5OX54.js → chunk-FQI62PIZ.js} +2 -2
  110. package/dist/{chunk-ELLRZ5XR.js → chunk-FURJVZCT.js} +72 -26
  111. package/dist/{chunk-5K7GGQNX.js → chunk-G4QZWVAB.js} +2 -2
  112. package/dist/{chunk-IABWA76I.js → chunk-H32JW6CZ.js} +2 -2
  113. package/dist/{chunk-PX54PALQ.js → chunk-HPI5J6AR.js} +1 -1
  114. package/dist/{chunk-ZEPUKRO7.js → chunk-IJ7KLXUZ.js} +1 -1
  115. package/dist/{chunk-PVZOP3QK.js → chunk-IPUEVTRJ.js} +1 -1
  116. package/dist/{chunk-RLBGU35B.js → chunk-J5WWMC35.js} +45 -46
  117. package/dist/{chunk-O3BNL4TV.js → chunk-JD7P2GJP.js} +1 -1
  118. package/dist/{chunk-SZFKGH2W.js → chunk-JIBWNHTC.js} +42 -9
  119. package/dist/{chunk-KIJJD4YD.js → chunk-JQEXAH7G.js} +1 -1
  120. package/dist/{chunk-K4IVKHKU.js → chunk-JT7WRPZ6.js} +1 -1
  121. package/dist/chunk-K4LZXSKZ.js +62 -0
  122. package/dist/{chunk-ZHVLDRAT.js → chunk-KAA3GFTP.js} +4 -4
  123. package/dist/{chunk-WDNURPXU.js → chunk-KL6A7JGH.js} +1 -1
  124. package/dist/{chunk-2JHGPXYG.js → chunk-KQWJWTED.js} +1 -1
  125. package/dist/{chunk-WU5JDEEY.js → chunk-L4HHWG4V.js} +1 -1
  126. package/dist/{chunk-GDDVI4US.js → chunk-LQWORB5B.js} +1 -1
  127. package/dist/{chunk-EHB4TSP2.js → chunk-NXNLAZPK.js} +2 -2
  128. package/dist/{chunk-WPMZKZUH.js → chunk-O3HCFM3D.js} +1 -1
  129. package/dist/{chunk-F32FFE6I.js → chunk-OBPINJNO.js} +1 -1
  130. package/dist/{chunk-T73DMDU4.js → chunk-OQG4P5KU.js} +17 -3
  131. package/dist/{chunk-UWOYDHVW.js → chunk-P64MIA7C.js} +1 -1
  132. package/dist/{chunk-DMK2A4IK.js → chunk-QSWQJX27.js} +1 -1
  133. package/dist/{chunk-D2ZXIQ23.js → chunk-R5OATXWU.js} +1 -1
  134. package/dist/{chunk-OFABBAUR.js → chunk-SMZPUHBL.js} +1 -1
  135. package/dist/{chunk-7QTJO3PV.js → chunk-SO5SXSTP.js} +1 -1
  136. package/dist/{chunk-IYG4ETAQ.js → chunk-T5GBTXNC.js} +1 -1
  137. package/dist/{chunk-DXVJSBEW.js → chunk-TKBFRGUV.js} +3 -3
  138. package/dist/{chunk-U7J52N67.js → chunk-TPCBPGSB.js} +1 -1
  139. package/dist/{chunk-W6UVBBNH.js → chunk-TYIHFDMP.js} +1 -1
  140. package/dist/{chunk-GJ7VIQWL.js → chunk-UY3FWQWG.js} +1 -1
  141. package/dist/{chunk-KHHDCNYM.js → chunk-V6X3DJ2G.js} +2 -2
  142. package/dist/{chunk-NTFVEOYY.js → chunk-VBA5FSWV.js} +1 -1
  143. package/dist/{chunk-7EOUVWGQ.js → chunk-VWMB3CJN.js} +1 -1
  144. package/dist/{chunk-CX6QT4CH.js → chunk-W5AXJWOW.js} +1 -1
  145. package/dist/{chunk-OWQATZGW.js → chunk-YGWIWDXE.js} +2 -2
  146. package/dist/{chunk-2T32N2WD.js → chunk-YUHKRRWO.js} +2 -2
  147. package/dist/{chunk-M25IV5MH.js → chunk-ZWCK4N4L.js} +1 -1
  148. package/dist/generated/index.d.ts +1 -0
  149. package/dist/generated/index.js +93 -92
  150. package/dist/index.js +93 -92
  151. package/dist/styles.css +333 -146
  152. package/package.json +3 -3
  153. package/dist/{chunk-XWOH3UPZ.js → chunk-5OFRDX66.js} +1 -1
  154. package/dist/{chunk-KBXSOBLD.js → chunk-ABZC3NLM.js} +0 -0
  155. package/dist/{chunk-VZICPYGR.js → chunk-SNQRGH4A.js} +1 -1
  156. package/dist/{chunk-AIMMHN5J.js → chunk-VLGGLLKH.js} +1 -1
package/dist/styles.css CHANGED
@@ -5887,7 +5887,7 @@ a.crewlet-breadcrumb__crumb:focus-visible {
5887
5887
  }
5888
5888
 
5889
5889
 
5890
- /* Button-VRRYSXFN.css */
5890
+ /* Button-GDEBGBX6.css */
5891
5891
  /*
5892
5892
  * The button, and the link drawn as one.
5893
5893
  *
@@ -6000,23 +6000,50 @@ a.crewlet-breadcrumb__crumb:focus-visible {
6000
6000
  per size. min-height rather than height, so a label that wraps is read
6001
6001
  rather than clipped. */
6002
6002
  .crewlet-btn--small {
6003
+ --crewlet-btn-inset: var(--spacing-2);
6004
+
6003
6005
  min-height: var(--size-control-sm);
6004
- padding: 0 var(--spacing-2);
6006
+ padding: 0 var(--crewlet-btn-inset);
6005
6007
  font-size: var(--font-size-xs);
6006
6008
  }
6007
6009
 
6008
6010
  .crewlet-btn--medium {
6011
+ --crewlet-btn-inset: var(--spacing-3);
6012
+
6009
6013
  min-height: var(--size-control-md);
6010
- padding: 0 var(--spacing-3);
6014
+ padding: 0 var(--crewlet-btn-inset);
6011
6015
  font-size: var(--font-size-compact);
6012
6016
  }
6013
6017
 
6014
6018
  .crewlet-btn--large {
6019
+ --crewlet-btn-inset: var(--spacing-4);
6020
+
6015
6021
  min-height: var(--size-control-lg);
6016
- padding: 0 var(--spacing-4);
6022
+ padding: 0 var(--crewlet-btn-inset);
6017
6023
  font-size: var(--font-size-sm);
6018
6024
  }
6019
6025
 
6026
+ /*
6027
+ * FLUSH: the words start on the line. The padding and the 1px edge are taken
6028
+ * back at the start, so a ghost button drawn as a value starts on the line
6029
+ * the plain values in its column start on, and only the hover ground and the
6030
+ * ring reach past it, into the gutter before it. The START ONLY: taken back at
6031
+ * the end too, the box overran its cell's content edge, which a column that
6032
+ * measures what it cuts short reads as a value that does not fit. The ring is
6033
+ * drawn inside, so a container that clips (a table, a card) never cuts it.
6034
+ *
6035
+ * A CONTAINER WITH NO GUTTER TO GIVE sets `--crewlet-btn-flush-outdent` to 0:
6036
+ * a table's first column and its card rows (DataGrid.css), where the outdent
6037
+ * would pull the control toward the frame.
6038
+ */
6039
+ .crewlet-btn--flush {
6040
+ margin-inline-start: var(--crewlet-btn-flush-outdent, calc(-1 * (var(--crewlet-btn-inset) + 1px)));
6041
+ }
6042
+
6043
+ .crewlet-btn--flush:focus-visible {
6044
+ outline-offset: var(--size-focus-ring-inset-offset);
6045
+ }
6046
+
6020
6047
  .crewlet-btn--square {
6021
6048
  border-radius: var(--radius-md);
6022
6049
  }
@@ -12344,7 +12371,7 @@ button.crewlet-histogram__bar[data-empty]:focus-visible > .crewlet-histogram__fi
12344
12371
  }
12345
12372
 
12346
12373
 
12347
- /* DataGrid-NHIN2I42.css */
12374
+ /* DataGrid-Q26F2V5Q.css */
12348
12375
  /*
12349
12376
  * DataGrid: a list as columns, one track list on the grid.
12350
12377
  *
@@ -12467,6 +12494,18 @@ button.crewlet-histogram__bar[data-empty]:focus-visible > .crewlet-histogram__fi
12467
12494
  --crewlet-data-grid-cell-start: var(--spacing-3);
12468
12495
  }
12469
12496
 
12497
+ /*
12498
+ * AND AN ICON COLUMN, whose track (`DATA_GRID_ICON_TRACK`) is the target size
12499
+ * and the cells' own step either side. At the grid's edge (a card's 16px) the
12500
+ * edge inset left 20px for a 24px mark; the column keeps the cells' step on
12501
+ * both sides wherever it stands, as the selection column does.
12502
+ */
12503
+ .crewlet-data-grid__th.crewlet-data-grid__th--icon,
12504
+ .crewlet-data-grid__cell.crewlet-data-grid__cell--icon {
12505
+ --crewlet-data-grid-cell-start: var(--spacing-3);
12506
+ --crewlet-data-grid-cell-end: var(--spacing-3);
12507
+ }
12508
+
12470
12509
  /*
12471
12510
  * THE LIST TABLE'S HEAD: the micro-label register every table takes, 11/500
12472
12511
  * uppercase. A sortable head is a button with its chrome reset; the reset
@@ -12474,6 +12513,7 @@ button.crewlet-histogram__bar[data-empty]:focus-visible > .crewlet-histogram__fi
12474
12513
  */
12475
12514
  .crewlet-data-grid__th {
12476
12515
  display: flex;
12516
+ align-self: stretch;
12477
12517
  align-items: center;
12478
12518
  gap: var(--spacing-1);
12479
12519
  padding-block: var(--spacing-2);
@@ -12520,22 +12560,91 @@ button.crewlet-histogram__bar[data-empty]:focus-visible > .crewlet-histogram__fi
12520
12560
  margin-inline: calc(-1 * var(--crewlet-data-grid-cell-start)) calc(-1 * var(--crewlet-data-grid-cell-end));
12521
12561
  padding-block: var(--spacing-2);
12522
12562
  padding-inline: var(--crewlet-data-grid-cell-start) var(--crewlet-data-grid-cell-end);
12563
+ /* THE HEAD'S WHOLE HEIGHT, so a press anywhere in the cell sorts. */
12564
+ align-self: stretch;
12523
12565
  cursor: pointer;
12524
12566
  }
12525
12567
 
12568
+ /*
12569
+ * ONE EDGE PER COLUMN, shared by its head and its values. `align` gives the
12570
+ * head and every cell the same modifier, and both take the same inline inset
12571
+ * (`--crewlet-data-grid-cell-start` and `-end`), so the word in the head and
12572
+ * the values under it start (or end, or centre) on one line. A head that
12573
+ * sorts is a button filling its head, and takes the same edge.
12574
+ */
12526
12575
  .crewlet-data-grid__th--right .crewlet-data-grid__sort {
12527
12576
  justify-content: flex-end;
12528
12577
  }
12529
12578
 
12579
+ .crewlet-data-grid__th--center .crewlet-data-grid__sort {
12580
+ justify-content: center;
12581
+ }
12582
+
12530
12583
  .crewlet-data-grid__th:not(.crewlet-data-grid__th--plain):hover,
12531
12584
  .crewlet-data-grid__th--sorted {
12532
12585
  color: var(--color-text-primary);
12533
12586
  }
12534
12587
 
12588
+ /*
12589
+ * A SORTABLE HEAD SAYS SO UNDER THE POINTER: the row's own hover overlay over
12590
+ * the whole cell, the way a row says it opens, so the target is the head and
12591
+ * not the word in it.
12592
+ */
12593
+ .crewlet-data-grid__th:not(.crewlet-data-grid__th--plain):hover {
12594
+ background: var(--color-surface-hover);
12595
+ }
12596
+
12597
+ /*
12598
+ * THE SORT ARROW. Its box is always laid out, so a head never changes width
12599
+ * when the arrow appears and the fit measured at rest still holds under the
12600
+ * pointer. The two-way arrow of a head that is not the sort shows only on
12601
+ * hover and focus, in the head's own ink; the sorted head's arrow is always
12602
+ * shown, at full ink, and names the direction.
12603
+ */
12604
+ .crewlet-data-grid__sort-mark {
12605
+ display: inline-flex;
12606
+ flex: none;
12607
+ inline-size: var(--spacing-3);
12608
+ color: inherit;
12609
+ transition: opacity var(--motion-duration-fast) var(--motion-easing-default);
12610
+ }
12611
+
12612
+ .crewlet-data-grid__th:not(.crewlet-data-grid__th--sorted) .crewlet-data-grid__sort-mark {
12613
+ opacity: 0;
12614
+ }
12615
+
12616
+ /* BEFORE THE WORD IN A RIGHT-ALIGNED COLUMN, so the word stays on the column's
12617
+ right edge over its figures, arrow or not. */
12618
+ .crewlet-data-grid__th--right .crewlet-data-grid__sort-mark {
12619
+ order: -1;
12620
+ }
12621
+
12622
+ /*
12623
+ * AND MIRRORED IN A CENTRED COLUMN: a box the arrow's size before the word, a
12624
+ * gap away, so the word stands on the column's middle over its values rather
12625
+ * than half an arrow off it. ONLY BEFORE A WORD: a head with none (a sortable
12626
+ * mark column) draws its arrow alone, already on the middle, and the reserve
12627
+ * would push it off.
12628
+ */
12629
+ .crewlet-data-grid__th--center .crewlet-data-grid__sort:has(> .crewlet-data-grid__truncate)::before {
12630
+ content: '';
12631
+ flex: none;
12632
+ inline-size: var(--spacing-3);
12633
+ }
12634
+
12635
+ .crewlet-data-grid__th:hover .crewlet-data-grid__sort-mark,
12636
+ .crewlet-data-grid__sort:focus-visible .crewlet-data-grid__sort-mark {
12637
+ opacity: 1;
12638
+ }
12639
+
12535
12640
  .crewlet-data-grid__th--right {
12536
12641
  justify-content: flex-end;
12537
12642
  }
12538
12643
 
12644
+ .crewlet-data-grid__th--center {
12645
+ justify-content: center;
12646
+ }
12647
+
12539
12648
  .crewlet-data-grid__sort:focus-visible,
12540
12649
  .crewlet-data-grid__cols-reset:focus-visible {
12541
12650
  outline: 2px solid var(--color-focus);
@@ -12642,23 +12751,30 @@ button.crewlet-data-grid__row-link {
12642
12751
  * A GHOST CONTROL STARTS ON THE COLUMN'S TEXT EDGE. A small ghost button that
12643
12752
  * opens a cell ("Open ENG-12", a choice made in place through a menu) drew its
12644
12753
  * word one padding and one edge (9px) inside the line its column starts on.
12645
- * Its padding and edge are taken back, as a card's foot does (StatusCard.css):
12646
- * the word sits on the line and only the hover's ground reaches past it, into
12647
- * the step between two columns. A column of figures ends its controls on the
12648
- * far edge, so it is left alone.
12649
- *
12650
- * NEVER AT THE GRID'S OWN EDGE: its first column, and every line of a phone's
12651
- * card (below). A grid standing alone has only its 12px edge there, and with
12652
- * the 9px taken back, the 4px the control's focus ring stands off it ran past
12653
- * the grid's clip: the ring lost a pixel and the hover ground stood 3px from
12654
- * the frame.
12655
- */
12656
- .crewlet-data-grid__cell:not(:first-child, .crewlet-data-grid__cell--right)
12657
- > .crewlet-btn--ghost.crewlet-btn--small:first-child,
12658
- .crewlet-data-grid__cell:not(:first-child, .crewlet-data-grid__cell--right)
12659
- > .crewlet-menu-anchor:first-child
12660
- > .crewlet-btn--ghost.crewlet-btn--small {
12661
- margin-inline-start: var(--crewlet-data-grid-control-outdent, calc(-1 * (var(--spacing-2) + 1px)));
12754
+ * ONE MECHANISM, Button's `flush`: a flush control anywhere in a cell takes
12755
+ * its padding and edge back, and a ghost control written straight into a cell
12756
+ * (or as a menu's trigger there) is drawn flush without being asked, by the
12757
+ * same declaration. The word sits on the line and only the hover's ground
12758
+ * reaches past it, into the step between two columns.
12759
+ *
12760
+ * THE EXEMPTIONS ARE ONE VARIABLE, `--crewlet-btn-flush-outdent: 0`, which
12761
+ * the flush declaration reads:
12762
+ *
12763
+ * - THE GRID'S OWN EDGE, its first column and every line of a phone's card
12764
+ * (below). A grid standing alone has only its 12px edge there, and with the
12765
+ * 9px taken back the control's focus ring ran past the grid's clip and the
12766
+ * hover ground stood 3px from the frame.
12767
+ * - A RIGHT OR A CENTRED COLUMN, which lines its values up by their end or
12768
+ * their middle, where a control taken back at its start would stand off
12769
+ * both.
12770
+ */
12771
+ .crewlet-data-grid__cell > .crewlet-btn--ghost.crewlet-btn--small:first-child,
12772
+ .crewlet-data-grid__cell > .crewlet-menu-anchor:first-child > .crewlet-btn--ghost.crewlet-btn--small {
12773
+ margin-inline-start: var(--crewlet-btn-flush-outdent, calc(-1 * (var(--crewlet-btn-inset) + 1px)));
12774
+ }
12775
+
12776
+ .crewlet-data-grid__cell:is(:first-child, .crewlet-data-grid__cell--right, .crewlet-data-grid__cell--center) {
12777
+ --crewlet-btn-flush-outdent: 0px;
12662
12778
  }
12663
12779
 
12664
12780
  /*
@@ -12672,10 +12788,18 @@ button.crewlet-data-grid__row-link {
12672
12788
  overflow: clip;
12673
12789
  }
12674
12790
 
12791
+ /* A RIGHT-ALIGNED COLUMN holds figures, times and dates: tabular digits, so
12792
+ "53s ago" and "12h ago" end on one edge and their digits stand in columns. */
12675
12793
  .crewlet-data-grid__cell--right {
12676
12794
  justify-content: flex-end;
12795
+ font-variant-numeric: tabular-nums;
12677
12796
  }
12678
12797
 
12798
+ .crewlet-data-grid__cell--center {
12799
+ justify-content: center;
12800
+ }
12801
+
12802
+
12679
12803
  .crewlet-data-grid__truncate {
12680
12804
  min-width: 0;
12681
12805
  overflow: hidden;
@@ -12748,14 +12872,25 @@ button.crewlet-data-grid__row-link {
12748
12872
  color: var(--color-text-primary);
12749
12873
  }
12750
12874
 
12875
+ /*
12876
+ * THE FOOT IS A CAPTION, NOT A ROW. At the row's height and on the head's
12877
+ * raised ground it read as one more row, so a grid's head, rows and foot
12878
+ * blurred into one stack. It takes the micro step of type, the tertiary ink,
12879
+ * half the row's inset and the grid's own ground under the rows' hairline:
12880
+ * quieter than either neighbour, and plainly the end of the list.
12881
+ */
12751
12882
  .crewlet-data-grid__foot {
12752
12883
  display: flex;
12753
12884
  align-items: center;
12754
- gap: var(--spacing-2);
12755
- padding: var(--spacing-2) var(--crewlet-data-grid-edge);
12756
- border-top: 1px solid var(--color-border-hover);
12757
- background: var(--color-surface-elevated);
12758
- font-size: var(--font-size-xs);
12885
+ flex-wrap: wrap;
12886
+ gap: var(--spacing-1) var(--spacing-3);
12887
+ min-height: var(--size-control-sm);
12888
+ padding: var(--spacing-1) var(--crewlet-data-grid-edge);
12889
+ border-top: 1px solid var(--color-border-default);
12890
+ background: transparent;
12891
+ color: var(--color-text-tertiary);
12892
+ font-size: var(--font-size-2xs);
12893
+ line-height: var(--font-line-height-tight);
12759
12894
  }
12760
12895
 
12761
12896
  .crewlet-data-grid__foot-spacer {
@@ -12763,7 +12898,7 @@ button.crewlet-data-grid__row-link {
12763
12898
  }
12764
12899
 
12765
12900
  .crewlet-data-grid__note {
12766
- font-size: var(--font-size-xs);
12901
+ font-size: inherit;
12767
12902
  color: var(--color-text-tertiary);
12768
12903
  }
12769
12904
 
@@ -12807,9 +12942,21 @@ button.crewlet-data-grid__row-link {
12807
12942
  cursor: pointer;
12808
12943
  }
12809
12944
 
12945
+ /*
12946
+ * WHERE NOTHING HOVERS (a touch screen), a sortable head shows its arrow at
12947
+ * rest: there is no pointer to bring it out, and a head that only says it
12948
+ * sorts under a pointer says nothing there.
12949
+ */
12950
+ @media (hover: none) {
12951
+ .crewlet-data-grid__th:not(.crewlet-data-grid__th--plain) .crewlet-data-grid__sort-mark {
12952
+ opacity: 1;
12953
+ }
12954
+ }
12955
+
12810
12956
  @media (prefers-reduced-motion: reduce) {
12811
12957
  .crewlet-data-grid__th,
12812
- .crewlet-data-grid__row {
12958
+ .crewlet-data-grid__row,
12959
+ .crewlet-data-grid__sort-mark {
12813
12960
  transition: none;
12814
12961
  }
12815
12962
  }
@@ -12833,7 +12980,7 @@ button.crewlet-data-grid__row-link {
12833
12980
  /* No ghost control is pulled out here (see above): every line of a card
12834
12981
  starts at the grid's edge, and a compact row's marks run on one line,
12835
12982
  where the hover ground swallowed the gap before it. */
12836
- --crewlet-data-grid-control-outdent: 0px;
12983
+ --crewlet-btn-flush-outdent: 0px;
12837
12984
 
12838
12985
  display: block;
12839
12986
  }
@@ -12879,7 +13026,8 @@ button.crewlet-data-grid__row-link {
12879
13026
 
12880
13027
  /* `shrink` and `right` are column shapes, and there are no columns here. */
12881
13028
  :where(.crewlet-data-grid[data-stacked]) .crewlet-data-grid__cell--shrink,
12882
- :where(.crewlet-data-grid[data-stacked]) .crewlet-data-grid__cell--right {
13029
+ :where(.crewlet-data-grid[data-stacked]) .crewlet-data-grid__cell--right,
13030
+ :where(.crewlet-data-grid[data-stacked]) .crewlet-data-grid__cell--center {
12883
13031
  white-space: normal;
12884
13032
  justify-content: flex-start;
12885
13033
  }
@@ -15219,7 +15367,7 @@ body.crewlet-data-table-resizing {
15219
15367
  }
15220
15368
 
15221
15369
 
15222
- /* DataView-RH5UDA5F.css */
15370
+ /* DataView-L7HLNW7C.css */
15223
15371
  /*
15224
15372
  * The list screen: header, toolbar, filter chips, table.
15225
15373
  *
@@ -15442,118 +15590,7 @@ body.crewlet-data-table-resizing {
15442
15590
 
15443
15591
  /* ── One chip ─────────────────────────────────────────────────────────── */
15444
15592
 
15445
- /*
15446
- * TWO CONTROLS IN ONE PILL: pressing the chip opens its editor, pressing the
15447
- * cross takes the filter off. They are drawn as one object with a divider
15448
- * because they are one filter, and they are two BUTTONS because they do two
15449
- * different things, which is also why the cross carries its own name rather
15450
- * than relying on the chip's.
15451
- */
15452
- .crewlet-filter-axis-chip {
15453
- display: inline-flex;
15454
- align-items: stretch;
15455
- height: var(--size-control-sm);
15456
- background: var(--color-brand-accent-soft);
15457
- border: 1px solid var(--color-brand-accent-soft-strong);
15458
- border-radius: var(--radius-pill);
15459
- overflow: hidden;
15460
- max-width: 100%;
15461
- transition: border-color var(--motion-duration-fast) var(--motion-easing-default);
15462
- }
15463
-
15464
- /*
15465
- * THE EDGE, NOT THE FILL. `--color-surface-hover` is the overlay a row at rest
15466
- * carries, and the token says a surface shows it OR a selected tint, never
15467
- * both: put on a chip it REPLACED the accent fill, so the one control on screen
15468
- * that means "this filter is on" went pale under the pointer and read as the
15469
- * filter being switched off.
15470
- *
15471
- * The fill stays where it is and the boundary takes the accent itself.
15472
- * Deepening the fill to the next accent step instead measures 4.48:1 under the
15473
- * chip's own ink on the light ground, and 4.18:1 on a card, which is why that
15474
- * step is a BORDER value in the palette and is used as one here.
15475
- */
15476
- .crewlet-filter-axis-chip:hover {
15477
- border-color: var(--color-brand-accent);
15478
- }
15479
-
15480
- .crewlet-filter-axis-chip__trigger {
15481
- display: inline-flex;
15482
- align-items: center;
15483
- gap: var(--spacing-1);
15484
- min-width: 0;
15485
- padding: 0 var(--spacing-2) 0 var(--spacing-3);
15486
- background: transparent;
15487
- border: none;
15488
- cursor: pointer;
15489
- color: var(--color-brand-accent-ink);
15490
- font-family: var(--font-family-sans);
15491
- font-size: var(--font-size-xs);
15492
- line-height: 1;
15493
- }
15494
-
15495
- .crewlet-filter-axis-chip__trigger:focus-visible {
15496
- outline: 2px solid var(--color-focus);
15497
- outline-offset: var(--size-focus-ring-inset-offset);
15498
- }
15499
-
15500
- /*
15501
- * THE AXIS NAME IS NOT DIMMED. It read at 0.85 opacity, which takes the chip's
15502
- * own ink off the step the pairing was measured at, and the name of the axis
15503
- * is exactly what a reader checks before the value: "status" and "stage" narrow
15504
- * a list to very different things. The value's own weight is what separates
15505
- * the halves, which is a difference a reader can see at any contrast.
15506
- */
15507
- .crewlet-filter-axis-chip__label {
15508
- white-space: nowrap;
15509
- }
15510
-
15511
- .crewlet-filter-axis-chip__value {
15512
- font-weight: var(--font-weight-semibold);
15513
- overflow: hidden;
15514
- text-overflow: ellipsis;
15515
- white-space: nowrap;
15516
- }
15517
-
15518
- /*
15519
- * The chevron carries the chip's own ink rather than a fainter version of it,
15520
- * for the reason every mark beside its words does: a grey glyph next to
15521
- * coloured text reads as two things. At 0.7 it measured 3.00:1 on a card in
15522
- * light, which is the 3:1 floor for a glyph to the second decimal place.
15523
- */
15524
- .crewlet-filter-axis-chip__chevron {
15525
- flex: none;
15526
- }
15527
-
15528
- /*
15529
- * The remove control keeps the chip's own ink rather than taking the critical
15530
- * hue on hover: removing a filter destroys nothing, and a row of chips that
15531
- * turns red under the pointer reads as a row of dangerous things.
15532
- */
15533
- .crewlet-filter-axis-chip__remove {
15534
- /* AS TALL AS THE PILL'S INSIDE, as the trigger beside it is. At the small
15535
- control's own height it stood 2px past the pill's inner edge, cut off at
15536
- the bottom, and its cross sat 1px under the chip's middle. */
15537
- height: auto;
15538
- border-radius: 0;
15539
- border-left: 1px solid var(--color-brand-accent-soft-strong);
15540
- color: var(--color-brand-accent-ink);
15541
- }
15542
-
15543
- /*
15544
- * Its ring is drawn INSIDE it, like the trigger's beside it. The pill clips to
15545
- * its own radius, so the outset ring an icon button carries everywhere else is
15546
- * cut off on every edge the control touches, which here is all of them.
15547
- */
15548
- .crewlet-filter-axis-chip__remove:focus-visible {
15549
- outline-offset: var(--size-focus-ring-inset-offset);
15550
- }
15551
-
15552
- @media (prefers-reduced-motion: reduce) {
15553
- .crewlet-filter-axis-chip {
15554
- transition: none;
15555
- }
15556
- }
15593
+ /* A chip is a [FilterPill] (FilterPill.css) whose words open its editor. */
15557
15594
 
15558
15595
  /* ── A chip's editor ──────────────────────────────────────────────────── */
15559
15596
 
@@ -18500,6 +18537,143 @@ svg.crewlet-datetime__chevron {
18500
18537
  }
18501
18538
 
18502
18539
 
18540
+ /* FilterPill-4GMNFZND.css */
18541
+ /*
18542
+ * The filter pill: one filter in force, as a sentence on the accent ground.
18543
+ *
18544
+ * TWO CONTROLS IN ONE PILL where the words open an editor: pressing the words
18545
+ * opens it, pressing the cross takes the filter off. They are drawn as one
18546
+ * object with a divider because they are one filter, and they are two BUTTONS
18547
+ * because they do two different things, which is also why the cross carries
18548
+ * its own name rather than relying on the words'.
18549
+ */
18550
+ .crewlet-filter-pill {
18551
+ display: inline-flex;
18552
+ align-items: stretch;
18553
+ height: var(--size-control-sm);
18554
+ max-width: 100%;
18555
+ min-width: 0;
18556
+ background: var(--color-brand-accent-soft);
18557
+ border: 1px solid var(--color-brand-accent-soft-strong);
18558
+ border-radius: var(--radius-pill);
18559
+ overflow: hidden;
18560
+ box-sizing: border-box;
18561
+ transition: border-color var(--motion-duration-fast) var(--motion-easing-default);
18562
+ }
18563
+
18564
+ /*
18565
+ * THE EDGE, NOT THE FILL, under the pointer. The surface hover overlay put on
18566
+ * the pill REPLACED the accent fill, so the one control on screen that means
18567
+ * "this filter is on" went pale and read as the filter being switched off.
18568
+ * The fill stays and the boundary takes the accent itself: the next fill step
18569
+ * measures under 4.5:1 beneath the pill's own ink, which is why that step is a
18570
+ * border value in the palette and is used as one here.
18571
+ */
18572
+ .crewlet-filter-pill:hover {
18573
+ border-color: var(--color-brand-accent);
18574
+ }
18575
+
18576
+ /*
18577
+ * THE WORDS: one line, the parts a step apart. The gap draws the space; the
18578
+ * space characters between the parts are still in the text, which is what a
18579
+ * copy and a screen reader take, but a flex row does not draw them, so the
18580
+ * step is the one spacing. A long value ends in an ellipsis at the pill's
18581
+ * edge. Plain text, or the control `renderWords` makes, which gives up a
18582
+ * button's chrome and keeps the same line.
18583
+ */
18584
+ .crewlet-filter-pill__words {
18585
+ display: inline-flex;
18586
+ align-items: center;
18587
+ gap: var(--spacing-1);
18588
+ min-width: 0;
18589
+ margin: 0;
18590
+ padding: 0 var(--spacing-3);
18591
+ background: transparent;
18592
+ border: 0;
18593
+ color: var(--color-text-secondary);
18594
+ font-family: var(--font-family-sans);
18595
+ font-size: var(--font-size-xs);
18596
+ font-weight: var(--font-weight-regular);
18597
+ line-height: 1;
18598
+ white-space: nowrap;
18599
+ }
18600
+
18601
+ /* A pill with a remove control gives the words' trailing inset to the divider. */
18602
+ .crewlet-filter-pill:has(> .crewlet-filter-pill__remove) > .crewlet-filter-pill__words {
18603
+ padding-inline-end: var(--spacing-2);
18604
+ }
18605
+
18606
+ button.crewlet-filter-pill__words {
18607
+ cursor: pointer;
18608
+ }
18609
+
18610
+ .crewlet-filter-pill__words:focus-visible {
18611
+ outline: 2px solid var(--color-focus);
18612
+ outline-offset: var(--size-focus-ring-inset-offset);
18613
+ }
18614
+
18615
+ /*
18616
+ * THREE REGISTERS. The field and the relation are what the filter is ABOUT,
18617
+ * in the secondary ink at the regular weight; the value is the answer, in the
18618
+ * accent ink at the semibold weight, and the only part a long filter cuts.
18619
+ */
18620
+ .crewlet-filter-pill__field,
18621
+ .crewlet-filter-pill__operator {
18622
+ flex: none;
18623
+ color: var(--color-text-secondary);
18624
+ }
18625
+
18626
+ .crewlet-filter-pill__value {
18627
+ min-width: 0;
18628
+ overflow: hidden;
18629
+ text-overflow: ellipsis;
18630
+ color: var(--color-brand-accent-ink);
18631
+ font-weight: var(--font-weight-semibold);
18632
+ }
18633
+
18634
+ /*
18635
+ * A glyph after the words (a popover's chevron) carries the value's ink: a
18636
+ * grey glyph next to coloured text reads as two things.
18637
+ */
18638
+ .crewlet-filter-pill__words > svg {
18639
+ flex: none;
18640
+ color: var(--color-brand-accent-ink);
18641
+ }
18642
+
18643
+ /*
18644
+ * The remove control: as tall as the pill's inside, behind a hairline, in the
18645
+ * pill's own ink. At the small control's own height it stood past the pill's
18646
+ * inner edge and was cut off at the bottom.
18647
+ *
18648
+ * RAISED OVER ICONBUTTON'S OWN RULES (`.crewlet-icon-btn`, `--sm`), which
18649
+ * carry the same weight as one class and can load after this sheet in a
18650
+ * bundle: at equal weight the control kept its 26px height and its corner
18651
+ * radius in a 26px pill with a 1px edge, overran the pill by a pixel and lost
18652
+ * the bottom of its focus ring. The child combinator is the extra weight, and
18653
+ * a test holds it above every IconButton rule.
18654
+ */
18655
+ .crewlet-filter-pill > .crewlet-filter-pill__remove {
18656
+ height: auto;
18657
+ border-radius: 0;
18658
+ border-inline-start: 1px solid var(--color-brand-accent-soft-strong);
18659
+ color: var(--color-brand-accent-ink);
18660
+ }
18661
+
18662
+ /*
18663
+ * Its ring is drawn INSIDE it, like the words'. The pill clips to its own
18664
+ * radius, so an outset ring is cut off on every edge the control touches.
18665
+ */
18666
+ .crewlet-filter-pill > .crewlet-filter-pill__remove:focus-visible {
18667
+ outline-offset: var(--size-focus-ring-inset-offset);
18668
+ }
18669
+
18670
+ @media (prefers-reduced-motion: reduce) {
18671
+ .crewlet-filter-pill {
18672
+ transition: none;
18673
+ }
18674
+ }
18675
+
18676
+
18503
18677
  /* FindingList-MPLA2ZTO.css */
18504
18678
  /*
18505
18679
  * What a checker found: a quiet list, one row each, the tone's glyph in its
@@ -23141,7 +23315,7 @@ a.crewlet-icon-btn {
23141
23315
  }
23142
23316
 
23143
23317
 
23144
- /* Menu-OLUGHX56.css */
23318
+ /* Menu-I4SNXHOT.css */
23145
23319
  /*
23146
23320
  * The menu button's panel.
23147
23321
  *
@@ -23431,6 +23605,18 @@ a.crewlet-icon-btn {
23431
23605
  }
23432
23606
  }
23433
23607
 
23608
+ /*
23609
+ * A TRIGGER THAT IS THE VALUE it changes (`valueTrigger`): the surrounding
23610
+ * text's size, weight and ink, not a button label's, so a writer's row reads
23611
+ * as a reader's. Its start is Button's `flush`. Raised over the button's own
23612
+ * size and variant rules, which carry one class each.
23613
+ */
23614
+ .crewlet-menu-anchor > .crewlet-btn.crewlet-menu__value-trigger {
23615
+ font-size: inherit;
23616
+ font-weight: inherit;
23617
+ color: inherit;
23618
+ }
23619
+
23434
23620
 
23435
23621
  /* MergeConflicts-HCXPRQVR.css */
23436
23622
  /* MergeConflicts: each clash as the other side's lines beside the draft's,
@@ -36350,7 +36536,7 @@ b.crewlet-switcher__match {
36350
36536
  }
36351
36537
 
36352
36538
 
36353
- /* TableCells-F6MUV572.css */
36539
+ /* TableCells-TKSNLRK3.css */
36354
36540
  /* The read-only table cells. Each one holds a single line and shrinks inside
36355
36541
  its column (`min-width: 0`), so a long value is cut with an ellipsis and
36356
36542
  its whole text on the title rather than standing the row two lines tall. */
@@ -36384,6 +36570,7 @@ b.crewlet-switcher__match {
36384
36570
  .crewlet-table-cell__date {
36385
36571
  color: var(--color-text-tertiary);
36386
36572
  white-space: nowrap;
36573
+ font-variant-numeric: tabular-nums;
36387
36574
  }
36388
36575
 
36389
36576
  /*
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crewlethq/ui",
3
- "version": "0.69.0",
3
+ "version": "0.71.0",
4
4
  "description": "Crewlet shared React components built on @crewlethq/tokens and @crewlethq/icons.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -42,8 +42,8 @@
42
42
  "clean": "rm -rf dist src/generated"
43
43
  },
44
44
  "dependencies": {
45
- "@crewlethq/icons": "0.69.0",
46
- "@crewlethq/tokens": "0.69.0",
45
+ "@crewlethq/icons": "0.71.0",
46
+ "@crewlethq/tokens": "0.71.0",
47
47
  "prosemirror-commands": "1.7.2",
48
48
  "prosemirror-gapcursor": "1.4.1",
49
49
  "prosemirror-history": "1.5.1",
@@ -1,5 +1,5 @@
1
- import { Textarea } from './chunk-ETSF7SU6.js';
2
1
  import { Kbd } from './chunk-ANTAQAR4.js';
2
+ import { Textarea } from './chunk-ETSF7SU6.js';
3
3
  import { isComposing } from './chunk-H5XTJ7GJ.js';
4
4
  import { VisuallyHidden } from './chunk-UT6CW3C7.js';
5
5
  import { cx } from './chunk-ODEQTPFM.js';
File without changes
@@ -1,5 +1,5 @@
1
- import { Avatar } from './chunk-PZKHBB7D.js';
2
1
  import { useRoving, tabStop } from './chunk-EGMQURBR.js';
2
+ import { Avatar } from './chunk-PZKHBB7D.js';
3
3
  import { cx } from './chunk-ODEQTPFM.js';
4
4
  import { CREWLET_CHARACTERS, CREWLET_CHARACTER_GEOMETRY } from '@crewlethq/icons/characters';
5
5
  import { jsx } from 'react/jsx-runtime';