@crewlethq/ui 0.49.1 → 0.51.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 (82) hide show
  1. package/README.md +34 -0
  2. package/dist/ArtifactCard/index.js +1 -1
  3. package/dist/{ArtifactCard-SOB63NV5.css → ArtifactCard-F7IVRL3A.css} +3 -0
  4. package/dist/AvatarPicker/index.js +2 -2
  5. package/dist/BrandSample/index.js +3 -3
  6. package/dist/BrandScope/index.js +2 -2
  7. package/dist/Callout/index.js +1 -1
  8. package/dist/{Callout-ZAVG3P66.css → Callout-G3N3IE6M.css} +9 -0
  9. package/dist/ColorChip/ColorChip.d.ts +26 -0
  10. package/dist/ColorChip/index.d.ts +3 -0
  11. package/dist/ColorChip/index.js +3 -0
  12. package/dist/ColorChip-A5XHTH3J.css +46 -0
  13. package/dist/ColorField/ColorField.d.ts +16 -8
  14. package/dist/ColorField/index.js +2 -2
  15. package/dist/ColorSwatch/index.js +2 -2
  16. package/dist/ContrastBadge/ContrastBadge.d.ts +38 -3
  17. package/dist/ContrastBadge/index.d.ts +2 -2
  18. package/dist/ContrastBadge/index.js +2 -2
  19. package/dist/ContrastHelp/ContrastHelp.d.ts +40 -0
  20. package/dist/ContrastHelp/index.d.ts +3 -0
  21. package/dist/ContrastHelp/index.js +12 -0
  22. package/dist/ContrastHelp-MZCAW5WQ.css +43 -0
  23. package/dist/DataView/index.js +2 -2
  24. package/dist/EditingStatus/EditingStatus.d.ts +13 -1
  25. package/dist/EditingStatus/index.js +3 -1
  26. package/dist/{EditingStatus-NNA2CKIL.css → EditingStatus-YU7EGM6Y.css} +22 -7
  27. package/dist/FolderTile/index.js +1 -1
  28. package/dist/{FolderTile-FDT5Y63Z.css → FolderTile-MIUEB7SO.css} +12 -5
  29. package/dist/FollowBanner/index.js +2 -2
  30. package/dist/InlineEditor/index.js +4 -2
  31. package/dist/LinkInterstitial/index.js +2 -2
  32. package/dist/ListInput/ListInput.d.ts +3 -1
  33. package/dist/ListInput/index.js +1 -1
  34. package/dist/{ListInput-WUP2YITQ.css → ListInput-P2ECUQJ2.css} +1 -1
  35. package/dist/LogoSlot/index.js +3 -3
  36. package/dist/RichEditor/index.js +2 -2
  37. package/dist/SandboxedFrame/index.js +2 -2
  38. package/dist/SetupWizard/SetupWizard.d.ts +87 -0
  39. package/dist/SetupWizard/index.d.ts +3 -0
  40. package/dist/SetupWizard/index.js +11 -0
  41. package/dist/SetupWizard-GZK5UDKC.css +223 -0
  42. package/dist/ShareDialog/index.js +2 -2
  43. package/dist/Stepper/Stepper.d.ts +60 -11
  44. package/dist/Stepper/index.d.ts +1 -1
  45. package/dist/Stepper/index.js +1 -1
  46. package/dist/Stepper-QEJI5RGX.css +355 -0
  47. package/dist/{chunk-ITI2Z44C.js → chunk-2UFUP2ZH.js} +2 -2
  48. package/dist/{chunk-4A4QG6UC.js → chunk-34C7NYIQ.js} +1 -1
  49. package/dist/chunk-6GTTRJWJ.js +24 -0
  50. package/dist/{chunk-7P336RA5.js → chunk-6RMZH7P7.js} +1 -1
  51. package/dist/{chunk-W6FOEBIL.js → chunk-73WHPLWQ.js} +24 -15
  52. package/dist/chunk-7W3LYIOC.js +27 -0
  53. package/dist/{chunk-OEEYL2CM.js → chunk-AVMQMY66.js} +2 -2
  54. package/dist/{chunk-SZZRIHGT.js → chunk-BPCY7ZID.js} +1 -1
  55. package/dist/chunk-DTSZUH6H.js +124 -0
  56. package/dist/chunk-EJWPYEG4.js +38 -0
  57. package/dist/{chunk-M4QM477B.js → chunk-FXHWOXGD.js} +1 -1
  58. package/dist/{chunk-7PCDKRNB.js → chunk-KHP7TJF7.js} +2 -2
  59. package/dist/chunk-KIRQZG3G.js +53 -0
  60. package/dist/chunk-LDGQIDIZ.js +129 -0
  61. package/dist/{chunk-JFDIMO3A.js → chunk-PGYIDNGG.js} +1 -1
  62. package/dist/{chunk-WLSEAIVC.js → chunk-RHPBTE3F.js} +1 -1
  63. package/dist/{chunk-Q44X36QC.js → chunk-S63QOMXC.js} +1 -1
  64. package/dist/{chunk-GP4YWZFO.js → chunk-U3LNU4B2.js} +1 -1
  65. package/dist/{chunk-PGR2PKH6.js → chunk-UUTEWGO6.js} +10 -10
  66. package/dist/{chunk-356JNSER.js → chunk-WQQ5T5SA.js} +1 -1
  67. package/dist/{chunk-B235ANDO.js → chunk-WW7TU6HE.js} +34 -16
  68. package/dist/{chunk-P3OIM6OC.js → chunk-X7WEE3EK.js} +1 -1
  69. package/dist/generated/index.d.ts +3 -0
  70. package/dist/generated/index.js +76 -73
  71. package/dist/index.js +76 -73
  72. package/dist/styles.css +564 -30
  73. package/dist/utils/hexColour.d.ts +13 -0
  74. package/package.json +3 -3
  75. package/dist/Stepper-HW4JM3YH.css +0 -176
  76. package/dist/chunk-5QWIJSQM.js +0 -73
  77. package/dist/chunk-MULOZYHL.js +0 -30
  78. package/dist/chunk-UZMNR366.js +0 -9
  79. package/dist/{Editor-ZYDXHGJE.js → Editor-MLGK3KOG.js} +1 -1
  80. package/dist/{chunk-3QSKDZR5.js → chunk-EW2N4FOD.js} +1 -1
  81. package/dist/{chunk-3WMOEGEL.js → chunk-P432I5DQ.js} +0 -0
  82. package/dist/{chunk-NAWUXCBC.js → chunk-WX6IJJ4U.js} +1 -1
@@ -0,0 +1,355 @@
1
+ /*
2
+ * The stepper: where a sequence has got to (Stepper.tsx).
3
+ *
4
+ * THE APPROVED DESIGN'S STEP ROW. Each step is a 20px pill inside the default
5
+ * hairline, the 11px step at the medium weight, 8px inside each end and 5px
6
+ * between a mark and the word; two pills are joined by a 10px rule in the
7
+ * strong hairline's colour with 6px either side of it. A finished step is the
8
+ * secondary ink behind a check, the current step its tone's soft tint under
9
+ * its ink behind its dot, and a step still to come the tertiary ink.
10
+ *
11
+ * EVERY INK IS A MEASURED PAIR. The secondary and tertiary steps are held to
12
+ * 4.5:1 on every opaque rung, and each tone's ink to 4.5:1 on its own soft
13
+ * tint over every rung, by the palette suite in @crewlethq/tokens; the pill
14
+ * draws nothing else. The current pill is the design's `work-soft` under
15
+ * `work-ink` in the default tone, and a Tag's colours in every tone, which is
16
+ * what a chip naming a state is in this kit.
17
+ */
18
+
19
+ .crewlet-stepper {
20
+ display: flex;
21
+ flex-wrap: wrap;
22
+ align-items: center;
23
+ /* The design's 6px between a pill and the rule beside it: a step and a half. */
24
+ gap: calc(var(--spacing-1) * 1.5);
25
+ min-width: 0;
26
+ margin: 0;
27
+ padding: 0;
28
+ list-style: none;
29
+ }
30
+
31
+ .crewlet-stepper__step {
32
+ display: inline-flex;
33
+ align-items: center;
34
+ gap: calc(var(--spacing-1) * 1.5);
35
+ min-width: 0;
36
+ }
37
+
38
+ /*
39
+ * THE RULE BETWEEN TWO STEPS is drawn by the second of them, so a sequence of
40
+ * one draws none and nothing trails the last. A pseudo-element, because it is
41
+ * furniture: it carries nothing a reader has to be told, and the list already
42
+ * says the steps are in order. 10px by a hairline, the measure of this one
43
+ * mark, and fixed at every density as a hairline is.
44
+ */
45
+ .crewlet-stepper__step + .crewlet-stepper__step::before {
46
+ content: '';
47
+ flex: none;
48
+ width: 10px;
49
+ height: 1px;
50
+ background: var(--color-border-strong);
51
+ }
52
+
53
+ .crewlet-stepper__chip {
54
+ display: inline-flex;
55
+ align-items: center;
56
+ /* The design's 5px between the check or the dot and the word. */
57
+ gap: calc(var(--spacing-1) * 1.25);
58
+ box-sizing: border-box;
59
+ /* The design's 20px pill, which follows the density with every other step
60
+ height in the kit. It labels and takes no press, so the 24px target floor
61
+ is not its to clear. */
62
+ height: calc(20px * var(--density, 1));
63
+ max-width: 100%;
64
+ padding: 0 var(--spacing-2);
65
+ border: 1px solid var(--color-border-default);
66
+ border-radius: var(--radius-pill);
67
+ color: var(--color-text-tertiary);
68
+ font-family: var(--font-family-sans);
69
+ font-size: var(--font-size-2xs);
70
+ font-weight: var(--font-weight-medium);
71
+ line-height: 1;
72
+ white-space: nowrap;
73
+ }
74
+
75
+ .crewlet-stepper__label {
76
+ min-width: 0;
77
+ overflow: hidden;
78
+ text-overflow: ellipsis;
79
+ }
80
+
81
+ .crewlet-stepper__check {
82
+ flex: none;
83
+ }
84
+
85
+ .crewlet-stepper__step--done > .crewlet-stepper__chip {
86
+ color: var(--color-text-secondary);
87
+ }
88
+
89
+ /*
90
+ * THE CURRENT STEP, in its tone: the pill in a row, the mark in a column. The
91
+ * hairline goes transparent rather than away, so the pill keeps its box and
92
+ * the row does not move by a pixel as the current step advances along it, and
93
+ * so forced-colors mode, which draws a transparent border in the system's own
94
+ * colour, still outlines it.
95
+ */
96
+ .crewlet-stepper--info .crewlet-stepper__step--current > .crewlet-stepper__chip,
97
+ .crewlet-stepper--info .crewlet-stepper__step--current .crewlet-stepper__mark {
98
+ border-color: transparent;
99
+ background: var(--color-feedback-info-soft);
100
+ color: var(--color-feedback-info-ink);
101
+ }
102
+
103
+ .crewlet-stepper--success .crewlet-stepper__step--current > .crewlet-stepper__chip,
104
+ .crewlet-stepper--success .crewlet-stepper__step--current .crewlet-stepper__mark {
105
+ border-color: transparent;
106
+ background: var(--color-feedback-success-soft);
107
+ color: var(--color-feedback-success-ink);
108
+ }
109
+
110
+ .crewlet-stepper--warning .crewlet-stepper__step--current > .crewlet-stepper__chip,
111
+ .crewlet-stepper--warning .crewlet-stepper__step--current .crewlet-stepper__mark {
112
+ border-color: transparent;
113
+ background: var(--color-feedback-warning-soft);
114
+ color: var(--color-feedback-warning-ink);
115
+ }
116
+
117
+ .crewlet-stepper--danger .crewlet-stepper__step--current > .crewlet-stepper__chip,
118
+ .crewlet-stepper--danger .crewlet-stepper__step--current .crewlet-stepper__mark {
119
+ border-color: transparent;
120
+ background: var(--color-feedback-danger-soft);
121
+ color: var(--color-feedback-danger-ink);
122
+ }
123
+
124
+ .crewlet-stepper--brand .crewlet-stepper__step--current > .crewlet-stepper__chip,
125
+ .crewlet-stepper--brand .crewlet-stepper__step--current .crewlet-stepper__mark {
126
+ border-color: transparent;
127
+ background: var(--color-brand-accent-soft);
128
+ color: var(--color-brand-accent-ink);
129
+ }
130
+
131
+ /*
132
+ * A STEP THAT NEEDS ATTENTION is the warning tint under the warning ink, the
133
+ * pair the palette suite holds to 4.5:1 over every rung, with the warning
134
+ * glyph: the pill of a step that is not current, and the mark of any step in
135
+ * a column. A CURRENT pill keeps its tone, so the row still says which step
136
+ * the reader is on, and carries the glyph in that tone's ink.
137
+ */
138
+ .crewlet-stepper .crewlet-stepper__step--attention:not(.crewlet-stepper__step--current) > .crewlet-stepper__chip,
139
+ .crewlet-stepper .crewlet-stepper__step--attention .crewlet-stepper__mark {
140
+ border-color: transparent;
141
+ background: var(--color-feedback-warning-soft);
142
+ color: var(--color-feedback-warning-ink);
143
+ }
144
+
145
+ .crewlet-stepper__warning {
146
+ flex: none;
147
+ }
148
+
149
+ /*
150
+ * INSIDE THE PILL THE DOT IS THE PILL'S OWN INK, as a Tag's is, and for the
151
+ * Tag's reason: StatusDot paints the fill step, measured as a mark on the
152
+ * opaque rungs, and here it stands on the tone's soft tint instead, where
153
+ * nothing measures it. The ink is the step that IS measured on that tint, at
154
+ * 4.5:1, and the colour of the word beside it. A pulsing dot keeps
155
+ * StatusDot's halo, the same soft step drawn once more over the pill, which
156
+ * stands dE 3.92 off it at the least (the light warning pill on the frame).
157
+ *
158
+ * Two classes deep, so it beats StatusDot's own tone rule whichever order the
159
+ * bundle writes the two files in.
160
+ */
161
+ .crewlet-stepper .crewlet-stepper__dot {
162
+ background: currentColor;
163
+ }
164
+
165
+ /*
166
+ * FORCED COLORS repaints every background to Canvas, which takes the current
167
+ * step's tint and its dot, so the one step the row is about would read like
168
+ * any other. The current pill is drawn as the system draws a selection,
169
+ * HighlightText on Highlight, with its dot in the same ink, and the rule
170
+ * between two steps in GrayText; the chips' hairlines are borders, which the
171
+ * mode keeps in its own colour.
172
+ *
173
+ * THE CURRENT PILL OPTS OUT OF THE ADJUSTMENT, which is safe only because
174
+ * every colour it draws in that mode is a system colour. Left to it, Chromium
175
+ * paints a Canvas backplate behind every run of text, and HighlightText is
176
+ * written for Highlight, not for Canvas: in a dark high-contrast theme the
177
+ * step's words drew black on black (measured in Chromium 153 with the mode
178
+ * emulated). Opting out also keeps shadows, so the pulsing dot's halo, which
179
+ * is the tone's soft tint and no system colour, is held still inside it.
180
+ */
181
+ /*
182
+ * A STEP THAT CAN BE PICKED is a button with no look of its own: the pill or
183
+ * the row it carries draws it, and a hover lays the kit's hover overlay over
184
+ * a step at rest. The current step keeps its tint under the pointer, since a
185
+ * tone rule weighs more than the hover. The ring sits inside the step's own
186
+ * box, over the pill's hairline rather than a second line beside it.
187
+ */
188
+ .crewlet-stepper__target {
189
+ appearance: none;
190
+ margin: 0;
191
+ background: transparent;
192
+ font: inherit;
193
+ text-align: start;
194
+ cursor: pointer;
195
+ }
196
+
197
+ .crewlet-stepper__chip.crewlet-stepper__target {
198
+ font-family: var(--font-family-sans);
199
+ font-size: var(--font-size-2xs);
200
+ font-weight: var(--font-weight-medium);
201
+ line-height: 1;
202
+ }
203
+
204
+ .crewlet-stepper__target:hover {
205
+ background: var(--color-surface-hover);
206
+ }
207
+
208
+ .crewlet-stepper__target:focus-visible {
209
+ outline: 2px solid var(--color-focus);
210
+ outline-offset: var(--size-focus-ring-inset-offset);
211
+ }
212
+
213
+ /*
214
+ * THE COLUMN, a setup wizard's rail. Each step is a row: a 20px mark (the
215
+ * check, the dot, the warning glyph, or the step's number for one still to
216
+ * come) and beside it the label, with the description and the status words
217
+ * under it. A hairline in the strong hairline's colour joins one mark to the
218
+ * next, 4px clear of each, drawn by the step it leaves so nothing trails the
219
+ * last. The mark is the pills' 20px, following the density as they do, and
220
+ * the label's line is the mark's height so the two stand level. The row's words follow the same three inks as the pills: the current
221
+ * step primary and medium, a finished one secondary, the rest tertiary.
222
+ */
223
+ .crewlet-stepper--vertical {
224
+ flex-direction: column;
225
+ flex-wrap: nowrap;
226
+ align-items: stretch;
227
+ gap: 0;
228
+ }
229
+
230
+ .crewlet-stepper--vertical .crewlet-stepper__step {
231
+ position: relative;
232
+ display: block;
233
+ }
234
+
235
+ .crewlet-stepper--vertical .crewlet-stepper__step + .crewlet-stepper__step::before {
236
+ content: none;
237
+ }
238
+
239
+ .crewlet-stepper--vertical .crewlet-stepper__step:not(:last-child)::after {
240
+ content: '';
241
+ position: absolute;
242
+ top: calc(var(--spacing-2) + 20px * var(--density, 1) + 4px);
243
+ bottom: calc(4px - var(--spacing-2));
244
+ left: calc(var(--spacing-2) + 10px * var(--density, 1));
245
+ width: 1px;
246
+ background: var(--color-border-strong);
247
+ pointer-events: none;
248
+ }
249
+
250
+ .crewlet-stepper__row {
251
+ display: flex;
252
+ align-items: flex-start;
253
+ gap: var(--spacing-3);
254
+ box-sizing: border-box;
255
+ width: 100%;
256
+ padding: var(--spacing-2);
257
+ border: 0;
258
+ border-radius: var(--radius-md);
259
+ color: var(--color-text-tertiary);
260
+ font-family: var(--font-family-sans);
261
+ font-size: var(--font-size-sm);
262
+ }
263
+
264
+ .crewlet-stepper__mark {
265
+ display: inline-flex;
266
+ flex: none;
267
+ align-items: center;
268
+ justify-content: center;
269
+ box-sizing: border-box;
270
+ width: calc(20px * var(--density, 1));
271
+ height: calc(20px * var(--density, 1));
272
+ border: 1px solid var(--color-border-default);
273
+ border-radius: var(--radius-pill);
274
+ font-size: var(--font-size-2xs);
275
+ font-weight: var(--font-weight-medium);
276
+ font-variant-numeric: tabular-nums;
277
+ line-height: 1;
278
+ }
279
+
280
+ .crewlet-stepper__text {
281
+ display: flex;
282
+ flex-direction: column;
283
+ gap: var(--spacing-1);
284
+ min-width: 0;
285
+ }
286
+
287
+ .crewlet-stepper__title {
288
+ line-height: calc(20px * var(--density, 1));
289
+ overflow-wrap: anywhere;
290
+ }
291
+
292
+ .crewlet-stepper__row .crewlet-stepper__label {
293
+ overflow: visible;
294
+ }
295
+
296
+ .crewlet-stepper__description,
297
+ .crewlet-stepper__note {
298
+ color: var(--color-text-tertiary);
299
+ font-size: var(--font-size-xs);
300
+ line-height: var(--font-line-height-snug);
301
+ }
302
+
303
+ .crewlet-stepper__step--attention .crewlet-stepper__note {
304
+ color: var(--color-text-secondary);
305
+ }
306
+
307
+ .crewlet-stepper__step--done > .crewlet-stepper__row {
308
+ color: var(--color-text-secondary);
309
+ }
310
+
311
+ /*
312
+ * THE CURRENT ROW is lifted as the rail's current row is (SidebarNav): the
313
+ * elevated rung inside a one-pixel hairline drawn as an outline, so forced
314
+ * colors keeps it, and it does not move the row by a pixel.
315
+ */
316
+ .crewlet-stepper__step--current > .crewlet-stepper__row {
317
+ outline: 1px solid var(--color-border-default);
318
+ outline-offset: -1px;
319
+ background: var(--color-surface-elevated);
320
+ color: var(--color-text-primary);
321
+ font-weight: var(--font-weight-medium);
322
+ }
323
+
324
+ .crewlet-stepper__step--current .crewlet-stepper__description,
325
+ .crewlet-stepper__step--current .crewlet-stepper__note {
326
+ font-weight: var(--font-weight-regular);
327
+ }
328
+
329
+ @media (forced-colors: active) {
330
+ .crewlet-stepper .crewlet-stepper__step--current > .crewlet-stepper__chip,
331
+ .crewlet-stepper .crewlet-stepper__step--current .crewlet-stepper__mark {
332
+ forced-color-adjust: none;
333
+ border-color: Highlight;
334
+ background: Highlight;
335
+ color: HighlightText;
336
+ }
337
+
338
+ .crewlet-stepper .crewlet-stepper__dot {
339
+ background: HighlightText;
340
+ }
341
+
342
+ .crewlet-stepper .crewlet-stepper__dot.is-pulsing::after {
343
+ animation: none;
344
+ }
345
+
346
+ .crewlet-stepper__step + .crewlet-stepper__step::before,
347
+ .crewlet-stepper--vertical .crewlet-stepper__step:not(:last-child)::after {
348
+ background: GrayText;
349
+ }
350
+
351
+ .crewlet-stepper__target:hover {
352
+ outline: 1px solid Highlight;
353
+ outline-offset: var(--size-focus-ring-inset-offset);
354
+ }
355
+ }
@@ -1,6 +1,6 @@
1
1
  import { FileDrop, FilePickButton } from './chunk-THDGBD6Y.js';
2
- import { contrastRatio } from './chunk-B235ANDO.js';
3
- import { normalizeHex } from './chunk-UZMNR366.js';
2
+ import { contrastRatio } from './chunk-WW7TU6HE.js';
3
+ import { normalizeHex } from './chunk-7W3LYIOC.js';
4
4
  import { Button } from './chunk-OG6CL3EB.js';
5
5
  import { VisuallyHidden } from './chunk-BZFWDIV6.js';
6
6
  import { cx } from './chunk-ODEQTPFM.js';
@@ -1,4 +1,4 @@
1
- import { Callout } from './chunk-SZZRIHGT.js';
1
+ import { Callout } from './chunk-BPCY7ZID.js';
2
2
  import { Button } from './chunk-OG6CL3EB.js';
3
3
  import { isComposing } from './chunk-H5XTJ7GJ.js';
4
4
  import { cx } from './chunk-ODEQTPFM.js';
@@ -0,0 +1,24 @@
1
+ import { normalizeHex } from './chunk-7W3LYIOC.js';
2
+ import { cx } from './chunk-ODEQTPFM.js';
3
+ import './ColorChip-A5XHTH3J.css';
4
+ import { jsx } from 'react/jsx-runtime';
5
+
6
+ function ColorChip({ value, size = "xs", shape = "round", className }) {
7
+ const hex = normalizeHex(value);
8
+ return /* @__PURE__ */ jsx(
9
+ "span",
10
+ {
11
+ className: cx(
12
+ "crewlet-color-chip",
13
+ `crewlet-color-chip--${size}`,
14
+ `crewlet-color-chip--${shape}`,
15
+ !hex && "is-empty",
16
+ className
17
+ ),
18
+ style: hex ? { "--crewlet-color-chip-value": hex } : void 0,
19
+ "aria-hidden": "true"
20
+ }
21
+ );
22
+ }
23
+
24
+ export { ColorChip };
@@ -1,4 +1,4 @@
1
- import { EditingStatus } from './chunk-MULOZYHL.js';
1
+ import { EditingStatus } from './chunk-EJWPYEG4.js';
2
2
  import { Kbd } from './chunk-SMBKXWML.js';
3
3
  import { Button } from './chunk-OG6CL3EB.js';
4
4
  import { isComposing } from './chunk-H5XTJ7GJ.js';
@@ -1,16 +1,20 @@
1
- import { normalizeHex } from './chunk-UZMNR366.js';
2
- import { FormField, Input } from './chunk-EXRRTKWT.js';
1
+ import { normalizeHex, parseColourInput } from './chunk-7W3LYIOC.js';
2
+ import { FormField, Input, InputAffix } from './chunk-EXRRTKWT.js';
3
3
  import { cx } from './chunk-ODEQTPFM.js';
4
4
  import './ColorField-2OIOWT3Z.css';
5
5
  import { useId, useState } from 'react';
6
6
  import { jsx, jsxs } from 'react/jsx-runtime';
7
7
 
8
8
  var LABELS = {
9
- invalid: "Enter the colour as # and six hex digits, such as #5b3df5.",
9
+ invalid: "Enter six hex digits, such as 5b3df5, or rgb(91, 61, 245).",
10
10
  missing: "Choose a colour.",
11
11
  picker: (label) => `Pick the ${label} colour`,
12
- placeholder: "#rrggbb"
12
+ placeholder: "rrggbb",
13
+ prefix: "Hex colour, after #"
13
14
  };
15
+ var digits = (colour) => colour.replace(/^#/, "");
16
+ var typedText = (value) => value.replace(/^\s*#/, "");
17
+ var SIX_DIGITS = /^[0-9a-f]{6}$/i;
14
18
  var PICKER_START = "#000000";
15
19
  function ColorField({
16
20
  label,
@@ -30,30 +34,34 @@ function ColorField({
30
34
  const autoId = useId();
31
35
  const fieldId = id ?? autoId;
32
36
  const committed = normalizeHex(value) ?? "";
33
- const [draft, setDraft] = useState(committed);
37
+ const [draft, setDraft] = useState(digits(committed));
34
38
  const [seen, setSeen] = useState(committed);
35
39
  const [left, setLeft] = useState(false);
36
40
  if (committed !== seen) {
37
41
  setSeen(committed);
38
- if ((normalizeHex(draft) ?? "") !== committed) {
39
- setDraft(committed);
42
+ if ((parseColourInput(draft) ?? "") !== committed) {
43
+ setDraft(digits(committed));
40
44
  setLeft(false);
41
45
  }
42
46
  }
43
47
  const typed = draft.trim();
44
- const reads = normalizeHex(typed);
48
+ const reads = parseColourInput(typed);
45
49
  const refusal = typed === "" ? required ? text.missing : null : reads === null ? text.invalid : null;
46
50
  const shown = error ?? (left ? refusal : null);
47
51
  const swatch = reads ?? (typed === "" ? null : committed || null);
52
+ const functional = /^rgb/i.test(typed);
53
+ const prefixId = `${fieldId}-prefix`;
48
54
  const take = (next) => {
49
- setDraft(next);
50
- const colour = normalizeHex(next);
51
- if (colour !== null) onChange(colour);
52
- else if (next.trim() === "" && !required) onChange("");
55
+ const held = typedText(next);
56
+ setDraft(held);
57
+ if (SIX_DIGITS.test(held.trim())) onChange(normalizeHex(`#${held.trim()}`));
58
+ else if (held.trim() === "" && !required) onChange("");
53
59
  };
54
60
  const settle = () => {
55
61
  setLeft(true);
56
- if (reads !== null && reads !== draft) setDraft(reads);
62
+ if (reads === null) return;
63
+ if (reads !== committed) onChange(reads);
64
+ if (digits(reads) !== draft) setDraft(digits(reads));
57
65
  };
58
66
  return /* @__PURE__ */ jsx(
59
67
  FormField,
@@ -96,13 +104,14 @@ function ColorField({
96
104
  width: "sm",
97
105
  value: draft,
98
106
  placeholder: text.placeholder,
99
- maxLength: 9,
107
+ leading: functional ? void 0 : /* @__PURE__ */ jsx(InputAffix, { text: "#", id: prefixId, sentence: text.prefix }),
108
+ maxLength: 24,
100
109
  spellCheck: false,
101
110
  autoComplete: "off",
102
111
  autoCapitalize: "off",
103
112
  disabled,
104
113
  error: Boolean(shown),
105
- "aria-describedby": field.describedBy,
114
+ "aria-describedby": [functional ? null : prefixId, field.describedBy].filter(Boolean).join(" ") || void 0,
106
115
  "aria-required": required || void 0,
107
116
  onChange: (event) => take(event.target.value),
108
117
  onBlur: settle,
@@ -0,0 +1,27 @@
1
+ import { parseHex } from '@crewlethq/tokens';
2
+
3
+ // src/utils/hexColour.ts
4
+ function normalizeHex(value) {
5
+ if (typeof value !== "string") return null;
6
+ return parseHex(value) === null ? null : value.trim().toLowerCase();
7
+ }
8
+ var SIX = /^#?([0-9a-f]{6})$/i;
9
+ var THREE = /^#?([0-9a-f])([0-9a-f])([0-9a-f])$/i;
10
+ var RGB = /^rgb\(\s*(\d{1,3})(?:\s*,\s*|\s+)(\d{1,3})(?:\s*,\s*|\s+)(\d{1,3})\s*\)$/i;
11
+ function parseColourInput(value) {
12
+ if (typeof value !== "string") return null;
13
+ const text = value.trim();
14
+ const six = SIX.exec(text);
15
+ if (six) return normalizeHex(`#${six[1]}`);
16
+ const three = THREE.exec(text);
17
+ if (three) return normalizeHex(`#${three[1]}${three[1]}${three[2]}${three[2]}${three[3]}${three[3]}`);
18
+ const rgb = RGB.exec(text);
19
+ if (rgb) {
20
+ const channels = [rgb[1], rgb[2], rgb[3]].map(Number);
21
+ if (channels.some((channel) => channel > 255)) return null;
22
+ return normalizeHex(`#${channels.map((channel) => channel.toString(16).padStart(2, "0")).join("")}`);
23
+ }
24
+ return null;
25
+ }
26
+
27
+ export { normalizeHex, parseColourInput };
@@ -1,5 +1,5 @@
1
- import { BrandScope } from './chunk-P3OIM6OC.js';
2
- import { normalizeHex } from './chunk-UZMNR366.js';
1
+ import { BrandScope } from './chunk-X7WEE3EK.js';
2
+ import { normalizeHex } from './chunk-7W3LYIOC.js';
3
3
  import { cx } from './chunk-ODEQTPFM.js';
4
4
  import './BrandSample-G5V7GKR2.css';
5
5
  import { jsx, jsxs } from 'react/jsx-runtime';
@@ -1,5 +1,5 @@
1
1
  import { cx } from './chunk-ODEQTPFM.js';
2
- import './Callout-ZAVG3P66.css';
2
+ import './Callout-G3N3IE6M.css';
3
3
  import { CircleAlertGlyph, TriangleAlertGlyph, CircleCheckGlyph, InfoGlyph } from '@crewlethq/icons/glyphs';
4
4
  import { jsxs, jsx } from 'react/jsx-runtime';
5
5
 
@@ -0,0 +1,124 @@
1
+ import { Stepper } from './chunk-LDGQIDIZ.js';
2
+ import { PageHeader } from './chunk-DKB73KZI.js';
3
+ import { Disclosure } from './chunk-OGXHZHRX.js';
4
+ import { useHeadingLevel, nextHeadingLevel, headingTag, HeadingLevelProvider } from './chunk-PQADV6P6.js';
5
+ import { useMediaMatch } from './chunk-RTPQDNW3.js';
6
+ import { cx } from './chunk-ODEQTPFM.js';
7
+ import './SetupWizard-GZK5UDKC.css';
8
+ import { useId, useRef, useEffect, createElement } from 'react';
9
+ import { breakpoint } from '@crewlethq/tokens';
10
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
11
+
12
+ var LABELS = {
13
+ progress: (position, total) => `Step ${position} of ${total}`,
14
+ asideToggle: "Preview"
15
+ };
16
+ var PHONE = `(width < ${breakpoint.phone})`;
17
+ function SetupWizard({
18
+ title,
19
+ headingLevel,
20
+ trail,
21
+ status,
22
+ actions,
23
+ steps,
24
+ current,
25
+ reached,
26
+ onSelect,
27
+ stepsLabel,
28
+ heading,
29
+ lead,
30
+ children,
31
+ aside,
32
+ asideLabel,
33
+ footer,
34
+ footerStart,
35
+ wide = false,
36
+ labels,
37
+ className,
38
+ ...rest
39
+ }) {
40
+ const text = { ...LABELS, ...labels };
41
+ const phone = useMediaMatch(PHONE);
42
+ const context = useHeadingLevel();
43
+ const titleLevel = headingLevel ?? context;
44
+ const stepLevel = nextHeadingLevel(titleLevel);
45
+ const contentLevel = nextHeadingLevel(stepLevel);
46
+ const headingId = useId();
47
+ const headingRef = useRef(null);
48
+ const shown = useRef(current);
49
+ useEffect(() => {
50
+ if (shown.current === current) return;
51
+ shown.current = current;
52
+ headingRef.current?.focus();
53
+ }, [current]);
54
+ if (aside !== void 0 && aside !== null && !asideLabel) {
55
+ throw new TypeError("SetupWizard needs an asideLabel with an aside: it names the aside\u2019s landmark");
56
+ }
57
+ const position = steps.findIndex((step2) => step2.id === current);
58
+ const step = steps[position];
59
+ const stepper = /* @__PURE__ */ jsx(
60
+ Stepper,
61
+ {
62
+ label: stepsLabel,
63
+ steps,
64
+ current,
65
+ reached,
66
+ onSelect,
67
+ tone: "brand",
68
+ orientation: phone ? "horizontal" : "vertical"
69
+ }
70
+ );
71
+ const asideBlock = aside === void 0 || aside === null ? null : /* @__PURE__ */ jsx("aside", { className: "crewlet-setup-wizard__aside", "aria-label": asideLabel, children: /* @__PURE__ */ jsx(HeadingLevelProvider, { level: contentLevel, children: aside }) });
72
+ return /* @__PURE__ */ jsx(
73
+ "div",
74
+ {
75
+ ...rest,
76
+ className: cx(
77
+ "crewlet-setup-wizard",
78
+ asideBlock === null && "crewlet-setup-wizard--no-aside",
79
+ wide && "crewlet-setup-wizard--wide",
80
+ className
81
+ ),
82
+ children: /* @__PURE__ */ jsxs("div", { className: "crewlet-setup-wizard__frame", children: [
83
+ /* @__PURE__ */ jsxs("div", { className: "crewlet-setup-wizard__head", children: [
84
+ trail ? /* @__PURE__ */ jsx("div", { className: "crewlet-setup-wizard__trail", children: trail }) : null,
85
+ /* @__PURE__ */ jsx(
86
+ PageHeader,
87
+ {
88
+ title,
89
+ headingLevel: titleLevel,
90
+ actions: status || actions ? /* @__PURE__ */ jsxs(Fragment, { children: [
91
+ status ? /* @__PURE__ */ jsx("span", { className: "crewlet-setup-wizard__status", children: status }) : null,
92
+ actions
93
+ ] }) : void 0
94
+ }
95
+ )
96
+ ] }),
97
+ /* @__PURE__ */ jsxs("nav", { className: "crewlet-setup-wizard__rail", "aria-label": stepsLabel, children: [
98
+ phone && step ? /* @__PURE__ */ jsxs("p", { className: "crewlet-setup-wizard__position", children: [
99
+ text.progress(position + 1, steps.length),
100
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: " \xB7 " }),
101
+ /* @__PURE__ */ jsx("span", { className: "crewlet-setup-wizard__position-step", children: step.label })
102
+ ] }) : null,
103
+ stepper
104
+ ] }),
105
+ /* @__PURE__ */ jsxs("section", { className: "crewlet-setup-wizard__content", "aria-labelledby": headingId, children: [
106
+ createElement(
107
+ headingTag(stepLevel),
108
+ { id: headingId, ref: headingRef, tabIndex: -1, className: "crewlet-setup-wizard__heading" },
109
+ heading
110
+ ),
111
+ lead ? /* @__PURE__ */ jsx("p", { className: "crewlet-setup-wizard__lead", children: lead }) : null,
112
+ /* @__PURE__ */ jsx("div", { className: "crewlet-setup-wizard__body", children: /* @__PURE__ */ jsx(HeadingLevelProvider, { level: contentLevel, children }) })
113
+ ] }),
114
+ asideBlock === null ? null : phone ? /* @__PURE__ */ jsx(Disclosure, { className: "crewlet-setup-wizard__preview", title: text.asideToggle, headingLevel: stepLevel, children: asideBlock }) : asideBlock,
115
+ /* @__PURE__ */ jsxs("footer", { className: "crewlet-setup-wizard__footer", children: [
116
+ footerStart ? /* @__PURE__ */ jsx("div", { className: "crewlet-setup-wizard__footer-start", children: footerStart }) : null,
117
+ /* @__PURE__ */ jsx("div", { className: "crewlet-setup-wizard__footer-end", children: footer })
118
+ ] })
119
+ ] })
120
+ }
121
+ );
122
+ }
123
+
124
+ export { SetupWizard };