@crewlethq/ui 0.10.0 → 0.12.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 (90) hide show
  1. package/README.md +27 -1
  2. package/dist/Accordion/index.js +3 -3
  3. package/dist/AppShell/index.js +2 -2
  4. package/dist/AvatarPicker/AvatarPicker.d.ts +32 -0
  5. package/dist/AvatarPicker/index.d.ts +3 -0
  6. package/dist/AvatarPicker/index.js +14 -0
  7. package/dist/AvatarPicker-PREY36MG.css +54 -0
  8. package/dist/Canvas/index.js +3 -3
  9. package/dist/Card/index.js +2 -2
  10. package/dist/CharacterPicker/index.js +2 -1
  11. package/dist/ChoiceList/ChoiceList.d.ts +45 -0
  12. package/dist/ChoiceList/index.d.ts +3 -0
  13. package/dist/ChoiceList/index.js +2 -0
  14. package/dist/ChoiceList-2PQJS4DX.css +109 -0
  15. package/dist/CodeBlock/index.js +3 -3
  16. package/dist/Combobox/index.js +3 -3
  17. package/dist/CommandPalette/index.js +7 -7
  18. package/dist/Composer/Composer.d.ts +27 -0
  19. package/dist/Composer/index.d.ts +3 -0
  20. package/dist/Composer/index.js +7 -0
  21. package/dist/Composer-ABGJIAIR.css +88 -0
  22. package/dist/Copyable/index.js +2 -2
  23. package/dist/DataTable/index.js +7 -7
  24. package/dist/DataView/index.js +14 -14
  25. package/dist/DateTimePicker/index.js +4 -4
  26. package/dist/Disclosure/index.js +3 -3
  27. package/dist/FactList/FactList.d.ts +33 -0
  28. package/dist/FactList/index.d.ts +3 -0
  29. package/dist/FactList/index.js +6 -0
  30. package/dist/FactList-G2H73NFR.css +57 -0
  31. package/dist/HuePicker/index.js +4 -3
  32. package/dist/Input/FormField.d.ts +8 -1
  33. package/dist/Input/index.js +1 -1
  34. package/dist/{Input-DRFNI26F.css → Input-RAKNQJCV.css} +7 -0
  35. package/dist/ListInput/ListInput.d.ts +3 -1
  36. package/dist/ListInput/index.js +3 -3
  37. package/dist/Menu/index.js +3 -3
  38. package/dist/Modal/index.js +3 -3
  39. package/dist/OrgTable/index.js +5 -5
  40. package/dist/SegmentedControl/index.js +3 -3
  41. package/dist/Tabs/Tabs.d.ts +18 -0
  42. package/dist/Tabs/index.d.ts +1 -1
  43. package/dist/Tabs/index.js +1 -1
  44. package/dist/{Tabs-BWFQSWY3.css → Tabs-5I5Q5KKM.css} +33 -0
  45. package/dist/TagsInput/index.js +2 -2
  46. package/dist/ThemeSwitcher/index.js +4 -4
  47. package/dist/TimeWindowPicker/index.js +5 -5
  48. package/dist/TreeCanvas/index.js +4 -4
  49. package/dist/TreeGrid/index.js +2 -2
  50. package/dist/chunk-3L5NHASN.js +1 -0
  51. package/dist/{chunk-L7THQMFB.js → chunk-5WEVLIB6.js} +1 -1
  52. package/dist/{chunk-LPHHDCN3.js → chunk-EBBAAQDY.js} +1 -1
  53. package/dist/chunk-EXHQ2QVW.js +1 -0
  54. package/dist/{chunk-ZGX2DP7F.js → chunk-FTEJPHBI.js} +8 -2
  55. package/dist/{chunk-RIAZM6L3.js → chunk-G2AVKPSL.js} +1 -1
  56. package/dist/{chunk-6HXH57BL.js → chunk-GARACZAH.js} +4 -2
  57. package/dist/{chunk-CVB7O3SZ.js → chunk-GOUKOXJK.js} +5 -5
  58. package/dist/{chunk-UYK72NOS.js → chunk-GXYNEDNA.js} +1 -1
  59. package/dist/{chunk-IZHN5I3H.js → chunk-HLBRPES3.js} +4 -4
  60. package/dist/chunk-HV6IZFBK.js +64 -0
  61. package/dist/{chunk-EUT7VBQG.js → chunk-IINFVK3W.js} +8 -8
  62. package/dist/{chunk-HEOVQZL7.js → chunk-JHQUT4WJ.js} +6 -2
  63. package/dist/{chunk-26TXVHN2.js → chunk-K5Q2DK3P.js} +1 -2
  64. package/dist/{chunk-MORLKUGM.js → chunk-KGTQ5CVD.js} +1 -1
  65. package/dist/chunk-QBXZLGK2.js +40 -0
  66. package/dist/chunk-QSLIN64M.js +47 -0
  67. package/dist/{chunk-MICH6QSJ.js → chunk-S4RCG44T.js} +1 -1
  68. package/dist/{chunk-UI6HWAWE.js → chunk-UAQIUSSK.js} +1 -1
  69. package/dist/chunk-URYDN2KA.js +25 -0
  70. package/dist/{chunk-X6K6OZ47.js → chunk-WEIINZPA.js} +1 -1
  71. package/dist/{chunk-IGWPZZIB.js → chunk-XV65NTIT.js} +3 -3
  72. package/dist/{chunk-UO5UK7V2.js → chunk-YXMCUKFI.js} +0 -1
  73. package/dist/{chunk-7FFDJQ23.js → chunk-ZMJHK7DR.js} +1 -1
  74. package/dist/generated/index.d.ts +4 -0
  75. package/dist/generated/index.js +66 -60
  76. package/dist/index.js +66 -60
  77. package/dist/styles.css +362 -2
  78. package/dist/utils/index.js +1 -1
  79. package/package.json +3 -3
  80. package/dist/{chunk-VE6LD3KM.js → chunk-2PZBIHRV.js} +2 -2
  81. package/dist/{chunk-YPTC4TX5.js → chunk-74OVQWA5.js} +0 -0
  82. package/dist/{chunk-OVLJEVQS.js → chunk-7LD6P32I.js} +1 -1
  83. package/dist/{chunk-CEOXFO3E.js → chunk-EG6NYWVK.js} +1 -1
  84. package/dist/{chunk-FZVJDJFN.js → chunk-ENJUPIND.js} +1 -1
  85. package/dist/{chunk-5I56UXBJ.js → chunk-JCNUQ3US.js} +2 -2
  86. package/dist/{chunk-SX2DFTQV.js → chunk-MCPKHYMC.js} +1 -1
  87. package/dist/{chunk-BTHX2FS3.js → chunk-TEEJSTFG.js} +2 -2
  88. package/dist/{chunk-LSB3EHBW.js → chunk-TFH6SYWB.js} +2 -2
  89. package/dist/{chunk-26SCUACK.js → chunk-YACKC3K2.js} +1 -1
  90. package/dist/{chunk-MPXI6FM6.js → chunk-ZHOM65MI.js} +1 -1
package/README.md CHANGED
@@ -42,7 +42,7 @@ import { Button } from '@crewlethq/ui/Button'; // 8 KB of CSS, not 182 KB
42
42
  | ---- | ---------- |
43
43
  | Actions | `Button` and `ButtonLink` (variants `primary`, `secondary`, `outline`, `ghost`, `accent`, `danger`; sizes `small`, `medium`, `large`; shapes `square`, `pill`), `IconButton`, `Menu`, `Link`, `Copyable`, `CopyButton`, `Kbd` |
44
44
  | Content and text | `Text` (the eight registers), `Prose`, `InlineCode`, `List` and `ListItem`, `DescriptionList`, `Timeline`, `RelativeTime` |
45
- | Forms | `Input`, `Textarea`, `Label`, `FormField`, `FormRow`, `Checkbox`, `Select`, `Tag`, `TagsInput`, `DateTimePicker`, `TimeWindowPicker`, `ImageUpload`, `CharacterPicker`, `HuePicker` |
45
+ | Forms | `Input`, `Textarea`, `Label`, `FormField`, `FormRow`, `Checkbox`, `Select`, `Tag`, `TagsInput`, `DateTimePicker`, `TimeWindowPicker`, `ImageUpload`, `CharacterPicker`, `HuePicker`, `AvatarPicker`, `FactList`, `ChoiceList`, `Composer` |
46
46
  | Data display | `DataTable`, `CopyableCell`, `Table`, `StatCard`, `Meter`, `SegmentedMeter`, `Stepper`, `PricingCard`, `Avatar`, `AvatarStack`, `EntityChip`, `CodeBlock`, `Skeleton`, `Eyebrow` |
47
47
  | List screens | `DataView`, and its parts on their own: `DataViewToolbar`, `FilterAxisBar`, `FilterAxisChip`, plus the filter model (`filterDefsFromColumns`, `applyColumnFilters`, `filterPredicate`, `blankFilterValue`) |
48
48
  | Feedback and overlays | `Callout`, `Toaster`, `Modal` (with `variant="sheet"`), `ConfirmModal`, `CommandPalette`, `Tooltip`, `Popover`, `Announcer` |
@@ -191,6 +191,32 @@ places:
191
191
  - A surface that pans or zooms dispatches `LAYER_REPOSITION_EVENT` on its host
192
192
  when the content beneath it moves, and every panel anchored inside follows.
193
193
 
194
+ ## Changes in 0.12.0
195
+
196
+ 0.12.0 adds the parts a question is answered in place with.
197
+
198
+ **`ChoiceList`** draws one answer from a short list in one bordered box: each choice a native radio with its label, a line of `detail` under it and an optional `tag` at its end ("Recommended"). The whole row selects, the arrow keys move between choices, and the selected row takes the accent's soft fill. A choice marked `separated` is set apart by a dashed rule, and its `panel` is drawn under it only while it is selected, which is how a list ends in "Something else" with a field of its own. `footer` holds the list's Cancel and Submit.
199
+
200
+ **`Composer`** is a message written in place: a borderless field that grows with its text and a footer strip with the send shortcut, a counter and `actions`, in one box that takes the focus ring as a whole. `onSubmit` runs on Command+Enter (Control+Enter elsewhere) and adds the shortcut's hint; the counter appears from four fifths of `maxLength` (`COMPOSER_COUNTER_AT`).
201
+
202
+ What to change: nothing. Every addition is new.
203
+
204
+ ## Changes in 0.11.0
205
+
206
+ 0.11.0 adds the parts a dense editing form is built from.
207
+
208
+ **`FactList`** draws facts a form shows and does not edit as 32px rows in one bordered box: the label on the left, the value on the right. A row with a `reason` carries a lock and says why in a tooltip on hover and to a screen reader after its value, in place of a caption under every value.
209
+
210
+ **`AvatarPicker`** is an agent's badge that opens its own picker. Pressing it opens the characters and the hues in a popover, and each choice applies as it is made; a `disabled` one is the badge alone. It replaces a `CharacterPicker` and a `HuePicker` drawn open in a form.
211
+
212
+ **`Tabs` take a `marker`** per item: `{ tone: 'danger', count, label }` for problems, or `{ tone: 'warning' | 'changed', label }` for a 6px dot. One per tab, the most urgent, and it stands in for the item's `count` while set; `label` is what a screen reader hears. `TabsMarker` is its type.
213
+
214
+ **`FormField` takes `helperOnFocus`**: the helper is still in `aria-describedby`, and is drawn only while the field has focus, so a form whose every field carries a sentence reads as labels and values at rest. `ListInput` passes the same prop to its field.
215
+
216
+ `@crewlethq/icons` adds `LockGlyph` (Lucide's `lock`), which `FactList` draws.
217
+
218
+ What to change: nothing. Every addition is new.
219
+
194
220
  ## Breaking changes in 0.10.0
195
221
 
196
222
  0.10.0 moves an agent's state off the ring round its badge and onto a small badge on its corner.
@@ -1,6 +1,6 @@
1
- export { Accordion, AccordionItem } from '../chunk-RIAZM6L3.js';
2
- import '../chunk-FZVJDJFN.js';
3
- import '../chunk-BHHIIK3M.js';
1
+ export { Accordion, AccordionItem } from '../chunk-G2AVKPSL.js';
2
+ import '../chunk-ENJUPIND.js';
4
3
  import '../chunk-PQADV6P6.js';
4
+ import '../chunk-BHHIIK3M.js';
5
5
  import '../chunk-BZFWDIV6.js';
6
6
  import '../chunk-ODEQTPFM.js';
@@ -1,6 +1,6 @@
1
- export { AppShell, AppShellRail, AppShellRailRow, AppShellToggle, AppShellTopbar, useAppShell } from '../chunk-OVLJEVQS.js';
1
+ export { AppShell, AppShellRail, AppShellRailRow, AppShellToggle, AppShellTopbar, useAppShell } from '../chunk-7LD6P32I.js';
2
+ import '../chunk-4FQT6ZAY.js';
2
3
  import '../chunk-7RPGY3JE.js';
3
4
  import '../chunk-R25RGPUB.js';
4
- import '../chunk-4FQT6ZAY.js';
5
5
  import '../chunk-BZFWDIV6.js';
6
6
  import '../chunk-ODEQTPFM.js';
@@ -0,0 +1,32 @@
1
+ import { type CrewletCharacterId } from '@crewlethq/icons/characters';
2
+ import { type AvatarSize } from '../Avatar/Avatar.js';
3
+ import { type NodeHue } from '../utils/nodeHue.js';
4
+ /** An agent's look: its character and the hue it is drawn in. */
5
+ export interface AvatarPickerValue {
6
+ character: CrewletCharacterId;
7
+ hue: NodeHue;
8
+ }
9
+ export interface AvatarPickerProps {
10
+ value: AvatarPickerValue;
11
+ onChange: (next: AvatarPickerValue) => void;
12
+ /** The agent's name, for the button's accessible name. */
13
+ name: string;
14
+ /** The badge's size. 40px, the size a form's header draws an identity at. */
15
+ size?: AvatarSize | undefined;
16
+ /** The characters offered, in order. Every character, by default. */
17
+ characters?: readonly CrewletCharacterId[] | undefined;
18
+ /** The badge is drawn, and nothing opens. */
19
+ disabled?: boolean | undefined;
20
+ className?: string | undefined;
21
+ }
22
+ /**
23
+ * An agent's badge that opens its own picker: press it and the characters and
24
+ * the hues open in a popover beside it.
25
+ *
26
+ * THE BADGE IS THE CONTROL. The two pickers drawn open in a form took about
27
+ * 330px for a choice made once, so the form keeps one badge, marked with a
28
+ * pencil pip as the thing that changes it, and the grid opens on demand. A
29
+ * choice applies as it is made, as the pickers' own radios do; Escape or a
30
+ * press outside closes the popover.
31
+ */
32
+ export declare function AvatarPicker({ value, onChange, name, size, characters, disabled, className, }: AvatarPickerProps): import("react").JSX.Element;
@@ -0,0 +1,3 @@
1
+ import './AvatarPicker.css';
2
+ export { AvatarPicker } from './AvatarPicker.js';
3
+ export type { AvatarPickerProps, AvatarPickerValue } from './AvatarPicker.js';
@@ -0,0 +1,14 @@
1
+ export { AvatarPicker } from '../chunk-HV6IZFBK.js';
2
+ import '../chunk-K5Q2DK3P.js';
3
+ import '../chunk-AYKXMIOR.js';
4
+ import '../chunk-EBBAAQDY.js';
5
+ import '../chunk-JHQUT4WJ.js';
6
+ import '../chunk-PDUZO35I.js';
7
+ import '../chunk-YXMCUKFI.js';
8
+ import '../chunk-CBOICT64.js';
9
+ import '../chunk-BHHIIK3M.js';
10
+ import '../chunk-7RPGY3JE.js';
11
+ import '../chunk-R25RGPUB.js';
12
+ import '../chunk-BZFWDIV6.js';
13
+ import '../chunk-HI6Q2UXQ.js';
14
+ import '../chunk-ODEQTPFM.js';
@@ -0,0 +1,54 @@
1
+ /*
2
+ * The badge as a button, with a pencil pip on its corner saying it changes
3
+ * the badge. No chrome of its own beyond the focus ring: the badge is the
4
+ * control's face.
5
+ */
6
+ .crewlet-avatar-picker {
7
+ position: relative;
8
+ display: inline-flex;
9
+ flex: none;
10
+ padding: 0;
11
+ border: 0;
12
+ border-radius: var(--radius-lg);
13
+ background: none;
14
+ cursor: pointer;
15
+ }
16
+
17
+ button.crewlet-avatar-picker:focus-visible {
18
+ outline: 2px solid var(--color-focus);
19
+ outline-offset: 2px;
20
+ }
21
+
22
+ .crewlet-avatar-picker__pip {
23
+ position: absolute;
24
+ right: calc(var(--spacing-1) * -1);
25
+ bottom: calc(var(--spacing-1) * -1);
26
+ display: grid;
27
+ place-items: center;
28
+ width: 16px;
29
+ height: 16px;
30
+ border: 1px solid var(--color-border-strong);
31
+ border-radius: var(--radius-circle);
32
+ background: var(--color-surface-elevated);
33
+ color: var(--color-text-secondary);
34
+ }
35
+
36
+ button.crewlet-avatar-picker:hover .crewlet-avatar-picker__pip {
37
+ color: var(--color-text-primary);
38
+ }
39
+
40
+ .crewlet-avatar-picker__body {
41
+ display: grid;
42
+ gap: var(--spacing-2);
43
+ width: max-content;
44
+ max-width: 100%;
45
+ padding: var(--spacing-3);
46
+ }
47
+
48
+ .crewlet-avatar-picker__label {
49
+ font-size: var(--font-size-2xs);
50
+ font-weight: var(--font-weight-medium);
51
+ letter-spacing: var(--font-letter-spacing-wide);
52
+ text-transform: uppercase;
53
+ color: var(--color-text-tertiary);
54
+ }
@@ -1,8 +1,8 @@
1
- export { CANVAS_COMPOSE_CONTEXT, CANVAS_FIT_MAX_ZOOM, CANVAS_FIT_PADDING, CANVAS_FOCUS_CONTEXT, CANVAS_MAX_ZOOM, CANVAS_MIN_ZOOM, CANVAS_PAN_MARGIN, CANVAS_PAN_STEP, CANVAS_REVEAL_PADDING, CANVAS_TAP_SLOP, CANVAS_WHEEL_LINE_PX, CANVAS_WHEEL_ZOOM_PER_PIXEL, CANVAS_ZOOM_CEILING, CANVAS_ZOOM_LIMITS, CANVAS_ZOOM_STEP, Canvas, IDENTITY_VIEW, anchorView, beyondSlop, clampPan, clampZoom, fitView, panBy, pinchView, regionView, revealView, screenRect, toScreen, toWorld, wheelPixels, wheelZoomFactor, zoomAt, zoomLimits } from '../chunk-VE6LD3KM.js';
1
+ export { CANVAS_COMPOSE_CONTEXT, CANVAS_FIT_MAX_ZOOM, CANVAS_FIT_PADDING, CANVAS_FOCUS_CONTEXT, CANVAS_MAX_ZOOM, CANVAS_MIN_ZOOM, CANVAS_PAN_MARGIN, CANVAS_PAN_STEP, CANVAS_REVEAL_PADDING, CANVAS_TAP_SLOP, CANVAS_WHEEL_LINE_PX, CANVAS_WHEEL_ZOOM_PER_PIXEL, CANVAS_ZOOM_CEILING, CANVAS_ZOOM_LIMITS, CANVAS_ZOOM_STEP, Canvas, IDENTITY_VIEW, anchorView, beyondSlop, clampPan, clampZoom, fitView, panBy, pinchView, regionView, revealView, screenRect, toScreen, toWorld, wheelPixels, wheelZoomFactor, zoomAt, zoomLimits } from '../chunk-2PZBIHRV.js';
2
2
  import '../chunk-53DVJCVW.js';
3
+ import '../chunk-OG6CL3EB.js';
4
+ import '../chunk-4FQT6ZAY.js';
3
5
  import '../chunk-7RPGY3JE.js';
4
6
  import '../chunk-R25RGPUB.js';
5
- import '../chunk-4FQT6ZAY.js';
6
- import '../chunk-OG6CL3EB.js';
7
7
  import '../chunk-BZFWDIV6.js';
8
8
  import '../chunk-ODEQTPFM.js';
@@ -1,6 +1,6 @@
1
- export { Card } from '../chunk-CEOXFO3E.js';
1
+ export { Card } from '../chunk-EG6NYWVK.js';
2
2
  export { useCardHeaderSlot } from '../chunk-AV2DXAEL.js';
3
- import '../chunk-BHHIIK3M.js';
4
3
  import '../chunk-PQADV6P6.js';
4
+ import '../chunk-BHHIIK3M.js';
5
5
  import '../chunk-BZFWDIV6.js';
6
6
  import '../chunk-ODEQTPFM.js';
@@ -1,4 +1,5 @@
1
- export { CHARACTER_PICKER_COLUMNS, CharacterPicker } from '../chunk-UO5UK7V2.js';
1
+ import '../chunk-3L5NHASN.js';
2
+ export { CHARACTER_PICKER_COLUMNS, CharacterPicker } from '../chunk-YXMCUKFI.js';
2
3
  import '../chunk-CBOICT64.js';
3
4
  import '../chunk-HI6Q2UXQ.js';
4
5
  import '../chunk-ODEQTPFM.js';
@@ -0,0 +1,45 @@
1
+ import { type ReactNode } from 'react';
2
+ /** One choice in a [ChoiceList]. */
3
+ export interface ChoiceListOption {
4
+ /** Stable identity, and what `onChange` is called with. */
5
+ value: string;
6
+ /** What the choice is, in a few words. */
7
+ label: ReactNode;
8
+ /** One line under the label saying what choosing it means. */
9
+ detail?: ReactNode;
10
+ /** A short word at the row's end, such as "Recommended". */
11
+ tag?: ReactNode;
12
+ /**
13
+ * Draws a rule above this choice, setting it apart from the ones before it:
14
+ * the "Something else" a list of set answers ends with.
15
+ */
16
+ separated?: boolean | undefined;
17
+ /**
18
+ * Drawn under the choice while it is selected, such as the field a
19
+ * "Something else" choice opens.
20
+ */
21
+ panel?: ReactNode;
22
+ }
23
+ export interface ChoiceListProps {
24
+ options: readonly ChoiceListOption[];
25
+ /** The selected choice's `value`, or null when none is. */
26
+ value: string | null;
27
+ onChange: (value: string) => void;
28
+ /** Names the group for a screen reader. */
29
+ label: string;
30
+ /** Drawn at the foot of the box, after every choice: its Cancel and Submit. */
31
+ footer?: ReactNode;
32
+ disabled?: boolean | undefined;
33
+ className?: string | undefined;
34
+ }
35
+ /**
36
+ * One answer from a short list, each choice a row with its label, a line of
37
+ * detail and an optional tag, in one bordered box.
38
+ *
39
+ * NATIVE RADIOS, so the arrow keys move the choice and Tab leaves the group as
40
+ * the platform does, and every row is its radio's label, so the whole row
41
+ * takes the pointer. A choice's `panel` is drawn under it only while it is
42
+ * selected, which is how a list ends in "Something else" with a field of its
43
+ * own without a second control beside the list.
44
+ */
45
+ export declare function ChoiceList({ options, value, onChange, label, footer, disabled, className }: ChoiceListProps): import("react").JSX.Element;
@@ -0,0 +1,3 @@
1
+ import './ChoiceList.css';
2
+ export { ChoiceList } from './ChoiceList.js';
3
+ export type { ChoiceListOption, ChoiceListProps } from './ChoiceList.js';
@@ -0,0 +1,2 @@
1
+ export { ChoiceList } from '../chunk-QBXZLGK2.js';
2
+ import '../chunk-ODEQTPFM.js';
@@ -0,0 +1,109 @@
1
+ /*
2
+ * A short list of answers in one bordered box: a radio, the label with a line
3
+ * of detail under it, and a tag at the row's end. The selected row takes the
4
+ * accent's soft fill, so the answer reads at a glance without the radio.
5
+ */
6
+ .crewlet-choice-list {
7
+ display: grid;
8
+ gap: var(--spacing-1);
9
+ padding: var(--spacing-1);
10
+ border: 1px solid var(--color-border-strong);
11
+ border-radius: var(--radius-md);
12
+ background: var(--color-surface-subtle);
13
+ }
14
+
15
+ .crewlet-choice-list.is-disabled {
16
+ opacity: 0.6;
17
+ }
18
+
19
+ .crewlet-choice-list__group {
20
+ display: grid;
21
+ gap: var(--spacing-1);
22
+ }
23
+
24
+ .crewlet-choice-list__item {
25
+ display: grid;
26
+ gap: var(--spacing-1);
27
+ }
28
+
29
+ /* The "Something else" a list ends with, set apart by a dashed rule. */
30
+ .crewlet-choice-list__item.is-separated {
31
+ padding-top: var(--spacing-1);
32
+ border-top: 1px dashed var(--color-border-strong);
33
+ }
34
+
35
+ .crewlet-choice-list__row {
36
+ display: grid;
37
+ grid-template-columns: auto minmax(0, 1fr) auto;
38
+ align-items: start;
39
+ gap: var(--spacing-3);
40
+ padding: var(--spacing-2);
41
+ border-radius: var(--radius-sm);
42
+ cursor: pointer;
43
+ transition: background-color var(--motion-duration-fast) var(--motion-easing-default);
44
+ }
45
+
46
+ .crewlet-choice-list__row:hover {
47
+ background: var(--color-surface-hover);
48
+ }
49
+
50
+ .crewlet-choice-list__row.is-checked {
51
+ background: var(--color-brand-accent-soft);
52
+ }
53
+
54
+ .crewlet-choice-list.is-disabled .crewlet-choice-list__row {
55
+ cursor: not-allowed;
56
+ }
57
+
58
+ .crewlet-choice-list__radio {
59
+ margin: 3px 0 0;
60
+ accent-color: var(--color-brand-accent);
61
+ cursor: inherit;
62
+ }
63
+
64
+ /* A radio draws its own edge, so the ring sits on it, as a checkbox's does. */
65
+ .crewlet-choice-list__radio:focus-visible {
66
+ outline: 2px solid var(--color-focus);
67
+ outline-offset: 0;
68
+ }
69
+
70
+ .crewlet-choice-list__text {
71
+ display: grid;
72
+ min-width: 0;
73
+ }
74
+
75
+ .crewlet-choice-list__label {
76
+ font-size: var(--font-size-compact);
77
+ font-weight: 500;
78
+ color: var(--color-text-primary);
79
+ overflow-wrap: anywhere;
80
+ }
81
+
82
+ .crewlet-choice-list__detail {
83
+ font-size: var(--font-size-xs);
84
+ color: var(--color-text-tertiary);
85
+ overflow-wrap: anywhere;
86
+ }
87
+
88
+ .crewlet-choice-list__tag {
89
+ padding-top: 2px;
90
+ font-size: var(--font-size-2xs);
91
+ font-weight: 500;
92
+ letter-spacing: 0.05em;
93
+ text-transform: uppercase;
94
+ color: var(--color-brand-accent-ink);
95
+ white-space: nowrap;
96
+ }
97
+
98
+ .crewlet-choice-list__footer {
99
+ display: flex;
100
+ justify-content: flex-end;
101
+ gap: var(--spacing-2);
102
+ padding: var(--spacing-1);
103
+ }
104
+
105
+ @media (prefers-reduced-motion: reduce) {
106
+ .crewlet-choice-list__row {
107
+ transition: none;
108
+ }
109
+ }
@@ -1,7 +1,7 @@
1
- export { CodeBlock } from '../chunk-MORLKUGM.js';
2
- import '../chunk-26SCUACK.js';
1
+ export { CodeBlock } from '../chunk-KGTQ5CVD.js';
2
+ import '../chunk-YACKC3K2.js';
3
3
  import '../chunk-5VNUYO76.js';
4
- import '../chunk-4FQT6ZAY.js';
5
4
  import '../chunk-OG6CL3EB.js';
5
+ import '../chunk-4FQT6ZAY.js';
6
6
  import '../chunk-BZFWDIV6.js';
7
7
  import '../chunk-ODEQTPFM.js';
@@ -1,8 +1,8 @@
1
- export { Combobox } from '../chunk-UYK72NOS.js';
1
+ export { Combobox } from '../chunk-GXYNEDNA.js';
2
2
  import '../chunk-6MU7HNB4.js';
3
- import '../chunk-ZGX2DP7F.js';
3
+ import '../chunk-FTEJPHBI.js';
4
4
  import '../chunk-PQADV6P6.js';
5
- import '../chunk-R25RGPUB.js';
6
5
  import '../chunk-4FQT6ZAY.js';
6
+ import '../chunk-R25RGPUB.js';
7
7
  import '../chunk-BZFWDIV6.js';
8
8
  import '../chunk-ODEQTPFM.js';
@@ -1,13 +1,13 @@
1
- export { CommandPalette } from '../chunk-IGWPZZIB.js';
2
- import '../chunk-SMBKXWML.js';
1
+ export { CommandPalette } from '../chunk-XV65NTIT.js';
3
2
  import '../chunk-6MU7HNB4.js';
4
- import '../chunk-ZGX2DP7F.js';
5
- import '../chunk-BTHX2FS3.js';
6
- import '../chunk-BHHIIK3M.js';
3
+ import '../chunk-SMBKXWML.js';
4
+ import '../chunk-FTEJPHBI.js';
5
+ import '../chunk-TEEJSTFG.js';
6
+ import '../chunk-OG6CL3EB.js';
7
7
  import '../chunk-PQADV6P6.js';
8
+ import '../chunk-4FQT6ZAY.js';
9
+ import '../chunk-BHHIIK3M.js';
8
10
  import '../chunk-7RPGY3JE.js';
9
11
  import '../chunk-R25RGPUB.js';
10
- import '../chunk-4FQT6ZAY.js';
11
- import '../chunk-OG6CL3EB.js';
12
12
  import '../chunk-BZFWDIV6.js';
13
13
  import '../chunk-ODEQTPFM.js';
@@ -0,0 +1,27 @@
1
+ import { type ReactNode, type TextareaHTMLAttributes } from 'react';
2
+ /** The share of `maxLength` at which the counter appears. */
3
+ export declare const COMPOSER_COUNTER_AT = 0.8;
4
+ export interface ComposerProps extends Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, 'value' | 'onChange' | 'onSubmit' | 'children'> {
5
+ value: string;
6
+ onChange: (value: string) => void;
7
+ /**
8
+ * Called on Command+Enter (Control+Enter elsewhere). With it, the footer
9
+ * carries the shortcut's hint.
10
+ */
11
+ onSubmit?: (() => void) | undefined;
12
+ /** Names the field for a screen reader, since it carries no visible label. */
13
+ label: string;
14
+ /** The footer's controls, at its end: Cancel and Submit. */
15
+ actions?: ReactNode;
16
+ className?: string | undefined;
17
+ }
18
+ /**
19
+ * A message written in place: a borderless field that grows with its text,
20
+ * and a footer strip holding the send shortcut, a counter and the actions, in
21
+ * one box that takes the focus ring as a whole.
22
+ *
23
+ * THE COUNTER IS DRAWN ONLY NEAR THE LIMIT, from [COMPOSER_COUNTER_AT] of
24
+ * `maxLength`: a count under every short reply is noise, and a field that
25
+ * stops taking text with no warning reads as a broken keyboard.
26
+ */
27
+ export declare const Composer: import("react").ForwardRefExoticComponent<ComposerProps & import("react").RefAttributes<HTMLTextAreaElement>>;
@@ -0,0 +1,3 @@
1
+ import './Composer.css';
2
+ export { COMPOSER_COUNTER_AT, Composer } from './Composer.js';
3
+ export type { ComposerProps } from './Composer.js';
@@ -0,0 +1,7 @@
1
+ export { COMPOSER_COUNTER_AT, Composer } from '../chunk-QSLIN64M.js';
2
+ import '../chunk-SMBKXWML.js';
3
+ import '../chunk-FTEJPHBI.js';
4
+ import '../chunk-PQADV6P6.js';
5
+ import '../chunk-4FQT6ZAY.js';
6
+ import '../chunk-BZFWDIV6.js';
7
+ import '../chunk-ODEQTPFM.js';
@@ -0,0 +1,88 @@
1
+ /*
2
+ * A message written in place: the field and its footer strip in one box. The
3
+ * BOX takes the focus ring, an accent border and a 2px soft halo, so the
4
+ * field inside draws no border or outline of its own and the footer reads as
5
+ * part of what is being written.
6
+ */
7
+ .crewlet-composer {
8
+ display: grid;
9
+ overflow: hidden;
10
+ border: 1px solid var(--color-border-strong);
11
+ border-radius: var(--radius-md);
12
+ background: var(--color-surface-background);
13
+ transition:
14
+ border-color var(--motion-duration-fast) var(--motion-easing-default),
15
+ box-shadow var(--motion-duration-fast) var(--motion-easing-default);
16
+ }
17
+
18
+ .crewlet-composer:hover {
19
+ border-color: var(--color-border-strong-hover);
20
+ }
21
+
22
+ .crewlet-composer:focus-within {
23
+ border-color: var(--color-brand-accent);
24
+ box-shadow: 0 0 0 2px var(--color-brand-accent-soft);
25
+ }
26
+
27
+ .crewlet-composer .crewlet-composer__field {
28
+ min-height: 68px;
29
+ max-height: 220px;
30
+ padding: var(--spacing-2) var(--spacing-3);
31
+ border: 0;
32
+ border-radius: 0;
33
+ background: transparent;
34
+ resize: none;
35
+ }
36
+
37
+ /* The ring is the box's, above. A transparent outline stays, because forced
38
+ colors drops the box's shadow and paints an outline in its place. */
39
+ .crewlet-composer .crewlet-composer__field:focus-visible {
40
+ outline: 2px solid transparent;
41
+ outline-offset: -2px;
42
+ }
43
+
44
+ /* Past its cap the field scrolls rather than pushing the page. */
45
+ .crewlet-composer .crewlet-composer__field.is-auto-resize {
46
+ overflow-y: auto;
47
+ }
48
+
49
+ .crewlet-composer__footer {
50
+ display: flex;
51
+ flex-wrap: wrap;
52
+ align-items: center;
53
+ gap: var(--spacing-2);
54
+ padding: var(--spacing-1) var(--spacing-1) var(--spacing-1) var(--spacing-3);
55
+ border-top: 1px solid var(--color-border-default);
56
+ background: var(--color-surface-subtle);
57
+ }
58
+
59
+ .crewlet-composer__hint {
60
+ display: inline-flex;
61
+ align-items: center;
62
+ gap: var(--spacing-1);
63
+ font-size: var(--font-size-2xs);
64
+ color: var(--color-text-tertiary);
65
+ }
66
+
67
+ .crewlet-composer__counter {
68
+ font-family: var(--font-family-mono);
69
+ font-size: var(--font-size-2xs);
70
+ font-variant-numeric: tabular-nums;
71
+ color: var(--color-feedback-warning-ink);
72
+ }
73
+
74
+ .crewlet-composer__spacer {
75
+ flex: 1;
76
+ }
77
+
78
+ @media (width < 640px) {
79
+ .crewlet-composer__hint {
80
+ display: none;
81
+ }
82
+ }
83
+
84
+ @media (prefers-reduced-motion: reduce) {
85
+ .crewlet-composer {
86
+ transition: none;
87
+ }
88
+ }
@@ -1,6 +1,6 @@
1
- export { CopyButton, Copyable } from '../chunk-26SCUACK.js';
1
+ export { CopyButton, Copyable } from '../chunk-YACKC3K2.js';
2
2
  import '../chunk-5VNUYO76.js';
3
- import '../chunk-4FQT6ZAY.js';
4
3
  import '../chunk-OG6CL3EB.js';
4
+ import '../chunk-4FQT6ZAY.js';
5
5
  import '../chunk-BZFWDIV6.js';
6
6
  import '../chunk-ODEQTPFM.js';
@@ -1,14 +1,14 @@
1
- export { ALL_ITEMS, CopyableCell, DATA_TABLE_LABELS, DataTable, RowActionsMenu } from '../chunk-CVB7O3SZ.js';
2
- import '../chunk-LSB3EHBW.js';
3
- import '../chunk-EUCC37WY.js';
4
- import '../chunk-BTHX2FS3.js';
1
+ export { ALL_ITEMS, CopyableCell, DATA_TABLE_LABELS, DataTable, RowActionsMenu } from '../chunk-GOUKOXJK.js';
5
2
  import '../chunk-AV2DXAEL.js';
6
- import '../chunk-YCTMKKRA.js';
3
+ import '../chunk-TFH6SYWB.js';
4
+ import '../chunk-EUCC37WY.js';
5
+ import '../chunk-TEEJSTFG.js';
7
6
  import '../chunk-5VNUYO76.js';
7
+ import '../chunk-OG6CL3EB.js';
8
+ import '../chunk-YCTMKKRA.js';
8
9
  import '../chunk-PQADV6P6.js';
10
+ import '../chunk-4FQT6ZAY.js';
9
11
  import '../chunk-7RPGY3JE.js';
10
12
  import '../chunk-R25RGPUB.js';
11
- import '../chunk-4FQT6ZAY.js';
12
- import '../chunk-OG6CL3EB.js';
13
13
  import '../chunk-BZFWDIV6.js';
14
14
  import '../chunk-ODEQTPFM.js';
@@ -1,25 +1,25 @@
1
- export { DATA_VIEW_TOOLBAR_LABELS, DataView, DataViewToolbar, FILTER_AXIS_LABELS, FilterAxisBar, FilterAxisChip, applyColumnFilters, applyFilters, blankFilterValue, defaultOperator, filterDefsFromColumns, filterHasValue, filterPredicate, formatFilterValue, operatorOf, tableColumns } from '../chunk-EUT7VBQG.js';
1
+ export { DATA_VIEW_TOOLBAR_LABELS, DataView, DataViewToolbar, FILTER_AXIS_LABELS, FilterAxisBar, FilterAxisChip, applyColumnFilters, applyFilters, blankFilterValue, defaultOperator, filterDefsFromColumns, filterHasValue, filterPredicate, formatFilterValue, operatorOf, tableColumns } from '../chunk-IINFVK3W.js';
2
2
  import '../chunk-PGRPNDWM.js';
3
- import '../chunk-3CZ7XAVY.js';
4
3
  import '../chunk-HOXGBLEY.js';
5
- import '../chunk-SMBKXWML.js';
4
+ import '../chunk-3CZ7XAVY.js';
5
+ import '../chunk-JCNUQ3US.js';
6
6
  import '../chunk-6MU7HNB4.js';
7
- import '../chunk-ZGX2DP7F.js';
8
- import '../chunk-CVB7O3SZ.js';
9
- import '../chunk-LSB3EHBW.js';
7
+ import '../chunk-SMBKXWML.js';
8
+ import '../chunk-FTEJPHBI.js';
9
+ import '../chunk-GOUKOXJK.js';
10
+ import '../chunk-AV2DXAEL.js';
11
+ import '../chunk-TFH6SYWB.js';
10
12
  import '../chunk-EUCC37WY.js';
11
- import '../chunk-BTHX2FS3.js';
12
- import '../chunk-5I56UXBJ.js';
13
- import '../chunk-PDUZO35I.js';
13
+ import '../chunk-TEEJSTFG.js';
14
+ import '../chunk-5VNUYO76.js';
14
15
  import '../chunk-GXQ3B46I.js';
15
- import '../chunk-AV2DXAEL.js';
16
+ import '../chunk-OG6CL3EB.js';
16
17
  import '../chunk-YCTMKKRA.js';
17
- import '../chunk-5VNUYO76.js';
18
- import '../chunk-BHHIIK3M.js';
19
18
  import '../chunk-PQADV6P6.js';
19
+ import '../chunk-4FQT6ZAY.js';
20
+ import '../chunk-PDUZO35I.js';
21
+ import '../chunk-BHHIIK3M.js';
20
22
  import '../chunk-7RPGY3JE.js';
21
23
  import '../chunk-R25RGPUB.js';
22
- import '../chunk-4FQT6ZAY.js';
23
- import '../chunk-OG6CL3EB.js';
24
24
  import '../chunk-BZFWDIV6.js';
25
25
  import '../chunk-ODEQTPFM.js';
@@ -1,9 +1,9 @@
1
- export { DEFAULT_DATE_TIME_PICKER_LABELS, DateTimePicker } from '../chunk-5I56UXBJ.js';
2
- import '../chunk-PDUZO35I.js';
1
+ export { DEFAULT_DATE_TIME_PICKER_LABELS, DateTimePicker } from '../chunk-JCNUQ3US.js';
3
2
  import '../chunk-GXQ3B46I.js';
3
+ import '../chunk-OG6CL3EB.js';
4
+ import '../chunk-4FQT6ZAY.js';
5
+ import '../chunk-PDUZO35I.js';
4
6
  import '../chunk-7RPGY3JE.js';
5
7
  import '../chunk-R25RGPUB.js';
6
- import '../chunk-4FQT6ZAY.js';
7
- import '../chunk-OG6CL3EB.js';
8
8
  import '../chunk-BZFWDIV6.js';
9
9
  import '../chunk-ODEQTPFM.js';
@@ -1,6 +1,6 @@
1
- export { Disclosure } from '../chunk-MICH6QSJ.js';
2
- export { DisclosureAnatomy } from '../chunk-FZVJDJFN.js';
3
- import '../chunk-BHHIIK3M.js';
1
+ export { Disclosure } from '../chunk-S4RCG44T.js';
2
+ export { DisclosureAnatomy } from '../chunk-ENJUPIND.js';
4
3
  import '../chunk-PQADV6P6.js';
4
+ import '../chunk-BHHIIK3M.js';
5
5
  import '../chunk-BZFWDIV6.js';
6
6
  import '../chunk-ODEQTPFM.js';