@crewlethq/ui 0.13.0 → 0.15.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 (76) hide show
  1. package/README.md +42 -0
  2. package/dist/AppShell/AppShell.d.ts +76 -11
  3. package/dist/AppShell/index.d.ts +1 -1
  4. package/dist/AppShell/index.js +2 -2
  5. package/dist/{AppShell-CEVLW4QG.css → AppShell-6QUD7NWM.css} +74 -1
  6. package/dist/AvatarPicker/index.js +4 -4
  7. package/dist/Canvas/index.js +3 -3
  8. package/dist/Charts/StackedColumns.d.ts +30 -7
  9. package/dist/Charts/index.d.ts +1 -1
  10. package/dist/Charts/index.js +1 -1
  11. package/dist/{Charts-JUERFLAR.css → Charts-JYW4X5ZL.css} +18 -1
  12. package/dist/CommandPalette/index.js +3 -3
  13. package/dist/DataTable/index.js +5 -5
  14. package/dist/DataView/index.js +9 -9
  15. package/dist/DateTimePicker/index.js +3 -3
  16. package/dist/{DateTimePicker-4AZBTODT.css → DateTimePicker-NJ6XH2TE.css} +4 -3
  17. package/dist/DescriptionList/DescriptionList.d.ts +9 -1
  18. package/dist/DescriptionList/index.js +1 -1
  19. package/dist/{DescriptionList-YYY3V3O6.css → DescriptionList-IXMRCSMK.css} +24 -0
  20. package/dist/FactList/index.js +3 -3
  21. package/dist/Layer/index.js +1 -1
  22. package/dist/Layer-J222IFNX.css +33 -0
  23. package/dist/Layout/index.js +1 -1
  24. package/dist/{Layout-2ZCV3IGF.css → Layout-ZBEGLXAE.css} +18 -0
  25. package/dist/ListInput/index.js +3 -3
  26. package/dist/MarkdownEditor/index.js +1 -1
  27. package/dist/Menu/index.js +2 -2
  28. package/dist/Modal/index.js +2 -2
  29. package/dist/{Modal-3YJ2GG2T.css → Modal-RQAYGG4L.css} +1 -1
  30. package/dist/OrgTable/index.js +5 -5
  31. package/dist/Popover/index.js +2 -2
  32. package/dist/Select/index.js +2 -2
  33. package/dist/{Select-XMZ44RWY.css → Select-2P7AWUE4.css} +32 -6
  34. package/dist/Shortcut/index.js +1 -1
  35. package/dist/Switcher/index.js +5 -5
  36. package/dist/TagsInput/index.js +3 -3
  37. package/dist/TimeWindowPicker/index.js +4 -4
  38. package/dist/{TimeWindowPicker-GBF4JDFI.css → TimeWindowPicker-BZ5HHATU.css} +5 -4
  39. package/dist/Toaster/Toaster.d.ts +6 -1
  40. package/dist/Toaster/index.js +2 -2
  41. package/dist/{Toaster-KZ7YE2HA.css → Toaster-EOOOTSJT.css} +82 -87
  42. package/dist/Toolbar/index.js +1 -1
  43. package/dist/Tooltip/index.js +2 -2
  44. package/dist/TreeCanvas/index.js +4 -4
  45. package/dist/TreeGrid/index.js +3 -3
  46. package/dist/{chunk-UZPHPW3Z.js → chunk-2GXTIK37.js} +4 -4
  47. package/dist/{chunk-RZ7RGECB.js → chunk-2OLCUNG7.js} +1 -1
  48. package/dist/{chunk-JDPAA2JU.js → chunk-2UU5IGZI.js} +2 -2
  49. package/dist/{chunk-B2CITO6R.js → chunk-7BZPYA5P.js} +3 -3
  50. package/dist/{chunk-2PZBIHRV.js → chunk-AMH67MLM.js} +2 -2
  51. package/dist/{chunk-6LXMLQUM.js → chunk-B2Z2CDM5.js} +2 -2
  52. package/dist/{chunk-O2ZDZZS7.js → chunk-BWRGFKJP.js} +3 -2
  53. package/dist/{chunk-75WOCYGC.js → chunk-DYHSQHAZ.js} +1 -1
  54. package/dist/{chunk-4FFHJBEN.js → chunk-EFNHOVC2.js} +1 -1
  55. package/dist/{chunk-XN4JBAN3.js → chunk-F2XSYBKH.js} +8 -2
  56. package/dist/{chunk-XFE5W2I4.js → chunk-FC4YTTFJ.js} +14 -4
  57. package/dist/{chunk-L3CTFFLZ.js → chunk-H3XOMT7W.js} +53 -9
  58. package/dist/{chunk-7RPGY3JE.js → chunk-HMPFGIWM.js} +1 -1
  59. package/dist/{chunk-HKGS67VG.js → chunk-IYZZL3MZ.js} +1 -1
  60. package/dist/{chunk-URYDN2KA.js → chunk-JI5AVQLA.js} +1 -1
  61. package/dist/{chunk-CF6DTETT.js → chunk-K4VORB64.js} +2 -2
  62. package/dist/{chunk-S3IENQ3E.js → chunk-LCF4WPYS.js} +3 -3
  63. package/dist/{chunk-4WNNEDKO.js → chunk-MLT2HBPN.js} +87 -74
  64. package/dist/{chunk-TFH6SYWB.js → chunk-NS7BVLL3.js} +1 -1
  65. package/dist/{chunk-LELD5KPA.js → chunk-QH3AKP2N.js} +22 -9
  66. package/dist/{chunk-WY2NLRZN.js → chunk-QV266R6G.js} +3 -3
  67. package/dist/{chunk-CQY5NTRS.js → chunk-QWOPX2MN.js} +1 -1
  68. package/dist/{chunk-53DVJCVW.js → chunk-VYOKRN2I.js} +1 -1
  69. package/dist/{chunk-W4ENKCXJ.js → chunk-ZAC7SKUN.js} +1 -1
  70. package/dist/generated/index.js +33 -33
  71. package/dist/index.js +33 -33
  72. package/dist/styles.css +279 -114
  73. package/package.json +3 -3
  74. package/dist/Layer-NAFSGCFA.css +0 -23
  75. package/dist/{chunk-LZP7FGT7.js → chunk-GARACZAH.js} +1 -1
  76. package/dist/{chunk-GG2QEZO2.js → chunk-JCO3SIST.js} +1 -1
@@ -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,28 @@
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 rather than a
106
+ * red strip: the outcome is said by the glyph and the title, and the sentence
107
+ * beside them is read in the ink every sentence is read in. The wash is the
108
+ * countdown, so only a toast that counts down draws one: a success is a moss
109
+ * mark on a faint moss wash, and a failure, sticky unless it is given a
110
+ * duration, draws none. Information is the neutral mark on the neutral wash.
111
+ */
106
112
  .crewlet-toast--success {
107
- --crewlet-toast-mark: var(--color-feedback-success);
113
+ --crewlet-toast-mark: var(--color-feedback-success-ink);
114
+ --crewlet-toast-wash: var(--color-feedback-success-soft);
108
115
  }
109
116
 
110
117
  .crewlet-toast--warning {
111
- --crewlet-toast-mark: var(--color-feedback-warning);
118
+ --crewlet-toast-mark: var(--color-feedback-warning-ink);
119
+ --crewlet-toast-wash: var(--color-feedback-warning-soft);
112
120
  }
113
121
 
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
122
  .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);
123
+ --crewlet-toast-mark: var(--color-feedback-danger-ink);
124
+ --crewlet-toast-wash: var(--color-feedback-danger-soft);
131
125
  }
132
126
 
133
127
  /* A usage limit notice is the application's own variant: it paints the glyph
@@ -149,12 +143,12 @@
149
143
  }
150
144
 
151
145
  .crewlet-toast__message {
152
- color: var(--crewlet-toast-ink-quiet);
146
+ color: var(--color-text-secondary);
153
147
  overflow-wrap: anywhere;
154
148
  }
155
149
 
156
150
  .crewlet-toast__actions {
157
- margin-top: var(--spacing-2);
151
+ margin-top: calc(var(--spacing-2) + var(--spacing-1) / 2);
158
152
  display: flex;
159
153
  gap: var(--spacing-2);
160
154
  }
@@ -186,6 +180,7 @@
186
180
  border-color: var(--color-brand-accent-hover);
187
181
  }
188
182
 
183
+ /* A failure's one filled thing is the way out of it. */
189
184
  .crewlet-toast--danger .crewlet-toast__action-btn,
190
185
  .crewlet-toast--danger .crewlet-toast__action-link {
191
186
  background: var(--color-feedback-danger);
@@ -207,8 +202,9 @@
207
202
  }
208
203
 
209
204
  /* The dismiss sits absolute in the corner so a multi-line message flows
210
- under it rather than around it. 24px square: the smallest target
211
- WCAG 2.2 accepts. */
205
+ under it rather than around it, and after the body in the document, so it
206
+ is drawn over the words at the same raised step. 24px square: the smallest
207
+ target WCAG 2.2 accepts. */
212
208
  .crewlet-toast__dismiss {
213
209
  position: absolute;
214
210
  top: var(--spacing-2);
@@ -222,10 +218,7 @@
222
218
  border: 0;
223
219
  border-radius: var(--radius-sm);
224
220
  background: transparent;
225
- /* The strip's own quiet ink rather than the neutral tertiary step, so the
226
- close on a failure is part of the failure rather than the one grey thing
227
- inside it. */
228
- color: var(--crewlet-toast-ink-quiet);
221
+ color: var(--color-text-tertiary);
229
222
  cursor: pointer;
230
223
  transition:
231
224
  background var(--motion-duration-fast) var(--motion-easing-default),
@@ -233,25 +226,28 @@
233
226
  }
234
227
 
235
228
  .crewlet-toast__dismiss:hover {
236
- background: var(--color-surface-hover);
237
- color: var(--crewlet-toast-ink);
229
+ background: var(--color-surface-elevated);
230
+ color: var(--color-text-primary);
238
231
  }
239
232
 
233
+ /*
234
+ * THE COUNTDOWN IS A WASH BEHIND THE WORDS, the variant's soft step over the
235
+ * whole strip, draining from the right as the time runs out. It sits under
236
+ * every raised child, and it is the timer's picture, not the timer.
237
+ */
240
238
  .crewlet-toast__progress {
241
239
  position: absolute;
242
- left: 0;
243
- right: 0;
244
- bottom: 0;
245
- height: 2px;
240
+ inset: 0;
241
+ z-index: var(--z-index-base);
246
242
  transform-origin: left center;
247
- background: var(--crewlet-toast-mark);
243
+ background: var(--crewlet-toast-wash);
248
244
  pointer-events: none;
249
245
  animation-name: crewlet-toast-drain;
250
246
  animation-timing-function: linear;
251
247
  animation-fill-mode: forwards;
252
248
  }
253
249
 
254
- /* Paused by the class rather than by :hover, so the bar and the timer that
250
+ /* Paused by the class rather than by :hover, so the wash and the timer that
255
251
  actually dismisses are stopped by the same event. */
256
252
  .crewlet-toast__progress.is-paused {
257
253
  animation-play-state: paused;
@@ -261,7 +257,6 @@
261
257
  from {
262
258
  transform: scaleX(1);
263
259
  }
264
-
265
260
  to {
266
261
  transform: scaleX(0);
267
262
  }
@@ -287,8 +282,8 @@
287
282
 
288
283
  /*
289
284
  * The strip still arrives and still goes; it just does not slide, and the
290
- * countdown bar holds still. The timer is untouched: a reader who asked for
291
- * less motion did not ask to be left with a toast that never leaves.
285
+ * wash is not drawn. The timer is untouched: a reader who asked for less
286
+ * motion did not ask to be left with a toast that never leaves.
292
287
  */
293
288
  @media (prefers-reduced-motion: reduce) {
294
289
  .crewlet-toast {
@@ -1,4 +1,4 @@
1
1
  export { Toolbar, ToolbarOverflow, ToolbarWide } from '../chunk-PGRPNDWM.js';
2
- import '../chunk-7RPGY3JE.js';
2
+ import '../chunk-HMPFGIWM.js';
3
3
  import '../chunk-R25RGPUB.js';
4
4
  import '../chunk-ODEQTPFM.js';
@@ -1,4 +1,4 @@
1
- export { Tooltip } from '../chunk-CQY5NTRS.js';
2
- import '../chunk-7RPGY3JE.js';
1
+ export { Tooltip } from '../chunk-QWOPX2MN.js';
2
+ import '../chunk-HMPFGIWM.js';
3
3
  import '../chunk-R25RGPUB.js';
4
4
  import '../chunk-ODEQTPFM.js';
@@ -1,10 +1,10 @@
1
- export { TreeCanvas } from '../chunk-RZ7RGECB.js';
1
+ export { TreeCanvas } from '../chunk-2OLCUNG7.js';
2
2
  import '../chunk-MY374UUD.js';
3
- import '../chunk-2PZBIHRV.js';
4
- import '../chunk-53DVJCVW.js';
3
+ import '../chunk-AMH67MLM.js';
4
+ import '../chunk-VYOKRN2I.js';
5
5
  import '../chunk-OG6CL3EB.js';
6
6
  import '../chunk-4FQT6ZAY.js';
7
- import '../chunk-7RPGY3JE.js';
7
+ import '../chunk-HMPFGIWM.js';
8
8
  import '../chunk-R25RGPUB.js';
9
9
  import '../chunk-BZFWDIV6.js';
10
10
  import '../chunk-ODEQTPFM.js';
@@ -1,8 +1,8 @@
1
- export { TreeGrid } from '../chunk-6LXMLQUM.js';
1
+ export { TreeGrid } from '../chunk-B2Z2CDM5.js';
2
2
  import '../chunk-MY374UUD.js';
3
- import '../chunk-53DVJCVW.js';
3
+ import '../chunk-VYOKRN2I.js';
4
4
  import '../chunk-4FQT6ZAY.js';
5
- import '../chunk-7RPGY3JE.js';
5
+ import '../chunk-HMPFGIWM.js';
6
6
  import '../chunk-R25RGPUB.js';
7
7
  import '../chunk-BZFWDIV6.js';
8
8
  import '../chunk-ODEQTPFM.js';
@@ -1,15 +1,15 @@
1
1
  import { PageHeader } from './chunk-HOXGBLEY.js';
2
2
  import { RelativeTime } from './chunk-3CZ7XAVY.js';
3
3
  import { Toolbar } from './chunk-PGRPNDWM.js';
4
- import { DataTable } from './chunk-WY2NLRZN.js';
5
- import { Menu } from './chunk-TFH6SYWB.js';
6
- import { DateTimePicker } from './chunk-JDPAA2JU.js';
4
+ import { DataTable } from './chunk-QV266R6G.js';
5
+ import { Menu } from './chunk-NS7BVLL3.js';
6
+ import { DateTimePicker } from './chunk-2UU5IGZI.js';
7
7
  import { useListbox, useOptionKeys } from './chunk-F73MC7EZ.js';
8
8
  import { Kbd } from './chunk-SMBKXWML.js';
9
9
  import { Input } from './chunk-FTEJPHBI.js';
10
10
  import { Button } from './chunk-OG6CL3EB.js';
11
11
  import { IconButton } from './chunk-4FQT6ZAY.js';
12
- import { Popover } from './chunk-O2ZDZZS7.js';
12
+ import { Popover } from './chunk-BWRGFKJP.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,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-2PZBIHRV.js';
2
+ import { CANVAS_COMPOSE_CONTEXT, CANVAS_FIT_MAX_ZOOM, Canvas } from './chunk-AMH67MLM.js';
3
3
  import { focusables } from './chunk-R25RGPUB.js';
4
4
  import { cx } from './chunk-ODEQTPFM.js';
5
5
  import './TreeCanvas-L2XYONWL.css';
@@ -1,9 +1,9 @@
1
1
  import { today, CalendarGrid, shiftMonth, compareDays } from './chunk-GXQ3B46I.js';
2
2
  import { Button } from './chunk-OG6CL3EB.js';
3
3
  import { IconButton } from './chunk-4FQT6ZAY.js';
4
- import { Popover } from './chunk-O2ZDZZS7.js';
4
+ import { Popover } from './chunk-BWRGFKJP.js';
5
5
  import { cx } from './chunk-ODEQTPFM.js';
6
- import './DateTimePicker-4AZBTODT.css';
6
+ import './DateTimePicker-NJ6XH2TE.css';
7
7
  import { useMemo, useState, useEffect } from 'react';
8
8
  import { CalendarGlyph, ChevronDownGlyph, ChevronsLeftGlyph, ChevronLeftGlyph, ChevronRightGlyph, ChevronsRightGlyph } from '@crewlethq/icons/glyphs';
9
9
  import { jsx, jsxs } from 'react/jsx-runtime';
@@ -1,12 +1,12 @@
1
- import { Select } from './chunk-XFE5W2I4.js';
1
+ import { Select } from './chunk-FC4YTTFJ.js';
2
2
  import { Input } from './chunk-FTEJPHBI.js';
3
3
  import { today, shiftMonth, CalendarGrid, compareDays } from './chunk-GXQ3B46I.js';
4
4
  import { Button } from './chunk-OG6CL3EB.js';
5
5
  import { IconButton } from './chunk-4FQT6ZAY.js';
6
- import { Popover } from './chunk-O2ZDZZS7.js';
6
+ import { Popover } from './chunk-BWRGFKJP.js';
7
7
  import { isComposing } from './chunk-R25RGPUB.js';
8
8
  import { cx } from './chunk-ODEQTPFM.js';
9
- import './TimeWindowPicker-GBF4JDFI.css';
9
+ import './TimeWindowPicker-BZ5HHATU.css';
10
10
  import { useMemo, useState, useRef, useId, useEffect } from 'react';
11
11
  import { ClockGlyph, ChevronDownGlyph, CheckGlyph, ChevronLeftGlyph, ChevronRightGlyph } from '@crewlethq/icons/glyphs';
12
12
  import { jsx, jsxs } from 'react/jsx-runtime';
@@ -1,7 +1,7 @@
1
- import { LayerNodeBridge } from './chunk-53DVJCVW.js';
1
+ import { LayerNodeBridge } from './chunk-VYOKRN2I.js';
2
2
  import { Button } from './chunk-OG6CL3EB.js';
3
3
  import { IconButton } from './chunk-4FQT6ZAY.js';
4
- import { LAYER_REPOSITION_EVENT, LayerHost } from './chunk-7RPGY3JE.js';
4
+ import { LAYER_REPOSITION_EVENT, LayerHost } from './chunk-HMPFGIWM.js';
5
5
  import { VisuallyHidden } from './chunk-BZFWDIV6.js';
6
6
  import { cx } from './chunk-ODEQTPFM.js';
7
7
  import './Canvas-YVXHMWLN.css';
@@ -1,7 +1,7 @@
1
1
  import { useTreeState, treeExpandable, treeLevel, treePosInSet, treeSetSize, treeItemAction, treePrevious, treeNext, treeStep } from './chunk-MY374UUD.js';
2
- import { LayerNodeBridge } from './chunk-53DVJCVW.js';
2
+ import { LayerNodeBridge } from './chunk-VYOKRN2I.js';
3
3
  import { IconButton } from './chunk-4FQT6ZAY.js';
4
- import { LayerHost, LAYER_REPOSITION_EVENT } from './chunk-7RPGY3JE.js';
4
+ import { LayerHost, LAYER_REPOSITION_EVENT } from './chunk-HMPFGIWM.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';
@@ -1,4 +1,4 @@
1
- import { useLayerContainer, viewportBounds, LAYER_GAP, outsideBounds, placePopup, LAYER_REPOSITION_EVENT } from './chunk-7RPGY3JE.js';
1
+ import { useLayerContainer, viewportBounds, LAYER_GAP, outsideBounds, placePopup, LAYER_REPOSITION_EVENT } from './chunk-HMPFGIWM.js';
2
2
  import { usePopupLayer, focusables } from './chunk-R25RGPUB.js';
3
3
  import { cx } from './chunk-ODEQTPFM.js';
4
4
  import './Popover-QCINR7WG.css';
@@ -44,7 +44,8 @@ function Popover({
44
44
  }, []);
45
45
  const close = useCallback(
46
46
  (reason) => {
47
- if (reason === "escape" || reason === "tab") anchor.current?.focus();
47
+ const held = panel.current?.contains(document.activeElement) ?? false;
48
+ if (reason === "escape" || reason === "tab" || reason === "content" && held) anchor.current?.focus();
48
49
  setOpen(false, reason);
49
50
  },
50
51
  [setOpen]
@@ -1,4 +1,4 @@
1
- import { TreeGrid } from './chunk-6LXMLQUM.js';
1
+ import { TreeGrid } from './chunk-B2Z2CDM5.js';
2
2
  import { createTreeModel, treeParent } from './chunk-MY374UUD.js';
3
3
  import { OrgLabel } from './chunk-6OF2DBKY.js';
4
4
  import { AddPill } from './chunk-74WGARJE.js';
@@ -1,6 +1,6 @@
1
1
  import { HuePicker } from './chunk-NXDEPUVG.js';
2
2
  import { NODE_HUE_NAMES } from './chunk-AYKXMIOR.js';
3
- import { Popover } from './chunk-O2ZDZZS7.js';
3
+ import { Popover } from './chunk-BWRGFKJP.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';
@@ -1,9 +1,10 @@
1
1
  import { cx } from './chunk-ODEQTPFM.js';
2
- import './DescriptionList-YYY3V3O6.css';
2
+ import './DescriptionList-IXMRCSMK.css';
3
3
  import { jsxs, jsx } from 'react/jsx-runtime';
4
4
 
5
5
  function DescriptionList({
6
6
  dense = false,
7
+ fit = false,
7
8
  items,
8
9
  className,
9
10
  children,
@@ -13,7 +14,12 @@ function DescriptionList({
13
14
  "dl",
14
15
  {
15
16
  ...rest,
16
- className: cx("crewlet-description-list", dense && "crewlet-description-list--dense", className),
17
+ className: cx(
18
+ "crewlet-description-list",
19
+ dense && "crewlet-description-list--dense",
20
+ fit && "crewlet-description-list--fit",
21
+ className
22
+ ),
17
23
  children: [
18
24
  items?.map(([term, detail], index) => /* @__PURE__ */ jsx(DescriptionListItem, { term, children: detail }, index)),
19
25
  children
@@ -1,7 +1,7 @@
1
1
  import { useListbox, useOptionKeys, useHighlightRest } from './chunk-F73MC7EZ.js';
2
- import { useLayerContainer, viewportBounds, outsideBounds, placePopup, LAYER_GAP, LAYER_REPOSITION_EVENT } from './chunk-7RPGY3JE.js';
2
+ import { useLayerContainer, viewportBounds, outsideBounds, placePopup, LAYER_GAP, LAYER_REPOSITION_EVENT } from './chunk-HMPFGIWM.js';
3
3
  import { cx } from './chunk-ODEQTPFM.js';
4
- import './Select-XMZ44RWY.css';
4
+ import './Select-2P7AWUE4.css';
5
5
  import { forwardRef, useId, useMemo, useState, useRef, useCallback, useEffect, useLayoutEffect } from 'react';
6
6
  import { createPortal } from 'react-dom';
7
7
  import { ChevronDownGlyph, CheckGlyph, SearchGlyph } from '@crewlethq/icons/glyphs';
@@ -208,6 +208,7 @@ var ListboxSelect = forwardRef(function ListboxSelect2({
208
208
  return out;
209
209
  }, [offered]);
210
210
  const flat = useMemo(() => groups.flatMap((group) => group.items), [groups]);
211
+ const tickAtEnd = useMemo(() => flat.some((option) => option.leading !== void 0), [flat]);
211
212
  const close = useCallback((returnFocus) => {
212
213
  setOpen(false);
213
214
  setQuery("");
@@ -399,6 +400,14 @@ var ListboxSelect = forwardRef(function ListboxSelect2({
399
400
  const at = index;
400
401
  const selected = isChosen(option.value);
401
402
  const highlighted = at === listbox.active;
403
+ const tick = /* @__PURE__ */ jsx(
404
+ "span",
405
+ {
406
+ className: cx("crewlet-select__option-tick", tickAtEnd && "crewlet-select__option-tick--end"),
407
+ "aria-hidden": "true",
408
+ children: selected ? /* @__PURE__ */ jsx(CheckGlyph, { size: "sm" }) : null
409
+ }
410
+ );
402
411
  return /* @__PURE__ */ jsx(
403
412
  "div",
404
413
  {
@@ -416,7 +425,7 @@ var ListboxSelect = forwardRef(function ListboxSelect2({
416
425
  ),
417
426
  ...option.disabled ? {} : optionHandlers(at),
418
427
  children: renderOption ? renderOption(option, { active: highlighted, selected }) : /* @__PURE__ */ jsxs(Fragment, { children: [
419
- /* @__PURE__ */ jsx("span", { className: "crewlet-select__option-tick", "aria-hidden": "true", children: selected ? /* @__PURE__ */ jsx(CheckGlyph, { size: "sm" }) : null }),
428
+ tickAtEnd ? null : tick,
420
429
  option.leading !== void 0 ? /* @__PURE__ */ jsx("span", { className: "crewlet-select__option-leading", "aria-hidden": "true", children: option.leading }) : null,
421
430
  /* @__PURE__ */ jsxs("span", { className: "crewlet-select__option-body", children: [
422
431
  /* @__PURE__ */ jsx("span", { className: "crewlet-select__option-label", children: option.label }),
@@ -425,7 +434,8 @@ var ListboxSelect = forwardRef(function ListboxSelect2({
425
434
  option.hint !== void 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [
426
435
  " ",
427
436
  /* @__PURE__ */ jsx("span", { className: "crewlet-listbox__hint", children: option.hint })
428
- ] }) : null
437
+ ] }) : null,
438
+ tickAtEnd ? tick : null
429
439
  ] })
430
440
  },
431
441
  String(option.value)
@@ -1,12 +1,13 @@
1
1
  import { useMediaMatch } from './chunk-IG75YMUN.js';
2
2
  import { IconButton } from './chunk-4FQT6ZAY.js';
3
3
  import { useModalLayer, focusables } from './chunk-R25RGPUB.js';
4
+ import { VisuallyHidden } from './chunk-BZFWDIV6.js';
4
5
  import { cx } from './chunk-ODEQTPFM.js';
5
- import './AppShell-CEVLW4QG.css';
6
- import { createContext, useContext, useId, useState, useRef, useCallback, useEffect, useLayoutEffect } from 'react';
6
+ import './AppShell-6QUD7NWM.css';
7
+ import { createContext, forwardRef, useContext, useId, useState, useRef, useCallback, useEffect, useLayoutEffect } from 'react';
7
8
  import { breakpoint } from '@crewlethq/tokens';
8
- import { MenuGlyph } from '@crewlethq/icons/glyphs';
9
- import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
9
+ import { ChevronUpGlyph, MenuGlyph } from '@crewlethq/icons/glyphs';
10
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
10
11
 
11
12
  var NARROW = `(width < ${breakpoint.shell})`;
12
13
  var AppShellContext = createContext(null);
@@ -156,37 +157,80 @@ function AppShellRail({ header, footer, className, children }) {
156
157
  footer ? /* @__PURE__ */ jsx("div", { className: "crewlet-app-shell__rail-foot", children: footer }) : null
157
158
  ] });
158
159
  }
159
- function AppShellRailRow({ icon, trailing, detail, onClick, label, className, children }) {
160
+ function opensSomething(haspopup) {
161
+ return haspopup !== void 0 && haspopup !== false && haspopup !== "false";
162
+ }
163
+ var AppShellRailRow = forwardRef(function AppShellRailRow2({
164
+ icon,
165
+ trailing,
166
+ count,
167
+ detail,
168
+ onClick,
169
+ label,
170
+ className,
171
+ children,
172
+ "aria-expanded": expanded,
173
+ "aria-haspopup": haspopup,
174
+ "aria-controls": controls
175
+ }, ref) {
160
176
  const block = detail !== void 0 && detail !== null && detail !== false && detail !== "";
177
+ const opens = onClick !== void 0 && opensSomething(haspopup);
161
178
  const inside = /* @__PURE__ */ jsxs(Fragment, { children: [
162
179
  icon ? /* @__PURE__ */ jsx("span", { className: "crewlet-app-shell__rail-row-icon", "aria-hidden": true, children: icon }) : null,
163
180
  /* @__PURE__ */ jsxs("span", { className: "crewlet-app-shell__rail-row-body", children: [
164
181
  /* @__PURE__ */ jsxs("span", { className: "crewlet-app-shell__rail-row-text", children: [
165
- /* @__PURE__ */ jsx("span", { className: "crewlet-app-shell__rail-row-label", children }),
182
+ /* @__PURE__ */ jsxs("span", { className: "crewlet-app-shell__rail-row-label", children: [
183
+ children,
184
+ count ? /* @__PURE__ */ jsx(VisuallyHidden, { children: `, ${String(count.value)} ${count.label}` }) : null
185
+ ] }),
166
186
  block ? /* @__PURE__ */ jsxs(Fragment, { children: [
167
187
  " ",
168
188
  /* @__PURE__ */ jsx("span", { className: "crewlet-app-shell__rail-row-detail", children: detail })
169
189
  ] }) : null
170
190
  ] }),
191
+ count ? /* @__PURE__ */ jsxs(Fragment, { children: [
192
+ " ",
193
+ /* @__PURE__ */ jsxs(
194
+ "span",
195
+ {
196
+ className: cx(
197
+ "crewlet-app-shell__rail-row-count",
198
+ count.tone === "warning" && "crewlet-app-shell__rail-row-count--warning"
199
+ ),
200
+ "aria-hidden": true,
201
+ children: [
202
+ count.mark ? /* @__PURE__ */ jsx("span", { className: "crewlet-app-shell__rail-row-count-mark", children: count.mark }) : null,
203
+ count.value
204
+ ]
205
+ }
206
+ )
207
+ ] }) : null,
171
208
  trailing ? /* @__PURE__ */ jsxs(Fragment, { children: [
172
209
  " ",
173
210
  /* @__PURE__ */ jsx("span", { className: "crewlet-app-shell__rail-row-trailing", children: trailing })
174
211
  ] }) : null
175
- ] })
212
+ ] }),
213
+ opens ? /* @__PURE__ */ jsx("span", { className: "crewlet-app-shell__rail-row-opens", "aria-hidden": true, children: /* @__PURE__ */ jsx(ChevronUpGlyph, { size: "xs" }) }) : null
176
214
  ] });
177
215
  const shape = cx("crewlet-app-shell__rail-row", block && "crewlet-app-shell__rail-row--block", className);
178
- if (onClick === void 0) return /* @__PURE__ */ jsx("div", { className: shape, children: inside });
216
+ if (onClick === void 0) {
217
+ return /* @__PURE__ */ jsx("div", { ref, className: shape, children: inside });
218
+ }
179
219
  return /* @__PURE__ */ jsx(
180
220
  "button",
181
221
  {
222
+ ref,
182
223
  type: "button",
183
224
  className: cx(shape, "crewlet-app-shell__rail-row--action"),
184
225
  "aria-label": label,
226
+ "aria-expanded": expanded,
227
+ "aria-haspopup": haspopup,
228
+ "aria-controls": controls,
185
229
  onClick,
186
230
  children: inside
187
231
  }
188
232
  );
189
- }
233
+ });
190
234
  function AppShellToggle({ className }) {
191
235
  const { drawerOpen, toggleDrawer, railId, toggleLabel, hasRail } = useAppShell();
192
236
  if (!hasRail) return null;
@@ -1,5 +1,5 @@
1
1
  import { cx } from './chunk-ODEQTPFM.js';
2
- import './Layer-NAFSGCFA.css';
2
+ import './Layer-J222IFNX.css';
3
3
  import { createContext, useState, useContext } from 'react';
4
4
  import { jsxs, jsx } from 'react/jsx-runtime';
5
5