@crewlethq/ui 0.87.0 → 0.89.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 (40) hide show
  1. package/dist/ActivityLine/ActivityLine.d.ts +8 -1
  2. package/dist/ActivityLine/index.js +2 -2
  3. package/dist/ArrangeList/index.js +2 -2
  4. package/dist/ArtifactCard/index.js +3 -3
  5. package/dist/AvatarPicker/index.js +2 -2
  6. package/dist/List/List.d.ts +14 -1
  7. package/dist/List/index.js +1 -1
  8. package/dist/{List-JOELBLTU.css → List-ZZF6ZHRT.css} +32 -0
  9. package/dist/MentionMenu/index.js +2 -2
  10. package/dist/PersonRow/PersonRow.d.ts +7 -0
  11. package/dist/PersonRow/index.js +1 -1
  12. package/dist/{PersonRow-V5GTPNVP.css → PersonRow-ZR6US2QJ.css} +25 -0
  13. package/dist/RoomRow/RoomRow.d.ts +41 -0
  14. package/dist/RoomRow/index.d.ts +4 -0
  15. package/dist/RoomRow/index.js +4 -0
  16. package/dist/RoomRow-3OTEY6GK.css +55 -0
  17. package/dist/SetupWizard/index.js +2 -2
  18. package/dist/Switch/Switch.d.ts +14 -0
  19. package/dist/Switch/index.js +2 -1
  20. package/dist/{Switch-AUYLQLTN.css → Switch-XJE34BZH.css} +15 -0
  21. package/dist/ThinkingIndicator/ThinkingIndicator.d.ts +19 -3
  22. package/dist/ThinkingIndicator/index.js +1 -1
  23. package/dist/{ThinkingIndicator-S7ZL2C77.css → ThinkingIndicator-G72NYYAM.css} +27 -0
  24. package/dist/{chunk-3XDT5ZWL.js → chunk-3N3XK2G5.js} +27 -9
  25. package/dist/{chunk-ED4A6Q24.js → chunk-3OIVYHAA.js} +5 -4
  26. package/dist/{chunk-EALRMP7N.js → chunk-6TD2PCZB.js} +8 -3
  27. package/dist/{chunk-XTJHMP3W.js → chunk-75EGNXPZ.js} +1 -1
  28. package/dist/{chunk-PS5ZYIA6.js → chunk-A7UOYLK3.js} +12 -3
  29. package/dist/{chunk-3BRXEMYT.js → chunk-G7SAFRSJ.js} +2 -2
  30. package/dist/{chunk-C4256UXE.js → chunk-V7N5XWZ6.js} +11 -3
  31. package/dist/chunk-Z34W5TM6.js +40 -0
  32. package/dist/generated/index.d.ts +1 -0
  33. package/dist/generated/index.js +40 -39
  34. package/dist/index.js +40 -39
  35. package/dist/styles.css +161 -4
  36. package/package.json +3 -3
  37. package/dist/{chunk-K2HEYQJL.js → chunk-22CU7V4J.js} +1 -1
  38. package/dist/{chunk-CWCQCOIG.js → chunk-7IWZN5Q2.js} +1 -1
  39. package/dist/{chunk-DWZCMMRX.js → chunk-VNACAMDK.js} +0 -0
  40. package/dist/{chunk-3BVNNQZY.js → chunk-WRZPO4YL.js} +1 -1
@@ -14,6 +14,13 @@ export interface ActivityLineProps extends Omit<HTMLAttributes<HTMLDivElement>,
14
14
  * `working` by default.
15
15
  */
16
16
  workingLabel?: string | undefined;
17
+ /**
18
+ * The agent has not started on it yet: the request waits behind something
19
+ * it is already doing, and `working` says so ("Product Manager is queued
20
+ * behind its current task"). Drawn as a queued `ThinkingIndicator`, still,
21
+ * until the work starts.
22
+ */
23
+ queued?: boolean | undefined;
17
24
  }
18
25
  /**
19
26
  * Who is typing and which agent is working, in one quiet line under a
@@ -24,4 +31,4 @@ export interface ActivityLineProps extends Omit<HTMLAttributes<HTMLDivElement>,
24
31
  * `ThinkingIndicator`, which announces its label once and keeps its changing
25
32
  * steps to the eye.
26
33
  */
27
- export declare function ActivityLine({ typing, working, workingLabel, className, ...rest }: ActivityLineProps): import("react").JSX.Element;
34
+ export declare function ActivityLine({ typing, working, workingLabel, queued, className, ...rest }: ActivityLineProps): import("react").JSX.Element;
@@ -1,4 +1,4 @@
1
- export { ActivityLine } from '../chunk-C4256UXE.js';
2
- import '../chunk-ED4A6Q24.js';
1
+ export { ActivityLine } from '../chunk-V7N5XWZ6.js';
2
+ import '../chunk-3OIVYHAA.js';
3
3
  import '../chunk-UT6CW3C7.js';
4
4
  import '../chunk-ODEQTPFM.js';
@@ -1,5 +1,5 @@
1
- export { ArrangeList, DEFAULT_ARRANGE_LABELS } from '../chunk-XTJHMP3W.js';
2
- import '../chunk-3XDT5ZWL.js';
1
+ export { ArrangeList, DEFAULT_ARRANGE_LABELS } from '../chunk-75EGNXPZ.js';
2
+ import '../chunk-3N3XK2G5.js';
3
3
  import '../chunk-BVML4UVB.js';
4
4
  import '../chunk-YQ7Q52XU.js';
5
5
  import '../chunk-YJQXESOJ.js';
@@ -1,12 +1,12 @@
1
- export { ArtifactCard, ArtifactCardSkeleton, ArtifactPreviewGlyph } from '../chunk-CWCQCOIG.js';
1
+ export { ArtifactCard, ArtifactCardSkeleton, ArtifactPreviewGlyph } from '../chunk-7IWZN5Q2.js';
2
2
  import '../chunk-I4IUX3JF.js';
3
3
  import '../chunk-HF5L56YQ.js';
4
4
  import '../chunk-EJNJMHQG.js';
5
5
  import '../chunk-RE3FBGQQ.js';
6
- import '../chunk-YTLWOHOY.js';
7
- import '../chunk-XZY6S3UC.js';
8
6
  import '../chunk-U2IQNDDR.js';
9
7
  import '../chunk-AV2DXAEL.js';
8
+ import '../chunk-YTLWOHOY.js';
9
+ import '../chunk-XZY6S3UC.js';
10
10
  import '../chunk-J5T5TDM2.js';
11
11
  import '../chunk-YQ7Q52XU.js';
12
12
  import '../chunk-DOY3KC6I.js';
@@ -1,8 +1,8 @@
1
- export { AvatarPicker } from '../chunk-K2HEYQJL.js';
1
+ export { AvatarPicker } from '../chunk-22CU7V4J.js';
2
2
  import '../chunk-SHH7UD5U.js';
3
3
  import '../chunk-EC6EUIAD.js';
4
- import '../chunk-LNQSNXGJ.js';
5
4
  import '../chunk-AYKXMIOR.js';
5
+ import '../chunk-LNQSNXGJ.js';
6
6
  import '../chunk-XZY6S3UC.js';
7
7
  import '../chunk-AZYE7NR4.js';
8
8
  import '../chunk-MVKUE4FI.js';
@@ -72,6 +72,19 @@ export interface ListItemProps extends Omit<LiHTMLAttributes<HTMLLIElement>, 'on
72
72
  leading?: ReactNode;
73
73
  /** Drawn after it: a time, a count, a chevron. */
74
74
  trailing?: ReactNode;
75
+ /**
76
+ * A control of its own at the row's end (Join, a switch), drawn BESIDE the
77
+ * row's link or button rather than inside it: a control inside another is
78
+ * one a keyboard cannot reach and a screen reader announces as part of the
79
+ * row's name. Not part of the row's hover or its name.
80
+ */
81
+ action?: ReactNode;
82
+ /**
83
+ * A line under the row, across its whole width: what pressing `action` came
84
+ * to when that needs saying (a refusal, a next step). Not part of the row's
85
+ * name either.
86
+ */
87
+ note?: ReactNode;
75
88
  tone?: ListItemTone | undefined;
76
89
  /** Read in place of the danger rail, so colour is never the only signal. */
77
90
  dangerLabel?: string | undefined;
@@ -93,4 +106,4 @@ export interface ListItemProps extends Omit<LiHTMLAttributes<HTMLLIElement>, 'on
93
106
  * it, which is what stops a keyboard reader seeing a ring around a row they
94
107
  * cannot activate.
95
108
  */
96
- export declare function ListItem({ href, onClick, leading, trailing, tone, dangerLabel, selected, asChild, className, children, ...rest }: ListItemProps): import("react").JSX.Element;
109
+ export declare function ListItem({ href, onClick, leading, trailing, action, note, tone, dangerLabel, selected, asChild, className, children, ...rest }: ListItemProps): import("react").JSX.Element;
@@ -1,3 +1,3 @@
1
- export { List, ListItem } from '../chunk-PS5ZYIA6.js';
1
+ export { List, ListItem } from '../chunk-A7UOYLK3.js';
2
2
  import '../chunk-UT6CW3C7.js';
3
3
  import '../chunk-ODEQTPFM.js';
@@ -210,6 +210,38 @@
210
210
  max-inline-size: var(--size-measure-wide);
211
211
  }
212
212
 
213
+ /*
214
+ * A ROW WITH A CONTROL OF ITS OWN (`action`) or a line under it (`note`): the
215
+ * row's link or button takes the room and the action stands beside it, at the
216
+ * row's end and on its middle, so the two are two controls and the action is
217
+ * never inside the row's hover or its name. The note wraps under both, at the
218
+ * row's own inset.
219
+ */
220
+ .crewlet-list__item--split {
221
+ display: flex;
222
+ flex-wrap: wrap;
223
+ align-items: center;
224
+ column-gap: var(--spacing-2);
225
+ }
226
+
227
+ .crewlet-list__item--split > .crewlet-list__row {
228
+ flex: 1 1 0;
229
+ }
230
+
231
+ .crewlet-list__action {
232
+ display: inline-flex;
233
+ flex: none;
234
+ align-items: center;
235
+ gap: var(--spacing-2);
236
+ padding-inline-end: var(--spacing-3);
237
+ }
238
+
239
+ .crewlet-list__note {
240
+ flex-basis: 100%;
241
+ min-width: 0;
242
+ padding: 0 var(--spacing-3) var(--spacing-2);
243
+ }
244
+
213
245
  /* ---- States ------------------------------------------------------------ */
214
246
 
215
247
  /*
@@ -1,3 +1,3 @@
1
- export { MENTION_MENU_LABELS, MentionMenu, mentionQuery } from '../chunk-3BRXEMYT.js';
2
- import '../chunk-EALRMP7N.js';
1
+ export { MENTION_MENU_LABELS, MentionMenu, mentionQuery } from '../chunk-G7SAFRSJ.js';
2
+ import '../chunk-6TD2PCZB.js';
3
3
  import '../chunk-ODEQTPFM.js';
@@ -36,6 +36,13 @@ export interface PersonRowButtonProps extends PersonRowLook, Omit<ButtonHTMLAttr
36
36
  selected?: boolean | undefined;
37
37
  /** Pressing the row. */
38
38
  onSelect?: (() => void) | undefined;
39
+ /**
40
+ * A control of the row's own at its end (a `Switch` that sets how this
41
+ * member follows a room), drawn BESIDE the row's button rather than inside
42
+ * it: a control inside a button cannot be reached by Tab, and is read as
43
+ * part of the row's name. Pressing the row still does what `onSelect` says.
44
+ */
45
+ action?: ReactNode;
39
46
  }
40
47
  export interface PersonRowOptionProps extends PersonRowLook, Omit<LiHTMLAttributes<HTMLLIElement>, 'children'> {
41
48
  /**
@@ -1,2 +1,2 @@
1
- export { PersonRow } from '../chunk-EALRMP7N.js';
1
+ export { PersonRow } from '../chunk-6TD2PCZB.js';
2
2
  import '../chunk-ODEQTPFM.js';
@@ -147,6 +147,31 @@
147
147
  color: var(--color-text-on-accent);
148
148
  }
149
149
 
150
+ /*
151
+ * A ROW WITH A CONTROL OF ITS OWN (`action`): the row's button takes the room
152
+ * and the control stands after it on the row's middle, outside the button's
153
+ * hover, so the two read as two controls.
154
+ */
155
+ .crewlet-person-row-group {
156
+ display: flex;
157
+ align-items: center;
158
+ gap: var(--spacing-1);
159
+ min-width: 0;
160
+ }
161
+
162
+ .crewlet-person-row-group > .crewlet-person-row {
163
+ flex: 1 1 0;
164
+ min-width: 0;
165
+ }
166
+
167
+ .crewlet-person-row__action {
168
+ display: inline-flex;
169
+ flex: none;
170
+ align-items: center;
171
+ gap: var(--spacing-2);
172
+ padding-inline-end: var(--spacing-2);
173
+ }
174
+
150
175
  /*
151
176
  * FORCED COLORS repaints every background to Canvas, which took the chosen
152
177
  * tint and the arrows' row with it. An outline is the one mark the mode
@@ -0,0 +1,41 @@
1
+ import { type ReactNode } from 'react';
2
+ import { type ListItemProps } from '../List/index.js';
3
+ export interface RoomRowProps extends Omit<ListItemProps, 'children' | 'href' | 'onClick' | 'asChild' | 'leading' | 'trailing' | 'tone' | 'dangerLabel'> {
4
+ /** The room's own address: the whole row opens it. */
5
+ href: string;
6
+ /**
7
+ * The room's kind, as its glyph at the small step (a hash, a lock, a team's
8
+ * mark). Decorative: the name says which room it is, and a kind that matters
9
+ * to the reader is said in `tags` or `facts`.
10
+ */
11
+ mark: ReactNode;
12
+ /** The room's name. A long one wraps rather than running under the action. */
13
+ name: ReactNode;
14
+ /** Small labels after the name: `Tag`s such as "Joined" or "Archived". */
15
+ tags?: ReactNode;
16
+ /** What the room is about now. One line, cut with an ellipsis. */
17
+ topic?: ReactNode;
18
+ /**
19
+ * The quiet facts under it, in order: how many are in it, when it last
20
+ * spoke, a sentence about who may join. Joined with a middle dot that a
21
+ * screen reader skips; an empty or missing fact is left out.
22
+ */
23
+ facts?: readonly ReactNode[] | undefined;
24
+ }
25
+ /**
26
+ * A room as a directory of rooms lists it: its kind's mark and its name with
27
+ * its state, what it is about, a line of facts, and one control at the row's
28
+ * end (Join, Open) beside the row's own link.
29
+ *
30
+ * A LIST ROW, NOT A CARD. It is `List.Item` with its words arranged for a
31
+ * room, so a list of rooms is drawn by `List` (`variant="divided"`) and takes
32
+ * the list's hairlines, hover and focus ring, and a row is the same height as
33
+ * every other list in the product.
34
+ *
35
+ * TWO CONTROLS, NEVER ONE INSIDE THE OTHER. The whole row is a link to the
36
+ * room; the action stands beside it (`List.Item`'s `action`), so Tab reaches
37
+ * each and the link's name is the room's words without "Join" in it. What
38
+ * pressing the action came to, when it needs saying, is the row's `note`,
39
+ * under both.
40
+ */
41
+ export declare function RoomRow({ href, mark, name, tags, topic, facts, className, ...rest }: RoomRowProps): import("react").JSX.Element;
@@ -0,0 +1,4 @@
1
+ import '../ChatMessage/ChatScale.css';
2
+ import './RoomRow.css';
3
+ export { RoomRow } from './RoomRow.js';
4
+ export type { RoomRowProps } from './RoomRow.js';
@@ -0,0 +1,4 @@
1
+ export { RoomRow } from '../chunk-Z34W5TM6.js';
2
+ import '../chunk-A7UOYLK3.js';
3
+ import '../chunk-UT6CW3C7.js';
4
+ import '../chunk-ODEQTPFM.js';
@@ -0,0 +1,55 @@
1
+ /*
2
+ * RoomRow: a room as a directory of rooms lists it, on List.Item.
3
+ *
4
+ * The row's words stack: the name line, the topic, the facts. They take the
5
+ * conversation's own scale (ChatScale.css), so a room's name in a directory
6
+ * is the size it is in the room's header and its messages.
7
+ */
8
+
9
+ .crewlet-room-row > .crewlet-list__row > .crewlet-list__content {
10
+ display: flex;
11
+ flex: 1;
12
+ flex-direction: column;
13
+ gap: var(--spacing-1);
14
+ }
15
+
16
+ /* A room's name wraps rather than pushing past the row: one unbroken name (a
17
+ slug with no hyphen) otherwise runs over its own tag and into the action. */
18
+ .crewlet-room-row__name {
19
+ display: inline-flex;
20
+ flex-wrap: wrap;
21
+ align-items: center;
22
+ gap: var(--spacing-2);
23
+ min-height: var(--spacing-5);
24
+ min-width: 0;
25
+ overflow-wrap: anywhere;
26
+ font-size: var(--crewlet-chat-text);
27
+ font-weight: var(--font-weight-medium);
28
+ }
29
+
30
+ .crewlet-room-row__mark {
31
+ display: inline-flex;
32
+ flex: none;
33
+ color: var(--color-text-secondary);
34
+ }
35
+
36
+ .crewlet-room-row__title {
37
+ min-width: 0;
38
+ }
39
+
40
+ .crewlet-room-row__topic {
41
+ overflow: hidden;
42
+ color: var(--color-text-secondary);
43
+ font-size: var(--crewlet-chat-text);
44
+ text-overflow: ellipsis;
45
+ white-space: nowrap;
46
+ }
47
+
48
+ .crewlet-room-row__facts {
49
+ color: var(--color-text-secondary);
50
+ font-size: var(--crewlet-chat-meta);
51
+ }
52
+
53
+ .crewlet-room-row__sep {
54
+ color: var(--color-text-tertiary);
55
+ }
@@ -1,6 +1,6 @@
1
- export { SetupWizard } from '../chunk-3BVNNQZY.js';
2
- import '../chunk-FPDIHEM4.js';
1
+ export { SetupWizard } from '../chunk-WRZPO4YL.js';
3
2
  import '../chunk-TMML7BHT.js';
3
+ import '../chunk-FPDIHEM4.js';
4
4
  import '../chunk-YJQXESOJ.js';
5
5
  import '../chunk-CYQBDZ6M.js';
6
6
  import '../chunk-NAHA62WD.js';
@@ -8,6 +8,20 @@ export interface SwitchProps extends Omit<InputHTMLAttributes<HTMLInputElement>,
8
8
  framed?: boolean;
9
9
  /** The new state, for a caller that does not want to read it off an event. */
10
10
  onCheckedChange?: (checked: boolean) => void;
11
+ /**
12
+ * The label stays the switch's name and is not drawn: for a switch at the
13
+ * end of a row whose own words already say what it sets (a member's row in
14
+ * a room, "Answers when named"). The track alone is drawn.
15
+ */
16
+ labelHidden?: boolean | undefined;
17
+ /**
18
+ * Why the switch cannot be moved, as a sentence. It is drawn dimmed and
19
+ * does not move, and stays a tab stop whose reason is read after its name
20
+ * (`aria-describedby`), where a natively disabled control is skipped by Tab
21
+ * and says nothing. Pair it with a `Tooltip` to show the sentence to a
22
+ * pointer. Leave it out for a switch that can move.
23
+ */
24
+ disabledReason?: string | undefined;
11
25
  }
12
26
  /**
13
27
  * A setting that is on or off, and takes effect as it is switched.
@@ -1,2 +1,3 @@
1
- export { Switch } from '../chunk-3XDT5ZWL.js';
1
+ export { Switch } from '../chunk-3N3XK2G5.js';
2
+ import '../chunk-UT6CW3C7.js';
2
3
  import '../chunk-ODEQTPFM.js';
@@ -172,6 +172,21 @@
172
172
  border-radius: var(--radius-lg);
173
173
  }
174
174
 
175
+ /*
176
+ * THE TRACK ALONE, for a switch whose label is its name and not drawn: no
177
+ * gap after it and no padding to centre a line of text that is not there, so
178
+ * it stands on the middle of the row it ends.
179
+ */
180
+ .crewlet-switch--label-hidden {
181
+ align-items: center;
182
+ gap: 0;
183
+ padding-block: 0;
184
+ }
185
+
186
+ .crewlet-switch--label-hidden .crewlet-switch__track {
187
+ margin-block: 0;
188
+ }
189
+
175
190
  .crewlet-switch.is-disabled,
176
191
  .crewlet-switch.is-disabled .crewlet-switch__control {
177
192
  cursor: not-allowed;
@@ -8,10 +8,20 @@ export interface ThinkingIndicatorProps extends Omit<HTMLAttributes<HTMLDivEleme
8
8
  status?: string | undefined;
9
9
  /**
10
10
  * What a screen reader is told, once, when the indicator appears.
11
- * "Thinking" by default. It never changes with `status`, so a reader is not
12
- * told every step the assistant takes while they read.
11
+ * "Thinking" by default, and "Queued" while `queued`. It never changes with
12
+ * `status`, so a reader is not told every step the assistant takes while
13
+ * they read.
13
14
  */
14
15
  label?: string | undefined;
16
+ /**
17
+ * The work has not started: the request is waiting behind something the
18
+ * agent is already doing ("is queued behind its current task"). The mark
19
+ * rests in its idle pose and the line is drawn without its shimmer, so a
20
+ * person can tell a reply that is being written from one that is waiting
21
+ * its turn. When the work starts, drop it and the indicator moves again in
22
+ * place, with nothing else on the page moving.
23
+ */
24
+ queued?: boolean | undefined;
15
25
  }
16
26
  /**
17
27
  * Ask Crewlet at work, drawn where its answer will be: the Ask Crewlet mark
@@ -36,5 +46,11 @@ export interface ThinkingIndicatorProps extends Omit<HTMLAttributes<HTMLDivEleme
36
46
  * tucked, the companion dimmed) and the line is drawn in the secondary ink
37
47
  * without the shimmer: the mark and the words still say that work is under
38
48
  * way.
49
+ *
50
+ * QUEUED, NOTHING MOVES. A request waiting behind the agent's current task is
51
+ * drawn with the mark in its idle pose and the line in the secondary ink, at
52
+ * the same height, so the moment the work starts is the moment the mark
53
+ * starts to turn. Motion means work under way, and a queued request has none
54
+ * yet.
39
55
  */
40
- export declare function ThinkingIndicator({ status, label, className, ...rest }: ThinkingIndicatorProps): import("react").JSX.Element;
56
+ export declare function ThinkingIndicator({ status, label, queued, className, ...rest }: ThinkingIndicatorProps): import("react").JSX.Element;
@@ -1,3 +1,3 @@
1
- export { ThinkingIndicator } from '../chunk-ED4A6Q24.js';
1
+ export { ThinkingIndicator } from '../chunk-3OIVYHAA.js';
2
2
  import '../chunk-UT6CW3C7.js';
3
3
  import '../chunk-ODEQTPFM.js';
@@ -192,6 +192,33 @@
192
192
  }
193
193
  }
194
194
 
195
+ /*
196
+ * QUEUED, THE MARK RESTS AND THE LINE IS STILL. Work has not started, so
197
+ * nothing moves: both parts of the mark stop in the idle pose (the spark at
198
+ * full size and upright, the companion at full strength), which is the pose
199
+ * the working loop rests in for half of every period, and the line drops its
200
+ * shimmer for the secondary ink. The same height, so the indicator starts
201
+ * moving in place when the work begins.
202
+ */
203
+ .crewlet-thinking--queued .crewlet-thinking__mark [data-motion='turn'],
204
+ .crewlet-thinking--queued .crewlet-thinking__mark [data-motion='twinkle'] {
205
+ animation: none;
206
+ transform: none;
207
+ opacity: 1;
208
+ }
209
+
210
+ .crewlet-thinking--queued .crewlet-thinking__status {
211
+ background-image: none;
212
+ color: var(--color-text-secondary);
213
+ animation: crewlet-thinking-enter var(--motion-duration-moderate) var(--motion-easing-out);
214
+ }
215
+
216
+ @media (prefers-reduced-motion: reduce) {
217
+ .crewlet-thinking--queued .crewlet-thinking__status {
218
+ animation: none;
219
+ }
220
+ }
221
+
195
222
  /* The system's own ink: a gradient clipped to text is dropped there. */
196
223
  @media (forced-colors: active) {
197
224
  .crewlet-thinking__status {
@@ -1,5 +1,6 @@
1
+ import { VisuallyHidden } from './chunk-UT6CW3C7.js';
1
2
  import { cx } from './chunk-ODEQTPFM.js';
2
- import './Switch-AUYLQLTN.css';
3
+ import './Switch-XJE34BZH.css';
3
4
  import { forwardRef, useId } from 'react';
4
5
  import { jsxs, jsx } from 'react/jsx-runtime';
5
6
 
@@ -9,6 +10,9 @@ var Switch = forwardRef(function Switch2({
9
10
  framed = false,
10
11
  onCheckedChange,
11
12
  onChange,
13
+ onClick,
14
+ labelHidden = false,
15
+ disabledReason,
12
16
  className = "",
13
17
  disabled,
14
18
  id,
@@ -19,13 +23,20 @@ var Switch = forwardRef(function Switch2({
19
23
  const inputId = id ?? generatedId;
20
24
  const labelId = `${inputId}-label`;
21
25
  const descriptionId = description ? `${inputId}-description` : void 0;
26
+ const reasonId = disabledReason ? `${inputId}-reason` : void 0;
27
+ const inert = disabledReason !== void 0 && disabledReason !== "";
28
+ const text = /* @__PURE__ */ jsxs("span", { className: "crewlet-switch__text", children: [
29
+ /* @__PURE__ */ jsx("span", { className: "crewlet-switch__label", id: labelId, children: label }),
30
+ description ? /* @__PURE__ */ jsx("span", { className: "crewlet-switch__description", id: descriptionId, children: description }) : null
31
+ ] });
22
32
  return /* @__PURE__ */ jsxs(
23
33
  "label",
24
34
  {
25
35
  className: cx(
26
36
  "crewlet-switch",
27
37
  framed && "crewlet-switch--framed",
28
- disabled && "is-disabled",
38
+ labelHidden && "crewlet-switch--label-hidden",
39
+ (disabled || inert) && "is-disabled",
29
40
  className
30
41
  ),
31
42
  children: [
@@ -40,20 +51,27 @@ var Switch = forwardRef(function Switch2({
40
51
  className: "crewlet-switch__control",
41
52
  disabled,
42
53
  "aria-labelledby": labelId,
43
- "aria-describedby": cx(descriptionId, describedBy) || void 0,
54
+ "aria-describedby": cx(descriptionId, reasonId, describedBy) || void 0,
55
+ "aria-disabled": inert || void 0,
56
+ ...rest,
57
+ onClick: (event) => {
58
+ if (inert) {
59
+ if (rest.checked === void 0) event.preventDefault();
60
+ return;
61
+ }
62
+ onClick?.(event);
63
+ },
44
64
  onChange: (event) => {
65
+ if (inert) return;
45
66
  onChange?.(event);
46
67
  onCheckedChange?.(event.target.checked);
47
- },
48
- ...rest
68
+ }
49
69
  }
50
70
  ),
51
71
  /* @__PURE__ */ jsx("span", { className: "crewlet-switch__thumb", "aria-hidden": "true" })
52
72
  ] }),
53
- /* @__PURE__ */ jsxs("span", { className: "crewlet-switch__text", children: [
54
- /* @__PURE__ */ jsx("span", { className: "crewlet-switch__label", id: labelId, children: label }),
55
- description ? /* @__PURE__ */ jsx("span", { className: "crewlet-switch__description", id: descriptionId, children: description }) : null
56
- ] })
73
+ labelHidden ? /* @__PURE__ */ jsx(VisuallyHidden, { children: text }) : text,
74
+ inert ? /* @__PURE__ */ jsx(VisuallyHidden, { id: reasonId, children: disabledReason }) : null
57
75
  ]
58
76
  }
59
77
  );
@@ -1,18 +1,19 @@
1
1
  import { VisuallyHidden } from './chunk-UT6CW3C7.js';
2
2
  import { cx } from './chunk-ODEQTPFM.js';
3
- import './ThinkingIndicator-S7ZL2C77.css';
3
+ import './ThinkingIndicator-G72NYYAM.css';
4
4
  import { ProductMark } from '@crewlethq/icons/product-mark';
5
5
  import { jsxs, jsx } from 'react/jsx-runtime';
6
6
 
7
- function ThinkingIndicator({ status, label = "Thinking", className, ...rest }) {
8
- return /* @__PURE__ */ jsxs("div", { ...rest, className: cx("crewlet-thinking", className), children: [
7
+ function ThinkingIndicator({ status, label, queued = false, className, ...rest }) {
8
+ const announced = label ?? (queued ? "Queued" : "Thinking");
9
+ return /* @__PURE__ */ jsxs("div", { ...rest, className: cx("crewlet-thinking", queued && "crewlet-thinking--queued", className), children: [
9
10
  /* @__PURE__ */ jsx(ProductMark, { product: "assistant", size: "md", className: "crewlet-thinking__mark" }),
10
11
  status === void 0 || status === "" ? null : (
11
12
  // Keyed by its words, so a new step's line fades in rather than
12
13
  // swapping in place mid shimmer.
13
14
  /* @__PURE__ */ jsx("span", { className: "crewlet-thinking__status", "aria-hidden": "true", children: status }, status)
14
15
  ),
15
- /* @__PURE__ */ jsx(VisuallyHidden, { children: /* @__PURE__ */ jsx("span", { role: "status", children: label }) })
16
+ /* @__PURE__ */ jsx(VisuallyHidden, { children: /* @__PURE__ */ jsx("span", { role: "status", children: announced }) })
16
17
  ] });
17
18
  }
18
19
 
@@ -1,5 +1,5 @@
1
1
  import { cx } from './chunk-ODEQTPFM.js';
2
- import './PersonRow-V5GTPNVP.css';
2
+ import './PersonRow-ZR6US2QJ.css';
3
3
  import { forwardRef } from 'react';
4
4
  import { CheckGlyph, PlusGlyph } from '@crewlethq/icons/glyphs';
5
5
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
@@ -48,8 +48,8 @@ var PersonRow = forwardRef(function PersonRow2(props, ref) {
48
48
  }
49
49
  );
50
50
  }
51
- const { as: _as, avatar, name, tag, detail, meta, mark, density = "default", selected, onSelect, onClick, className, type = "button", ...rest } = props;
52
- return /* @__PURE__ */ jsx(
51
+ const { as: _as, avatar, name, tag, detail, meta, mark, density = "default", selected, onSelect, onClick, action, className, type = "button", ...rest } = props;
52
+ const row = /* @__PURE__ */ jsx(
53
53
  "button",
54
54
  {
55
55
  ...rest,
@@ -64,6 +64,11 @@ var PersonRow = forwardRef(function PersonRow2(props, ref) {
64
64
  children: /* @__PURE__ */ jsx(PersonRowBody, { avatar, name, tag, detail, meta, mark, density, selected })
65
65
  }
66
66
  );
67
+ if (action === void 0 || action === null) return row;
68
+ return /* @__PURE__ */ jsxs("div", { className: cx("crewlet-person-row-group", `crewlet-person-row-group--${density}`), children: [
69
+ row,
70
+ /* @__PURE__ */ jsx("span", { className: "crewlet-person-row__action", children: action })
71
+ ] });
67
72
  });
68
73
 
69
74
  export { PersonRow };
@@ -1,4 +1,4 @@
1
- import { Switch } from './chunk-3XDT5ZWL.js';
1
+ import { Switch } from './chunk-3N3XK2G5.js';
2
2
  import { useReorder } from './chunk-BVML4UVB.js';
3
3
  import { Checkbox } from './chunk-YQ7Q52XU.js';
4
4
  import { IconButton } from './chunk-UAUP6XGK.js';
@@ -1,6 +1,6 @@
1
1
  import { VisuallyHidden } from './chunk-UT6CW3C7.js';
2
2
  import { cx } from './chunk-ODEQTPFM.js';
3
- import './List-JOELBLTU.css';
3
+ import './List-ZZF6ZHRT.css';
4
4
  import { createContext, useContext, Children, isValidElement, cloneElement } from 'react';
5
5
  import { CircleAlertGlyph } from '@crewlethq/icons/glyphs';
6
6
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
@@ -40,6 +40,8 @@ function ListItem({
40
40
  onClick,
41
41
  leading,
42
42
  trailing,
43
+ action,
44
+ note,
43
45
  tone = "default",
44
46
  dangerLabel = "Failed",
45
47
  selected = false,
@@ -98,7 +100,9 @@ function ListItem({
98
100
  } else {
99
101
  row = /* @__PURE__ */ jsx("span", { className: rowClass, children: contents(children) });
100
102
  }
101
- return /* @__PURE__ */ jsx(
103
+ const hasAction = action !== void 0 && action !== null;
104
+ const hasNote = note !== void 0 && note !== null;
105
+ return /* @__PURE__ */ jsxs(
102
106
  "li",
103
107
  {
104
108
  ...rest,
@@ -106,10 +110,15 @@ function ListItem({
106
110
  "crewlet-list__item",
107
111
  tone === "danger" && "crewlet-list__item--danger",
108
112
  selected && "crewlet-list__item--selected",
113
+ (hasAction || hasNote) && "crewlet-list__item--split",
109
114
  className
110
115
  ),
111
116
  "aria-current": interactive ? void 0 : current,
112
- children: row
117
+ children: [
118
+ row,
119
+ hasAction ? /* @__PURE__ */ jsx("span", { className: "crewlet-list__action", children: action }) : null,
120
+ hasNote ? /* @__PURE__ */ jsx("div", { className: "crewlet-list__note", children: note }) : null
121
+ ]
113
122
  }
114
123
  );
115
124
  }
@@ -1,6 +1,6 @@
1
- import { PersonRow } from './chunk-EALRMP7N.js';
1
+ import { PersonRow } from './chunk-6TD2PCZB.js';
2
2
  import { cx } from './chunk-ODEQTPFM.js';
3
- import './PersonRow-V5GTPNVP.css';
3
+ import './PersonRow-ZR6US2QJ.css';
4
4
  import './MentionMenu-4NAQ45S4.css';
5
5
  import { jsx, jsxs } from 'react/jsx-runtime';
6
6