@crewlethq/ui 0.12.0 → 0.14.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 +82 -5
  2. package/dist/AppShell/index.js +2 -1
  3. package/dist/Avatar/index.js +1 -1
  4. package/dist/{Avatar-QHYOFID3.css → Avatar-BPJ36QZR.css} +1 -1
  5. package/dist/AvatarPicker/index.js +5 -5
  6. package/dist/Breadcrumb/Breadcrumb.d.ts +68 -0
  7. package/dist/Breadcrumb/index.d.ts +3 -0
  8. package/dist/Breadcrumb/index.js +3 -0
  9. package/dist/Breadcrumb-YMWVM3SV.css +193 -0
  10. package/dist/ChoiceButtons/ChoiceButtons.d.ts +43 -0
  11. package/dist/ChoiceButtons/index.d.ts +3 -0
  12. package/dist/ChoiceButtons/index.js +3 -0
  13. package/dist/ChoiceButtons-DJ5EOGUA.css +127 -0
  14. package/dist/Combobox/index.js +2 -2
  15. package/dist/CommandPalette/CommandPalette.d.ts +48 -1
  16. package/dist/CommandPalette/index.js +3 -3
  17. package/dist/{CommandPalette-C5AMKGN2.css → CommandPalette-HBTNKHZQ.css} +55 -2
  18. package/dist/DataTable/index.js +4 -4
  19. package/dist/DataView/index.js +11 -11
  20. package/dist/DateTimePicker/index.js +2 -2
  21. package/dist/{DateTimePicker-4AZBTODT.css → DateTimePicker-NJ6XH2TE.css} +4 -3
  22. package/dist/Document/Document.d.ts +56 -0
  23. package/dist/Document/index.d.ts +3 -0
  24. package/dist/Document/index.js +2 -0
  25. package/dist/Document-PQGXJHB7.css +288 -0
  26. package/dist/EntityChip/index.js +1 -1
  27. package/dist/Highlight/Highlight.d.ts +45 -0
  28. package/dist/Highlight/index.d.ts +3 -0
  29. package/dist/Highlight/index.js +2 -0
  30. package/dist/Highlight-DXLV2R6L.css +29 -0
  31. package/dist/HuePicker/index.js +3 -3
  32. package/dist/ImageUpload/index.js +2 -2
  33. package/dist/{ImageUpload-L2GE4JUM.css → ImageUpload-NVGMN7DP.css} +9 -6
  34. package/dist/InboxList/InboxList.d.ts +116 -0
  35. package/dist/InboxList/index.d.ts +3 -0
  36. package/dist/InboxList/index.js +5 -0
  37. package/dist/InboxList-YMFWKGGS.css +252 -0
  38. package/dist/KeyChip/KeyChip.d.ts +21 -0
  39. package/dist/KeyChip/index.d.ts +3 -0
  40. package/dist/KeyChip/index.js +2 -0
  41. package/dist/KeyChip-4XJU4BBE.css +30 -0
  42. package/dist/Link/Link.d.ts +17 -2
  43. package/dist/Link/index.js +1 -1
  44. package/dist/{Link-6BEFNMN2.css → Link-WPMVLKLY.css} +36 -1
  45. package/dist/Listbox/index.d.ts +2 -0
  46. package/dist/Listbox/index.js +1 -1
  47. package/dist/Listbox/useHighlightRest.d.ts +35 -0
  48. package/dist/MarkdownEditor/MarkdownEditor.d.ts +93 -0
  49. package/dist/MarkdownEditor/format.d.ts +34 -0
  50. package/dist/MarkdownEditor/index.d.ts +5 -0
  51. package/dist/MarkdownEditor/index.js +12 -0
  52. package/dist/MarkdownEditor-ZLSHTOIZ.css +146 -0
  53. package/dist/Modal/Modal.d.ts +5 -1
  54. package/dist/Modal/index.js +1 -1
  55. package/dist/{Modal-BNT3TDV2.css → Modal-RQAYGG4L.css} +34 -1
  56. package/dist/OrgLabel/index.js +1 -1
  57. package/dist/OrgNode/index.js +1 -1
  58. package/dist/OrgTable/index.js +4 -4
  59. package/dist/Outline/Outline.d.ts +72 -0
  60. package/dist/Outline/index.d.ts +3 -0
  61. package/dist/Outline/index.js +2 -0
  62. package/dist/Outline-VCXKKU3E.css +78 -0
  63. package/dist/Popover/Popover.d.ts +21 -1
  64. package/dist/Popover/index.js +1 -1
  65. package/dist/ReadingPane/ReadingPane.d.ts +95 -0
  66. package/dist/ReadingPane/index.d.ts +3 -0
  67. package/dist/ReadingPane/index.js +4 -0
  68. package/dist/ReadingPane-5UOLPWY5.css +194 -0
  69. package/dist/SegmentedControl/SegmentedControl.d.ts +9 -1
  70. package/dist/SegmentedControl/index.js +3 -3
  71. package/dist/{SegmentedControl-76HODRBT.css → SegmentedControl-PKBLJVSA.css} +18 -0
  72. package/dist/Select/Select.d.ts +22 -0
  73. package/dist/Select/index.js +2 -2
  74. package/dist/{Select-4ANVLHUY.css → Select-2P7AWUE4.css} +56 -6
  75. package/dist/SidebarNav/index.js +2 -1
  76. package/dist/{SidebarNav-X5NLZNWA.css → SidebarNav-KF66MLOM.css} +4 -19
  77. package/dist/Switcher/Switcher.d.ts +151 -0
  78. package/dist/Switcher/index.d.ts +3 -0
  79. package/dist/Switcher/index.js +16 -0
  80. package/dist/Switcher-B44Q4WF4.css +346 -0
  81. package/dist/Tabs/Tabs.d.ts +7 -1
  82. package/dist/Tabs/index.js +1 -1
  83. package/dist/{Tabs-5I5Q5KKM.css → Tabs-ITJYJFMU.css} +49 -0
  84. package/dist/TagsInput/index.js +2 -2
  85. package/dist/ThemeGallery/ThemeGallery.d.ts +65 -0
  86. package/dist/ThemeGallery/index.d.ts +3 -0
  87. package/dist/ThemeGallery/index.js +6 -0
  88. package/dist/ThemeGallery-NITASULQ.css +93 -0
  89. package/dist/ThemeSwatch/ThemeSwatch.d.ts +71 -0
  90. package/dist/ThemeSwatch/index.d.ts +3 -0
  91. package/dist/ThemeSwatch/index.js +2 -0
  92. package/dist/ThemeSwatch-4DL457ZB.css +256 -0
  93. package/dist/ThemeSwitcher/ThemeSwitcher.d.ts +5 -1
  94. package/dist/ThemeSwitcher/index.js +4 -4
  95. package/dist/ThemeToggle/ThemeToggle.d.ts +1 -1
  96. package/dist/ThemeToggle/index.js +1 -1
  97. package/dist/TimeWindowPicker/index.js +4 -4
  98. package/dist/{TimeWindowPicker-GBF4JDFI.css → TimeWindowPicker-BZ5HHATU.css} +5 -4
  99. package/dist/Toaster/index.js +1 -1
  100. package/dist/{Toaster-NVDCEIP5.css → Toaster-VZKISP2S.css} +81 -87
  101. package/dist/Tree/index.d.ts +1 -1
  102. package/dist/Tree/index.js +1 -1
  103. package/dist/Tree/useTreeState.d.ts +37 -7
  104. package/dist/TreeCanvas/index.js +2 -2
  105. package/dist/TreeGrid/TreeGrid.d.ts +22 -2
  106. package/dist/TreeGrid/index.js +2 -2
  107. package/dist/{TreeGrid-NSW7VMOX.css → TreeGrid-FBX3MSJA.css} +19 -0
  108. package/dist/{chunk-EBBAAQDY.js → chunk-26PEPONN.js} +3 -1
  109. package/dist/{chunk-GOUKOXJK.js → chunk-3VVKJ7AZ.js} +3 -3
  110. package/dist/{chunk-HV6IZFBK.js → chunk-4FFHJBEN.js} +2 -2
  111. package/dist/{chunk-JHQUT4WJ.js → chunk-4LDTQWS7.js} +1 -1
  112. package/dist/{chunk-GXYNEDNA.js → chunk-4Y7WKXAW.js} +1 -1
  113. package/dist/{chunk-IINFVK3W.js → chunk-5IXMLWGW.js} +6 -6
  114. package/dist/{chunk-MCPKHYMC.js → chunk-6LXMLQUM.js} +17 -4
  115. package/dist/{chunk-3UK4VFSK.js → chunk-6NIZCQUM.js} +1 -1
  116. package/dist/{chunk-ORNOOMVY.js → chunk-6TSZCBID.js} +2 -2
  117. package/dist/{chunk-ZMJHK7DR.js → chunk-75WOCYGC.js} +2 -2
  118. package/dist/chunk-77IEHFY4.js +299 -0
  119. package/dist/chunk-A5YKNRG6.js +94 -0
  120. package/dist/{chunk-JCNUQ3US.js → chunk-AXNQCAFC.js} +2 -2
  121. package/dist/{chunk-UG5ZMAXW.js → chunk-CBZSSKH3.js} +5 -5
  122. package/dist/{chunk-LAQK4V3Z.js → chunk-DJMLHCLD.js} +1 -1
  123. package/dist/{chunk-6MU7HNB4.js → chunk-F73MC7EZ.js} +47 -2
  124. package/dist/{chunk-ZPSOF6VL.js → chunk-FBSEJO2C.js} +1 -1
  125. package/dist/chunk-FYTIJM2T.js +40 -0
  126. package/dist/chunk-H6VKCIWV.js +41 -0
  127. package/dist/{chunk-HLBRPES3.js → chunk-IFM63LAG.js} +3 -3
  128. package/dist/chunk-IG75YMUN.js +22 -0
  129. package/dist/{chunk-SEFMO2EV.js → chunk-IXUU5DLZ.js} +55 -6
  130. package/dist/{chunk-ZHOM65MI.js → chunk-JCO3SIST.js} +1 -1
  131. package/dist/chunk-KLIEPFEZ.js +95 -0
  132. package/dist/{chunk-7LD6P32I.js → chunk-L3CTFFLZ.js} +2 -18
  133. package/dist/chunk-MNFU2RNT.js +74 -0
  134. package/dist/{chunk-S3BCVWTU.js → chunk-MY374UUD.js} +49 -31
  135. package/dist/{chunk-K5Q2DK3P.js → chunk-NXDEPUVG.js} +1 -1
  136. package/dist/{chunk-PDUZO35I.js → chunk-O2ZDZZS7.js} +15 -6
  137. package/dist/{chunk-5WEVLIB6.js → chunk-RZ7RGECB.js} +1 -1
  138. package/dist/{chunk-WEIINZPA.js → chunk-SBRE7IML.js} +6 -2
  139. package/dist/{chunk-TEEJSTFG.js → chunk-TFMJH2E6.js} +1 -1
  140. package/dist/{chunk-IVFJD7WY.js → chunk-UCCC7YVZ.js} +3 -2
  141. package/dist/chunk-VWNC2L6W.js +110 -0
  142. package/dist/chunk-VYY56AMX.js +2 -0
  143. package/dist/chunk-WI6K5M5X.js +24 -0
  144. package/dist/{chunk-XV65NTIT.js → chunk-WYQOHFML.js} +94 -41
  145. package/dist/chunk-XYCADWZN.js +100 -0
  146. package/dist/chunk-Y6NR7QJ3.js +336 -0
  147. package/dist/chunk-YSJC7AZC.js +62 -0
  148. package/dist/chunk-ZAJHGDAW.js +93 -0
  149. package/dist/generated/index.d.ts +12 -0
  150. package/dist/generated/index.js +64 -51
  151. package/dist/index.js +64 -51
  152. package/dist/styles.css +2711 -402
  153. package/dist/utils/highlight.d.ts +17 -0
  154. package/dist/utils/useMediaMatch.d.ts +12 -0
  155. package/package.json +3 -3
  156. package/dist/chunk-UAQIUSSK.js +0 -2
  157. /package/dist/{chunk-74OVQWA5.js → chunk-6AR2T5Y4.js} +0 -0
@@ -1,98 +1,98 @@
1
1
  /*
2
- * The toast stack.
2
+ * The toast stack, drawn as the first release drew it (24a60c3): a dark strip
3
+ * on the page's deepest ground with the large shadow and the rim light, a
4
+ * 12px corner, the variant said by its mark alone, never a flood of its hue,
5
+ * and the countdown as a wash behind the words that drains from the right.
3
6
  *
4
- * ITS SURFACE IS A THEME TOKEN. 0.2.0 mixed the subtle surface 60 percent with
5
- * black, which is a dark strip whatever palette is painting: on a light page
6
- * the toast's own text measured 1.56:1 against it.
7
+ * IN TOKENS RATHER THAN ITS LITERALS, so it follows every theme. The strip is
8
+ * --color-surface-background: the first release mixed the panel with black,
9
+ * which read as a dark bar on a light page, where its words measured 1.56:1.
10
+ * The marks are the feedback INK steps, the soft moss, amber and rose it drew,
11
+ * measured as text on every theme. The washes are the feedback SOFT steps.
7
12
  *
8
- * THE DRAIN IS A RULE ALONG THE FOOT, not a wash behind the words. A tinted
9
- * layer under the message is a composite nothing measured, and it moves while
10
- * the message is being read; a 2px bar at the edge says the same thing and
11
- * touches no text at all. It is decoration either way: the dismissal is a
12
- * timer now, so a reader who asks for reduced motion still gets the toast
13
- * taken away.
13
+ * The wash is decoration: the dismissal is a timer, so a reader who asks for
14
+ * reduced motion gets no wash and still gets the toast taken away.
14
15
  */
15
-
16
16
  .crewlet-toaster {
17
17
  position: fixed;
18
18
  z-index: var(--z-index-toast);
19
19
  display: flex;
20
20
  flex-direction: column;
21
- gap: var(--spacing-2);
22
- /* The engine's 420px, held under the viewport at the width a phone has.
23
- The strip is one or two lines of 13px text and an action; at 380 the
24
- commonest failure message wrapped onto a third. */
25
- width: min(420px, calc(100vw - var(--spacing-9)));
21
+ gap: calc(var(--spacing-2) + var(--spacing-1) / 2);
22
+ width: min(380px, calc(100vw - 2 * var(--spacing-6)));
26
23
  /* The stack itself takes no presses, so the screen under it stays live
27
24
  while nothing is up; each toast takes them back for its own strip. */
28
25
  pointer-events: none;
29
26
  }
30
27
 
31
28
  .crewlet-toaster--bottom-right {
32
- bottom: var(--spacing-4);
33
- right: var(--spacing-4);
29
+ bottom: var(--spacing-6);
30
+ right: var(--spacing-6);
34
31
  }
35
32
 
36
33
  .crewlet-toaster--top-right {
37
- top: var(--spacing-4);
38
- right: var(--spacing-4);
34
+ top: var(--spacing-6);
35
+ right: var(--spacing-6);
39
36
  }
40
37
 
41
38
  .crewlet-toaster--bottom-left {
42
- bottom: var(--spacing-4);
43
- left: var(--spacing-4);
39
+ bottom: var(--spacing-6);
40
+ left: var(--spacing-6);
44
41
  }
45
42
 
46
43
  .crewlet-toaster--top-left {
47
- top: var(--spacing-4);
48
- left: var(--spacing-4);
44
+ top: var(--spacing-6);
45
+ left: var(--spacing-6);
49
46
  }
50
47
 
51
48
  .crewlet-toast {
49
+ /* The mark and the wash are the two places a variant spends its hue. */
52
50
  --crewlet-toast-mark: var(--color-text-secondary);
53
- /*
54
- * The boundary and the two inks are variables so a tone can spend them. Only
55
- * one does: a failure, which is the engine's one toned strip.
56
- */
57
- --crewlet-toast-line: var(--color-border-default);
58
- --crewlet-toast-ink: var(--color-text-primary);
59
- --crewlet-toast-ink-quiet: var(--color-text-secondary);
51
+ --crewlet-toast-wash: var(--color-surface-pressed);
52
+ /* 14px at the normal density, and the corner the dismiss sits in beside it. */
53
+ --crewlet-toast-inset: calc(var(--spacing-3) + var(--spacing-1) / 2);
60
54
 
61
55
  pointer-events: auto;
62
56
  position: relative;
63
57
  display: flex;
64
58
  align-items: flex-start;
65
- /* The panel's own gap and padding, and the panel's own surface: the engine
66
- draws a toast as a small panel that happens to float, so it sits on the
67
- same ground, the same hairline and the same corner as everything the
68
- screen behind it is made of. */
69
- gap: var(--spacing-2);
70
- padding: var(--spacing-2) var(--spacing-8) var(--spacing-2) var(--spacing-3);
71
- background: var(--color-surface-subtle);
72
- border: 1px solid var(--crewlet-toast-line);
73
- border-radius: var(--radius-md);
74
- box-shadow: var(--shadow-md);
75
- color: var(--crewlet-toast-ink);
59
+ gap: var(--spacing-3);
60
+ padding: var(--crewlet-toast-inset) calc(var(--spacing-7) + var(--spacing-1) * 1.5) var(--crewlet-toast-inset)
61
+ var(--crewlet-toast-inset);
62
+ background: var(--color-surface-background);
63
+ border: 1px solid var(--color-border-default);
64
+ border-radius: var(--radius-lg);
65
+ /* The large shadow and the rim light, both from tokens that are a shadow in
66
+ every palette: --shadow-hairline is `none` in light, and a `none` inside a
67
+ list drops the whole declaration. */
68
+ box-shadow: var(--shadow-xl), var(--shadow-rim-lit);
69
+ color: var(--color-text-primary);
76
70
  font-family: var(--font-family-sans);
77
71
  font-size: var(--font-size-compact);
78
- line-height: var(--font-line-height-normal);
72
+ line-height: var(--font-line-height-body);
79
73
  letter-spacing: var(--font-letter-spacing-snug);
80
74
  overflow: hidden;
81
- animation: crewlet-toast-in var(--motion-duration-base) var(--motion-easing-emphasized);
75
+ animation: crewlet-toast-in var(--motion-duration-slow) var(--motion-easing-emphasized);
82
76
  }
83
77
 
84
78
  @keyframes crewlet-toast-in {
85
79
  from {
86
80
  opacity: 0;
87
- transform: translateY(6px);
81
+ transform: translateX(var(--spacing-4));
88
82
  }
89
-
90
83
  to {
91
84
  opacity: 1;
92
- transform: translateY(0);
85
+ transform: translateX(0);
93
86
  }
94
87
  }
95
88
 
89
+ /* The words sit over the wash: every child is raised, and the dismiss and the
90
+ wash below take their own places back. */
91
+ .crewlet-toast > * {
92
+ position: relative;
93
+ z-index: var(--z-index-raised);
94
+ }
95
+
96
96
  .crewlet-toast__icon {
97
97
  display: inline-flex;
98
98
  flex: none;
@@ -100,34 +100,26 @@
100
100
  color: var(--crewlet-toast-mark);
101
101
  }
102
102
 
103
- /* The mark is the tone's FILL step, which is measured at 3:1 as a mark. The
104
- words beside it stay in the primary ink: a coloured sentence on a coloured
105
- strip is the pair that has to be measured, and this one does not exist. */
103
+ /*
104
+ * A VARIANT IS ITS MARK AND ITS WASH. The words stay in the strip's own inks
105
+ * and the edge stays the hairline, so a failure is a rose mark on a faint rose
106
+ * wash rather than a red strip: the outcome is said by the glyph and the title,
107
+ * and the sentence beside them is read in the ink every sentence is read in.
108
+ * Information is the neutral mark on the neutral wash.
109
+ */
106
110
  .crewlet-toast--success {
107
- --crewlet-toast-mark: var(--color-feedback-success);
111
+ --crewlet-toast-mark: var(--color-feedback-success-ink);
112
+ --crewlet-toast-wash: var(--color-feedback-success-soft);
108
113
  }
109
114
 
110
115
  .crewlet-toast--warning {
111
- --crewlet-toast-mark: var(--color-feedback-warning);
116
+ --crewlet-toast-mark: var(--color-feedback-warning-ink);
117
+ --crewlet-toast-wash: var(--color-feedback-warning-soft);
112
118
  }
113
119
 
114
- /*
115
- * A FAILURE IS THE ONE TONED STRIP. It is the outcome that is news rather than
116
- * confirmation and the one that does not take itself away, so the engine gives
117
- * it the hue twice: the fill step on the edge, where 3:1 is the floor a
118
- * boundary has to clear, and the INK step on every word, which is the measured
119
- * text pair on this surface. Never the fill behind a word: that is the swap
120
- * the whole soft-and-ink split exists to stop.
121
- */
122
120
  .crewlet-toast--danger {
123
- --crewlet-toast-mark: var(--color-feedback-danger);
124
- --crewlet-toast-line: var(--color-feedback-danger);
125
- --crewlet-toast-ink: var(--color-feedback-danger-ink);
126
- --crewlet-toast-ink-quiet: var(--color-feedback-danger-ink);
127
- }
128
-
129
- .crewlet-toast--info {
130
- --crewlet-toast-mark: var(--color-feedback-info);
121
+ --crewlet-toast-mark: var(--color-feedback-danger-ink);
122
+ --crewlet-toast-wash: var(--color-feedback-danger-soft);
131
123
  }
132
124
 
133
125
  /* A usage limit notice is the application's own variant: it paints the glyph
@@ -149,12 +141,12 @@
149
141
  }
150
142
 
151
143
  .crewlet-toast__message {
152
- color: var(--crewlet-toast-ink-quiet);
144
+ color: var(--color-text-secondary);
153
145
  overflow-wrap: anywhere;
154
146
  }
155
147
 
156
148
  .crewlet-toast__actions {
157
- margin-top: var(--spacing-2);
149
+ margin-top: calc(var(--spacing-2) + var(--spacing-1) / 2);
158
150
  display: flex;
159
151
  gap: var(--spacing-2);
160
152
  }
@@ -186,10 +178,12 @@
186
178
  border-color: var(--color-brand-accent-hover);
187
179
  }
188
180
 
181
+ /* A failure's one filled thing is the way out of it. */
189
182
  .crewlet-toast--danger .crewlet-toast__action-btn,
190
183
  .crewlet-toast--danger .crewlet-toast__action-link {
191
184
  background: var(--color-feedback-danger);
192
185
  border-color: var(--color-feedback-danger);
186
+ color: var(--color-text-on-danger);
193
187
  }
194
188
 
195
189
  .crewlet-toast--danger .crewlet-toast__action-btn:hover,
@@ -206,8 +200,9 @@
206
200
  }
207
201
 
208
202
  /* The dismiss sits absolute in the corner so a multi-line message flows
209
- under it rather than around it. 24px square: the smallest target
210
- WCAG 2.2 accepts. */
203
+ under it rather than around it, and after the body in the document, so it
204
+ is drawn over the words at the same raised step. 24px square: the smallest
205
+ target WCAG 2.2 accepts. */
211
206
  .crewlet-toast__dismiss {
212
207
  position: absolute;
213
208
  top: var(--spacing-2);
@@ -221,10 +216,7 @@
221
216
  border: 0;
222
217
  border-radius: var(--radius-sm);
223
218
  background: transparent;
224
- /* The strip's own quiet ink rather than the neutral tertiary step, so the
225
- close on a failure is part of the failure rather than the one grey thing
226
- inside it. */
227
- color: var(--crewlet-toast-ink-quiet);
219
+ color: var(--color-text-tertiary);
228
220
  cursor: pointer;
229
221
  transition:
230
222
  background var(--motion-duration-fast) var(--motion-easing-default),
@@ -232,25 +224,28 @@
232
224
  }
233
225
 
234
226
  .crewlet-toast__dismiss:hover {
235
- background: var(--color-surface-hover);
236
- color: var(--crewlet-toast-ink);
227
+ background: var(--color-surface-elevated);
228
+ color: var(--color-text-primary);
237
229
  }
238
230
 
231
+ /*
232
+ * THE COUNTDOWN IS A WASH BEHIND THE WORDS, the variant's soft step over the
233
+ * whole strip, draining from the right as the time runs out. It sits under
234
+ * every raised child, and it is the timer's picture, not the timer.
235
+ */
239
236
  .crewlet-toast__progress {
240
237
  position: absolute;
241
- left: 0;
242
- right: 0;
243
- bottom: 0;
244
- height: 2px;
238
+ inset: 0;
239
+ z-index: var(--z-index-base);
245
240
  transform-origin: left center;
246
- background: var(--crewlet-toast-mark);
241
+ background: var(--crewlet-toast-wash);
247
242
  pointer-events: none;
248
243
  animation-name: crewlet-toast-drain;
249
244
  animation-timing-function: linear;
250
245
  animation-fill-mode: forwards;
251
246
  }
252
247
 
253
- /* Paused by the class rather than by :hover, so the bar and the timer that
248
+ /* Paused by the class rather than by :hover, so the wash and the timer that
254
249
  actually dismisses are stopped by the same event. */
255
250
  .crewlet-toast__progress.is-paused {
256
251
  animation-play-state: paused;
@@ -260,7 +255,6 @@
260
255
  from {
261
256
  transform: scaleX(1);
262
257
  }
263
-
264
258
  to {
265
259
  transform: scaleX(0);
266
260
  }
@@ -286,8 +280,8 @@
286
280
 
287
281
  /*
288
282
  * The strip still arrives and still goes; it just does not slide, and the
289
- * countdown bar holds still. The timer is untouched: a reader who asked for
290
- * less motion did not ask to be left with a toast that never leaves.
283
+ * wash is not drawn. The timer is untouched: a reader who asked for less
284
+ * motion did not ask to be left with a toast that never leaves.
291
285
  */
292
286
  @media (prefers-reduced-motion: reduce) {
293
287
  .crewlet-toast {
@@ -3,6 +3,6 @@ export type { TreeInput, TreeModel, TypeAheadState } from './model.js';
3
3
  export { layoutConnectors, layoutForest, placeGroups } from './layout.js';
4
4
  export type { ForestLayout, LayoutGaps, LayoutGroup, LayoutGroupInset, LayoutNode, LayoutRanks, PlacedGroup, PlacedNode, TreeConnector, TreeConnectorShape, } from './layout.js';
5
5
  export { treeItemAction, treeStep, useTreeState } from './useTreeState.js';
6
- export type { TreeItemAction, TreeKeyEvent, TreeState, TreeStep, TreeViewHandle } from './useTreeState.js';
6
+ export type { TreeDefaultExpanded, TreeItemAction, TreeKeyEvent, TreeState, TreeStateOptions, TreeStep, TreeViewHandle, } from './useTreeState.js';
7
7
  export { SIZE_EPSILON, useLayoutAnchor, useMeasuredSizes } from './useMeasuredSizes.js';
8
8
  export type { MeasuredSizes } from './useMeasuredSizes.js';
@@ -1 +1 @@
1
- export { SIZE_EPSILON, TYPE_AHEAD_RESET_MS, createTreeModel, isTypeAheadKey, layoutConnectors, layoutForest, placeGroups, treeAllExpandable, treeAncestors, treeCollapseOrAscend, treeExpandOrDescend, treeExpandTo, treeExpandable, treeFirst, treeFirstChild, treeItemAction, treeLast, treeLevel, treeNext, treeParent, treePosInSet, treePrevious, treeSetSize, treeStep, treeTypeAhead, treeVisible, typeAheadBuffer, useLayoutAnchor, useMeasuredSizes, useTreeState } from '../chunk-S3BCVWTU.js';
1
+ export { SIZE_EPSILON, TYPE_AHEAD_RESET_MS, createTreeModel, isTypeAheadKey, layoutConnectors, layoutForest, placeGroups, treeAllExpandable, treeAncestors, treeCollapseOrAscend, treeExpandOrDescend, treeExpandTo, treeExpandable, treeFirst, treeFirstChild, treeItemAction, treeLast, treeLevel, treeNext, treeParent, treePosInSet, treePrevious, treeSetSize, treeStep, treeTypeAhead, treeVisible, typeAheadBuffer, useLayoutAnchor, useMeasuredSizes, useTreeState } from '../chunk-MY374UUD.js';
@@ -35,16 +35,46 @@ export interface TreeState {
35
35
  */
36
36
  typed(event: TreeKeyEvent, from: string, now: number): string | null | undefined;
37
37
  }
38
+ /** Which nodes are open before anybody has opened or closed one. */
39
+ export type TreeDefaultExpanded =
40
+ /** Every node with children. A chart and an org outline are read whole. */
41
+ 'all'
38
42
  /**
39
- * What is collapsed, which node holds the tab stop, and type ahead.
43
+ * None. A tree whose levels are read on demand, a knowledge base's spaces
44
+ * say, opens one level at a time: a node that arrived open would ask for
45
+ * its children the moment it was drawn, and so would theirs.
46
+ */
47
+ | 'none';
48
+ export interface TreeStateOptions {
49
+ /** Which nodes start open while the tree holds its own expansion. `all` by default. */
50
+ defaultExpanded?: TreeDefaultExpanded | undefined;
51
+ /**
52
+ * The open nodes, when the CALLER holds them: to keep them across a visit,
53
+ * or to read a level the moment it opens. A node in the set that has no
54
+ * children is ignored rather than refused, since a level still loading has
55
+ * none yet.
56
+ */
57
+ expanded?: ReadonlySet<string> | undefined;
58
+ /**
59
+ * The open nodes a toggle, an open or an expand or collapse of everything
60
+ * has just produced. Called whether or not the caller holds the set, so a
61
+ * caller that only reads levels on demand need not hold it.
62
+ */
63
+ onExpandedChange?: ((expanded: ReadonlySet<string>) => void) | undefined;
64
+ }
65
+ /**
66
+ * What is open, which node holds the tab stop, and type ahead.
40
67
  *
41
- * COLLAPSED, NOT EXPANDED, IS WHAT IS KEPT: a node nobody has closed is open,
42
- * which is also what a node an operation just added should be. The tab stop is
43
- * the node last focused, else the selection, else the first node, and is moved
44
- * to the nearest visible ancestor when its own node is hidden or gone, so the
45
- * tree always has exactly one way in.
68
+ * WHAT IS KEPT IS WHAT WAS TOGGLED, read against the default: under `all` it
69
+ * is the nodes somebody closed, so a node an operation just added arrives
70
+ * open, as a chart wants; under `none` it is the nodes somebody opened, so a
71
+ * level that has just been read arrives closed. A caller that holds the set
72
+ * itself replaces both. The tab stop is the node last focused, else the
73
+ * selection, else the first node, and is moved to the nearest visible
74
+ * ancestor when its own node is hidden or gone, so the tree always has
75
+ * exactly one way in.
46
76
  */
47
- export declare function useTreeState(forest: readonly TreeInput[], selected: string | null): TreeState;
77
+ export declare function useTreeState(forest: readonly TreeInput[], selected: string | null, { defaultExpanded, expanded: held, onExpandedChange }?: TreeStateOptions): TreeState;
48
78
  /** What a navigation key asks of a tree: focus a node, or open or close one. */
49
79
  export type TreeStep = {
50
80
  readonly focus: string;
@@ -1,5 +1,5 @@
1
- export { TreeCanvas } from '../chunk-5WEVLIB6.js';
2
- import '../chunk-S3BCVWTU.js';
1
+ export { TreeCanvas } from '../chunk-RZ7RGECB.js';
2
+ import '../chunk-MY374UUD.js';
3
3
  import '../chunk-2PZBIHRV.js';
4
4
  import '../chunk-53DVJCVW.js';
5
5
  import '../chunk-OG6CL3EB.js';
@@ -29,7 +29,7 @@
29
29
  * Ported from the generic half of the engine dashboard's org builder outline.
30
30
  */
31
31
  import { type KeyboardEvent, type MouseEvent, type ReactNode, type Ref } from 'react';
32
- import { type TreeInput, type TreeItemAction, type TreeViewHandle } from '../Tree/index.js';
32
+ import { type TreeDefaultExpanded, type TreeInput, type TreeItemAction, type TreeViewHandle } from '../Tree/index.js';
33
33
  export interface TreeGridColumn {
34
34
  key: string;
35
35
  /** The column's name. */
@@ -135,8 +135,28 @@ export interface TreeGridProps {
135
135
  onSelect?: ((id: string) => void) | undefined;
136
136
  /** Sets `aria-readonly`: the rows can be read and navigated but not edited. */
137
137
  readOnly?: boolean | undefined;
138
+ /**
139
+ * Which rows start open while the grid holds its own expansion: every one
140
+ * (the default), or none, for a hierarchy whose levels are read on demand.
141
+ */
142
+ defaultExpanded?: TreeDefaultExpanded | undefined;
143
+ /**
144
+ * The open rows, when the caller holds them: to keep them across a visit,
145
+ * or to read a level the moment it opens. A row in the set with no children
146
+ * yet is ignored, so a level still loading can be held open.
147
+ */
148
+ expanded?: ReadonlySet<string> | undefined;
149
+ /** The open rows a toggle has just produced, whether or not the caller holds them. */
150
+ onExpandedChange?: ((expanded: ReadonlySet<string>) => void) | undefined;
151
+ /**
152
+ * The column names are READ BUT NOT SEEN: an outline whose cells say what
153
+ * they are in the sight of them (a title, a face, a time) and want no
154
+ * header band above them. A screen reader still hears every cell's column,
155
+ * because the header row is still there; only its band is not drawn.
156
+ */
157
+ headless?: boolean | undefined;
138
158
  labels?: Partial<TreeGridLabels> | undefined;
139
159
  ref?: Ref<TreeViewHandle> | undefined;
140
160
  className?: string | undefined;
141
161
  }
142
- export declare function TreeGrid({ label, columns, rows: forest, renderCell, cellHasControl, onRowKey, onRowKeyDown, hasRowMenu, addRow, selectedId, onSelect, readOnly, labels, ref, className, }: TreeGridProps): import("react").JSX.Element;
162
+ export declare function TreeGrid({ label, columns, rows: forest, renderCell, cellHasControl, onRowKey, onRowKeyDown, hasRowMenu, addRow, selectedId, onSelect, readOnly, defaultExpanded, expanded: held, onExpandedChange, headless, labels, ref, className, }: TreeGridProps): import("react").JSX.Element;
@@ -1,5 +1,5 @@
1
- export { TreeGrid } from '../chunk-MCPKHYMC.js';
2
- import '../chunk-S3BCVWTU.js';
1
+ export { TreeGrid } from '../chunk-6LXMLQUM.js';
2
+ import '../chunk-MY374UUD.js';
3
3
  import '../chunk-53DVJCVW.js';
4
4
  import '../chunk-4FQT6ZAY.js';
5
5
  import '../chunk-7RPGY3JE.js';
@@ -126,6 +126,25 @@
126
126
  outline-offset: var(--size-focus-ring-inset-offset);
127
127
  }
128
128
 
129
+ /*
130
+ * A HEADLESS GRID keeps its header row for a screen reader and draws no band:
131
+ * the row is taken out of the layout the way VisuallyHidden takes text out,
132
+ * and the first row of the body loses the hairline that would otherwise sit
133
+ * under the frame's own edge as a second line.
134
+ */
135
+ .crewlet-tree-grid--headless .crewlet-tree-grid__head {
136
+ position: absolute;
137
+ width: 1px;
138
+ height: 1px;
139
+ overflow: hidden;
140
+ clip-path: inset(50%);
141
+ white-space: nowrap;
142
+ }
143
+
144
+ .crewlet-tree-grid--headless .crewlet-tree-grid__head + [role='rowgroup'] > .crewlet-tree-grid__row:first-child {
145
+ border-top: 0;
146
+ }
147
+
129
148
  /* The selection is where the reader is, so it takes the accent. */
130
149
  .crewlet-tree-grid__row[aria-selected='true'] {
131
150
  box-shadow: inset 2px 0 0 var(--color-brand-accent);
@@ -1,4 +1,4 @@
1
- import { tabId } from './chunk-JHQUT4WJ.js';
1
+ import { tabId } from './chunk-4LDTQWS7.js';
2
2
  import { useRoving, tabStop } from './chunk-CBOICT64.js';
3
3
  import { Count } from './chunk-BHHIIK3M.js';
4
4
  import { VisuallyHidden } from './chunk-BZFWDIV6.js';
@@ -15,6 +15,7 @@ function SegmentedControl({
15
15
  size = "md",
16
16
  layout = "pill",
17
17
  trailing,
18
+ fill = false,
18
19
  className = "",
19
20
  semantics,
20
21
  panelId,
@@ -55,6 +56,7 @@ function SegmentedControl({
55
56
  "crewlet-segmented",
56
57
  cards && "crewlet-segmented--cards",
57
58
  !cards && layout === "chips" && "crewlet-segmented--chips",
59
+ fill && !cards && layout === "pill" && "crewlet-segmented--fill",
58
60
  className
59
61
  ),
60
62
  role: radio ? "radiogroup" : "tablist",
@@ -1,10 +1,10 @@
1
- import { useCardHeaderSlot } from './chunk-AV2DXAEL.js';
2
1
  import { Menu } from './chunk-TFH6SYWB.js';
3
2
  import { EmptyValue } from './chunk-EUCC37WY.js';
4
- import { Modal } from './chunk-TEEJSTFG.js';
3
+ import { Checkbox } from './chunk-YCTMKKRA.js';
4
+ import { Modal } from './chunk-TFMJH2E6.js';
5
5
  import { useClipboard } from './chunk-5VNUYO76.js';
6
6
  import { Button } from './chunk-OG6CL3EB.js';
7
- import { Checkbox } from './chunk-YCTMKKRA.js';
7
+ import { useCardHeaderSlot } from './chunk-AV2DXAEL.js';
8
8
  import { IconButton } from './chunk-4FQT6ZAY.js';
9
9
  import { VisuallyHidden } from './chunk-BZFWDIV6.js';
10
10
  import { cx } from './chunk-ODEQTPFM.js';
@@ -1,6 +1,6 @@
1
- import { HuePicker } from './chunk-K5Q2DK3P.js';
1
+ import { HuePicker } from './chunk-NXDEPUVG.js';
2
2
  import { NODE_HUE_NAMES } from './chunk-AYKXMIOR.js';
3
- import { Popover } from './chunk-PDUZO35I.js';
3
+ import { Popover } from './chunk-O2ZDZZS7.js';
4
4
  import { CharacterPicker } from './chunk-YXMCUKFI.js';
5
5
  import { Avatar } from './chunk-HI6Q2UXQ.js';
6
6
  import { cx } from './chunk-ODEQTPFM.js';
@@ -2,7 +2,7 @@ import { useRoving, tabStop } from './chunk-CBOICT64.js';
2
2
  import { Count } from './chunk-BHHIIK3M.js';
3
3
  import { VisuallyHidden } from './chunk-BZFWDIV6.js';
4
4
  import { cx } from './chunk-ODEQTPFM.js';
5
- import './Tabs-5I5Q5KKM.css';
5
+ import './Tabs-ITJYJFMU.css';
6
6
  import React, { useRef, useLayoutEffect } from 'react';
7
7
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
8
8
 
@@ -1,4 +1,4 @@
1
- import { useListbox } from './chunk-6MU7HNB4.js';
1
+ import { useListbox } from './chunk-F73MC7EZ.js';
2
2
  import { Input } from './chunk-FTEJPHBI.js';
3
3
  import { cx } from './chunk-ODEQTPFM.js';
4
4
  import './Combobox-4FUVYIE7.css';
@@ -1,15 +1,15 @@
1
- import { Toolbar } from './chunk-PGRPNDWM.js';
2
1
  import { PageHeader } from './chunk-HOXGBLEY.js';
3
2
  import { RelativeTime } from './chunk-3CZ7XAVY.js';
4
- import { DateTimePicker } from './chunk-JCNUQ3US.js';
5
- import { useListbox, useOptionKeys } from './chunk-6MU7HNB4.js';
3
+ import { Toolbar } from './chunk-PGRPNDWM.js';
4
+ import { DataTable } from './chunk-3VVKJ7AZ.js';
5
+ import { Menu } from './chunk-TFH6SYWB.js';
6
+ import { DateTimePicker } from './chunk-AXNQCAFC.js';
7
+ import { useListbox, useOptionKeys } from './chunk-F73MC7EZ.js';
6
8
  import { Kbd } from './chunk-SMBKXWML.js';
7
9
  import { Input } from './chunk-FTEJPHBI.js';
8
- import { DataTable } from './chunk-GOUKOXJK.js';
9
- import { Menu } from './chunk-TFH6SYWB.js';
10
10
  import { Button } from './chunk-OG6CL3EB.js';
11
11
  import { IconButton } from './chunk-4FQT6ZAY.js';
12
- import { Popover } from './chunk-PDUZO35I.js';
12
+ import { Popover } from './chunk-O2ZDZZS7.js';
13
13
  import { Count } from './chunk-BHHIIK3M.js';
14
14
  import { VisuallyHidden } from './chunk-BZFWDIV6.js';
15
15
  import { cx } from './chunk-ODEQTPFM.js';
@@ -1,11 +1,11 @@
1
- import { useTreeState, treeExpandable, treeLevel, treePosInSet, treeSetSize, treeItemAction, treePrevious, treeNext, treeStep } from './chunk-S3BCVWTU.js';
1
+ import { useTreeState, treeExpandable, treeLevel, treePosInSet, treeSetSize, treeItemAction, treePrevious, treeNext, treeStep } from './chunk-MY374UUD.js';
2
2
  import { LayerNodeBridge } from './chunk-53DVJCVW.js';
3
3
  import { IconButton } from './chunk-4FQT6ZAY.js';
4
4
  import { LayerHost, LAYER_REPOSITION_EVENT } from './chunk-7RPGY3JE.js';
5
5
  import { focusables } from './chunk-R25RGPUB.js';
6
6
  import { VisuallyHidden } from './chunk-BZFWDIV6.js';
7
7
  import { cx } from './chunk-ODEQTPFM.js';
8
- import './TreeGrid-NSW7VMOX.css';
8
+ import './TreeGrid-FBX3MSJA.css';
9
9
  import { useState, useRef, useCallback, useLayoutEffect, useImperativeHandle } from 'react';
10
10
  import { ChevronRightGlyph } from '@crewlethq/icons/glyphs';
11
11
  import { jsx, jsxs } from 'react/jsx-runtime';
@@ -17,6 +17,14 @@ var LABELS = {
17
17
  function controlIn(cell) {
18
18
  return focusables(cell).find((el) => !el.closest('[aria-hidden="true"]')) ?? null;
19
19
  }
20
+ var TEXT_INPUTS = /* @__PURE__ */ new Set(["text", "search", "url", "email", "tel", "password", "number"]);
21
+ function caretKey(target, key) {
22
+ const lines = target instanceof HTMLTextAreaElement || target.isContentEditable;
23
+ const field = lines || target instanceof HTMLInputElement && TEXT_INPUTS.has(target.type);
24
+ if (!field) return false;
25
+ if (key === "ArrowLeft" || key === "ArrowRight" || key === "Home" || key === "End") return true;
26
+ return lines && (key === "ArrowUp" || key === "ArrowDown");
27
+ }
20
28
  function TreeGrid({
21
29
  label,
22
30
  columns,
@@ -30,12 +38,16 @@ function TreeGrid({
30
38
  selectedId = null,
31
39
  onSelect,
32
40
  readOnly,
41
+ defaultExpanded,
42
+ expanded: held,
43
+ onExpandedChange,
44
+ headless = false,
33
45
  labels,
34
46
  ref,
35
47
  className
36
48
  }) {
37
49
  const text = { ...LABELS, ...labels };
38
- const tree = useTreeState(forest, selectedId);
50
+ const tree = useTreeState(forest, selectedId, { defaultExpanded, expanded: held, onExpandedChange });
39
51
  const { model, expanded, rows, active, setActive, toggle } = tree;
40
52
  const [column, setColumn] = useState(null);
41
53
  const [menuFor, setMenuFor] = useState(null);
@@ -128,6 +140,7 @@ function TreeGrid({
128
140
  const width = other ? other.cells : columns.length;
129
141
  focusAt(next, col === null ? null : Math.min(col, width));
130
142
  };
143
+ if (col !== null && caretKey(target, event.key)) return;
131
144
  if (col !== null) {
132
145
  switch (event.key) {
133
146
  case "ArrowRight":
@@ -197,7 +210,7 @@ function TreeGrid({
197
210
  setMenuOpen: (id, open) => setMenuFor((was) => open ? id : was === id ? null : was)
198
211
  };
199
212
  const template = columns.map((one) => one.width ?? "minmax(0, 1fr)").join(" ");
200
- return /* @__PURE__ */ jsx("div", { className: cx("crewlet-tree-grid", className), children: /* @__PURE__ */ jsxs(LayerHost, { className: "crewlet-tree-grid__layer", children: [
213
+ return /* @__PURE__ */ jsx("div", { className: cx("crewlet-tree-grid", headless && "crewlet-tree-grid--headless", className), children: /* @__PURE__ */ jsxs(LayerHost, { className: "crewlet-tree-grid__layer", children: [
201
214
  /* @__PURE__ */ jsx("div", { className: "crewlet-tree-grid__scroller", onScroll, children: /* @__PURE__ */ jsxs(
202
215
  "div",
203
216
  {
@@ -1,6 +1,6 @@
1
1
  import { AVATAR_SIZES, Avatar } from './chunk-HI6Q2UXQ.js';
2
2
  import { cx } from './chunk-ODEQTPFM.js';
3
- import './Avatar-QHYOFID3.css';
3
+ import './Avatar-BPJ36QZR.css';
4
4
  import './AvatarStack-GEJBNV7E.css';
5
5
  import { jsxs, jsx } from 'react/jsx-runtime';
6
6
 
@@ -32,8 +32,8 @@ function StoredThemeToggle({
32
32
  function ToggleButton({
33
33
  value,
34
34
  onChange,
35
- toLightLabel = "Switch to the light theme",
36
- toDarkLabel = "Switch to the dark theme",
35
+ toLightLabel = "Switch to light mode",
36
+ toDarkLabel = "Switch to dark mode",
37
37
  size = "sm",
38
38
  variant = "ghost",
39
39
  className
@@ -1,5 +1,5 @@
1
- import { TreeGrid } from './chunk-MCPKHYMC.js';
2
- import { createTreeModel, treeParent } from './chunk-S3BCVWTU.js';
1
+ import { TreeGrid } from './chunk-6LXMLQUM.js';
2
+ import { createTreeModel, treeParent } from './chunk-MY374UUD.js';
3
3
  import { OrgLabel } from './chunk-6OF2DBKY.js';
4
4
  import { AddPill } from './chunk-74WGARJE.js';
5
5
  import { IconButton } from './chunk-4FQT6ZAY.js';