@crewlethq/ui 0.84.2 → 0.85.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 (77) hide show
  1. package/README.md +36 -2
  2. package/dist/Accordion/index.js +1 -1
  3. package/dist/AgentHandoffPanel/index.js +2 -2
  4. package/dist/ArtifactBar/index.js +1 -1
  5. package/dist/AttentionList/AttentionList.d.ts +82 -0
  6. package/dist/AttentionList/index.d.ts +3 -0
  7. package/dist/AttentionList/index.js +9 -0
  8. package/dist/AttentionList-LVX7KRET.css +212 -0
  9. package/dist/AvatarPicker/index.js +2 -2
  10. package/dist/ChangeList/index.js +2 -2
  11. package/dist/ChoiceCards/ChoiceCards.d.ts +35 -6
  12. package/dist/ChoiceCards/index.d.ts +1 -1
  13. package/dist/ChoiceCards/index.js +1 -1
  14. package/dist/{ChoiceCards-TVMBO3HZ.css → ChoiceCards-KHJW2FKO.css} +49 -0
  15. package/dist/ChoiceList/ChoiceList.d.ts +2 -2
  16. package/dist/ChoiceList/index.js +1 -1
  17. package/dist/{ChoiceList-JN4PPNFW.css → ChoiceList-ZQMZTEZX.css} +33 -17
  18. package/dist/CodeBlock/index.js +2 -2
  19. package/dist/ColorSwatch/index.js +2 -2
  20. package/dist/ContrastBadge/index.js +2 -2
  21. package/dist/ContrastHelp/index.js +3 -3
  22. package/dist/Copyable/index.js +1 -1
  23. package/dist/{Copyable-IS3MHMPL.css → Copyable-P5AMRHFX.css} +18 -4
  24. package/dist/DataGrid/index.js +1 -1
  25. package/dist/{DataGrid-Q26F2V5Q.css → DataGrid-SAHEL4SN.css} +57 -0
  26. package/dist/DeepWorkCard/index.js +3 -3
  27. package/dist/Disclosure/Disclosure.d.ts +10 -1
  28. package/dist/Disclosure/index.js +1 -1
  29. package/dist/{Disclosure-D727FN5X.css → Disclosure-RJSKKO7Z.css} +20 -0
  30. package/dist/LogoSlot/index.js +3 -3
  31. package/dist/MarkdownEditor/index.js +1 -1
  32. package/dist/MemberPicker/MemberPicker.d.ts +86 -0
  33. package/dist/MemberPicker/index.d.ts +3 -0
  34. package/dist/MemberPicker/index.js +11 -0
  35. package/dist/MemberPicker-ZD35VEK6.css +162 -0
  36. package/dist/MergeConflicts/index.js +1 -1
  37. package/dist/ProposalCard/index.js +3 -3
  38. package/dist/RunChip/index.js +3 -3
  39. package/dist/SegmentedControl/index.js +1 -1
  40. package/dist/{SegmentedControl-B7XCUOML.css → SegmentedControl-7GY2KM44.css} +11 -0
  41. package/dist/SetupWizard/index.js +3 -3
  42. package/dist/ShareDialog/index.js +2 -2
  43. package/dist/{StepList-A4YVU4JI.css → StepList-OAJ45IBX.css} +12 -1
  44. package/dist/Stepper/StepList.d.ts +7 -4
  45. package/dist/Stepper/index.js +1 -1
  46. package/dist/ThemeSwitcher/index.js +1 -1
  47. package/dist/TimeRangePicker/index.js +1 -1
  48. package/dist/VersionCompare/index.js +1 -1
  49. package/dist/{chunk-CV2LU2T2.js → chunk-35CKF77R.js} +2 -2
  50. package/dist/{chunk-K6RWEQ6P.js → chunk-3BVNNQZY.js} +2 -2
  51. package/dist/{chunk-AOJ6ZA77.js → chunk-3MFRTZH6.js} +1 -1
  52. package/dist/{chunk-QSWQJX27.js → chunk-4ME4J3YY.js} +1 -1
  53. package/dist/{chunk-6FBPFG3C.js → chunk-6EZX26BD.js} +1 -1
  54. package/dist/chunk-AELKT34H.js +121 -0
  55. package/dist/{chunk-X7VZQKIW.js → chunk-AQ7ZV3CH.js} +1 -1
  56. package/dist/{chunk-XNC3M4IN.js → chunk-E2QPZGLG.js} +1 -1
  57. package/dist/{chunk-T5GBTXNC.js → chunk-ETNQYT5O.js} +1 -1
  58. package/dist/{chunk-36WK24AI.js → chunk-EVM6GYZ2.js} +1 -1
  59. package/dist/{chunk-B7NX425Z.js → chunk-JDMJVVVQ.js} +12 -4
  60. package/dist/chunk-KA4RBKQV.js +148 -0
  61. package/dist/{chunk-ABRWL5FJ.js → chunk-L2QRKIL4.js} +3 -2
  62. package/dist/{chunk-P7HMY3BQ.js → chunk-M33DABTW.js} +2 -2
  63. package/dist/{chunk-LVJGN5II.js → chunk-NAHA62WD.js} +3 -1
  64. package/dist/{chunk-6SFDL4QH.js → chunk-P3LNA6G4.js} +1 -1
  65. package/dist/{chunk-WMO722J2.js → chunk-TBQFZV4H.js} +1 -1
  66. package/dist/{chunk-RJWO2PC5.js → chunk-TMML7BHT.js} +14 -5
  67. package/dist/{chunk-DD7RBNT4.js → chunk-XH55NRHO.js} +1 -1
  68. package/dist/{chunk-6RW2MUTY.js → chunk-XU7RQNT6.js} +1 -1
  69. package/dist/{chunk-AQNP3KQU.js → chunk-Y7PPKQFQ.js} +1 -1
  70. package/dist/generated/index.d.ts +2 -0
  71. package/dist/generated/index.js +72 -70
  72. package/dist/index.js +72 -70
  73. package/dist/styles.css +587 -29
  74. package/package.json +3 -3
  75. package/dist/{chunk-22CU7V4J.js → chunk-K2HEYQJL.js} +1 -1
  76. package/dist/{chunk-REEZQCML.js → chunk-VIX3GZCD.js} +0 -0
  77. package/dist/{chunk-2ZSCHQOA.js → chunk-WMSXPF7T.js} +1 -1
@@ -136,6 +136,17 @@
136
136
  background: var(--color-brand-accent);
137
137
  }
138
138
 
139
+ /* A COUNT IN A CHIP IS A FIGURE IN THE CHIP'S OWN INK, as on a FilterChip and
140
+ a lens chip: no pill of its own, since a box inside a box beside its word
141
+ says nothing more. On the chosen chip the inset pill's tertiary figure lay
142
+ on the accent fill at 1.4:1; inheriting, it is the label's on-accent ink. */
143
+ .crewlet-segmented--chips .crewlet-count {
144
+ min-width: 0;
145
+ padding: 0;
146
+ background: none;
147
+ color: inherit;
148
+ }
149
+
139
150
  /* What completes the last choice sits in the row, at the chips' own height
140
151
  and in their face: a field at its own control step stood taller than every
141
152
  chip beside it. */
@@ -1,9 +1,9 @@
1
- export { SetupWizard } from '../chunk-K6RWEQ6P.js';
2
- import '../chunk-RJWO2PC5.js';
1
+ export { SetupWizard } from '../chunk-3BVNNQZY.js';
3
2
  import '../chunk-FPDIHEM4.js';
3
+ import '../chunk-TMML7BHT.js';
4
4
  import '../chunk-YJQXESOJ.js';
5
5
  import '../chunk-CYQBDZ6M.js';
6
- import '../chunk-LVJGN5II.js';
6
+ import '../chunk-NAHA62WD.js';
7
7
  import '../chunk-XSPCITPN.js';
8
8
  import '../chunk-ULYHDP7U.js';
9
9
  import '../chunk-D2GT3CR4.js';
@@ -1,7 +1,7 @@
1
- export { ARTIFACT_ROLES, SHAREABLE_ROLES, ShareDialog, roleAtLeast } from '../chunk-AQNP3KQU.js';
1
+ export { ARTIFACT_ROLES, SHAREABLE_ROLES, ShareDialog, roleAtLeast } from '../chunk-Y7PPKQFQ.js';
2
2
  import '../chunk-3IWZVEXA.js';
3
3
  import '../chunk-ZXXZESCD.js';
4
- import '../chunk-T5GBTXNC.js';
4
+ import '../chunk-ETNQYT5O.js';
5
5
  import '../chunk-STJ7QBC3.js';
6
6
  import '../chunk-DTIW4CHZ.js';
7
7
  import '../chunk-YGRTX67J.js';
@@ -35,7 +35,8 @@
35
35
  }
36
36
 
37
37
  .crewlet-step-mark--refused,
38
- .crewlet-step-mark--stopped {
38
+ .crewlet-step-mark--stopped,
39
+ .crewlet-step-mark--pending {
39
40
  color: var(--color-text-tertiary);
40
41
  }
41
42
 
@@ -88,6 +89,16 @@
88
89
  overflow-wrap: anywhere;
89
90
  }
90
91
 
92
+ /*
93
+ * A STEP THAT HAS NOT STARTED IS QUIET THROUGH: its words take the tertiary
94
+ * ink its mark and its detail already have, so the whole step reads as one
95
+ * thing still to come rather than as a label in full ink beside a dimmed
96
+ * mark.
97
+ */
98
+ .crewlet-step-list__step--pending .crewlet-step-list__label {
99
+ color: var(--color-text-tertiary);
100
+ }
101
+
91
102
  /*
92
103
  * WHAT THE STEP ASKED FOR, in the mono face. Each piece between separators is
93
104
  * one inline block, so a line breaks only between pieces (at a space, or
@@ -5,10 +5,12 @@ import { type HTMLAttributes, type ReactNode } from 'react';
5
5
  * request finish, fail or are refused on their own: `running` while it works,
6
6
  * `done`, `failed` (the system could not do it), `refused` (the person's own
7
7
  * access does not allow it), `stopped` (the person stopped the request before
8
- * it finished) and `waiting` (it waits on the person's approval).
8
+ * it finished), `waiting` (it waits on the person's approval) and `pending`
9
+ * (it has not started: the request has not reached it yet, or ended before
10
+ * it, as the steps after a failed check that the check never got to).
9
11
  */
10
- export type StepState = 'running' | 'done' | 'failed' | 'refused' | 'stopped' | 'waiting';
11
- export declare const STEP_STATES: readonly ["running", "done", "failed", "refused", "stopped", "waiting"];
12
+ export type StepState = 'running' | 'done' | 'failed' | 'refused' | 'stopped' | 'waiting' | 'pending';
13
+ export declare const STEP_STATES: readonly ["running", "done", "failed", "refused", "stopped", "waiting", "pending"];
12
14
  /** The words each state is said with, after the step's own words: "Read token spend by agent, Done". */
13
15
  export type StepStateLabels = Record<StepState, string>;
14
16
  export declare const STEP_STATE_LABELS: StepStateLabels;
@@ -20,7 +22,8 @@ export interface StepStateMarkProps {
20
22
  * A state's mark in its 16px box: the 14px glyph, or the spinner at the same
21
23
  * size while it runs, so nothing moves when the ring becomes a check. Running
22
24
  * takes the secondary ink, done the success ink, failed the danger ink,
23
- * waiting the warning ink, and refused and stopped the tertiary ink. One
25
+ * waiting the warning ink, and refused, stopped and pending the tertiary
26
+ * ink; pending is a dashed circle, the outline of a step still to come. One
24
27
  * mark for a request's steps and for the request's own state (`RunChip`),
25
28
  * which is what makes them one column.
26
29
  */
@@ -1,4 +1,4 @@
1
- export { STEP_STATES, STEP_STATE_LABELS, StepList, StepStateMark, Stepper, stepDetailPieces } from '../chunk-RJWO2PC5.js';
1
+ export { STEP_STATES, STEP_STATE_LABELS, StepList, StepStateMark, Stepper, stepDetailPieces } from '../chunk-TMML7BHT.js';
2
2
  import '../chunk-CYQBDZ6M.js';
3
3
  import '../chunk-XSPCITPN.js';
4
4
  import '../chunk-UT6CW3C7.js';
@@ -1,7 +1,7 @@
1
1
  export { DensitySwitcher, ThemeSwitcher } from '../chunk-5V6GW6HK.js';
2
2
  export { applyStoredPreferences, resolveTheme, useDensityPreference, useSystemTheme, useThemePreference } from '../chunk-Z24ZUSTX.js';
3
3
  export { DENSITY_PREFERENCES, PALETTE_ID, THEME_PREFERENCES, applyDensity, applyPalette, applyTheme, isDensityPreference, isPaletteId, isThemePreference } from '../chunk-ZXXDZJQN.js';
4
- import '../chunk-36WK24AI.js';
4
+ import '../chunk-EVM6GYZ2.js';
5
5
  import '../chunk-AZYE7NR4.js';
6
6
  import '../chunk-MVKUE4FI.js';
7
7
  import '../chunk-EGMQURBR.js';
@@ -1,7 +1,7 @@
1
1
  export { TIME_RANGE_CUSTOM, TIME_RANGE_PICKER_LABELS, TimeRangePicker, timeRangeFieldKey, timeRangeProblem } from '../chunk-ZJVLGYE3.js';
2
2
  import '../chunk-ZXXZESCD.js';
3
3
  import '../chunk-BPCY7ZID.js';
4
- import '../chunk-36WK24AI.js';
4
+ import '../chunk-EVM6GYZ2.js';
5
5
  import '../chunk-AZYE7NR4.js';
6
6
  import '../chunk-MVKUE4FI.js';
7
7
  import '../chunk-EGMQURBR.js';
@@ -1,6 +1,6 @@
1
1
  export { VERSION_COMPARE_LABELS, VERSION_COMPARE_LENSES, VersionCompare } from '../chunk-RBQRTGXX.js';
2
2
  import '../chunk-AOFVXE6V.js';
3
- import '../chunk-36WK24AI.js';
3
+ import '../chunk-EVM6GYZ2.js';
4
4
  import '../chunk-AZYE7NR4.js';
5
5
  import '../chunk-MVKUE4FI.js';
6
6
  import '../chunk-EGMQURBR.js';
@@ -1,8 +1,8 @@
1
- import { StepList } from './chunk-RJWO2PC5.js';
1
+ import { StepList } from './chunk-TMML7BHT.js';
2
2
  import { ReceiptStrip } from './chunk-ZWCK4N4L.js';
3
3
  import { Meter } from './chunk-RQFRRPV6.js';
4
4
  import { StatusCard } from './chunk-FLW5U7YS.js';
5
- import { Disclosure } from './chunk-LVJGN5II.js';
5
+ import { Disclosure } from './chunk-NAHA62WD.js';
6
6
  import { Spinner } from './chunk-XSPCITPN.js';
7
7
  import { cx } from './chunk-ODEQTPFM.js';
8
8
  import './DeepWorkCard-CMRRNISU.css';
@@ -1,7 +1,7 @@
1
- import { Stepper } from './chunk-RJWO2PC5.js';
2
1
  import { PageHeader } from './chunk-FPDIHEM4.js';
2
+ import { Stepper } from './chunk-TMML7BHT.js';
3
3
  import { useMediaMatch } from './chunk-YJQXESOJ.js';
4
- import { Disclosure } from './chunk-LVJGN5II.js';
4
+ import { Disclosure } from './chunk-NAHA62WD.js';
5
5
  import { useHeadingLevel, nextHeadingLevel, headingTag, HeadingLevelProvider } from './chunk-PQADV6P6.js';
6
6
  import { cx } from './chunk-ODEQTPFM.js';
7
7
  import './SetupWizard-Y2PFPBCZ.css';
@@ -1,6 +1,6 @@
1
1
  import { DiffList } from './chunk-LR4IWUWQ.js';
2
2
  import { Tag } from './chunk-LBGKLYBY.js';
3
- import { Disclosure } from './chunk-LVJGN5II.js';
3
+ import { Disclosure } from './chunk-NAHA62WD.js';
4
4
  import { VisuallyHidden } from './chunk-UT6CW3C7.js';
5
5
  import { cx } from './chunk-ODEQTPFM.js';
6
6
  import './ChangeList-ITJMTVDF.css';
@@ -1,4 +1,4 @@
1
- import { CopyButton } from './chunk-T5GBTXNC.js';
1
+ import { CopyButton } from './chunk-ETNQYT5O.js';
2
2
  import { cx } from './chunk-ODEQTPFM.js';
3
3
  import './CodeBlock-T47UA5GM.css';
4
4
  import { forwardRef, useRef, useState, useLayoutEffect } from 'react';
@@ -1,4 +1,4 @@
1
- import { Copyable } from './chunk-T5GBTXNC.js';
1
+ import { Copyable } from './chunk-ETNQYT5O.js';
2
2
  import { normalizeHex } from './chunk-7W3LYIOC.js';
3
3
  import { cx } from './chunk-ODEQTPFM.js';
4
4
  import './ColorSwatch-V4DA4TK5.css';
@@ -0,0 +1,121 @@
1
+ import { Card } from './chunk-U2IQNDDR.js';
2
+ import { Button } from './chunk-DGXZ635L.js';
3
+ import { useHeadingLevel, headingTag } from './chunk-PQADV6P6.js';
4
+ import { VisuallyHidden } from './chunk-UT6CW3C7.js';
5
+ import { cx } from './chunk-ODEQTPFM.js';
6
+ import './AttentionList-LVX7KRET.css';
7
+ import { useId, useState } from 'react';
8
+ import { BellGlyph, ChevronDownGlyph, CircleAlertGlyph, TriangleAlertGlyph, InfoGlyph } from '@crewlethq/icons/glyphs';
9
+ import { jsxs, jsx } from 'react/jsx-runtime';
10
+
11
+ var plural = (n, one, many) => `${n} ${n === 1 ? one : many}`;
12
+ var ATTENTION_LIST_LABELS = {
13
+ title: "Needs attention",
14
+ tones: { danger: "Problem", warning: "Warning", info: "Note" },
15
+ details: "Details",
16
+ more: (hidden) => `Show ${hidden} more`,
17
+ less: "Show fewer",
18
+ summary: (c) => [
19
+ c.danger ? plural(c.danger, "problem", "problems") : "",
20
+ c.warning ? plural(c.warning, "warning", "warnings") : "",
21
+ c.info ? plural(c.info, "note", "notes") : ""
22
+ ].filter(Boolean).join(", ")
23
+ };
24
+ var ORDER = { danger: 0, warning: 1, info: 2 };
25
+ var TONES = ["danger", "warning", "info"];
26
+ function ToneGlyph({ tone, size }) {
27
+ if (tone === "danger") return /* @__PURE__ */ jsx(CircleAlertGlyph, { size });
28
+ if (tone === "warning") return /* @__PURE__ */ jsx(TriangleAlertGlyph, { size });
29
+ return /* @__PURE__ */ jsx(InfoGlyph, { size });
30
+ }
31
+ function AttentionList({ items, collapseAfter = 3, labels: overrides, headingLevel, className }) {
32
+ const contextLevel = useHeadingLevel();
33
+ const Heading = headingTag(headingLevel ?? contextLevel);
34
+ const words = {
35
+ ...ATTENTION_LIST_LABELS,
36
+ ...overrides,
37
+ tones: { ...ATTENTION_LIST_LABELS.tones, ...overrides?.tones }
38
+ };
39
+ const id = useId();
40
+ const [expanded, setExpanded] = useState(false);
41
+ const [opened, setOpened] = useState(/* @__PURE__ */ new Set());
42
+ if (items.length === 0) return null;
43
+ const ordered = [...items].sort((a, b) => ORDER[a.tone] - ORDER[b.tone]);
44
+ const counts = { danger: 0, warning: 0, info: 0 };
45
+ for (const i of items) counts[i.tone] += 1;
46
+ const folds = ordered.length > collapseAfter + 1;
47
+ const shown = folds && !expanded ? ordered.slice(0, collapseAfter) : ordered;
48
+ const media = ordered.some((item) => item.media != null);
49
+ return /* @__PURE__ */ jsxs(Card, { as: "section", padding: "none", className: cx("crewlet-attention-list", className), children: [
50
+ /* @__PURE__ */ jsx(
51
+ Card.Header,
52
+ {
53
+ icon: /* @__PURE__ */ jsx(BellGlyph, { size: "sm" }),
54
+ actions: /* @__PURE__ */ jsxs("span", { className: "crewlet-attention-list__counts", children: [
55
+ TONES.filter((tone) => counts[tone] > 0).map((tone) => /* @__PURE__ */ jsxs("span", { className: cx("crewlet-attention-list__count", `is-${tone}`), "aria-hidden": true, children: [
56
+ /* @__PURE__ */ jsx(ToneGlyph, { tone, size: "xs" }),
57
+ counts[tone]
58
+ ] }, tone)),
59
+ /* @__PURE__ */ jsx(VisuallyHidden, { children: words.summary(counts) })
60
+ ] }),
61
+ children: /* @__PURE__ */ jsx(Card.Title, { as: Heading, children: words.title })
62
+ }
63
+ ),
64
+ /* @__PURE__ */ jsxs(Card.Body, { padding: "none", children: [
65
+ /* @__PURE__ */ jsx("ul", { className: cx("crewlet-attention-list__rows", media && "crewlet-attention-list__rows--media"), children: shown.map((item, index) => {
66
+ const open = opened.has(item.key);
67
+ const panel = `${id}-${index}`;
68
+ return /* @__PURE__ */ jsxs("li", { className: "crewlet-attention-list__item", children: [
69
+ /* @__PURE__ */ jsxs("div", { className: "crewlet-attention-list__row", children: [
70
+ /* @__PURE__ */ jsx("span", { className: cx("crewlet-attention-list__glyph", `is-${item.tone}`), "aria-hidden": true, children: /* @__PURE__ */ jsx(ToneGlyph, { tone: item.tone, size: "sm" }) }),
71
+ item.media != null ? /* @__PURE__ */ jsx("span", { className: "crewlet-attention-list__media", "aria-hidden": true, children: item.media }) : null,
72
+ /* @__PURE__ */ jsxs("span", { className: "crewlet-attention-list__text", children: [
73
+ /* @__PURE__ */ jsxs("span", { className: "crewlet-attention-list__line", children: [
74
+ /* @__PURE__ */ jsx(VisuallyHidden, { children: `${words.tones[item.tone]}: ` }),
75
+ item.title
76
+ ] }),
77
+ item.meta ? /* @__PURE__ */ jsx("span", { className: "crewlet-attention-list__meta", children: item.meta }) : null
78
+ ] }),
79
+ /* @__PURE__ */ jsxs("span", { className: "crewlet-attention-list__end", children: [
80
+ item.details ? /* @__PURE__ */ jsx(
81
+ Button,
82
+ {
83
+ variant: "ghost",
84
+ size: "small",
85
+ flush: true,
86
+ className: "crewlet-attention-list__details",
87
+ "aria-expanded": open,
88
+ "aria-controls": open ? panel : void 0,
89
+ trailingIcon: /* @__PURE__ */ jsx(ChevronDownGlyph, { size: "xs" }),
90
+ onClick: () => setOpened((was) => {
91
+ const next = new Set(was);
92
+ if (next.has(item.key)) next.delete(item.key);
93
+ else next.add(item.key);
94
+ return next;
95
+ }),
96
+ children: words.details
97
+ }
98
+ ) : null,
99
+ item.action != null ? /* @__PURE__ */ jsx("span", { className: "crewlet-attention-list__action", children: item.action }) : null
100
+ ] })
101
+ ] }),
102
+ item.details && open ? /* @__PURE__ */ jsx("div", { id: panel, className: "crewlet-attention-list__body", children: item.details }) : null
103
+ ] }, item.key);
104
+ }) }),
105
+ folds ? /* @__PURE__ */ jsx("div", { className: "crewlet-attention-list__foot", children: /* @__PURE__ */ jsx(
106
+ Button,
107
+ {
108
+ variant: "ghost",
109
+ size: "small",
110
+ flush: true,
111
+ className: "crewlet-attention-list__more",
112
+ "aria-expanded": expanded,
113
+ onClick: () => setExpanded((e) => !e),
114
+ children: expanded ? words.less : words.more(ordered.length - collapseAfter)
115
+ }
116
+ ) }) : null
117
+ ] })
118
+ ] });
119
+ }
120
+
121
+ export { ATTENTION_LIST_LABELS, AttentionList };
@@ -1,4 +1,4 @@
1
- import { StepStateMark } from './chunk-RJWO2PC5.js';
1
+ import { StepStateMark } from './chunk-TMML7BHT.js';
2
2
  import { DisclosureAnatomy } from './chunk-ULYHDP7U.js';
3
3
  import { VisuallyHidden } from './chunk-UT6CW3C7.js';
4
4
  import { cx } from './chunk-ODEQTPFM.js';
@@ -1,7 +1,7 @@
1
1
  import { DisclosureAnatomy } from './chunk-ULYHDP7U.js';
2
2
  import { useHeadingLevel } from './chunk-PQADV6P6.js';
3
3
  import { cx } from './chunk-ODEQTPFM.js';
4
- import './Disclosure-D727FN5X.css';
4
+ import './Disclosure-RJSKKO7Z.css';
5
5
  import './Accordion-V7YNDK7Y.css';
6
6
  import { createContext, useState, useCallback, useMemo, useContext, useId } from 'react';
7
7
  import { jsx, jsxs } from 'react/jsx-runtime';
@@ -3,7 +3,7 @@ import { Button } from './chunk-DGXZ635L.js';
3
3
  import { IconButton } from './chunk-UAUP6XGK.js';
4
4
  import { VisuallyHidden } from './chunk-UT6CW3C7.js';
5
5
  import { cx } from './chunk-ODEQTPFM.js';
6
- import './Copyable-IS3MHMPL.css';
6
+ import './Copyable-P5AMRHFX.css';
7
7
  import { useCallback } from 'react';
8
8
  import { CheckGlyph, CircleAlertGlyph, CopyGlyph } from '@crewlethq/icons/glyphs';
9
9
  import { jsxs, jsx } from 'react/jsx-runtime';
@@ -1,3 +1,3 @@
1
1
  import './HitArea-QUOS6ZDJ.css';
2
2
  import './Tabs-M2ELSU3V.css';
3
- import './SegmentedControl-B7XCUOML.css';
3
+ import './SegmentedControl-7GY2KM44.css';
@@ -1,7 +1,7 @@
1
1
  import { StatusDot } from './chunk-CYQBDZ6M.js';
2
2
  import { cx } from './chunk-ODEQTPFM.js';
3
- import './ChoiceCards-TVMBO3HZ.css';
4
- import { useId } from 'react';
3
+ import './ChoiceCards-KHJW2FKO.css';
4
+ import { useId, Fragment } from 'react';
5
5
  import { jsx, jsxs } from 'react/jsx-runtime';
6
6
 
7
7
  function ChoiceCards({
@@ -19,6 +19,8 @@ function ChoiceCards({
19
19
  const inFact = (o) => o.disabledReasonAt !== void 0 && o.disabledReasonAt >= 0 && o.disabledReasonAt < (o.facts?.length ?? 0);
20
20
  const reasons = options.some((o) => o.disabled && o.disabledReason && !inFact(o)) ? 1 : 0;
21
21
  const rows = { "--crewlet-choice-cards-rows": 1 + (described ? 1 : 0) + facts + reasons };
22
+ const chosen = options.find((o) => o.value === value && o.detail != null && !o.disabled) ?? null;
23
+ const detailId = `${name}-detail`;
22
24
  return /* @__PURE__ */ jsx(
23
25
  "div",
24
26
  {
@@ -43,7 +45,7 @@ function ChoiceCards({
43
45
  ...(option.facts ?? []).map((_, at) => at === reasonAt ? reason : part(`fact-${at}`)),
44
46
  reasonAt < 0 ? reason : null
45
47
  ].filter(Boolean).join(" ");
46
- return /* @__PURE__ */ jsxs(
48
+ const card = /* @__PURE__ */ jsxs(
47
49
  "label",
48
50
  {
49
51
  htmlFor: id,
@@ -60,6 +62,7 @@ function ChoiceCards({
60
62
  disabled: option.disabled,
61
63
  "aria-labelledby": labelledBy,
62
64
  "aria-describedby": describedBy || void 0,
65
+ "aria-controls": option === chosen ? detailId : void 0,
63
66
  onChange: () => onChange(option.value),
64
67
  className: "crewlet-choice-cards__radio"
65
68
  }
@@ -67,7 +70,7 @@ function ChoiceCards({
67
70
  /* @__PURE__ */ jsxs("span", { className: "crewlet-choice-cards__title", children: [
68
71
  option.media != null ? /* @__PURE__ */ jsx("span", { className: "crewlet-choice-cards__media", "aria-hidden": true, children: option.media }) : null,
69
72
  /* @__PURE__ */ jsx("span", { id: part("label"), className: "crewlet-choice-cards__label", children: option.label }),
70
- option.tag ? /* @__PURE__ */ jsx("span", { id: part("tag"), className: "crewlet-choice-cards__tag", children: option.tag }) : null
73
+ option.tag ? /* @__PURE__ */ jsx("span", { id: part("tag"), className: cx("crewlet-choice-cards__tag", option.tagTone && `is-${option.tagTone}`), children: option.tag }) : null
71
74
  ] }),
72
75
  option.description ? /* @__PURE__ */ jsx("span", { id: part("description"), className: "crewlet-choice-cards__description", children: option.description }) : described ? /* @__PURE__ */ jsx("span", { className: "crewlet-choice-cards__description", "aria-hidden": true }) : null,
73
76
  option.facts && option.facts.length > 0 ? /* @__PURE__ */ jsx("span", { className: "crewlet-choice-cards__facts", children: option.facts.map((fact, at) => /* @__PURE__ */ jsxs(
@@ -88,6 +91,11 @@ function ChoiceCards({
88
91
  },
89
92
  option.value
90
93
  );
94
+ if (option !== chosen) return card;
95
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
96
+ card,
97
+ /* @__PURE__ */ jsx("div", { id: detailId, role: "group", "aria-labelledby": part("label"), className: "crewlet-choice-cards__detail", children: option.detail })
98
+ ] }, option.value);
91
99
  })
92
100
  }
93
101
  );
@@ -0,0 +1,148 @@
1
+ import { Checkbox } from './chunk-YQ7Q52XU.js';
2
+ import { IconButton } from './chunk-UAUP6XGK.js';
3
+ import { cx } from './chunk-ODEQTPFM.js';
4
+ import './MemberPicker-ZD35VEK6.css';
5
+ import { useId, useState } from 'react';
6
+ import { ChevronRightGlyph } from '@crewlethq/icons/glyphs';
7
+ import { jsxs, jsx } from 'react/jsx-runtime';
8
+
9
+ var MEMBER_PICKER_LABELS = {
10
+ later: "Includes agents who join later",
11
+ through: (group) => `Through ${group}`,
12
+ leftOut: "Left out",
13
+ summary: (chosen, total) => `${chosen} of ${total} ${total === 1 ? "agent" : "agents"}`,
14
+ count: (n) => `${n} ${n === 1 ? "agent" : "agents"}`,
15
+ expand: (group) => `Show the agents in ${group}`
16
+ };
17
+ var without = (list, drop) => list.filter((k) => !drop.includes(k));
18
+ var plus = (list, add) => [.../* @__PURE__ */ new Set([...list, ...add])];
19
+ function chosenMembers(groups, ungrouped, value) {
20
+ const out = /* @__PURE__ */ new Set();
21
+ for (const g of groups) {
22
+ for (const m of g.members) {
23
+ if (value.groups.includes(g.key) && !value.except.includes(m.key) || value.members.includes(m.key)) out.add(m.key);
24
+ }
25
+ }
26
+ for (const m of ungrouped) if (value.members.includes(m.key)) out.add(m.key);
27
+ return out;
28
+ }
29
+ function MemberPicker({
30
+ label,
31
+ groups,
32
+ ungrouped = [],
33
+ value,
34
+ onChange,
35
+ defaultOpen = [],
36
+ labels: overrides,
37
+ className
38
+ }) {
39
+ const words = { ...MEMBER_PICKER_LABELS, ...overrides };
40
+ const id = useId();
41
+ const [open, setOpen] = useState(
42
+ () => /* @__PURE__ */ new Set([
43
+ ...defaultOpen,
44
+ ...groups.filter((g) => g.members.some((m) => value.except.includes(m.key) || value.members.includes(m.key))).map((g) => g.key)
45
+ ])
46
+ );
47
+ const total = (/* @__PURE__ */ new Set([...groups.flatMap((g) => g.members.map((m) => m.key)), ...ungrouped.map((m) => m.key)])).size;
48
+ const chosen = chosenMembers(groups, ungrouped, value);
49
+ const toggleGroup = (g, on) => {
50
+ const keys = g.members.map((m) => m.key);
51
+ onChange({
52
+ groups: on ? plus(value.groups, [g.key]) : without(value.groups, [g.key]),
53
+ // THE GROUP'S OWN OVERRIDES GO EITHER WAY: chosen whole, nobody is left
54
+ // out or chosen twice; unchosen, nobody stays chosen behind its back.
55
+ members: without(value.members, keys),
56
+ except: without(value.except, keys)
57
+ });
58
+ };
59
+ const toggleMember = (m, on) => {
60
+ const reached = groups.some((g) => value.groups.includes(g.key) && g.members.some((x) => x.key === m.key));
61
+ onChange({
62
+ ...value,
63
+ members: on && !reached ? plus(value.members, [m.key]) : without(value.members, [m.key]),
64
+ except: !on && reached ? plus(value.except, [m.key]) : without(value.except, [m.key])
65
+ });
66
+ };
67
+ const memberRow = (m, group, at) => {
68
+ const viaGroup = !!group && value.groups.includes(group.key);
69
+ const leftOut = viaGroup && value.except.includes(m.key);
70
+ const mark = viaGroup ? leftOut ? words.leftOut : words.through(group.label) : null;
71
+ const detailId = m.detail ? `${id}-${at}-detail` : null;
72
+ const markId = mark ? `${id}-${at}-mark` : null;
73
+ const describedBy = cx(detailId, markId);
74
+ const boxId = `${id}-${at}-box`;
75
+ return /* @__PURE__ */ jsxs("li", { className: cx("crewlet-member-picker__member", leftOut && "is-left-out"), children: [
76
+ /* @__PURE__ */ jsx(
77
+ Checkbox,
78
+ {
79
+ id: boxId,
80
+ label: m.name,
81
+ hideLabel: true,
82
+ size: "sm",
83
+ checked: chosen.has(m.key),
84
+ onCheckedChange: (on) => toggleMember(m, on),
85
+ ...describedBy ? { "aria-describedby": describedBy } : {}
86
+ }
87
+ ),
88
+ m.avatar != null ? /* @__PURE__ */ jsx("span", { className: "crewlet-member-picker__avatar", "aria-hidden": true, children: m.avatar }) : null,
89
+ /* @__PURE__ */ jsxs("label", { htmlFor: boxId, className: "crewlet-member-picker__text", children: [
90
+ /* @__PURE__ */ jsx("span", { className: "crewlet-member-picker__name", children: m.name }),
91
+ detailId ? /* @__PURE__ */ jsx("span", { id: detailId, className: "crewlet-member-picker__detail", children: m.detail }) : null
92
+ ] }),
93
+ markId ? /* @__PURE__ */ jsx("span", { id: markId, className: cx("crewlet-member-picker__mark", leftOut && "is-left-out"), children: mark }) : null
94
+ ] }, m.key);
95
+ };
96
+ return /* @__PURE__ */ jsxs("div", { className: cx("crewlet-member-picker", className), role: "group", "aria-label": label, children: [
97
+ /* @__PURE__ */ jsx("p", { className: "crewlet-member-picker__summary", "aria-live": "polite", children: words.summary(chosen.size, total) }),
98
+ /* @__PURE__ */ jsxs("ul", { className: "crewlet-member-picker__list", children: [
99
+ groups.map((g, gi) => {
100
+ const whole = value.groups.includes(g.key);
101
+ const reached = g.members.filter((m) => chosen.has(m.key)).length;
102
+ const all = g.members.length > 0 && reached === g.members.length;
103
+ const ticked = whole && (all || g.members.length === 0);
104
+ const mixed = !ticked && reached + (whole ? 1 : 0) > 0;
105
+ const isOpen = open.has(g.key);
106
+ const panel = `${id}-g${gi}`;
107
+ return /* @__PURE__ */ jsxs("li", { className: cx("crewlet-member-picker__group", isOpen && "is-open"), children: [
108
+ /* @__PURE__ */ jsxs("div", { className: "crewlet-member-picker__group-row", children: [
109
+ /* @__PURE__ */ jsx(
110
+ IconButton,
111
+ {
112
+ size: "sm",
113
+ variant: "ghost",
114
+ className: "crewlet-member-picker__toggle",
115
+ label: words.expand(g.label),
116
+ icon: /* @__PURE__ */ jsx(ChevronRightGlyph, { size: "sm" }),
117
+ "aria-expanded": isOpen,
118
+ "aria-controls": isOpen ? panel : void 0,
119
+ onClick: () => setOpen((was) => {
120
+ const next = new Set(was);
121
+ if (next.has(g.key)) next.delete(g.key);
122
+ else next.add(g.key);
123
+ return next;
124
+ })
125
+ }
126
+ ),
127
+ /* @__PURE__ */ jsx(
128
+ Checkbox,
129
+ {
130
+ label: g.label,
131
+ size: "sm",
132
+ checked: ticked,
133
+ indeterminate: mixed,
134
+ description: whole ? words.later : void 0,
135
+ onCheckedChange: () => toggleGroup(g, !ticked)
136
+ }
137
+ ),
138
+ /* @__PURE__ */ jsx("span", { className: "crewlet-member-picker__count", children: words.count(g.members.length) })
139
+ ] }),
140
+ isOpen ? /* @__PURE__ */ jsx("ul", { id: panel, className: "crewlet-member-picker__members", children: g.members.map((m, mi) => memberRow(m, g, `g${gi}-m${mi}`)) }) : null
141
+ ] }, g.key);
142
+ }),
143
+ ungrouped.length > 0 ? /* @__PURE__ */ jsx("li", { className: "crewlet-member-picker__group", children: /* @__PURE__ */ jsx("ul", { className: "crewlet-member-picker__members is-ungrouped", children: ungrouped.map((m, mi) => memberRow(m, null, `u-m${mi}`)) }) }) : null
144
+ ] })
145
+ ] });
146
+ }
147
+
148
+ export { MEMBER_PICKER_LABELS, MemberPicker, chosenMembers };
@@ -4,7 +4,7 @@ import { EmptyState } from './chunk-PPUR46MK.js';
4
4
  import { Button } from './chunk-DGXZ635L.js';
5
5
  import { VisuallyHidden } from './chunk-UT6CW3C7.js';
6
6
  import { cx } from './chunk-ODEQTPFM.js';
7
- import './DataGrid-Q26F2V5Q.css';
7
+ import './DataGrid-SAHEL4SN.css';
8
8
  import { useId, useRef, useState, useMemo, useCallback, useLayoutEffect, useImperativeHandle, useSyncExternalStore, useEffect } from 'react';
9
9
  import { breakpoint } from '@crewlethq/tokens';
10
10
  import { ArrowDownGlyph, ArrowUpGlyph, ArrowUpDownGlyph } from '@crewlethq/icons/glyphs';
@@ -414,7 +414,8 @@ function DataGrid({
414
414
  "crewlet-data-grid__cell",
415
415
  alignOf(column) !== "left" && `crewlet-data-grid__cell--${alignOf(column)}`,
416
416
  column.icon && "crewlet-data-grid__cell--icon",
417
- column.shrink && "crewlet-data-grid__cell--shrink"
417
+ column.shrink && "crewlet-data-grid__cell--shrink",
418
+ column.action && "crewlet-data-grid__cell--action"
418
419
  ),
419
420
  "data-lead": column.phoneLead || void 0,
420
421
  "data-phone-omit": column.phoneOmit || void 0,
@@ -1,8 +1,8 @@
1
1
  import { RefusalStrip, ReceiptStrip } from './chunk-ZWCK4N4L.js';
2
- import { ChangeList } from './chunk-AOJ6ZA77.js';
2
+ import { ChangeList } from './chunk-3MFRTZH6.js';
3
3
  import { StatusCard } from './chunk-FLW5U7YS.js';
4
4
  import { Checkbox } from './chunk-YQ7Q52XU.js';
5
- import { Disclosure } from './chunk-LVJGN5II.js';
5
+ import { Disclosure } from './chunk-NAHA62WD.js';
6
6
  import { Button } from './chunk-DGXZ635L.js';
7
7
  import { Spinner } from './chunk-XSPCITPN.js';
8
8
  import { cx } from './chunk-ODEQTPFM.js';
@@ -1,7 +1,7 @@
1
1
  import { DisclosureAnatomy } from './chunk-ULYHDP7U.js';
2
2
  import { useHeadingLevel } from './chunk-PQADV6P6.js';
3
3
  import { cx } from './chunk-ODEQTPFM.js';
4
- import './Disclosure-D727FN5X.css';
4
+ import './Disclosure-RJSKKO7Z.css';
5
5
  import { useState, useId, useCallback } from 'react';
6
6
  import { jsxs, jsx } from 'react/jsx-runtime';
7
7
 
@@ -17,6 +17,7 @@ function Disclosure({
17
17
  lazy = false,
18
18
  variant = "default",
19
19
  size = "default",
20
+ flush = false,
20
21
  headingLevel,
21
22
  className,
22
23
  children,
@@ -39,6 +40,7 @@ function Disclosure({
39
40
  "crewlet-disclosure",
40
41
  `crewlet-disclosure--${variant}`,
41
42
  size === "compact" && "crewlet-disclosure--compact",
43
+ flush && "crewlet-disclosure--flush",
42
44
  className
43
45
  ),
44
46
  "data-state": open ? "open" : "closed",
@@ -1,5 +1,5 @@
1
1
  import { FileDrop, FilePickButton } from './chunk-KQWJWTED.js';
2
- import { contrastRatio } from './chunk-2ZSCHQOA.js';
2
+ import { contrastRatio } from './chunk-WMSXPF7T.js';
3
3
  import { normalizeHex } from './chunk-7W3LYIOC.js';
4
4
  import { Button } from './chunk-DGXZ635L.js';
5
5
  import { VisuallyHidden } from './chunk-UT6CW3C7.js';
@@ -1,4 +1,4 @@
1
- import { ContrastLevelTag } from './chunk-2ZSCHQOA.js';
1
+ import { ContrastLevelTag } from './chunk-WMSXPF7T.js';
2
2
  import { Popover } from './chunk-EC6EUIAD.js';
3
3
  import { IconButton } from './chunk-UAUP6XGK.js';
4
4
  import { cx } from './chunk-ODEQTPFM.js';