@crewlethq/ui 0.50.0 → 0.52.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 (119) hide show
  1. package/README.md +34 -0
  2. package/dist/AgentHandoffPanel/index.js +3 -3
  3. package/dist/ArrangeList/index.js +3 -3
  4. package/dist/ArtifactCard/index.js +3 -3
  5. package/dist/{ArtifactCard-SOB63NV5.css → ArtifactCard-F7IVRL3A.css} +3 -0
  6. package/dist/AvatarPicker/index.js +2 -2
  7. package/dist/BrandSample/index.js +3 -3
  8. package/dist/BrandScope/index.js +2 -2
  9. package/dist/Callout/index.js +1 -1
  10. package/dist/{Callout-ZAVG3P66.css → Callout-G3N3IE6M.css} +9 -0
  11. package/dist/Checkbox/index.js +2 -2
  12. package/dist/ChoiceButtons/ChoiceButtons.d.ts +21 -1
  13. package/dist/ChoiceButtons/index.d.ts +1 -1
  14. package/dist/ChoiceButtons/index.js +1 -1
  15. package/dist/{ChoiceButtons-FLIFXFFS.css → ChoiceButtons-HWXEF2H3.css} +60 -0
  16. package/dist/ColorChip/ColorChip.d.ts +26 -0
  17. package/dist/ColorChip/index.d.ts +3 -0
  18. package/dist/ColorChip/index.js +3 -0
  19. package/dist/ColorChip-A5XHTH3J.css +46 -0
  20. package/dist/ColorField/ColorField.d.ts +16 -8
  21. package/dist/ColorField/index.js +3 -3
  22. package/dist/ColorSwatch/index.js +2 -2
  23. package/dist/Combobox/index.js +2 -2
  24. package/dist/CommandPalette/index.js +2 -2
  25. package/dist/CommentThread/index.js +3 -3
  26. package/dist/Composer/index.js +2 -2
  27. package/dist/ConfirmField/index.js +2 -2
  28. package/dist/ContrastBadge/ContrastBadge.d.ts +13 -0
  29. package/dist/ContrastBadge/index.d.ts +2 -2
  30. package/dist/ContrastBadge/index.js +2 -2
  31. package/dist/ContrastHelp/ContrastHelp.d.ts +40 -0
  32. package/dist/ContrastHelp/index.d.ts +3 -0
  33. package/dist/ContrastHelp/index.js +12 -0
  34. package/dist/ContrastHelp-MZCAW5WQ.css +43 -0
  35. package/dist/DataGrid/index.js +3 -3
  36. package/dist/DataTable/index.js +3 -3
  37. package/dist/DataView/index.js +4 -4
  38. package/dist/DocTabsEditor/index.js +2 -2
  39. package/dist/EditingStatus/EditingStatus.d.ts +3 -5
  40. package/dist/EditingStatus/index.js +1 -1
  41. package/dist/{EditingStatus-NNA2CKIL.css → EditingStatus-YU7EGM6Y.css} +22 -7
  42. package/dist/{Editor-MLGK3KOG.js → Editor-SZFWVDAU.js} +2 -2
  43. package/dist/FolderTile/index.js +1 -1
  44. package/dist/{FolderTile-FDT5Y63Z.css → FolderTile-MIUEB7SO.css} +12 -5
  45. package/dist/FollowBanner/index.js +2 -2
  46. package/dist/InlineEditor/index.js +2 -2
  47. package/dist/Input/FormField.d.ts +7 -1
  48. package/dist/Input/index.js +1 -1
  49. package/dist/{Input-VDSV7VWJ.css → Input-GMOWHZRG.css} +9 -0
  50. package/dist/LinkInterstitial/index.js +2 -2
  51. package/dist/ListInput/ListInput.d.ts +5 -1
  52. package/dist/ListInput/index.js +2 -2
  53. package/dist/{ListInput-WUP2YITQ.css → ListInput-RLQND5QK.css} +30 -6
  54. package/dist/LogoSlot/LogoSlot.d.ts +9 -1
  55. package/dist/LogoSlot/LogoSlotGroup.d.ts +38 -0
  56. package/dist/LogoSlot/index.d.ts +3 -1
  57. package/dist/LogoSlot/index.js +3 -3
  58. package/dist/{LogoSlot-T2UFOJXU.css → LogoSlot-ETD74ELF.css} +98 -0
  59. package/dist/PrincipalPicker/index.js +3 -3
  60. package/dist/RichEditor/index.js +2 -2
  61. package/dist/SandboxedFrame/index.js +2 -2
  62. package/dist/SetupWizard/SetupWizard.d.ts +13 -3
  63. package/dist/SetupWizard/index.js +1 -1
  64. package/dist/{SetupWizard-Y5BTXZX5.css → SetupWizard-GZK5UDKC.css} +27 -1
  65. package/dist/ShareDialog/index.js +2 -2
  66. package/dist/SheetColumnEditor/index.js +3 -3
  67. package/dist/Switcher/index.js +2 -2
  68. package/dist/TimeWindowPicker/index.js +2 -2
  69. package/dist/{chunk-ZCIL5IHU.js → chunk-2GIWL7IS.js} +1 -1
  70. package/dist/{chunk-4A4QG6UC.js → chunk-34C7NYIQ.js} +1 -1
  71. package/dist/{chunk-V7GOOXPK.js → chunk-3NXWH5NC.js} +1 -1
  72. package/dist/{chunk-WQ7S7CKZ.js → chunk-5O72FSOK.js} +1 -1
  73. package/dist/{chunk-W6FOEBIL.js → chunk-5WYPSVRX.js} +24 -15
  74. package/dist/chunk-6GTTRJWJ.js +24 -0
  75. package/dist/{chunk-QGRA2RHC.js → chunk-6RMZH7P7.js} +1 -1
  76. package/dist/{chunk-R6R2UHVG.js → chunk-6VQA2LZC.js} +1 -1
  77. package/dist/{chunk-FB5CFQTG.js → chunk-7PE56HHD.js} +1 -1
  78. package/dist/chunk-7W3LYIOC.js +27 -0
  79. package/dist/{chunk-OEEYL2CM.js → chunk-AVMQMY66.js} +2 -2
  80. package/dist/{chunk-SZZRIHGT.js → chunk-BPCY7ZID.js} +1 -1
  81. package/dist/{chunk-P5JBDHWC.js → chunk-C6Z3MLSA.js} +1 -1
  82. package/dist/{chunk-PGR2PKH6.js → chunk-CQEYF3UW.js} +14 -12
  83. package/dist/{chunk-Q44X36QC.js → chunk-CUL5XV6O.js} +2 -2
  84. package/dist/chunk-DTSZUH6H.js +124 -0
  85. package/dist/chunk-EJWPYEG4.js +38 -0
  86. package/dist/{chunk-H7NMJ5AI.js → chunk-EZ43L6T7.js} +1 -1
  87. package/dist/{chunk-627KFRON.js → chunk-FNPZ3LLQ.js} +1 -1
  88. package/dist/{chunk-M4QM477B.js → chunk-FXHWOXGD.js} +1 -1
  89. package/dist/{chunk-KHZYAEGZ.js → chunk-G5SUSCWL.js} +1 -1
  90. package/dist/{chunk-VBIM6HFC.js → chunk-GPZXBJFU.js} +1 -1
  91. package/dist/{chunk-NAWUXCBC.js → chunk-GRKGLZFM.js} +2 -2
  92. package/dist/{chunk-VTSJMDGP.js → chunk-J53T2QAH.js} +2 -2
  93. package/dist/{chunk-JWNYI7UD.js → chunk-KFR75JOK.js} +2 -2
  94. package/dist/chunk-KIRQZG3G.js +53 -0
  95. package/dist/{chunk-EXRRTKWT.js → chunk-LJHH4WWB.js} +8 -4
  96. package/dist/{chunk-MIEBOO7Y.js → chunk-NMR7AJSB.js} +1 -1
  97. package/dist/{chunk-JFDIMO3A.js → chunk-PGYIDNGG.js} +1 -1
  98. package/dist/{chunk-WLSEAIVC.js → chunk-RHPBTE3F.js} +1 -1
  99. package/dist/{chunk-NCHKKYPQ.js → chunk-RQI43UJ7.js} +1 -1
  100. package/dist/{chunk-H55D66IK.js → chunk-SSHDQBHR.js} +1 -1
  101. package/dist/{chunk-GP4YWZFO.js → chunk-U3LNU4B2.js} +1 -1
  102. package/dist/{chunk-GHY63X4C.js → chunk-UJ4VVK7R.js} +1 -1
  103. package/dist/{chunk-BEAXJARF.js → chunk-UKE7LTFZ.js} +29 -12
  104. package/dist/{chunk-356JNSER.js → chunk-WQQ5T5SA.js} +1 -1
  105. package/dist/{chunk-NSSOWQCJ.js → chunk-WW7TU6HE.js} +15 -12
  106. package/dist/chunk-WXRH7NZW.js +80 -0
  107. package/dist/{chunk-P3OIM6OC.js → chunk-X7WEE3EK.js} +1 -1
  108. package/dist/generated/index.d.ts +2 -0
  109. package/dist/generated/index.js +82 -80
  110. package/dist/index.js +82 -80
  111. package/dist/styles.css +374 -28
  112. package/dist/utils/hexColour.d.ts +13 -0
  113. package/package.json +3 -3
  114. package/dist/chunk-BWOIUOO3.js +0 -62
  115. package/dist/chunk-KKHCUHWS.js +0 -107
  116. package/dist/chunk-MMOXWAUG.js +0 -42
  117. package/dist/chunk-UZMNR366.js +0 -9
  118. package/dist/{chunk-3QSKDZR5.js → chunk-EW2N4FOD.js} +1 -1
  119. /package/dist/{chunk-HNQ2EIMR.js → chunk-P432I5DQ.js} +0 -0
@@ -1,7 +1,7 @@
1
- export { RichEditor, preloadRichEditor } from '../chunk-JWNYI7UD.js';
1
+ export { RichEditor, preloadRichEditor } from '../chunk-KFR75JOK.js';
2
2
  export { RICH_EDITOR_LABELS, richEditorLabels } from '../chunk-CSQTDGTS.js';
3
3
  import '../chunk-BAKPMH3S.js';
4
- import '../chunk-SZZRIHGT.js';
4
+ import '../chunk-BPCY7ZID.js';
5
5
  import '../chunk-TEUQWOWZ.js';
6
6
  import '../chunk-OG6CL3EB.js';
7
7
  import '../chunk-BZFWDIV6.js';
@@ -1,7 +1,7 @@
1
- export { FRAME_HELLO_TIMEOUT_MS, FRAME_LOAD_GRACE_MS, SandboxedFrame, SandboxedFrameNotice, SandboxedFramePlaceholder } from '../chunk-356JNSER.js';
1
+ export { FRAME_HELLO_TIMEOUT_MS, FRAME_LOAD_GRACE_MS, SandboxedFrame, SandboxedFrameNotice, SandboxedFramePlaceholder } from '../chunk-WQQ5T5SA.js';
2
2
  import '../chunk-F6V2PTN6.js';
3
3
  import '../chunk-ZXXDZJQN.js';
4
- import '../chunk-SZZRIHGT.js';
4
+ import '../chunk-BPCY7ZID.js';
5
5
  import '../chunk-TEUQWOWZ.js';
6
6
  import '../chunk-OG6CL3EB.js';
7
7
  import '../chunk-BZFWDIV6.js';
@@ -42,8 +42,16 @@ export interface SetupWizardProps extends Omit<HTMLAttributes<HTMLDivElement>, '
42
42
  aside?: ReactNode;
43
43
  /** What the aside is, for its complementary landmark: "Preview of your draft". Required with `aside`. */
44
44
  asideLabel?: string | undefined;
45
- /** The step's actions, held at the bottom of the view: Back, Skip for now, Continue. */
45
+ /** The step's actions, at the end of the footer row and held at the bottom of the view: Back, Skip for now, Continue. */
46
46
  footer: ReactNode;
47
+ /** What stands at the start of the footer row, apart from the step's actions: Exit. */
48
+ footerStart?: ReactNode;
49
+ /**
50
+ * The content takes the whole width beside the rail rather than one 640px
51
+ * column, for a step that lays out columns of its own (a review of every
52
+ * step beside a preview). Meant for a step with no `aside`.
53
+ */
54
+ wide?: boolean | undefined;
47
55
  labels?: Partial<SetupWizardLabels> | undefined;
48
56
  }
49
57
  /**
@@ -57,7 +65,9 @@ export interface SetupWizardProps extends Omit<HTMLAttributes<HTMLDivElement>, '
57
65
  * heading, with a lead sentence and the step's fields in one column of at
58
66
  * most 640px. The aside is a complementary landmark named by `asideLabel`,
59
67
  * held in view beside the content. The footer holds the step's actions at the
60
- * bottom of the view, above the device's safe area.
68
+ * end of its row (and `footerStart`, the way out, at its start) at the bottom
69
+ * of the view, above the device's safe area. A step that lays out columns of
70
+ * its own takes the whole width beside the rail with `wide`.
61
71
  *
62
72
  * THREE SHAPES. On a wide page the rail, the content and the aside stand side
63
73
  * by side (240px, the content, 320px). Where the wizard has under 70rem of its
@@ -74,4 +84,4 @@ export interface SetupWizardProps extends Omit<HTMLAttributes<HTMLDivElement>, '
74
84
  * so a keyboard or screen reader user starts on the new step rather than on a
75
85
  * Continue button that now belongs to it; the first render takes no focus.
76
86
  */
77
- export declare function SetupWizard({ title, headingLevel, trail, status, actions, steps, current, reached, onSelect, stepsLabel, heading, lead, children, aside, asideLabel, footer, labels, className, ...rest }: SetupWizardProps): import("react").JSX.Element;
87
+ export declare function SetupWizard({ title, headingLevel, trail, status, actions, steps, current, reached, onSelect, stepsLabel, heading, lead, children, aside, asideLabel, footer, footerStart, wide, labels, className, ...rest }: SetupWizardProps): import("react").JSX.Element;
@@ -1,4 +1,4 @@
1
- export { SetupWizard } from '../chunk-KKHCUHWS.js';
1
+ export { SetupWizard } from '../chunk-DTSZUH6H.js';
2
2
  import '../chunk-LDGQIDIZ.js';
3
3
  import '../chunk-DKB73KZI.js';
4
4
  import '../chunk-WIATRXEJ.js';
@@ -120,7 +120,6 @@
120
120
  display: flex;
121
121
  flex-wrap: wrap;
122
122
  align-items: center;
123
- justify-content: flex-end;
124
123
  gap: var(--spacing-2);
125
124
  grid-area: foot;
126
125
  padding: var(--spacing-3) 0 calc(var(--spacing-3) + env(safe-area-inset-bottom, var(--spacing-0)));
@@ -128,6 +127,24 @@
128
127
  background: var(--color-surface-background);
129
128
  }
130
129
 
130
+ /* The way out at the start of the row, the step's actions at its end. */
131
+ .crewlet-setup-wizard__footer-start,
132
+ .crewlet-setup-wizard__footer-end {
133
+ display: flex;
134
+ flex-wrap: wrap;
135
+ align-items: center;
136
+ gap: var(--spacing-2);
137
+ }
138
+
139
+ .crewlet-setup-wizard__footer-end {
140
+ margin-inline-start: auto;
141
+ }
142
+
143
+ /* A WIDE STEP lays out columns of its own across the whole width beside the rail. */
144
+ .crewlet-setup-wizard--wide .crewlet-setup-wizard__content {
145
+ max-width: none;
146
+ }
147
+
131
148
  /* BESIDE THE CONTENT, from 70rem of the wizard's own width: the aside holds in view. */
132
149
  @container (min-width: 70rem) {
133
150
  .crewlet-setup-wizard__frame {
@@ -139,6 +156,15 @@
139
156
  grid-template-rows: auto 1fr auto;
140
157
  }
141
158
 
159
+ /* With no aside, nothing is held for one: the content takes its column too. */
160
+ .crewlet-setup-wizard--no-aside .crewlet-setup-wizard__frame {
161
+ grid-template-columns: 240px minmax(0, 1fr);
162
+ grid-template-areas:
163
+ 'head head'
164
+ 'rail content'
165
+ 'foot foot';
166
+ }
167
+
142
168
  .crewlet-setup-wizard__aside {
143
169
  position: sticky;
144
170
  top: var(--spacing-5);
@@ -1,11 +1,11 @@
1
- export { ARTIFACT_ROLES, SHAREABLE_ROLES, ShareDialog, roleAtLeast } from '../chunk-JFDIMO3A.js';
1
+ export { ARTIFACT_ROLES, SHAREABLE_ROLES, ShareDialog, roleAtLeast } from '../chunk-PGYIDNGG.js';
2
2
  import '../chunk-XQZ6EWOE.js';
3
3
  import '../chunk-YCC2S7DF.js';
4
4
  import '../chunk-7KHM2FZH.js';
5
5
  import '../chunk-7SHAFLEX.js';
6
6
  import '../chunk-STJ7QBC3.js';
7
7
  import '../chunk-DTIW4CHZ.js';
8
- import '../chunk-SZZRIHGT.js';
8
+ import '../chunk-BPCY7ZID.js';
9
9
  import '../chunk-CI3VPIJN.js';
10
10
  import '../chunk-5AQBPHZD.js';
11
11
  import '../chunk-PZKHBB7D.js';
@@ -1,4 +1,4 @@
1
- export { SHEET_COLUMN_EDITOR_LABELS, SheetColumnEditor, SheetColumnTypeGlyph } from '../chunk-VTSJMDGP.js';
1
+ export { SHEET_COLUMN_EDITOR_LABELS, SheetColumnEditor, SheetColumnTypeGlyph } from '../chunk-J53T2QAH.js';
2
2
  import '../chunk-XQZ6EWOE.js';
3
3
  import '../chunk-FFMCMSJB.js';
4
4
  import '../chunk-7KHM2FZH.js';
@@ -10,9 +10,9 @@ import '../chunk-6FVGSWLS.js';
10
10
  import '../chunk-ILFEWRLG.js';
11
11
  import '../chunk-WIATRXEJ.js';
12
12
  import '../chunk-EGMQURBR.js';
13
- import '../chunk-NCHKKYPQ.js';
13
+ import '../chunk-RQI43UJ7.js';
14
14
  import '../chunk-SMBKXWML.js';
15
- import '../chunk-EXRRTKWT.js';
15
+ import '../chunk-LJHH4WWB.js';
16
16
  import '../chunk-XCUUI7E7.js';
17
17
  import '../chunk-BHHIIK3M.js';
18
18
  import '../chunk-PQADV6P6.js';
@@ -1,10 +1,10 @@
1
- export { Switcher } from '../chunk-VBIM6HFC.js';
1
+ export { Switcher } from '../chunk-GPZXBJFU.js';
2
2
  import '../chunk-YCC2S7DF.js';
3
3
  import '../chunk-7KHM2FZH.js';
4
4
  import '../chunk-KHJIEPZV.js';
5
5
  import '../chunk-FYTIJM2T.js';
6
6
  import '../chunk-TEUQWOWZ.js';
7
- import '../chunk-EXRRTKWT.js';
7
+ import '../chunk-LJHH4WWB.js';
8
8
  import '../chunk-XCUUI7E7.js';
9
9
  import '../chunk-PQADV6P6.js';
10
10
  import '../chunk-RSAQOKH3.js';
@@ -1,9 +1,9 @@
1
- export { DEFAULT_TIME_WINDOW_LABELS, TIME_WINDOW_SPANS, TimeWindowPicker, describeTimeWindow, isTimeWindowSet, parseTimeWindowDuration, resolveTimeWindow, timeWindowMatchesPreset } from '../chunk-R6R2UHVG.js';
1
+ export { DEFAULT_TIME_WINDOW_LABELS, TIME_WINDOW_SPANS, TimeWindowPicker, describeTimeWindow, isTimeWindowSet, parseTimeWindowDuration, resolveTimeWindow, timeWindowMatchesPreset } from '../chunk-6VQA2LZC.js';
2
2
  import '../chunk-XQZ6EWOE.js';
3
3
  import '../chunk-7KHM2FZH.js';
4
4
  import '../chunk-GXQ3B46I.js';
5
5
  import '../chunk-KHJIEPZV.js';
6
- import '../chunk-EXRRTKWT.js';
6
+ import '../chunk-LJHH4WWB.js';
7
7
  import '../chunk-XCUUI7E7.js';
8
8
  import '../chunk-PQADV6P6.js';
9
9
  import '../chunk-RSAQOKH3.js';
@@ -1,5 +1,5 @@
1
1
  import { InlineCode } from './chunk-5CLW2CXT.js';
2
- import { FormField, Input } from './chunk-EXRRTKWT.js';
2
+ import { FormField, Input } from './chunk-LJHH4WWB.js';
3
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
4
 
5
5
  function confirmMatches(typed, phrase) {
@@ -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';
@@ -1,7 +1,7 @@
1
1
  import { Timeline } from './chunk-AUQPBL4O.js';
2
2
  import { Section } from './chunk-JQ7IFSF6.js';
3
3
  import { Disclosure } from './chunk-OGXHZHRX.js';
4
- import { Composer } from './chunk-GHY63X4C.js';
4
+ import { Composer } from './chunk-UJ4VVK7R.js';
5
5
  import { ArtifactPanel } from './chunk-NBDN5JZV.js';
6
6
  import { Button } from './chunk-OG6CL3EB.js';
7
7
  import { cx } from './chunk-ODEQTPFM.js';
@@ -2,7 +2,7 @@ import { Modal } from './chunk-YCC2S7DF.js';
2
2
  import { useClipboard } from './chunk-STJ7QBC3.js';
3
3
  import { EmptyValue } from './chunk-EUCC37WY.js';
4
4
  import { useCardHeaderSlot } from './chunk-AV2DXAEL.js';
5
- import { Checkbox } from './chunk-NCHKKYPQ.js';
5
+ import { Checkbox } from './chunk-RQI43UJ7.js';
6
6
  import { Menu } from './chunk-TMM32U7D.js';
7
7
  import { Button } from './chunk-OG6CL3EB.js';
8
8
  import { IconButton } from './chunk-LACA4JGC.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-LJHH4WWB.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,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-MMOXWAUG.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,7 +1,7 @@
1
1
  import { Select } from './chunk-XQZ6EWOE.js';
2
2
  import { today, shiftMonth, CalendarGrid, compareDays } from './chunk-GXQ3B46I.js';
3
3
  import { Popover } from './chunk-KHJIEPZV.js';
4
- import { Input } from './chunk-EXRRTKWT.js';
4
+ import { Input } from './chunk-LJHH4WWB.js';
5
5
  import { Button } from './chunk-OG6CL3EB.js';
6
6
  import { isComposing } from './chunk-H5XTJ7GJ.js';
7
7
  import { IconButton } from './chunk-LACA4JGC.js';
@@ -1,4 +1,4 @@
1
- import { Checkbox } from './chunk-NCHKKYPQ.js';
1
+ import { Checkbox } from './chunk-RQI43UJ7.js';
2
2
  import { EmptyState } from './chunk-PPUR46MK.js';
3
3
  import { useMediaMatch } from './chunk-RTPQDNW3.js';
4
4
  import { Button } from './chunk-OG6CL3EB.js';
@@ -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
 
@@ -1,5 +1,5 @@
1
1
  import { useListbox, useOptionKeys } from './chunk-7KHM2FZH.js';
2
- import { Input } from './chunk-EXRRTKWT.js';
2
+ import { Input } from './chunk-LJHH4WWB.js';
3
3
  import { HIT_AREA_CLASS } from './chunk-2YTOOH3A.js';
4
4
  import { cx } from './chunk-ODEQTPFM.js';
5
5
  import './HitArea-QUOS6ZDJ.css';
@@ -1,15 +1,15 @@
1
1
  import { useReorder } from './chunk-XJ2QEBMM.js';
2
2
  import { Kbd } from './chunk-SMBKXWML.js';
3
- import { FormField, Textarea } from './chunk-EXRRTKWT.js';
3
+ import { FormField, Textarea } from './chunk-LJHH4WWB.js';
4
4
  import { characterCountState, CharacterCount, countCharacters } from './chunk-XCUUI7E7.js';
5
5
  import { announce } from './chunk-RSAQOKH3.js';
6
6
  import { Button } from './chunk-OG6CL3EB.js';
7
7
  import { isComposing } from './chunk-H5XTJ7GJ.js';
8
8
  import { IconButton } from './chunk-LACA4JGC.js';
9
9
  import { cx } from './chunk-ODEQTPFM.js';
10
- import './ListInput-WUP2YITQ.css';
10
+ import './ListInput-RLQND5QK.css';
11
11
  import { forwardRef, useState, useRef, useImperativeHandle, useLayoutEffect, useId } from 'react';
12
- import { PlusGlyph, GripVerticalGlyph, ArrowUpGlyph, ArrowDownGlyph, XGlyph } from '@crewlethq/icons/glyphs';
12
+ import { GripVerticalGlyph, ArrowUpGlyph, ArrowDownGlyph, XGlyph } from '@crewlethq/icons/glyphs';
13
13
  import { jsx, jsxs } from 'react/jsx-runtime';
14
14
 
15
15
  function withDraft(value, draft) {
@@ -41,8 +41,10 @@ var ListInput = forwardRef(function ListInput2({
41
41
  maxLength,
42
42
  undoRemove = false,
43
43
  itemError,
44
- fullMessage = (max) => `The list is full at ${max}. Remove one to add another.`,
44
+ fullMessage = () => "That's the most. Remove one to add another.",
45
+ tallyLabel = (count, max) => `${count} of ${max}`,
45
46
  addLabel = (name) => `Add ${name}`,
47
+ addText = "Add",
46
48
  itemLabel = (name, position) => `${name} ${position}`,
47
49
  newItemLabel = (name) => `New ${name}`,
48
50
  moveUpLabel = (name, position) => `Move ${name} ${position} up`,
@@ -237,14 +239,14 @@ var ListInput = forwardRef(function ListInput2({
237
239
  )
238
240
  );
239
241
  const addControl = /* @__PURE__ */ jsx(
240
- IconButton,
242
+ Button,
241
243
  {
242
- size: "sm",
243
- variant: "soft-brand",
244
- label: addLabel(itemName),
245
- icon: /* @__PURE__ */ jsx(PlusGlyph, {}),
244
+ size: "medium",
245
+ variant: "secondary",
246
+ "aria-label": addLabel(itemName),
246
247
  disabled: disabled || full || draftRefused,
247
- onClick: add
248
+ onClick: add,
249
+ children: addText
248
250
  }
249
251
  );
250
252
  return /* @__PURE__ */ jsxs(
@@ -257,8 +259,8 @@ var ListInput = forwardRef(function ListInput2({
257
259
  helper,
258
260
  helperOnFocus,
259
261
  error,
262
+ tally: maxItems === void 0 ? void 0 : tallyLabel(count, maxItems),
260
263
  className: "crewlet-list-input",
261
- labelAction: hideLabel ? void 0 : addControl,
262
264
  children: [
263
265
  full ? (
264
266
  /*
@@ -291,7 +293,7 @@ var ListInput = forwardRef(function ListInput2({
291
293
  addBox.current = el;
292
294
  }
293
295
  }),
294
- hideLabel ? /* @__PURE__ */ jsx("span", { className: "crewlet-list-input__add-control", children: addControl }) : null
296
+ /* @__PURE__ */ jsx("span", { className: "crewlet-list-input__add-control", children: addControl })
295
297
  ] }),
296
298
  count > 0 || removed !== null ? /* @__PURE__ */ jsx("ol", { className: "crewlet-list-input__items", ...drags ? reorder.containerProps : {}, children: withRemoved(
297
299
  order.map((key) => {
@@ -4,13 +4,13 @@ import { RelativeTime } from './chunk-3CZ7XAVY.js';
4
4
  import { AvatarStack } from './chunk-5AQBPHZD.js';
5
5
  import { ArtifactKindGround } from './chunk-RV6XB5UV.js';
6
6
  import { Card } from './chunk-INHXF2CL.js';
7
- import { Checkbox } from './chunk-NCHKKYPQ.js';
7
+ import { Checkbox } from './chunk-RQI43UJ7.js';
8
8
  import { ArtifactAccessGlyph } from './chunk-BGLKLXL3.js';
9
9
  import { ArtifactKindGlyph } from './chunk-RSKW25Y5.js';
10
10
  import { VisuallyHidden } from './chunk-BZFWDIV6.js';
11
11
  import { cx } from './chunk-ODEQTPFM.js';
12
12
  import './ArtifactKinds-O3CALPVX.css';
13
- import './ArtifactCard-SOB63NV5.css';
13
+ import './ArtifactCard-F7IVRL3A.css';
14
14
  import { useId } from 'react';
15
15
  import { PinGlyph } from '@crewlethq/icons/glyphs';
16
16
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
@@ -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 };