@crewlethq/ui 0.11.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.
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`, `AvatarPicker`, `FactList` |
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,16 @@ 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
+
194
204
  ## Changes in 0.11.0
195
205
 
196
206
  0.11.0 adds the parts a dense editing form is built from.
@@ -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,6 +1,6 @@
1
- export { Combobox } from '../chunk-ELZKOVEC.js';
2
- import '../chunk-FTEJPHBI.js';
1
+ export { Combobox } from '../chunk-GXYNEDNA.js';
3
2
  import '../chunk-6MU7HNB4.js';
3
+ import '../chunk-FTEJPHBI.js';
4
4
  import '../chunk-PQADV6P6.js';
5
5
  import '../chunk-4FQT6ZAY.js';
6
6
  import '../chunk-R25RGPUB.js';
@@ -1,7 +1,7 @@
1
- export { CommandPalette } from '../chunk-6SDGRKQ7.js';
1
+ export { CommandPalette } from '../chunk-XV65NTIT.js';
2
+ import '../chunk-6MU7HNB4.js';
2
3
  import '../chunk-SMBKXWML.js';
3
4
  import '../chunk-FTEJPHBI.js';
4
- import '../chunk-6MU7HNB4.js';
5
5
  import '../chunk-TEEJSTFG.js';
6
6
  import '../chunk-OG6CL3EB.js';
7
7
  import '../chunk-PQADV6P6.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,10 +1,10 @@
1
- export { ALL_ITEMS, CopyableCell, DATA_TABLE_LABELS, DataTable, RowActionsMenu } from '../chunk-R4ZJB5YX.js';
1
+ export { ALL_ITEMS, CopyableCell, DATA_TABLE_LABELS, DataTable, RowActionsMenu } from '../chunk-GOUKOXJK.js';
2
+ import '../chunk-AV2DXAEL.js';
2
3
  import '../chunk-TFH6SYWB.js';
3
4
  import '../chunk-EUCC37WY.js';
4
5
  import '../chunk-TEEJSTFG.js';
5
6
  import '../chunk-5VNUYO76.js';
6
7
  import '../chunk-OG6CL3EB.js';
7
- import '../chunk-AV2DXAEL.js';
8
8
  import '../chunk-YCTMKKRA.js';
9
9
  import '../chunk-PQADV6P6.js';
10
10
  import '../chunk-4FQT6ZAY.js';
@@ -1,19 +1,19 @@
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-CIOKUMVC.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';
4
+ import '../chunk-3CZ7XAVY.js';
5
5
  import '../chunk-JCNUQ3US.js';
6
+ import '../chunk-6MU7HNB4.js';
6
7
  import '../chunk-SMBKXWML.js';
7
8
  import '../chunk-FTEJPHBI.js';
8
- import '../chunk-6MU7HNB4.js';
9
- import '../chunk-R4ZJB5YX.js';
9
+ import '../chunk-GOUKOXJK.js';
10
+ import '../chunk-AV2DXAEL.js';
10
11
  import '../chunk-TFH6SYWB.js';
11
12
  import '../chunk-EUCC37WY.js';
12
13
  import '../chunk-TEEJSTFG.js';
13
14
  import '../chunk-5VNUYO76.js';
14
15
  import '../chunk-GXQ3B46I.js';
15
16
  import '../chunk-OG6CL3EB.js';
16
- import '../chunk-AV2DXAEL.js';
17
17
  import '../chunk-YCTMKKRA.js';
18
18
  import '../chunk-PQADV6P6.js';
19
19
  import '../chunk-4FQT6ZAY.js';
@@ -1,9 +1,9 @@
1
- export { ListInput } from '../chunk-LZP7FGT7.js';
1
+ export { ListInput } from '../chunk-GARACZAH.js';
2
2
  import '../chunk-SMBKXWML.js';
3
3
  import '../chunk-FTEJPHBI.js';
4
4
  import '../chunk-PQADV6P6.js';
5
- import '../chunk-4FQT6ZAY.js';
6
5
  import '../chunk-RSAQOKH3.js';
6
+ import '../chunk-4FQT6ZAY.js';
7
7
  import '../chunk-7RPGY3JE.js';
8
8
  import '../chunk-R25RGPUB.js';
9
9
  import '../chunk-BZFWDIV6.js';
@@ -1,9 +1,9 @@
1
- export { TagsInput } from '../chunk-7JGWSOLM.js';
1
+ export { TagsInput } from '../chunk-ZHOM65MI.js';
2
2
  import '../chunk-LOECRMHA.js';
3
3
  import '../chunk-WIATRXEJ.js';
4
4
  import '../chunk-6MU7HNB4.js';
5
- import '../chunk-4FQT6ZAY.js';
6
5
  import '../chunk-RSAQOKH3.js';
6
+ import '../chunk-4FQT6ZAY.js';
7
7
  import '../chunk-7RPGY3JE.js';
8
8
  import '../chunk-R25RGPUB.js';
9
9
  import '../chunk-BZFWDIV6.js';
@@ -1,7 +1,7 @@
1
1
  export { DEFAULT_TIME_WINDOW_LABELS, TIME_WINDOW_SPANS, TimeWindowPicker, describeTimeWindow, isTimeWindowSet, parseTimeWindowDuration, resolveTimeWindow, timeWindowMatchesPreset } from '../chunk-HLBRPES3.js';
2
2
  import '../chunk-SEFMO2EV.js';
3
- import '../chunk-FTEJPHBI.js';
4
3
  import '../chunk-6MU7HNB4.js';
4
+ import '../chunk-FTEJPHBI.js';
5
5
  import '../chunk-GXQ3B46I.js';
6
6
  import '../chunk-OG6CL3EB.js';
7
7
  import '../chunk-PQADV6P6.js';
@@ -1,11 +1,11 @@
1
1
  import { Toolbar } from './chunk-PGRPNDWM.js';
2
- import { RelativeTime } from './chunk-3CZ7XAVY.js';
3
2
  import { PageHeader } from './chunk-HOXGBLEY.js';
3
+ import { RelativeTime } from './chunk-3CZ7XAVY.js';
4
4
  import { DateTimePicker } from './chunk-JCNUQ3US.js';
5
+ import { useListbox, useOptionKeys } from './chunk-6MU7HNB4.js';
5
6
  import { Kbd } from './chunk-SMBKXWML.js';
6
7
  import { Input } from './chunk-FTEJPHBI.js';
7
- import { useListbox, useOptionKeys } from './chunk-6MU7HNB4.js';
8
- import { DataTable } from './chunk-R4ZJB5YX.js';
8
+ import { DataTable } from './chunk-GOUKOXJK.js';
9
9
  import { Menu } from './chunk-TFH6SYWB.js';
10
10
  import { Button } from './chunk-OG6CL3EB.js';
11
11
  import { IconButton } from './chunk-4FQT6ZAY.js';
@@ -0,0 +1,40 @@
1
+ import { cx } from './chunk-ODEQTPFM.js';
2
+ import './ChoiceList-2PQJS4DX.css';
3
+ import { useId } from 'react';
4
+ import { jsxs, jsx } from 'react/jsx-runtime';
5
+
6
+ function ChoiceList({ options, value, onChange, label, footer, disabled, className }) {
7
+ const name = useId();
8
+ return /* @__PURE__ */ jsxs("div", { className: cx("crewlet-choice-list", disabled && "is-disabled", className), children: [
9
+ /* @__PURE__ */ jsx("div", { role: "radiogroup", "aria-label": label, className: "crewlet-choice-list__group", children: options.map((option) => {
10
+ const id = `${name}-${option.value}`;
11
+ const checked = option.value === value;
12
+ return /* @__PURE__ */ jsxs("div", { className: cx("crewlet-choice-list__item", option.separated && "is-separated"), children: [
13
+ /* @__PURE__ */ jsxs("label", { className: cx("crewlet-choice-list__row", checked && "is-checked"), htmlFor: id, children: [
14
+ /* @__PURE__ */ jsx(
15
+ "input",
16
+ {
17
+ id,
18
+ type: "radio",
19
+ name,
20
+ value: option.value,
21
+ checked,
22
+ disabled,
23
+ onChange: () => onChange(option.value),
24
+ className: "crewlet-choice-list__radio"
25
+ }
26
+ ),
27
+ /* @__PURE__ */ jsxs("span", { className: "crewlet-choice-list__text", children: [
28
+ /* @__PURE__ */ jsx("span", { className: "crewlet-choice-list__label", children: option.label }),
29
+ option.detail ? /* @__PURE__ */ jsx("span", { className: "crewlet-choice-list__detail", children: option.detail }) : null
30
+ ] }),
31
+ option.tag ? /* @__PURE__ */ jsx("span", { className: "crewlet-choice-list__tag", children: option.tag }) : null
32
+ ] }),
33
+ checked && option.panel ? /* @__PURE__ */ jsx("div", { className: "crewlet-choice-list__panel", children: option.panel }) : null
34
+ ] }, option.value);
35
+ }) }),
36
+ footer ? /* @__PURE__ */ jsx("div", { className: "crewlet-choice-list__footer", children: footer }) : null
37
+ ] });
38
+ }
39
+
40
+ export { ChoiceList };
@@ -0,0 +1,47 @@
1
+ import { Kbd } from './chunk-SMBKXWML.js';
2
+ import { Textarea } from './chunk-FTEJPHBI.js';
3
+ import { cx } from './chunk-ODEQTPFM.js';
4
+ import './Composer-ABGJIAIR.css';
5
+ import { forwardRef } from 'react';
6
+ import { jsxs, jsx } from 'react/jsx-runtime';
7
+
8
+ var COMPOSER_COUNTER_AT = 0.8;
9
+ var Composer = forwardRef(function Composer2({ value, onChange, onSubmit, label, actions, maxLength, className, rows = 3, onKeyDown, ...rest }, ref) {
10
+ const near = maxLength !== void 0 && value.length >= maxLength * COMPOSER_COUNTER_AT;
11
+ const keyDown = (event) => {
12
+ onKeyDown?.(event);
13
+ if (event.defaultPrevented || !onSubmit) return;
14
+ if (event.key === "Enter" && (event.metaKey || event.ctrlKey)) {
15
+ event.preventDefault();
16
+ onSubmit();
17
+ }
18
+ };
19
+ return /* @__PURE__ */ jsxs("div", { className: cx("crewlet-composer", className), children: [
20
+ /* @__PURE__ */ jsx(
21
+ Textarea,
22
+ {
23
+ ref,
24
+ className: "crewlet-composer__field",
25
+ "aria-label": label,
26
+ value,
27
+ onChange: (event) => onChange(event.target.value),
28
+ onKeyDown: keyDown,
29
+ maxLength,
30
+ rows,
31
+ autoResize: true,
32
+ ...rest
33
+ }
34
+ ),
35
+ /* @__PURE__ */ jsxs("div", { className: "crewlet-composer__footer", children: [
36
+ onSubmit ? /* @__PURE__ */ jsxs("span", { className: "crewlet-composer__hint", children: [
37
+ /* @__PURE__ */ jsx(Kbd, { keys: ["Mod", "Enter"], subtle: true }),
38
+ " to send"
39
+ ] }) : null,
40
+ near ? /* @__PURE__ */ jsx("span", { className: "crewlet-composer__counter", "aria-live": "polite", children: `${value.length.toLocaleString()} / ${maxLength.toLocaleString()}` }) : null,
41
+ /* @__PURE__ */ jsx("span", { className: "crewlet-composer__spacer" }),
42
+ actions
43
+ ] })
44
+ ] });
45
+ });
46
+
47
+ export { COMPOSER_COUNTER_AT, Composer };
@@ -13,9 +13,11 @@ export * from '../Card/index.js';
13
13
  export * from '../CharacterPicker/index.js';
14
14
  export * from '../Charts/index.js';
15
15
  export * from '../Checkbox/index.js';
16
+ export * from '../ChoiceList/index.js';
16
17
  export * from '../CodeBlock/index.js';
17
18
  export * from '../Combobox/index.js';
18
19
  export * from '../CommandPalette/index.js';
20
+ export * from '../Composer/index.js';
19
21
  export * from '../Container/index.js';
20
22
  export * from '../Copyable/index.js';
21
23
  export * from '../Count/index.js';
@@ -1,24 +1,26 @@
1
- import '../chunk-PQLMLG5K.js';
1
+ import '../chunk-74OVQWA5.js';
2
2
  export { TreeCanvas } from '../chunk-5WEVLIB6.js';
3
+ export { Card } from '../chunk-EG6NYWVK.js';
3
4
  import '../chunk-AER7UDD4.js';
5
+ export { DensitySwitcher, ThemeSwitcher } from '../chunk-WEIINZPA.js';
4
6
  export { ThemeToggle } from '../chunk-ORNOOMVY.js';
7
+ export { applyDensity, applyStoredPreferences, applyTheme, resolveTheme, useDensityPreference, useSystemTheme, useThemePreference } from '../chunk-K3OWD7BJ.js';
5
8
  export { DEFAULT_TIME_WINDOW_LABELS, TIME_WINDOW_SPANS, TimeWindowPicker, describeTimeWindow, isTimeWindowSet, parseTimeWindowDuration, resolveTimeWindow, timeWindowMatchesPreset } from '../chunk-HLBRPES3.js';
6
9
  export { Timeline, TimelineItem } from '../chunk-O67VF5MS.js';
7
10
  export { ToastProvider, Toaster, useToast } from '../chunk-UG5ZMAXW.js';
11
+ export { Stepper } from '../chunk-5QWIJSQM.js';
8
12
  export { Switch } from '../chunk-A722MUNR.js';
9
13
  export { Table } from '../chunk-V2N3BMOT.js';
10
14
  export { TagGroup } from '../chunk-E6UWRXNM.js';
11
- export { TagsInput } from '../chunk-7JGWSOLM.js';
15
+ export { TagsInput } from '../chunk-ZHOM65MI.js';
12
16
  export { Text } from '../chunk-23DHIMJA.js';
13
- export { DensitySwitcher, ThemeSwitcher } from '../chunk-WEIINZPA.js';
14
- export { applyDensity, applyStoredPreferences, applyTheme, resolveTheme, useDensityPreference, useSystemTheme, useThemePreference } from '../chunk-K3OWD7BJ.js';
17
+ export { SegmentedMeter, segmentedMeterLabel } from '../chunk-4AK52VHB.js';
15
18
  export { Select } from '../chunk-SEFMO2EV.js';
16
19
  export { matchesShortcut, useShortcut } from '../chunk-2FPENTCF.js';
17
20
  export { NavGroup, NavItem, SidebarNav } from '../chunk-IVFJD7WY.js';
18
21
  export { Skeleton } from '../chunk-W5J7R5EB.js';
19
22
  export { StatCard } from '../chunk-IKB6HFGK.js';
20
23
  export { StatGroup } from '../chunk-QVAFL2LE.js';
21
- export { Stepper } from '../chunk-5QWIJSQM.js';
22
24
  export { PricingCard } from '../chunk-UCYIRDND.js';
23
25
  export { Tag } from '../chunk-LOECRMHA.js';
24
26
  export { StatusDot } from '../chunk-WIATRXEJ.js';
@@ -26,7 +28,6 @@ export { Prose } from '../chunk-JCSA3XVH.js';
26
28
  export { SearchTrigger } from '../chunk-6DRDCT22.js';
27
29
  export { Section } from '../chunk-A2UXBCLO.js';
28
30
  import '../chunk-UAQIUSSK.js';
29
- export { SegmentedMeter, segmentedMeterLabel } from '../chunk-4AK52VHB.js';
30
31
  export { DEFAULT_METER_THRESHOLDS, METER_STATES, Meter, meterState, meterStateTone, meterTone, progressTone } from '../chunk-4PZ6FJKW.js';
31
32
  export { NewItemsNotice } from '../chunk-PXU6HOZB.js';
32
33
  export { OrgNodeDisclosure, OrgNodeLabel, OrgNodeLead } from '../chunk-IHGKPEEV.js';
@@ -34,10 +35,12 @@ export { OrgTable, OrgTableActions, OrgTableAdd, OrgTableName } from '../chunk-Z
34
35
  export { TreeGrid } from '../chunk-MCPKHYMC.js';
35
36
  export { SIZE_EPSILON, TYPE_AHEAD_RESET_MS, createTreeModel, isTypeAheadKey, layoutConnectors, layoutForest, placeGroups, treeAllExpandable, treeAncestors, treeCollapseOrAscend, treeExpandOrDescend, treeExpandTo, treeExpandable, treeFirst, treeFirstChild, treeItemAction, treeLast, treeLevel, treeNext, treeParent, treePosInSet, treePrevious, treeSetSize, treeStep, treeTypeAhead, treeVisible, typeAheadBuffer, useLayoutAnchor, useMeasuredSizes, useTreeState } from '../chunk-S3BCVWTU.js';
36
37
  export { OrgLabel } from '../chunk-6OF2DBKY.js';
38
+ export { InlineCode } from '../chunk-NN62JQLR.js';
37
39
  export { AutoGrid, Inline, Spacer, Stack } from '../chunk-W4ENKCXJ.js';
38
40
  export { Link } from '../chunk-ZPSOF6VL.js';
39
41
  export { List, ListItem } from '../chunk-DS2C73RJ.js';
40
- export { ListInput } from '../chunk-LZP7FGT7.js';
42
+ export { ListInput } from '../chunk-GARACZAH.js';
43
+ export { ErrorBoundary } from '../chunk-XX2VQE55.js';
41
44
  export { Eyebrow } from '../chunk-RK4XPHVG.js';
42
45
  export { FactList } from '../chunk-URYDN2KA.js';
43
46
  export { Tooltip } from '../chunk-CQY5NTRS.js';
@@ -45,27 +48,27 @@ export { FILTER_CHIP_ATTRIBUTE, FilterChip, FilterChipGroup } from '../chunk-5YL
45
48
  export { useFullscreen } from '../chunk-XDTYBF2F.js';
46
49
  import '../chunk-EXHQ2QVW.js';
47
50
  export { ImageUpload } from '../chunk-LAQK4V3Z.js';
48
- export { InlineCode } from '../chunk-NN62JQLR.js';
51
+ 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';
52
+ export { Toolbar, ToolbarOverflow, ToolbarWide } from '../chunk-PGRPNDWM.js';
53
+ export { PageHeader } from '../chunk-HOXGBLEY.js';
54
+ export { RelativeTime, currentNow, formatElapsed, formatExact, formatRelative, formatUntil, toISO, toInstant, useNow } from '../chunk-3CZ7XAVY.js';
55
+ export { DEFAULT_DATE_TIME_PICKER_LABELS, DateTimePicker } from '../chunk-JCNUQ3US.js';
49
56
  export { DescriptionList, DescriptionListItem } from '../chunk-XN4JBAN3.js';
50
57
  export { DIFF_LIST_LABELS, DiffList } from '../chunk-LFHCXZO5.js';
51
58
  export { Disclosure } from '../chunk-S4RCG44T.js';
52
59
  export { EmptyState } from '../chunk-RA2ULG6H.js';
53
60
  export { EntityChip } from '../chunk-DDTDN5L2.js';
54
- export { ErrorBoundary } from '../chunk-XX2VQE55.js';
55
61
  export { CodeBlock } from '../chunk-KGTQ5CVD.js';
56
- export { Combobox } from '../chunk-ELZKOVEC.js';
57
- export { CommandPalette } from '../chunk-6SDGRKQ7.js';
58
- export { Container } from '../chunk-QVE4GJAT.js';
59
- export { CopyButton, Copyable } from '../chunk-YACKC3K2.js';
60
- export { DATA_VIEW_TOOLBAR_LABELS, DataView, DataViewToolbar, FILTER_AXIS_LABELS, FilterAxisBar, FilterAxisChip, applyColumnFilters, applyFilters, blankFilterValue, defaultOperator, filterDefsFromColumns, filterHasValue, filterPredicate, formatFilterValue, operatorOf, tableColumns } from '../chunk-CIOKUMVC.js';
61
- export { Toolbar, ToolbarOverflow, ToolbarWide } from '../chunk-PGRPNDWM.js';
62
- export { RelativeTime, currentNow, formatElapsed, formatExact, formatRelative, formatUntil, toISO, toInstant, useNow } from '../chunk-3CZ7XAVY.js';
63
- export { PageHeader } from '../chunk-HOXGBLEY.js';
64
- export { DEFAULT_DATE_TIME_PICKER_LABELS, DateTimePicker } from '../chunk-JCNUQ3US.js';
62
+ export { Combobox } from '../chunk-GXYNEDNA.js';
63
+ export { CommandPalette } from '../chunk-XV65NTIT.js';
64
+ export { TYPE_AHEAD_WINDOW, useListbox, useOptionKeys } from '../chunk-6MU7HNB4.js';
65
+ export { COMPOSER_COUNTER_AT, Composer } from '../chunk-QSLIN64M.js';
65
66
  export { Kbd, isApplePlatform, keyGlyph } from '../chunk-SMBKXWML.js';
66
67
  export { FormField, FormRow, FormSection, Input, InputAffix, Label, ReadOnlyField, Textarea } from '../chunk-FTEJPHBI.js';
67
- export { TYPE_AHEAD_WINDOW, useListbox, useOptionKeys } from '../chunk-6MU7HNB4.js';
68
- export { ALL_ITEMS, CopyableCell, DATA_TABLE_LABELS, DataTable, RowActionsMenu } from '../chunk-R4ZJB5YX.js';
68
+ export { Container } from '../chunk-QVE4GJAT.js';
69
+ export { CopyButton, Copyable } from '../chunk-YACKC3K2.js';
70
+ export { ALL_ITEMS, CopyableCell, DATA_TABLE_LABELS, DataTable, RowActionsMenu } from '../chunk-GOUKOXJK.js';
71
+ export { useCardHeaderSlot } from '../chunk-AV2DXAEL.js';
69
72
  export { Menu } from '../chunk-TFH6SYWB.js';
70
73
  export { EMPTY_VALUE, EmptyValue } from '../chunk-EUCC37WY.js';
71
74
  export { ConfirmModal, Modal } from '../chunk-TEEJSTFG.js';
@@ -75,19 +78,19 @@ export { Callout } from '../chunk-R6FBDTP3.js';
75
78
  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';
76
79
  import '../chunk-53DVJCVW.js';
77
80
  export { Button, ButtonLink } from '../chunk-OG6CL3EB.js';
78
- export { Card } from '../chunk-EG6NYWVK.js';
79
- export { useCardHeaderSlot } from '../chunk-AV2DXAEL.js';
80
81
  import '../chunk-3L5NHASN.js';
81
82
  export { ActivityStrip, BarList, ChartTooltip, DATA_COLORS, DATA_COLOR_OTHER, Legend, Sparkline, StackedBar, StackedColumns, TimeSeries, dataColor, niceScale, useChartHover } from '../chunk-4WNNEDKO.js';
82
83
  export { Checkbox } from '../chunk-YCTMKKRA.js';
84
+ export { ChoiceList } from '../chunk-QBXZLGK2.js';
83
85
  export { Accordion, AccordionItem } from '../chunk-G2AVKPSL.js';
84
86
  export { DisclosureAnatomy } from '../chunk-ENJUPIND.js';
85
87
  export { HeadingLevelProvider, headingTag, nextHeadingLevel, useHeadingLevel } from '../chunk-PQADV6P6.js';
86
88
  export { ADD_PILL_MS, AddPill } from '../chunk-74WGARJE.js';
89
+ export { Announcer, announce, useAnnouncer } from '../chunk-RSAQOKH3.js';
87
90
  export { AppShell, AppShellRail, AppShellRailRow, AppShellToggle, AppShellTopbar, useAppShell } from '../chunk-7LD6P32I.js';
88
91
  export { IconButton } from '../chunk-4FQT6ZAY.js';
89
- export { Announcer, announce, useAnnouncer } from '../chunk-RSAQOKH3.js';
90
92
  export { AvatarStack, avatarStackLabel } from '../chunk-3UK4VFSK.js';
93
+ export { BrandLockup } from '../chunk-7KBNFFM3.js';
91
94
  export { AvatarPicker } from '../chunk-HV6IZFBK.js';
92
95
  export { HuePicker } from '../chunk-K5Q2DK3P.js';
93
96
  export { NODE_HUES, NODE_HUE_NAMES, isNodeHue } from '../chunk-AYKXMIOR.js';
@@ -101,5 +104,4 @@ export { LAYER_GAP, LAYER_REPOSITION_EVENT, LayerHost, outsideBounds, placePopup
101
104
  export { focusables, isComposing, isModalLayerOpen, layerCount, useBodyScrollLock, useModalLayer, usePopupLayer } from '../chunk-R25RGPUB.js';
102
105
  export { VisuallyHidden } from '../chunk-BZFWDIV6.js';
103
106
  export { AVATAR_CHARACTER_FULL_DETAIL, AVATAR_CORNER_RATIO, AVATAR_SIZES, AVATAR_STATUSES, AVATAR_STATUS_LABELS, Avatar, avatarCorner, avatarPixels, avatarTint, getInitials } from '../chunk-HI6Q2UXQ.js';
104
- export { BrandLockup } from '../chunk-7KBNFFM3.js';
105
107
  export { cx } from '../chunk-ODEQTPFM.js';
package/dist/index.js CHANGED
@@ -1,24 +1,26 @@
1
- import './chunk-PQLMLG5K.js';
1
+ import './chunk-74OVQWA5.js';
2
2
  export { TreeCanvas } from './chunk-5WEVLIB6.js';
3
+ export { Card } from './chunk-EG6NYWVK.js';
3
4
  import './chunk-AER7UDD4.js';
5
+ export { DensitySwitcher, ThemeSwitcher } from './chunk-WEIINZPA.js';
4
6
  export { ThemeToggle } from './chunk-ORNOOMVY.js';
7
+ export { applyDensity, applyStoredPreferences, applyTheme, resolveTheme, useDensityPreference, useSystemTheme, useThemePreference } from './chunk-K3OWD7BJ.js';
5
8
  export { DEFAULT_TIME_WINDOW_LABELS, TIME_WINDOW_SPANS, TimeWindowPicker, describeTimeWindow, isTimeWindowSet, parseTimeWindowDuration, resolveTimeWindow, timeWindowMatchesPreset } from './chunk-HLBRPES3.js';
6
9
  export { Timeline, TimelineItem } from './chunk-O67VF5MS.js';
7
10
  export { ToastProvider, Toaster, useToast } from './chunk-UG5ZMAXW.js';
11
+ export { Stepper } from './chunk-5QWIJSQM.js';
8
12
  export { Switch } from './chunk-A722MUNR.js';
9
13
  export { Table } from './chunk-V2N3BMOT.js';
10
14
  export { TagGroup } from './chunk-E6UWRXNM.js';
11
- export { TagsInput } from './chunk-7JGWSOLM.js';
15
+ export { TagsInput } from './chunk-ZHOM65MI.js';
12
16
  export { Text } from './chunk-23DHIMJA.js';
13
- export { DensitySwitcher, ThemeSwitcher } from './chunk-WEIINZPA.js';
14
- export { applyDensity, applyStoredPreferences, applyTheme, resolveTheme, useDensityPreference, useSystemTheme, useThemePreference } from './chunk-K3OWD7BJ.js';
17
+ export { SegmentedMeter, segmentedMeterLabel } from './chunk-4AK52VHB.js';
15
18
  export { Select } from './chunk-SEFMO2EV.js';
16
19
  export { matchesShortcut, useShortcut } from './chunk-2FPENTCF.js';
17
20
  export { NavGroup, NavItem, SidebarNav } from './chunk-IVFJD7WY.js';
18
21
  export { Skeleton } from './chunk-W5J7R5EB.js';
19
22
  export { StatCard } from './chunk-IKB6HFGK.js';
20
23
  export { StatGroup } from './chunk-QVAFL2LE.js';
21
- export { Stepper } from './chunk-5QWIJSQM.js';
22
24
  export { PricingCard } from './chunk-UCYIRDND.js';
23
25
  export { Tag } from './chunk-LOECRMHA.js';
24
26
  export { StatusDot } from './chunk-WIATRXEJ.js';
@@ -26,7 +28,6 @@ export { Prose } from './chunk-JCSA3XVH.js';
26
28
  export { SearchTrigger } from './chunk-6DRDCT22.js';
27
29
  export { Section } from './chunk-A2UXBCLO.js';
28
30
  import './chunk-UAQIUSSK.js';
29
- export { SegmentedMeter, segmentedMeterLabel } from './chunk-4AK52VHB.js';
30
31
  export { DEFAULT_METER_THRESHOLDS, METER_STATES, Meter, meterState, meterStateTone, meterTone, progressTone } from './chunk-4PZ6FJKW.js';
31
32
  export { NewItemsNotice } from './chunk-PXU6HOZB.js';
32
33
  export { OrgNodeDisclosure, OrgNodeLabel, OrgNodeLead } from './chunk-IHGKPEEV.js';
@@ -34,10 +35,12 @@ export { OrgTable, OrgTableActions, OrgTableAdd, OrgTableName } from './chunk-ZM
34
35
  export { TreeGrid } from './chunk-MCPKHYMC.js';
35
36
  export { SIZE_EPSILON, TYPE_AHEAD_RESET_MS, createTreeModel, isTypeAheadKey, layoutConnectors, layoutForest, placeGroups, treeAllExpandable, treeAncestors, treeCollapseOrAscend, treeExpandOrDescend, treeExpandTo, treeExpandable, treeFirst, treeFirstChild, treeItemAction, treeLast, treeLevel, treeNext, treeParent, treePosInSet, treePrevious, treeSetSize, treeStep, treeTypeAhead, treeVisible, typeAheadBuffer, useLayoutAnchor, useMeasuredSizes, useTreeState } from './chunk-S3BCVWTU.js';
36
37
  export { OrgLabel } from './chunk-6OF2DBKY.js';
38
+ export { InlineCode } from './chunk-NN62JQLR.js';
37
39
  export { AutoGrid, Inline, Spacer, Stack } from './chunk-W4ENKCXJ.js';
38
40
  export { Link } from './chunk-ZPSOF6VL.js';
39
41
  export { List, ListItem } from './chunk-DS2C73RJ.js';
40
- export { ListInput } from './chunk-LZP7FGT7.js';
42
+ export { ListInput } from './chunk-GARACZAH.js';
43
+ export { ErrorBoundary } from './chunk-XX2VQE55.js';
41
44
  export { Eyebrow } from './chunk-RK4XPHVG.js';
42
45
  export { FactList } from './chunk-URYDN2KA.js';
43
46
  export { Tooltip } from './chunk-CQY5NTRS.js';
@@ -45,27 +48,27 @@ export { FILTER_CHIP_ATTRIBUTE, FilterChip, FilterChipGroup } from './chunk-5YLO
45
48
  export { useFullscreen } from './chunk-XDTYBF2F.js';
46
49
  import './chunk-EXHQ2QVW.js';
47
50
  export { ImageUpload } from './chunk-LAQK4V3Z.js';
48
- export { InlineCode } from './chunk-NN62JQLR.js';
51
+ 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';
52
+ export { Toolbar, ToolbarOverflow, ToolbarWide } from './chunk-PGRPNDWM.js';
53
+ export { PageHeader } from './chunk-HOXGBLEY.js';
54
+ export { RelativeTime, currentNow, formatElapsed, formatExact, formatRelative, formatUntil, toISO, toInstant, useNow } from './chunk-3CZ7XAVY.js';
55
+ export { DEFAULT_DATE_TIME_PICKER_LABELS, DateTimePicker } from './chunk-JCNUQ3US.js';
49
56
  export { DescriptionList, DescriptionListItem } from './chunk-XN4JBAN3.js';
50
57
  export { DIFF_LIST_LABELS, DiffList } from './chunk-LFHCXZO5.js';
51
58
  export { Disclosure } from './chunk-S4RCG44T.js';
52
59
  export { EmptyState } from './chunk-RA2ULG6H.js';
53
60
  export { EntityChip } from './chunk-DDTDN5L2.js';
54
- export { ErrorBoundary } from './chunk-XX2VQE55.js';
55
61
  export { CodeBlock } from './chunk-KGTQ5CVD.js';
56
- export { Combobox } from './chunk-ELZKOVEC.js';
57
- export { CommandPalette } from './chunk-6SDGRKQ7.js';
58
- export { Container } from './chunk-QVE4GJAT.js';
59
- export { CopyButton, Copyable } from './chunk-YACKC3K2.js';
60
- export { DATA_VIEW_TOOLBAR_LABELS, DataView, DataViewToolbar, FILTER_AXIS_LABELS, FilterAxisBar, FilterAxisChip, applyColumnFilters, applyFilters, blankFilterValue, defaultOperator, filterDefsFromColumns, filterHasValue, filterPredicate, formatFilterValue, operatorOf, tableColumns } from './chunk-CIOKUMVC.js';
61
- export { Toolbar, ToolbarOverflow, ToolbarWide } from './chunk-PGRPNDWM.js';
62
- export { RelativeTime, currentNow, formatElapsed, formatExact, formatRelative, formatUntil, toISO, toInstant, useNow } from './chunk-3CZ7XAVY.js';
63
- export { PageHeader } from './chunk-HOXGBLEY.js';
64
- export { DEFAULT_DATE_TIME_PICKER_LABELS, DateTimePicker } from './chunk-JCNUQ3US.js';
62
+ export { Combobox } from './chunk-GXYNEDNA.js';
63
+ export { CommandPalette } from './chunk-XV65NTIT.js';
64
+ export { TYPE_AHEAD_WINDOW, useListbox, useOptionKeys } from './chunk-6MU7HNB4.js';
65
+ export { COMPOSER_COUNTER_AT, Composer } from './chunk-QSLIN64M.js';
65
66
  export { Kbd, isApplePlatform, keyGlyph } from './chunk-SMBKXWML.js';
66
67
  export { FormField, FormRow, FormSection, Input, InputAffix, Label, ReadOnlyField, Textarea } from './chunk-FTEJPHBI.js';
67
- export { TYPE_AHEAD_WINDOW, useListbox, useOptionKeys } from './chunk-6MU7HNB4.js';
68
- export { ALL_ITEMS, CopyableCell, DATA_TABLE_LABELS, DataTable, RowActionsMenu } from './chunk-R4ZJB5YX.js';
68
+ export { Container } from './chunk-QVE4GJAT.js';
69
+ export { CopyButton, Copyable } from './chunk-YACKC3K2.js';
70
+ export { ALL_ITEMS, CopyableCell, DATA_TABLE_LABELS, DataTable, RowActionsMenu } from './chunk-GOUKOXJK.js';
71
+ export { useCardHeaderSlot } from './chunk-AV2DXAEL.js';
69
72
  export { Menu } from './chunk-TFH6SYWB.js';
70
73
  export { EMPTY_VALUE, EmptyValue } from './chunk-EUCC37WY.js';
71
74
  export { ConfirmModal, Modal } from './chunk-TEEJSTFG.js';
@@ -75,19 +78,19 @@ export { Callout } from './chunk-R6FBDTP3.js';
75
78
  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';
76
79
  import './chunk-53DVJCVW.js';
77
80
  export { Button, ButtonLink } from './chunk-OG6CL3EB.js';
78
- export { Card } from './chunk-EG6NYWVK.js';
79
- export { useCardHeaderSlot } from './chunk-AV2DXAEL.js';
80
81
  import './chunk-3L5NHASN.js';
81
82
  export { ActivityStrip, BarList, ChartTooltip, DATA_COLORS, DATA_COLOR_OTHER, Legend, Sparkline, StackedBar, StackedColumns, TimeSeries, dataColor, niceScale, useChartHover } from './chunk-4WNNEDKO.js';
82
83
  export { Checkbox } from './chunk-YCTMKKRA.js';
84
+ export { ChoiceList } from './chunk-QBXZLGK2.js';
83
85
  export { Accordion, AccordionItem } from './chunk-G2AVKPSL.js';
84
86
  export { DisclosureAnatomy } from './chunk-ENJUPIND.js';
85
87
  export { HeadingLevelProvider, headingTag, nextHeadingLevel, useHeadingLevel } from './chunk-PQADV6P6.js';
86
88
  export { ADD_PILL_MS, AddPill } from './chunk-74WGARJE.js';
89
+ export { Announcer, announce, useAnnouncer } from './chunk-RSAQOKH3.js';
87
90
  export { AppShell, AppShellRail, AppShellRailRow, AppShellToggle, AppShellTopbar, useAppShell } from './chunk-7LD6P32I.js';
88
91
  export { IconButton } from './chunk-4FQT6ZAY.js';
89
- export { Announcer, announce, useAnnouncer } from './chunk-RSAQOKH3.js';
90
92
  export { AvatarStack, avatarStackLabel } from './chunk-3UK4VFSK.js';
93
+ export { BrandLockup } from './chunk-7KBNFFM3.js';
91
94
  export { AvatarPicker } from './chunk-HV6IZFBK.js';
92
95
  export { HuePicker } from './chunk-K5Q2DK3P.js';
93
96
  export { NODE_HUES, NODE_HUE_NAMES, isNodeHue } from './chunk-AYKXMIOR.js';
@@ -101,5 +104,4 @@ export { LAYER_GAP, LAYER_REPOSITION_EVENT, LayerHost, outsideBounds, placePopup
101
104
  export { focusables, isComposing, isModalLayerOpen, layerCount, useBodyScrollLock, useModalLayer, usePopupLayer } from './chunk-R25RGPUB.js';
102
105
  export { VisuallyHidden } from './chunk-BZFWDIV6.js';
103
106
  export { AVATAR_CHARACTER_FULL_DETAIL, AVATAR_CORNER_RATIO, AVATAR_SIZES, AVATAR_STATUSES, AVATAR_STATUS_LABELS, Avatar, avatarCorner, avatarPixels, avatarTint, getInitials } from './chunk-HI6Q2UXQ.js';
104
- export { BrandLockup } from './chunk-7KBNFFM3.js';
105
107
  export { cx } from './chunk-ODEQTPFM.js';
package/dist/styles.css CHANGED
@@ -4053,6 +4053,118 @@ button.crewlet-avatar-picker:hover .crewlet-avatar-picker__pip {
4053
4053
  }
4054
4054
 
4055
4055
 
4056
+ /* ChoiceList-2PQJS4DX.css */
4057
+ /*
4058
+ * A short list of answers in one bordered box: a radio, the label with a line
4059
+ * of detail under it, and a tag at the row's end. The selected row takes the
4060
+ * accent's soft fill, so the answer reads at a glance without the radio.
4061
+ */
4062
+ .crewlet-choice-list {
4063
+ display: grid;
4064
+ gap: var(--spacing-1);
4065
+ padding: var(--spacing-1);
4066
+ border: 1px solid var(--color-border-strong);
4067
+ border-radius: var(--radius-md);
4068
+ background: var(--color-surface-subtle);
4069
+ }
4070
+
4071
+ .crewlet-choice-list.is-disabled {
4072
+ opacity: 0.6;
4073
+ }
4074
+
4075
+ .crewlet-choice-list__group {
4076
+ display: grid;
4077
+ gap: var(--spacing-1);
4078
+ }
4079
+
4080
+ .crewlet-choice-list__item {
4081
+ display: grid;
4082
+ gap: var(--spacing-1);
4083
+ }
4084
+
4085
+ /* The "Something else" a list ends with, set apart by a dashed rule. */
4086
+ .crewlet-choice-list__item.is-separated {
4087
+ padding-top: var(--spacing-1);
4088
+ border-top: 1px dashed var(--color-border-strong);
4089
+ }
4090
+
4091
+ .crewlet-choice-list__row {
4092
+ display: grid;
4093
+ grid-template-columns: auto minmax(0, 1fr) auto;
4094
+ align-items: start;
4095
+ gap: var(--spacing-3);
4096
+ padding: var(--spacing-2);
4097
+ border-radius: var(--radius-sm);
4098
+ cursor: pointer;
4099
+ transition: background-color var(--motion-duration-fast) var(--motion-easing-default);
4100
+ }
4101
+
4102
+ .crewlet-choice-list__row:hover {
4103
+ background: var(--color-surface-hover);
4104
+ }
4105
+
4106
+ .crewlet-choice-list__row.is-checked {
4107
+ background: var(--color-brand-accent-soft);
4108
+ }
4109
+
4110
+ .crewlet-choice-list.is-disabled .crewlet-choice-list__row {
4111
+ cursor: not-allowed;
4112
+ }
4113
+
4114
+ .crewlet-choice-list__radio {
4115
+ margin: 3px 0 0;
4116
+ accent-color: var(--color-brand-accent);
4117
+ cursor: inherit;
4118
+ }
4119
+
4120
+ /* A radio draws its own edge, so the ring sits on it, as a checkbox's does. */
4121
+ .crewlet-choice-list__radio:focus-visible {
4122
+ outline: 2px solid var(--color-focus);
4123
+ outline-offset: 0;
4124
+ }
4125
+
4126
+ .crewlet-choice-list__text {
4127
+ display: grid;
4128
+ min-width: 0;
4129
+ }
4130
+
4131
+ .crewlet-choice-list__label {
4132
+ font-size: var(--font-size-compact);
4133
+ font-weight: 500;
4134
+ color: var(--color-text-primary);
4135
+ overflow-wrap: anywhere;
4136
+ }
4137
+
4138
+ .crewlet-choice-list__detail {
4139
+ font-size: var(--font-size-xs);
4140
+ color: var(--color-text-tertiary);
4141
+ overflow-wrap: anywhere;
4142
+ }
4143
+
4144
+ .crewlet-choice-list__tag {
4145
+ padding-top: 2px;
4146
+ font-size: var(--font-size-2xs);
4147
+ font-weight: 500;
4148
+ letter-spacing: 0.05em;
4149
+ text-transform: uppercase;
4150
+ color: var(--color-brand-accent-ink);
4151
+ white-space: nowrap;
4152
+ }
4153
+
4154
+ .crewlet-choice-list__footer {
4155
+ display: flex;
4156
+ justify-content: flex-end;
4157
+ gap: var(--spacing-2);
4158
+ padding: var(--spacing-1);
4159
+ }
4160
+
4161
+ @media (prefers-reduced-motion: reduce) {
4162
+ .crewlet-choice-list__row {
4163
+ transition: none;
4164
+ }
4165
+ }
4166
+
4167
+
4056
4168
  /* CodeBlock-GYNJ2HI6.css */
4057
4169
  /*
4058
4170
  * CodeBlock, a monospace command, config or record surface. One step off the
@@ -4589,6 +4701,97 @@ button.crewlet-avatar-picker:hover .crewlet-avatar-picker__pip {
4589
4701
  }
4590
4702
 
4591
4703
 
4704
+ /* Composer-ABGJIAIR.css */
4705
+ /*
4706
+ * A message written in place: the field and its footer strip in one box. The
4707
+ * BOX takes the focus ring, an accent border and a 2px soft halo, so the
4708
+ * field inside draws no border or outline of its own and the footer reads as
4709
+ * part of what is being written.
4710
+ */
4711
+ .crewlet-composer {
4712
+ display: grid;
4713
+ overflow: hidden;
4714
+ border: 1px solid var(--color-border-strong);
4715
+ border-radius: var(--radius-md);
4716
+ background: var(--color-surface-background);
4717
+ transition:
4718
+ border-color var(--motion-duration-fast) var(--motion-easing-default),
4719
+ box-shadow var(--motion-duration-fast) var(--motion-easing-default);
4720
+ }
4721
+
4722
+ .crewlet-composer:hover {
4723
+ border-color: var(--color-border-strong-hover);
4724
+ }
4725
+
4726
+ .crewlet-composer:focus-within {
4727
+ border-color: var(--color-brand-accent);
4728
+ box-shadow: 0 0 0 2px var(--color-brand-accent-soft);
4729
+ }
4730
+
4731
+ .crewlet-composer .crewlet-composer__field {
4732
+ min-height: 68px;
4733
+ max-height: 220px;
4734
+ padding: var(--spacing-2) var(--spacing-3);
4735
+ border: 0;
4736
+ border-radius: 0;
4737
+ background: transparent;
4738
+ resize: none;
4739
+ }
4740
+
4741
+ /* The ring is the box's, above. A transparent outline stays, because forced
4742
+ colors drops the box's shadow and paints an outline in its place. */
4743
+ .crewlet-composer .crewlet-composer__field:focus-visible {
4744
+ outline: 2px solid transparent;
4745
+ outline-offset: -2px;
4746
+ }
4747
+
4748
+ /* Past its cap the field scrolls rather than pushing the page. */
4749
+ .crewlet-composer .crewlet-composer__field.is-auto-resize {
4750
+ overflow-y: auto;
4751
+ }
4752
+
4753
+ .crewlet-composer__footer {
4754
+ display: flex;
4755
+ flex-wrap: wrap;
4756
+ align-items: center;
4757
+ gap: var(--spacing-2);
4758
+ padding: var(--spacing-1) var(--spacing-1) var(--spacing-1) var(--spacing-3);
4759
+ border-top: 1px solid var(--color-border-default);
4760
+ background: var(--color-surface-subtle);
4761
+ }
4762
+
4763
+ .crewlet-composer__hint {
4764
+ display: inline-flex;
4765
+ align-items: center;
4766
+ gap: var(--spacing-1);
4767
+ font-size: var(--font-size-2xs);
4768
+ color: var(--color-text-tertiary);
4769
+ }
4770
+
4771
+ .crewlet-composer__counter {
4772
+ font-family: var(--font-family-mono);
4773
+ font-size: var(--font-size-2xs);
4774
+ font-variant-numeric: tabular-nums;
4775
+ color: var(--color-feedback-warning-ink);
4776
+ }
4777
+
4778
+ .crewlet-composer__spacer {
4779
+ flex: 1;
4780
+ }
4781
+
4782
+ @media (width < 640px) {
4783
+ .crewlet-composer__hint {
4784
+ display: none;
4785
+ }
4786
+ }
4787
+
4788
+ @media (prefers-reduced-motion: reduce) {
4789
+ .crewlet-composer {
4790
+ transition: none;
4791
+ }
4792
+ }
4793
+
4794
+
4592
4795
  /* Container-3TSKMGNI.css */
4593
4796
  /*
4594
4797
  * Container, the centred content measure. One max-width scale shared by every
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crewlethq/ui",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "Crewlet shared React components built on @crewlethq/tokens and @crewlethq/icons.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -42,8 +42,8 @@
42
42
  "clean": "rm -rf dist src/generated"
43
43
  },
44
44
  "dependencies": {
45
- "@crewlethq/icons": "0.11.0",
46
- "@crewlethq/tokens": "0.11.0"
45
+ "@crewlethq/icons": "0.12.0",
46
+ "@crewlethq/tokens": "0.12.0"
47
47
  },
48
48
  "peerDependencies": {
49
49
  "react": ">=18",
File without changes
@@ -1,7 +1,7 @@
1
1
  import { Kbd } from './chunk-SMBKXWML.js';
2
2
  import { FormField, Textarea, Input } from './chunk-FTEJPHBI.js';
3
- import { IconButton } from './chunk-4FQT6ZAY.js';
4
3
  import { announce } from './chunk-RSAQOKH3.js';
4
+ import { IconButton } from './chunk-4FQT6ZAY.js';
5
5
  import { isComposing } from './chunk-R25RGPUB.js';
6
6
  import './ListInput-O7LJKOIG.css';
7
7
  import { useState, useRef, useLayoutEffect } from 'react';
@@ -1,9 +1,9 @@
1
+ import { useCardHeaderSlot } from './chunk-AV2DXAEL.js';
1
2
  import { Menu } from './chunk-TFH6SYWB.js';
2
3
  import { EmptyValue } from './chunk-EUCC37WY.js';
3
4
  import { Modal } from './chunk-TEEJSTFG.js';
4
5
  import { useClipboard } from './chunk-5VNUYO76.js';
5
6
  import { Button } from './chunk-OG6CL3EB.js';
6
- import { useCardHeaderSlot } from './chunk-AV2DXAEL.js';
7
7
  import { Checkbox } from './chunk-YCTMKKRA.js';
8
8
  import { IconButton } from './chunk-4FQT6ZAY.js';
9
9
  import { VisuallyHidden } from './chunk-BZFWDIV6.js';
@@ -1,5 +1,5 @@
1
- import { Input } from './chunk-FTEJPHBI.js';
2
1
  import { useListbox } from './chunk-6MU7HNB4.js';
2
+ import { Input } from './chunk-FTEJPHBI.js';
3
3
  import { cx } from './chunk-ODEQTPFM.js';
4
4
  import './Combobox-4FUVYIE7.css';
5
5
  import { forwardRef, useId, useMemo, useRef, useCallback } from 'react';
@@ -1,6 +1,6 @@
1
+ import { useListbox } from './chunk-6MU7HNB4.js';
1
2
  import { Kbd } from './chunk-SMBKXWML.js';
2
3
  import { Input } from './chunk-FTEJPHBI.js';
3
- import { useListbox } from './chunk-6MU7HNB4.js';
4
4
  import { Modal } from './chunk-TEEJSTFG.js';
5
5
  import { Count } from './chunk-BHHIIK3M.js';
6
6
  import { isComposing } from './chunk-R25RGPUB.js';
@@ -1,7 +1,7 @@
1
1
  import { Tag } from './chunk-LOECRMHA.js';
2
2
  import { useListbox } from './chunk-6MU7HNB4.js';
3
- import { IconButton } from './chunk-4FQT6ZAY.js';
4
3
  import { announce } from './chunk-RSAQOKH3.js';
4
+ import { IconButton } from './chunk-4FQT6ZAY.js';
5
5
  import { isComposing } from './chunk-R25RGPUB.js';
6
6
  import { cx } from './chunk-ODEQTPFM.js';
7
7
  import './TagsInput-P2HS5QL4.css';