@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,38 @@
1
+ import { toISO, useNow, formatRelative } from './chunk-3CZ7XAVY.js';
2
+ import { cx } from './chunk-ODEQTPFM.js';
3
+ import './EditingStatus-YU7EGM6Y.css';
4
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
5
+
6
+ var LABELS = {
7
+ editing: "Editing",
8
+ unsaved: "Unsaved changes",
9
+ saving: "Saving",
10
+ saved: "Saved"
11
+ };
12
+ function EditingStatus({ dirty, saving = false, savedAt, labels, className }) {
13
+ const text = { ...LABELS, ...labels };
14
+ const showSaved = !saving && !dirty && savedAt !== void 0 && savedAt !== null && toISO(savedAt) !== null;
15
+ const state = saving ? text.saving : dirty ? text.unsaved : showSaved ? text.saved : null;
16
+ return /* @__PURE__ */ jsxs("span", { className: cx("crewlet-editing-status", dirty && "crewlet-editing-status--dirty", className), children: [
17
+ /* @__PURE__ */ jsx("span", { className: "crewlet-editing-status__dot", "aria-hidden": "true" }),
18
+ /* @__PURE__ */ jsxs("span", { className: "crewlet-editing-status__text", children: [
19
+ /* @__PURE__ */ jsxs("span", { role: "status", "aria-live": "polite", className: "crewlet-editing-status__live", children: [
20
+ /* @__PURE__ */ jsx("span", { className: "crewlet-editing-status__label", children: text.editing }),
21
+ state ? " " : null,
22
+ state ? /* @__PURE__ */ jsx("span", { className: "crewlet-editing-status__state", children: state }) : null
23
+ ] }),
24
+ showSaved ? /* @__PURE__ */ jsxs(Fragment, { children: [
25
+ " ",
26
+ /* @__PURE__ */ jsx(SavedAgo, { at: savedAt })
27
+ ] }) : null
28
+ ] })
29
+ ] });
30
+ }
31
+ function SavedAgo({ at }) {
32
+ const now = useNow();
33
+ const ago = formatRelative(at, now);
34
+ if (ago === null) return null;
35
+ return /* @__PURE__ */ jsx("time", { className: "crewlet-editing-status__ago", dateTime: toISO(at) ?? void 0, children: ago });
36
+ }
37
+
38
+ export { EditingStatus };
@@ -1,7 +1,7 @@
1
1
  import { Card } from './chunk-INHXF2CL.js';
2
2
  import { VisuallyHidden } from './chunk-BZFWDIV6.js';
3
3
  import { cx } from './chunk-ODEQTPFM.js';
4
- import './FolderTile-FDT5Y63Z.css';
4
+ import './FolderTile-MIUEB7SO.css';
5
5
  import { useId } from 'react';
6
6
  import { FolderGlyph } from '@crewlethq/icons/glyphs';
7
7
  import { jsxs, jsx } from 'react/jsx-runtime';
@@ -1,5 +1,5 @@
1
1
  import { richEditorLabels } from './chunk-CSQTDGTS.js';
2
- import { Callout } from './chunk-SZZRIHGT.js';
2
+ import { Callout } from './chunk-BPCY7ZID.js';
3
3
  import { Skeleton } from './chunk-TEUQWOWZ.js';
4
4
  import { Button } from './chunk-OG6CL3EB.js';
5
5
  import './RichEditor-NPD2KAPS.css';
@@ -9,7 +9,7 @@ import { jsx } from 'react/jsx-runtime';
9
9
  var engine = null;
10
10
  var loading = null;
11
11
  function loadEngine() {
12
- loading ??= import('./Editor-ZYDXHGJE.js').then(
12
+ loading ??= import('./Editor-MLGK3KOG.js').then(
13
13
  (module) => {
14
14
  engine = module.Editor;
15
15
  return engine;
@@ -0,0 +1,53 @@
1
+ import { ContrastLevelTag } from './chunk-WW7TU6HE.js';
2
+ import { Popover } from './chunk-KHJIEPZV.js';
3
+ import { IconButton } from './chunk-LACA4JGC.js';
4
+ import { cx } from './chunk-ODEQTPFM.js';
5
+ import './ContrastHelp-MZCAW5WQ.css';
6
+ import { InfoGlyph } from '@crewlethq/icons/glyphs';
7
+ import { jsx, jsxs } from 'react/jsx-runtime';
8
+
9
+ var LABELS = {
10
+ trigger: "About contrast levels",
11
+ title: "Contrast levels",
12
+ intro: "Contrast compares two colours, from 1:1 to 21:1.",
13
+ aa: { term: "AA", meaning: "At least 4.5:1 for text, 3:1 for large text, icons and buttons." },
14
+ aaa: { term: "AAA", meaning: "At least 7:1 for text, 4.5:1 for large text." },
15
+ low: { term: "Low or Fails", meaning: "Below AA." }
16
+ };
17
+ function ContrastHelp({ align = "start", className, labels }) {
18
+ const text = { ...LABELS, ...labels };
19
+ return /* @__PURE__ */ jsx(
20
+ Popover,
21
+ {
22
+ role: "dialog",
23
+ label: text.title,
24
+ align,
25
+ className: cx("crewlet-contrast-help__panel", className),
26
+ trigger: (_, toggle) => /* @__PURE__ */ jsx(
27
+ IconButton,
28
+ {
29
+ size: "sm",
30
+ variant: "ghost",
31
+ label: text.trigger,
32
+ icon: /* @__PURE__ */ jsx(InfoGlyph, { size: "sm" }),
33
+ className: "crewlet-contrast-help__trigger",
34
+ onClick: toggle
35
+ }
36
+ ),
37
+ children: /* @__PURE__ */ jsxs("div", { className: "crewlet-contrast-help", children: [
38
+ /* @__PURE__ */ jsx("p", { className: "crewlet-contrast-help__title", children: text.title }),
39
+ /* @__PURE__ */ jsx("p", { className: "crewlet-contrast-help__intro", children: text.intro }),
40
+ /* @__PURE__ */ jsxs("dl", { className: "crewlet-contrast-help__levels", children: [
41
+ /* @__PURE__ */ jsx("dt", { children: /* @__PURE__ */ jsx(ContrastLevelTag, { level: "aa", children: text.aa.term }) }),
42
+ /* @__PURE__ */ jsx("dd", { children: text.aa.meaning }),
43
+ /* @__PURE__ */ jsx("dt", { children: /* @__PURE__ */ jsx(ContrastLevelTag, { level: "aaa", children: text.aaa.term }) }),
44
+ /* @__PURE__ */ jsx("dd", { children: text.aaa.meaning }),
45
+ /* @__PURE__ */ jsx("dt", { children: /* @__PURE__ */ jsx(ContrastLevelTag, { level: "low", children: text.low.term }) }),
46
+ /* @__PURE__ */ jsx("dd", { children: text.low.meaning })
47
+ ] })
48
+ ] })
49
+ }
50
+ );
51
+ }
52
+
53
+ export { ContrastHelp };
@@ -0,0 +1,129 @@
1
+ import { StatusDot } from './chunk-WIATRXEJ.js';
2
+ import { VisuallyHidden } from './chunk-BZFWDIV6.js';
3
+ import { cx } from './chunk-ODEQTPFM.js';
4
+ import './Stepper-QEJI5RGX.css';
5
+ import { CheckGlyph, TriangleAlertGlyph } from '@crewlethq/icons/glyphs';
6
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
+
8
+ function Stepper({
9
+ steps,
10
+ current,
11
+ label,
12
+ tone = "info",
13
+ pulse = false,
14
+ orientation = "horizontal",
15
+ onSelect,
16
+ reached,
17
+ doneLabel = "Done",
18
+ optionalLabel = "Optional",
19
+ attentionLabel = "Needs attention",
20
+ className,
21
+ ...rest
22
+ }) {
23
+ const seen = /* @__PURE__ */ new Set();
24
+ for (const step of steps) {
25
+ if (seen.has(step.id)) throw new RangeError(`Stepper step ids must be unique; "${step.id}" is used twice`);
26
+ seen.add(step.id);
27
+ }
28
+ const ids = () => steps.map((step) => `"${step.id}"`).join(", ");
29
+ const at = current === null ? steps.length : steps.findIndex((step) => step.id === current);
30
+ if (at < 0) {
31
+ throw new RangeError(
32
+ `Stepper current must be the id of one of its steps, or null once every step is done; "${current}" is not one of ${ids()}`
33
+ );
34
+ }
35
+ const furthest = reached === void 0 ? at : steps.findIndex((step) => step.id === reached);
36
+ if (furthest < 0) throw new RangeError(`Stepper reached must be the id of one of its steps; "${reached}" is not one of ${ids()}`);
37
+ for (const [index, step] of steps.entries()) {
38
+ if (step.status === "current" && index !== at) {
39
+ throw new RangeError(`Stepper step "${step.id}" says it is current, but current is ${current === null ? "null" : `"${current}"`}`);
40
+ }
41
+ }
42
+ if (steps.length === 0) return null;
43
+ const visitedTo = Math.max(at, furthest);
44
+ const vertical = orientation === "vertical";
45
+ const drawnOf = (step, index) => {
46
+ if (index === at) return "current";
47
+ if (step.status !== void 0 && step.status !== "current") return step.status;
48
+ return index < at ? "done" : "upcoming";
49
+ };
50
+ return (
51
+ /*
52
+ * `role="list"` although an `ol` already has one, which is why the lint
53
+ * rule that calls it redundant is silenced here rather than obeyed, as
54
+ * `Legend` and `DiffList` silence it: the stylesheet takes the markers off,
55
+ * and WebKit answers a marker-less list as a group of paragraphs, so a
56
+ * reader would no longer be told how many steps there are before hearing
57
+ * them. The role puts that back.
58
+ */
59
+ // eslint-disable-next-line jsx-a11y/no-redundant-roles
60
+ /* @__PURE__ */ jsx(
61
+ "ol",
62
+ {
63
+ ...rest,
64
+ role: "list",
65
+ className: cx(
66
+ "crewlet-stepper",
67
+ `crewlet-stepper--${tone}`,
68
+ vertical && "crewlet-stepper--vertical",
69
+ onSelect && "crewlet-stepper--selectable",
70
+ className
71
+ ),
72
+ "aria-label": label,
73
+ children: steps.map((step, index) => {
74
+ const drawn = drawnOf(step, index);
75
+ const isCurrent = drawn === "current";
76
+ const attention = drawn === "attention" || isCurrent && step.status === "attention";
77
+ const optional = drawn === "optional" || isCurrent && step.status === "optional";
78
+ const note = attention ? attentionLabel : optional ? optionalLabel : null;
79
+ const selectable = onSelect !== void 0 && index <= visitedTo;
80
+ const mark = drawn === "done" ? /* @__PURE__ */ jsx(CheckGlyph, { size: "xs", className: "crewlet-stepper__check" }) : attention ? /* @__PURE__ */ jsx(TriangleAlertGlyph, { size: "xs", className: "crewlet-stepper__warning" }) : isCurrent ? /* @__PURE__ */ jsx(StatusDot, { tone, pulse, className: "crewlet-stepper__dot" }) : vertical ? /* @__PURE__ */ jsx("span", { className: "crewlet-stepper__number", "aria-hidden": "true", children: index + 1 }) : null;
81
+ const words = /* @__PURE__ */ jsxs(Fragment, { children: [
82
+ drawn === "done" ? /* @__PURE__ */ jsxs(Fragment, { children: [
83
+ /* @__PURE__ */ jsx(VisuallyHidden, { children: doneLabel }),
84
+ " "
85
+ ] }) : null,
86
+ /* @__PURE__ */ jsx("span", { className: "crewlet-stepper__label", children: step.label }),
87
+ note !== null && !vertical ? /* @__PURE__ */ jsx(VisuallyHidden, { children: `, ${note}` }) : null
88
+ ] });
89
+ const content = vertical ? /* @__PURE__ */ jsxs(Fragment, { children: [
90
+ /* @__PURE__ */ jsx("span", { className: "crewlet-stepper__mark", children: mark }),
91
+ /* @__PURE__ */ jsxs("span", { className: "crewlet-stepper__text", children: [
92
+ /* @__PURE__ */ jsx("span", { className: "crewlet-stepper__title", children: words }),
93
+ step.description ? /* @__PURE__ */ jsx("span", { className: "crewlet-stepper__description", children: step.description }) : null,
94
+ note !== null ? /* @__PURE__ */ jsx("span", { className: "crewlet-stepper__note", children: note }) : null
95
+ ] })
96
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
97
+ mark,
98
+ words
99
+ ] });
100
+ const surface = vertical ? "crewlet-stepper__row" : "crewlet-stepper__chip";
101
+ return /* @__PURE__ */ jsx(
102
+ "li",
103
+ {
104
+ className: cx(
105
+ "crewlet-stepper__step",
106
+ `crewlet-stepper__step--${drawn}`,
107
+ attention && drawn !== "attention" && "crewlet-stepper__step--attention"
108
+ ),
109
+ "aria-current": isCurrent && !selectable ? "step" : void 0,
110
+ children: selectable ? /* @__PURE__ */ jsx(
111
+ "button",
112
+ {
113
+ type: "button",
114
+ className: cx(surface, "crewlet-stepper__target"),
115
+ "aria-current": isCurrent ? "step" : void 0,
116
+ onClick: () => onSelect(step.id),
117
+ children: content
118
+ }
119
+ ) : /* @__PURE__ */ jsx("span", { className: surface, children: content })
120
+ },
121
+ step.id
122
+ );
123
+ })
124
+ }
125
+ )
126
+ );
127
+ }
128
+
129
+ export { Stepper };
@@ -1,7 +1,7 @@
1
1
  import { Select } from './chunk-XQZ6EWOE.js';
2
2
  import { Modal } from './chunk-YCC2S7DF.js';
3
3
  import { CopyButton } from './chunk-7SHAFLEX.js';
4
- import { Callout } from './chunk-SZZRIHGT.js';
4
+ import { Callout } from './chunk-BPCY7ZID.js';
5
5
  import { PrincipalAvatar } from './chunk-CI3VPIJN.js';
6
6
  import { useHeadingLevel, headingTag } from './chunk-PQADV6P6.js';
7
7
  import { useMediaMatch } from './chunk-RTPQDNW3.js';
@@ -1,5 +1,5 @@
1
1
  import { Copyable } from './chunk-7SHAFLEX.js';
2
- import { normalizeHex } from './chunk-UZMNR366.js';
2
+ import { normalizeHex } from './chunk-7W3LYIOC.js';
3
3
  import { cx } from './chunk-ODEQTPFM.js';
4
4
  import './ColorSwatch-DNMUFHNS.css';
5
5
  import { jsxs, jsx } from 'react/jsx-runtime';
@@ -10,7 +10,7 @@ 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';
@@ -1,6 +1,6 @@
1
1
  import { ConfirmModal } from './chunk-YCC2S7DF.js';
2
2
  import { InlineCode } from './chunk-5CLW2CXT.js';
3
- import { Callout } from './chunk-SZZRIHGT.js';
3
+ import { Callout } from './chunk-BPCY7ZID.js';
4
4
  import './LinkInterstitial-ET4MSVSV.css';
5
5
  import { jsx, jsxs } from 'react/jsx-runtime';
6
6
 
@@ -7,9 +7,9 @@ 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-P2ECUQJ2.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) {
@@ -43,6 +43,7 @@ var ListInput = forwardRef(function ListInput2({
43
43
  itemError,
44
44
  fullMessage = (max) => `The list is full at ${max}. Remove one to add another.`,
45
45
  addLabel = (name) => `Add ${name}`,
46
+ addText = "Add",
46
47
  itemLabel = (name, position) => `${name} ${position}`,
47
48
  newItemLabel = (name) => `New ${name}`,
48
49
  moveUpLabel = (name, position) => `Move ${name} ${position} up`,
@@ -237,14 +238,14 @@ var ListInput = forwardRef(function ListInput2({
237
238
  )
238
239
  );
239
240
  const addControl = /* @__PURE__ */ jsx(
240
- IconButton,
241
+ Button,
241
242
  {
242
- size: "sm",
243
- variant: "soft-brand",
244
- label: addLabel(itemName),
245
- icon: /* @__PURE__ */ jsx(PlusGlyph, {}),
243
+ size: "small",
244
+ variant: "secondary",
245
+ "aria-label": addLabel(itemName),
246
246
  disabled: disabled || full || draftRefused,
247
- onClick: add
247
+ onClick: add,
248
+ children: addText
248
249
  }
249
250
  );
250
251
  return /* @__PURE__ */ jsxs(
@@ -258,7 +259,6 @@ var ListInput = forwardRef(function ListInput2({
258
259
  helperOnFocus,
259
260
  error,
260
261
  className: "crewlet-list-input",
261
- labelAction: hideLabel ? void 0 : addControl,
262
262
  children: [
263
263
  full ? (
264
264
  /*
@@ -291,7 +291,7 @@ var ListInput = forwardRef(function ListInput2({
291
291
  addBox.current = el;
292
292
  }
293
293
  }),
294
- hideLabel ? /* @__PURE__ */ jsx("span", { className: "crewlet-list-input__add-control", children: addControl }) : null
294
+ /* @__PURE__ */ jsx("span", { className: "crewlet-list-input__add-control", children: addControl })
295
295
  ] }),
296
296
  count > 0 || removed !== null ? /* @__PURE__ */ jsx("ol", { className: "crewlet-list-input__items", ...drags ? reorder.containerProps : {}, children: withRemoved(
297
297
  order.map((key) => {
@@ -1,5 +1,5 @@
1
1
  import { frameThemeMessage, readFrameHello, frameOriginMatches, negotiateBridge, FRAME_MESSAGE, portTargetOrigin, checkFrameSandbox, httpOrigin, isFrameNonce, frameFragment, readOpenLink, externalUrl, isFocusExit } from './chunk-F6V2PTN6.js';
2
- import { Callout } from './chunk-SZZRIHGT.js';
2
+ import { Callout } from './chunk-BPCY7ZID.js';
3
3
  import { Skeleton } from './chunk-TEUQWOWZ.js';
4
4
  import { Button } from './chunk-OG6CL3EB.js';
5
5
  import { cx } from './chunk-ODEQTPFM.js';
@@ -1,11 +1,11 @@
1
1
  import { Tag } from './chunk-KYIAFNU7.js';
2
- import { normalizeHex } from './chunk-UZMNR366.js';
2
+ import { normalizeHex } from './chunk-7W3LYIOC.js';
3
3
  import { VisuallyHidden } from './chunk-BZFWDIV6.js';
4
4
  import { cx } from './chunk-ODEQTPFM.js';
5
5
  import './ContrastBadge-CBZPGG3G.css';
6
6
  import { CircleAlertGlyph, TriangleAlertGlyph, CircleCheckGlyph } from '@crewlethq/icons/glyphs';
7
7
  import { WCAG_CONTRAST, parseHex, contrast } from '@crewlethq/tokens';
8
- import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
8
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
9
9
 
10
10
  function contrastLevel(ratio, scale = "body") {
11
11
  if (scale === "large") {
@@ -28,18 +28,44 @@ function formatContrastRatio(ratio) {
28
28
  return String(Number(cut.toFixed(2)));
29
29
  }
30
30
  var LABELS = {
31
- levels: { aaa: "AAA", aa: "AA", "aa-large": "AA large text", fail: "Fails" },
31
+ levels: { aaa: "AAA", aa: "AA", "aa-large": "AA large text", fail: "Fails", low: "Low" },
32
32
  unmeasured: "Not measured",
33
33
  ratio: (ratio) => `${ratio} to 1`,
34
34
  sample: "Aa"
35
35
  };
36
- var TONE = { aaa: "success", aa: "success", "aa-large": "warning", fail: "danger" };
37
- function ContrastBadge({ foreground, background, label, scale = "body", className, labels }) {
36
+ var TONE = {
37
+ aaa: "success",
38
+ aa: "success",
39
+ "aa-large": "warning",
40
+ fail: "danger",
41
+ low: "warning"
42
+ };
43
+ function ContrastLevelTag({ level, children }) {
44
+ return /* @__PURE__ */ jsx(
45
+ Tag,
46
+ {
47
+ size: "xs",
48
+ variant: TONE[level],
49
+ leadingIcon: level === "fail" ? /* @__PURE__ */ jsx(CircleAlertGlyph, { size: "xs" }) : level === "aa-large" || level === "low" ? /* @__PURE__ */ jsx(TriangleAlertGlyph, { size: "xs" }) : /* @__PURE__ */ jsx(CircleCheckGlyph, { size: "xs" }),
50
+ children
51
+ }
52
+ );
53
+ }
54
+ function ContrastBadge({
55
+ foreground,
56
+ background,
57
+ label,
58
+ scale = "body",
59
+ advisory = false,
60
+ className,
61
+ labels
62
+ }) {
38
63
  const text = { ...LABELS, ...labels, levels: { ...LABELS.levels, ...labels?.levels } };
39
64
  const ink = normalizeHex(foreground);
40
65
  const ground = normalizeHex(background);
41
66
  const ratio = ink && ground ? contrastRatio(ink, ground) : null;
42
- const level = ratio === null ? null : contrastLevel(ratio, scale);
67
+ const measured = ratio === null ? null : contrastLevel(ratio, scale);
68
+ const level = advisory && (measured === "fail" || measured === "aa-large") ? "low" : measured;
43
69
  const printed = ratio === null ? null : formatContrastRatio(ratio);
44
70
  const sample = ink && ground ? { "--crewlet-contrast-badge-ink": ink, "--crewlet-contrast-badge-ground": ground } : void 0;
45
71
  return /* @__PURE__ */ jsxs("span", { className: cx("crewlet-contrast-badge", level && `crewlet-contrast-badge--${level}`, className), children: [
@@ -50,17 +76,9 @@ function ContrastBadge({ foreground, background, label, scale = "body", classNam
50
76
  /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: `${printed}:1` }),
51
77
  /* @__PURE__ */ jsx(VisuallyHidden, { children: text.ratio(printed) })
52
78
  ] }),
53
- /* @__PURE__ */ jsx(
54
- Tag,
55
- {
56
- size: "xs",
57
- variant: TONE[level],
58
- leadingIcon: level === "fail" ? /* @__PURE__ */ jsx(CircleAlertGlyph, { size: "xs" }) : level === "aa-large" ? /* @__PURE__ */ jsx(TriangleAlertGlyph, { size: "xs" }) : /* @__PURE__ */ jsx(CircleCheckGlyph, { size: "xs" }),
59
- children: text.levels[level]
60
- }
61
- )
79
+ /* @__PURE__ */ jsx(ContrastLevelTag, { level, children: text.levels[level] })
62
80
  ] }) : /* @__PURE__ */ jsx("span", { className: "crewlet-contrast-badge__unmeasured", children: text.unmeasured })
63
81
  ] });
64
82
  }
65
83
 
66
- export { ContrastBadge, contrastLevel, contrastRatio, formatContrastRatio };
84
+ export { ContrastBadge, ContrastLevelTag, contrastLevel, contrastRatio, formatContrastRatio };
@@ -1,5 +1,5 @@
1
1
  import { safeFontFamily, fontStack } from './chunk-5SGHW42B.js';
2
- import { normalizeHex } from './chunk-UZMNR366.js';
2
+ import { normalizeHex } from './chunk-7W3LYIOC.js';
3
3
  import { cx } from './chunk-ODEQTPFM.js';
4
4
  import '@crewlethq/tokens/css/brand-scope';
5
5
  import './BrandScope-H2KZHGT7.css';
@@ -45,6 +45,7 @@ export * from '../Checkbox/index.js';
45
45
  export * from '../ChoiceButtons/index.js';
46
46
  export * from '../ChoiceList/index.js';
47
47
  export * from '../CodeBlock/index.js';
48
+ export * from '../ColorChip/index.js';
48
49
  export * from '../ColorField/index.js';
49
50
  export * from '../ColorSwatch/index.js';
50
51
  export * from '../Combobox/index.js';
@@ -55,6 +56,7 @@ export * from '../ConfirmField/index.js';
55
56
  export * from '../ConflictNote/index.js';
56
57
  export * from '../Container/index.js';
57
58
  export * from '../ContrastBadge/index.js';
59
+ export * from '../ContrastHelp/index.js';
58
60
  export * from '../Copyable/index.js';
59
61
  export * from '../Count/index.js';
60
62
  export * from '../CursorFlag/index.js';
@@ -155,6 +157,7 @@ export * from '../SegmentedMeter/index.js';
155
157
  export * from '../Select/index.js';
156
158
  export * from '../SelectionBar/index.js';
157
159
  export * from '../SettingsTable/index.js';
160
+ export * from '../SetupWizard/index.js';
158
161
  export * from '../ShareDialog/index.js';
159
162
  export * from '../SheetColumnEditor/index.js';
160
163
  export * from '../SheetGrid/index.js';