@crewlethq/ui 0.8.1 → 0.9.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 (62) hide show
  1. package/README.md +12 -2
  2. package/dist/Avatar/Avatar.d.ts +23 -2
  3. package/dist/Avatar/AvatarStack.d.ts +6 -0
  4. package/dist/Avatar/index.d.ts +1 -1
  5. package/dist/Avatar/index.js +2 -1
  6. package/dist/{Avatar-XID7Z74C.css → Avatar-JAU77SHZ.css} +73 -9
  7. package/dist/CharacterPicker/CharacterPicker.d.ts +38 -0
  8. package/dist/CharacterPicker/index.d.ts +3 -0
  9. package/dist/CharacterPicker/index.js +4 -0
  10. package/dist/CharacterPicker-ZEYIKUNQ.css +42 -0
  11. package/dist/CommandPalette/index.js +2 -2
  12. package/dist/DataTable/index.js +2 -2
  13. package/dist/DataView/index.js +6 -6
  14. package/dist/EntityChip/index.js +3 -2
  15. package/dist/HuePicker/HuePicker.d.ts +26 -0
  16. package/dist/HuePicker/index.d.ts +3 -0
  17. package/dist/HuePicker/index.js +8 -0
  18. package/dist/HuePicker-5QIUR6L7.css +18 -0
  19. package/dist/ImageUpload/index.js +3 -2
  20. package/dist/ListInput/index.js +2 -2
  21. package/dist/OrgLabel/index.js +3 -2
  22. package/dist/OrgNode/index.js +4 -3
  23. package/dist/OrgTable/index.js +4 -3
  24. package/dist/SegmentedControl/index.js +4 -2
  25. package/dist/Tabs/index.js +2 -1
  26. package/dist/Tabs/roving.d.ts +9 -1
  27. package/dist/TagsInput/index.js +2 -2
  28. package/dist/ThemeSwitcher/index.js +5 -3
  29. package/dist/TimeWindowPicker/index.js +3 -3
  30. package/dist/TreeCanvas/TreeCanvas.d.ts +5 -13
  31. package/dist/chunk-26TXVHN2.js +31 -0
  32. package/dist/chunk-AYKXMIOR.js +13 -0
  33. package/dist/chunk-CBOICT64.js +74 -0
  34. package/dist/{chunk-W4GQWFRX.js → chunk-E3HDS4F7.js} +1 -1
  35. package/dist/{chunk-A3K56LY6.js → chunk-EUT7VBQG.js} +4 -4
  36. package/dist/{chunk-DRHXRGB6.js → chunk-HEOVQZL7.js} +3 -62
  37. package/dist/chunk-IKH3Y4MP.js +73 -0
  38. package/dist/{chunk-B47YUQGM.js → chunk-J3IS2TOA.js} +1 -1
  39. package/dist/{chunk-6SIG5I72.js → chunk-JB6AN4ZC.js} +1 -1
  40. package/dist/{chunk-VCOELPCT.js → chunk-K7OS4O2U.js} +1 -1
  41. package/dist/{chunk-N5KCGFWI.js → chunk-LPHHDCN3.js} +2 -3
  42. package/dist/chunk-OAH4IEQJ.js +68 -0
  43. package/dist/{chunk-IA232OTU.js → chunk-UDW3DAP5.js} +31 -62
  44. package/dist/chunk-UI6HWAWE.js +2 -0
  45. package/dist/{chunk-RHHGLTXJ.js → chunk-X6K6OZ47.js} +1 -1
  46. package/dist/{chunk-WSOFKOLP.js → chunk-Y2V3TSQC.js} +1 -1
  47. package/dist/generated/index.d.ts +2 -0
  48. package/dist/generated/index.js +38 -32
  49. package/dist/index.js +38 -32
  50. package/dist/styles.css +140 -10
  51. package/dist/utils/index.d.ts +2 -0
  52. package/dist/utils/index.js +2 -1
  53. package/dist/utils/nodeHue.d.ts +25 -0
  54. package/dist/utils/tone.d.ts +4 -1
  55. package/package.json +3 -3
  56. package/dist/{chunk-4JHWMJZI.js → chunk-6HXH57BL.js} +1 -1
  57. package/dist/{chunk-IJ7QXNIJ.js → chunk-AER7UDD4.js} +0 -0
  58. package/dist/{chunk-KTIEJ5Q5.js → chunk-CVB7O3SZ.js} +1 -1
  59. package/dist/{chunk-BXPLX7YU.js → chunk-IGWPZZIB.js} +1 -1
  60. package/dist/{chunk-HVPC2GHY.js → chunk-IZHN5I3H.js} +1 -1
  61. package/dist/{chunk-DBUGBINU.js → chunk-MPXI6FM6.js} +1 -1
  62. /package/dist/{chunk-PKIN4IMB.js → chunk-YPTC4TX5.js} +0 -0
package/README.md CHANGED
@@ -42,13 +42,13 @@ 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` |
45
+ | Forms | `Input`, `Textarea`, `Label`, `FormField`, `FormRow`, `Checkbox`, `Select`, `Tag`, `TagsInput`, `DateTimePicker`, `TimeWindowPicker`, `ImageUpload`, `CharacterPicker`, `HuePicker` |
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` |
49
49
  | Charts | `Legend`, `BarList`, `StackedBar`, `StackedColumns`, `ActivityStrip`, `TimeSeries`, `Sparkline`, the reading layer they share (`ChartTooltip`, `useChartHover`), and the ramp (`DATA_COLORS`, `DATA_COLOR_OTHER`, `dataColor`) |
50
50
  | Marks | `Count`, `StatusDot`, `EmptyValue`, `VisuallyHidden` |
51
- | Hooks and seams | `useModalLayer`, `usePopupLayer`, `LayerHost`, `useListbox`, `useOptionKeys`, `useClipboard`, `useAnnouncer`, `useNow`, `formatRelative`, `HeadingLevelProvider`, `cx` |
51
+ | Hooks and seams | `useModalLayer`, `usePopupLayer`, `LayerHost`, `useListbox`, `useOptionKeys`, `useClipboard`, `useAnnouncer`, `useNow`, `formatRelative`, `HeadingLevelProvider`, `cx`, the node hues (`NODE_HUES`, `NODE_HUE_NAMES`, `isNodeHue`) |
52
52
  | Layout | `Container`, `Section`, `Card`, `Tabs`, `Accordion`, `Disclosure` |
53
53
  | Application shell | `AppShell` with `AppShell.Rail`, `AppShell.Topbar` and `useAppShell`, `SidebarNav` and `NavItem`, `BrandLockup`, `SearchTrigger`, `PageHeader`, `Toolbar`, `Stack`, `Inline`, `Spacer`, `AutoGrid`, `ErrorBoundary`, `useShortcut`, `useFullscreen` |
54
54
  | Preferences | `ThemeToggle`, `ThemeSwitcher`, `DensitySwitcher`, `useThemePreference`, `useDensityPreference`, `useSystemTheme`, `resolveTheme`, `applyStoredPreferences` |
@@ -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.9.0
195
+
196
+ 0.9.0 gives an agent a face of its own: one of the thirty Crewlet characters in `@crewlethq/icons/characters`, drawn in one of the six node hues an operator chooses for it.
197
+
198
+ **An agent's badge can be its character.** `Avatar` takes `character` and `hue`. An agent badge with a `character` draws that character, centred, on a plate of its hue (the hue's `-fill`, its `-line` round the badge and the hue itself as the ink), in place of its initials and of any image. A badge of `AVATAR_CHARACTER_FULL_DETAIL` (56px) and up draws the character's keyline and visor gap; a smaller one draws it compact, where a hairline would be a blur. A `human` badge ignores both and keeps its circle and initials, and what any badge says to a screen reader is unchanged. An `AvatarStack` member takes the same two fields, for a stack of agents drawn as themselves. What to change: nothing; a badge with neither prop draws as it did.
199
+
200
+ **The node hues are one exported set.** `NODE_HUES`, `NODE_HUE_NAMES`, `isNodeHue` and the `NodeHue` type name the six hues an entity is told apart by, where somebody chose one. `TreeCardTone` (and so `OrgTableTone`) is now `NodeHue`, so an agent's card, row and badge are drawn from one list. What to change: nothing; the six names are the same.
201
+
202
+ **Two pickers choose them.** `CharacterPicker` is a radio group of every character, laid out in rows of six (`CHARACTER_PICKER_COLUMNS`), each drawn as the badge it would make in the agent's hue; Left and Right walk the characters, Up and Down move a whole row, and the chosen badge carries the kit's selected ring. `HuePicker` is a `SegmentedControl` radio row of the six hues, each a swatch and the hue's name. Both take `disabled`, which keeps the choice shown and lets nothing in the group take focus or a press. Wrap either in `FormField as="fieldset"` for a labelled field.
203
+
194
204
  ## Changes in 0.7.0
195
205
 
196
206
  0.7.0 draws the org surfaces (`TreeCanvas`'s `node` appearance, `OrgTable`,
@@ -1,4 +1,6 @@
1
1
  import type { HTMLAttributes } from 'react';
2
+ import { type CrewletCharacterId } from '@crewlethq/icons/characters';
3
+ import type { NodeHue } from '../utils/nodeHue.js';
2
4
  import type { Tone } from '../utils/tone.js';
3
5
  /**
4
6
  * WHAT THE BADGE STANDS FOR, drawn as its outline.
@@ -91,7 +93,26 @@ export interface AvatarProps extends HTMLAttributes<HTMLElement> {
91
93
  * outlives a rename, so the colour does too. Only read with `tone="seeded"`.
92
94
  */
93
95
  colorSeed?: string | undefined;
96
+ /**
97
+ * The Crewlet character an AGENT is drawn as, in place of its initials and
98
+ * of any image. A person is never drawn as one: on a `human` badge this is
99
+ * ignored, and the circle and the initials stay.
100
+ */
101
+ character?: CrewletCharacterId | undefined;
102
+ /**
103
+ * The hue the agent's character is drawn in, on a plate of the same hue.
104
+ * Read only with `character`; a character with no hue is drawn in the
105
+ * neutral badge's ink, on its plate.
106
+ */
107
+ hue?: NodeHue | undefined;
94
108
  }
109
+ /**
110
+ * The smallest badge, in px, a character is drawn at full detail: its keyline
111
+ * and its visor gap. Under it both are hairlines finer than a pixel, which a
112
+ * screen draws as a blur round the body, so the character is drawn compact
113
+ * (see `CrewletCharacterDetail`).
114
+ */
115
+ export declare const AVATAR_CHARACTER_FULL_DETAIL = 56;
95
116
  /**
96
117
  * Two uppercase initials, or one where the name has only one letter to give.
97
118
  *
@@ -139,11 +160,11 @@ export declare function avatarPixels(size: AvatarSize): number;
139
160
  */
140
161
  export declare function avatarCorner(pixels: number): number;
141
162
  /**
142
- * An identity badge: an image, or the initials behind it.
163
+ * An identity badge: an agent's character, an image, or the initials behind it.
143
164
  *
144
165
  * If the image fails to load (a stale CDN URL, an expired signature) it
145
166
  * degrades to the initials rather than to a broken-image glyph. Either way it
146
167
  * keeps its kind's outline and its ring: whether somebody has uploaded a photo
147
168
  * says nothing about what they are or what they are doing.
148
169
  */
149
- export declare const Avatar: ({ src, name, size, kind, tone, ring, decorative, colorSeed, className, style, ...rest }: AvatarProps) => import("react").JSX.Element;
170
+ export declare const Avatar: ({ src, name, size, kind, tone, ring, decorative, colorSeed, character, hue, className, style, ...rest }: AvatarProps) => import("react").JSX.Element;
@@ -1,4 +1,6 @@
1
1
  import type { HTMLAttributes } from 'react';
2
+ import type { CrewletCharacterId } from '@crewlethq/icons/characters';
3
+ import type { NodeHue } from '../utils/nodeHue.js';
2
4
  import { type AvatarKind, type AvatarRing, type AvatarSizeStep } from './Avatar.js';
3
5
  /** One badge in a stack. */
4
6
  export interface AvatarStackMember {
@@ -9,6 +11,10 @@ export interface AvatarStackMember {
9
11
  src?: string | undefined;
10
12
  /** A state ring on this badge, as `Avatar` draws it. */
11
13
  ring?: AvatarRing | undefined;
14
+ /** The Crewlet character an agent member is drawn as, as `Avatar` draws it. */
15
+ character?: CrewletCharacterId | undefined;
16
+ /** The hue an agent member's character is drawn in, as `Avatar` draws it. */
17
+ hue?: NodeHue | undefined;
12
18
  /**
13
19
  * What tells two members apart when their names do not (a seat's handle, a
14
20
  * person's id), unique within the stack. The name is used when it is absent.
@@ -1,6 +1,6 @@
1
1
  import './Avatar.css';
2
2
  import './AvatarStack.css';
3
- export { AVATAR_CORNER_RATIO, AVATAR_SIZES, Avatar, avatarCorner, avatarPixels, avatarTint, getInitials, } from './Avatar.js';
3
+ export { AVATAR_CHARACTER_FULL_DETAIL, AVATAR_CORNER_RATIO, AVATAR_SIZES, Avatar, avatarCorner, avatarPixels, avatarTint, getInitials, } from './Avatar.js';
4
4
  export type { AvatarKind, AvatarProps, AvatarRing, AvatarSize, AvatarSizeStep, AvatarTone } from './Avatar.js';
5
5
  export { AvatarStack, avatarStackLabel } from './AvatarStack.js';
6
6
  export type { AvatarStackMember, AvatarStackProps } from './AvatarStack.js';
@@ -1,2 +1,3 @@
1
- export { AVATAR_CORNER_RATIO, AVATAR_SIZES, Avatar, AvatarStack, avatarCorner, avatarPixels, avatarStackLabel, avatarTint, getInitials } from '../chunk-IA232OTU.js';
1
+ export { AvatarStack, avatarStackLabel } from '../chunk-OAH4IEQJ.js';
2
+ export { AVATAR_CHARACTER_FULL_DETAIL, AVATAR_CORNER_RATIO, AVATAR_SIZES, Avatar, avatarCorner, avatarPixels, avatarTint, getInitials } from '../chunk-UDW3DAP5.js';
2
3
  import '../chunk-ODEQTPFM.js';
@@ -1,21 +1,28 @@
1
1
  /*
2
2
  * The identity badge.
3
3
  *
4
- * IT IS NEUTRAL, and that is the whole rule. The system this replaces coloured
5
- * a seat by `PALETTE[hash(name) % 8]`, over the same eight families it also
6
- * spent on phases and event categories, so one amber meant "the execute
7
- * phase", "the decision category" and "the Analyst" at once. A hash of a name
8
- * carries no information: rename the seat and its colour changes, which is the
9
- * proof it never meant anything. Identity is the OUTLINE (a squircle for an
10
- * agent, a circle for a person), the monogram and the name.
4
+ * IT IS NEUTRAL UNLESS SOMEBODY CHOSE OTHERWISE, and a hash never chooses. The
5
+ * system this replaces coloured a seat by `PALETTE[hash(name) % 8]`, over the
6
+ * same eight families it also spent on phases and event categories, so one
7
+ * amber meant "the execute phase", "the decision category" and "the Analyst"
8
+ * at once. A hash of a name carries no information: rename the seat and its
9
+ * colour changes, which is the proof it never meant anything. Identity is the
10
+ * OUTLINE (a squircle for an agent, a circle for a person), the monogram and
11
+ * the name, and for an agent an operator gave one, its character and its hue.
11
12
  *
12
- * THE ONE HUE A BADGE CARRIES IS A STATE, as a ring round it, and the ring is
13
- * the component's only coloured line.
13
+ * THE ONE HUE A BADGE CARRIES AS A LINE IS A STATE, as a ring round it, and the
14
+ * ring is the component's only coloured line outside its own plate.
14
15
  *
15
16
  * The seeded tints stay for the one case that earns them, a roster somebody
16
17
  * scans, and their grounds are TOKENS: measured under white initials and held
17
18
  * at 4.5:1 by the palette suite. Spelled as literals, five of the ten sat
18
19
  * under that floor while the suite measured ten values nothing painted with.
20
+ *
21
+ * AN AGENT'S OWN HUE IS NOT A HASH. An agent an operator gave a Crewlet
22
+ * character and a hue is drawn as that character, in that hue, on a plate of
23
+ * it: the hue was chosen for the seat and survives a rename, which a hash of
24
+ * the name never did. It is one of the six node hues (`NodeHue`), each a
25
+ * measured set of steps rather than a colour with alphas applied here.
19
26
  */
20
27
 
21
28
  .crewlet-avatar {
@@ -147,6 +154,63 @@
147
154
  .crewlet-avatar--tint-8 { background: var(--color-avatar-tint-8); }
148
155
  .crewlet-avatar--tint-9 { background: var(--color-avatar-tint-9); }
149
156
 
157
+ /* ── an agent's character ─────────────────────────────────────────────── */
158
+
159
+ /*
160
+ * THE CHARACTER FILLS MOST OF THE PLATE, centred by its own frame (it frames
161
+ * every silhouette square on what it draws), with the plate's corner clear of
162
+ * it: a wide character such as the original Crewlet reaches the plate's
163
+ * sides, a tall one its top and its foot, and none touches the curve.
164
+ */
165
+ .crewlet-avatar--character {
166
+ border: 1px solid transparent;
167
+ }
168
+
169
+ .crewlet-avatar__character {
170
+ display: block;
171
+ flex: none;
172
+ width: 74%;
173
+ height: 74%;
174
+ }
175
+
176
+ /* The plate an agent's hue is drawn on: the hue's fill, its line round the
177
+ badge and the hue itself as the character's ink. */
178
+ .crewlet-avatar--hue-purple {
179
+ background: var(--color-node-purple-fill);
180
+ border-color: var(--color-node-purple-line);
181
+ color: var(--color-node-purple);
182
+ }
183
+
184
+ .crewlet-avatar--hue-cyan {
185
+ background: var(--color-node-cyan-fill);
186
+ border-color: var(--color-node-cyan-line);
187
+ color: var(--color-node-cyan);
188
+ }
189
+
190
+ .crewlet-avatar--hue-green {
191
+ background: var(--color-node-green-fill);
192
+ border-color: var(--color-node-green-line);
193
+ color: var(--color-node-green);
194
+ }
195
+
196
+ .crewlet-avatar--hue-amber {
197
+ background: var(--color-node-amber-fill);
198
+ border-color: var(--color-node-amber-line);
199
+ color: var(--color-node-amber);
200
+ }
201
+
202
+ .crewlet-avatar--hue-rose {
203
+ background: var(--color-node-rose-fill);
204
+ border-color: var(--color-node-rose-line);
205
+ color: var(--color-node-rose);
206
+ }
207
+
208
+ .crewlet-avatar--hue-blue {
209
+ background: var(--color-node-blue-fill);
210
+ border-color: var(--color-node-blue-line);
211
+ color: var(--color-node-blue);
212
+ }
213
+
150
214
  /* ── the state ring ────────────────────────────────────────────────────── */
151
215
 
152
216
  /*
@@ -0,0 +1,38 @@
1
+ import type { HTMLAttributes } from 'react';
2
+ import { type CrewletCharacterId } from '@crewlethq/icons/characters';
3
+ import type { NodeHue } from '../utils/nodeHue.js';
4
+ /**
5
+ * How many characters a row of the grid holds. Thirty characters make five
6
+ * full rows, and a grid that wraps by width would leave the arrow keys
7
+ * guessing which option sits above which.
8
+ */
9
+ export declare const CHARACTER_PICKER_COLUMNS = 6;
10
+ export interface CharacterPickerProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children' | 'onChange'> {
11
+ /** The group's name, said on entering it: "Character". */
12
+ label: string;
13
+ /** The chosen character. */
14
+ value: CrewletCharacterId;
15
+ onValueChange: (character: CrewletCharacterId) => void;
16
+ /** The hue every option is shown in, so the grid previews the agent it will be. */
17
+ hue?: NodeHue | undefined;
18
+ /** The characters offered, in order. Every character, by default. */
19
+ characters?: readonly CrewletCharacterId[] | undefined;
20
+ /** Nothing can be chosen, and the grid says so. */
21
+ disabled?: boolean | undefined;
22
+ }
23
+ /**
24
+ * The choice of an agent's Crewlet character: a grid of the characters, each
25
+ * drawn as the badge it would make, in the agent's own hue.
26
+ *
27
+ * A RADIO GROUP, because a character is a setting and exactly one is chosen:
28
+ * the grid is one tab stop, the arrows move through it and choose as they
29
+ * move, as the platform's own radio group does. Left and Right walk the
30
+ * options in reading order and Up and Down move a whole row, because the
31
+ * options are laid out in rows and an arrow that ignored that would move
32
+ * somewhere the reader is not looking.
33
+ *
34
+ * THE CHOSEN OPTION IS SAID THE WAY THE KIT SAYS SELECTED, with the badge's
35
+ * own `brand` ring, rather than a frame the grid draws round a tile: one
36
+ * badge, one line round it, and the line means "this one".
37
+ */
38
+ export declare function CharacterPicker({ label, value, onValueChange, hue, characters, disabled, className, ...rest }: CharacterPickerProps): import("react").JSX.Element;
@@ -0,0 +1,3 @@
1
+ import './CharacterPicker.css';
2
+ export { CHARACTER_PICKER_COLUMNS, CharacterPicker } from './CharacterPicker.js';
3
+ export type { CharacterPickerProps } from './CharacterPicker.js';
@@ -0,0 +1,4 @@
1
+ export { CHARACTER_PICKER_COLUMNS, CharacterPicker } from '../chunk-IKH3Y4MP.js';
2
+ import '../chunk-CBOICT64.js';
3
+ import '../chunk-UDW3DAP5.js';
4
+ import '../chunk-ODEQTPFM.js';
@@ -0,0 +1,42 @@
1
+ /*
2
+ * The grid of characters.
3
+ *
4
+ * SIX COLUMNS, ALWAYS, and the tiles share the width: the arrow keys move a
5
+ * whole row on Up and Down, so a row has to hold the same options at every
6
+ * width (`CHARACTER_PICKER_COLUMNS`). A tile is a target the size of the
7
+ * badge it holds and the gap round it, never smaller than the kit's control
8
+ * floor.
9
+ */
10
+
11
+ .crewlet-character-picker {
12
+ display: grid;
13
+ grid-template-columns: repeat(6, minmax(0, 1fr));
14
+ gap: var(--spacing-1);
15
+ justify-items: center;
16
+ }
17
+
18
+ .crewlet-character-picker__option {
19
+ display: grid;
20
+ place-items: center;
21
+ min-width: var(--size-control-lg);
22
+ min-height: var(--size-control-lg);
23
+ padding: var(--spacing-1);
24
+ border: 0;
25
+ border-radius: var(--radius-md);
26
+ background: transparent;
27
+ cursor: pointer;
28
+ }
29
+
30
+ .crewlet-character-picker__option:hover:not(:disabled) {
31
+ background: var(--color-surface-hover);
32
+ }
33
+
34
+ .crewlet-character-picker__option:focus-visible {
35
+ outline: 2px solid var(--color-focus);
36
+ outline-offset: 2px;
37
+ }
38
+
39
+ .crewlet-character-picker__option:disabled {
40
+ cursor: not-allowed;
41
+ opacity: 0.5;
42
+ }
@@ -1,8 +1,8 @@
1
- export { CommandPalette } from '../chunk-BXPLX7YU.js';
1
+ export { CommandPalette } from '../chunk-IGWPZZIB.js';
2
2
  import '../chunk-SMBKXWML.js';
3
- import '../chunk-BTHX2FS3.js';
4
3
  import '../chunk-6MU7HNB4.js';
5
4
  import '../chunk-ZGX2DP7F.js';
5
+ import '../chunk-BTHX2FS3.js';
6
6
  import '../chunk-BHHIIK3M.js';
7
7
  import '../chunk-PQADV6P6.js';
8
8
  import '../chunk-7RPGY3JE.js';
@@ -1,10 +1,10 @@
1
- export { ALL_ITEMS, CopyableCell, DATA_TABLE_LABELS, DataTable, RowActionsMenu } from '../chunk-KTIEJ5Q5.js';
1
+ export { ALL_ITEMS, CopyableCell, DATA_TABLE_LABELS, DataTable, RowActionsMenu } from '../chunk-CVB7O3SZ.js';
2
2
  import '../chunk-LSB3EHBW.js';
3
3
  import '../chunk-EUCC37WY.js';
4
4
  import '../chunk-BTHX2FS3.js';
5
5
  import '../chunk-AV2DXAEL.js';
6
- import '../chunk-5VNUYO76.js';
7
6
  import '../chunk-YCTMKKRA.js';
7
+ import '../chunk-5VNUYO76.js';
8
8
  import '../chunk-PQADV6P6.js';
9
9
  import '../chunk-7RPGY3JE.js';
10
10
  import '../chunk-R25RGPUB.js';
@@ -1,9 +1,11 @@
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-A3K56LY6.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-EUT7VBQG.js';
2
2
  import '../chunk-PGRPNDWM.js';
3
- import '../chunk-HOXGBLEY.js';
4
3
  import '../chunk-3CZ7XAVY.js';
4
+ import '../chunk-HOXGBLEY.js';
5
5
  import '../chunk-SMBKXWML.js';
6
- import '../chunk-KTIEJ5Q5.js';
6
+ import '../chunk-6MU7HNB4.js';
7
+ import '../chunk-ZGX2DP7F.js';
8
+ import '../chunk-CVB7O3SZ.js';
7
9
  import '../chunk-LSB3EHBW.js';
8
10
  import '../chunk-EUCC37WY.js';
9
11
  import '../chunk-BTHX2FS3.js';
@@ -11,10 +13,8 @@ import '../chunk-5I56UXBJ.js';
11
13
  import '../chunk-PDUZO35I.js';
12
14
  import '../chunk-GXQ3B46I.js';
13
15
  import '../chunk-AV2DXAEL.js';
14
- import '../chunk-5VNUYO76.js';
15
16
  import '../chunk-YCTMKKRA.js';
16
- import '../chunk-6MU7HNB4.js';
17
- import '../chunk-ZGX2DP7F.js';
17
+ import '../chunk-5VNUYO76.js';
18
18
  import '../chunk-BHHIIK3M.js';
19
19
  import '../chunk-PQADV6P6.js';
20
20
  import '../chunk-7RPGY3JE.js';
@@ -1,3 +1,4 @@
1
- export { EntityChip } from '../chunk-WSOFKOLP.js';
2
- import '../chunk-IA232OTU.js';
1
+ export { EntityChip } from '../chunk-Y2V3TSQC.js';
2
+ import '../chunk-OAH4IEQJ.js';
3
+ import '../chunk-UDW3DAP5.js';
3
4
  import '../chunk-ODEQTPFM.js';
@@ -0,0 +1,26 @@
1
+ import { type SegmentedSize } from '../SegmentedControl/SegmentedControl.js';
2
+ import { type NodeHue } from '../utils/nodeHue.js';
3
+ export interface HuePickerProps {
4
+ /** The group's name, said on entering it: "Color". */
5
+ label: string;
6
+ value: NodeHue;
7
+ onValueChange: (hue: NodeHue) => void;
8
+ size?: SegmentedSize | undefined;
9
+ /** Nothing can be chosen, and the row says so. */
10
+ disabled?: boolean | undefined;
11
+ className?: string | undefined;
12
+ }
13
+ /**
14
+ * The choice of an entity's hue: the six node hues as a row of chips, each a
15
+ * swatch and the hue's name.
16
+ *
17
+ * THE NAME IS PRINTED, not left to the swatch, because a swatch alone asks the
18
+ * reader to tell six hues apart, which some readers cannot, and says nothing
19
+ * to a screen reader. It is a `SegmentedControl` radio row, so it keeps the
20
+ * kit's one tab stop and the arrows that choose as they move.
21
+ *
22
+ * DISABLED IS EVERY CHIP DISABLED, as `CharacterPicker` is every tile: the
23
+ * row is still read and the chosen hue still shown, and nothing in it takes
24
+ * focus or a press.
25
+ */
26
+ export declare function HuePicker({ label, value, onValueChange, size, disabled, className }: HuePickerProps): import("react").JSX.Element;
@@ -0,0 +1,3 @@
1
+ import './HuePicker.css';
2
+ export { HuePicker } from './HuePicker.js';
3
+ export type { HuePickerProps } from './HuePicker.js';
@@ -0,0 +1,8 @@
1
+ export { HuePicker } from '../chunk-26TXVHN2.js';
2
+ import '../chunk-AYKXMIOR.js';
3
+ import '../chunk-LPHHDCN3.js';
4
+ import '../chunk-HEOVQZL7.js';
5
+ import '../chunk-CBOICT64.js';
6
+ import '../chunk-BHHIIK3M.js';
7
+ import '../chunk-BZFWDIV6.js';
8
+ import '../chunk-ODEQTPFM.js';
@@ -0,0 +1,18 @@
1
+ /*
2
+ * A hue's swatch: the hue itself, as a dot beside its name. The name carries
3
+ * the choice; the dot is there so the row can be scanned for a colour.
4
+ */
5
+
6
+ .crewlet-hue-picker__swatch {
7
+ display: block;
8
+ width: var(--spacing-3);
9
+ height: var(--spacing-3);
10
+ border-radius: var(--radius-circle);
11
+ }
12
+
13
+ .crewlet-hue-picker__swatch--purple { background: var(--color-node-purple); }
14
+ .crewlet-hue-picker__swatch--cyan { background: var(--color-node-cyan); }
15
+ .crewlet-hue-picker__swatch--green { background: var(--color-node-green); }
16
+ .crewlet-hue-picker__swatch--amber { background: var(--color-node-amber); }
17
+ .crewlet-hue-picker__swatch--rose { background: var(--color-node-rose); }
18
+ .crewlet-hue-picker__swatch--blue { background: var(--color-node-blue); }
@@ -1,3 +1,4 @@
1
- export { ImageUpload } from '../chunk-W4GQWFRX.js';
2
- import '../chunk-IA232OTU.js';
1
+ export { ImageUpload } from '../chunk-E3HDS4F7.js';
2
+ import '../chunk-OAH4IEQJ.js';
3
+ import '../chunk-UDW3DAP5.js';
3
4
  import '../chunk-ODEQTPFM.js';
@@ -1,10 +1,10 @@
1
- export { ListInput } from '../chunk-4JHWMJZI.js';
1
+ export { ListInput } from '../chunk-6HXH57BL.js';
2
2
  import '../chunk-SMBKXWML.js';
3
3
  import '../chunk-ZGX2DP7F.js';
4
4
  import '../chunk-PQADV6P6.js';
5
+ import '../chunk-RSAQOKH3.js';
5
6
  import '../chunk-7RPGY3JE.js';
6
7
  import '../chunk-R25RGPUB.js';
7
8
  import '../chunk-4FQT6ZAY.js';
8
- import '../chunk-RSAQOKH3.js';
9
9
  import '../chunk-BZFWDIV6.js';
10
10
  import '../chunk-ODEQTPFM.js';
@@ -1,3 +1,4 @@
1
- export { OrgLabel } from '../chunk-B47YUQGM.js';
2
- import '../chunk-IA232OTU.js';
1
+ export { OrgLabel } from '../chunk-J3IS2TOA.js';
2
+ import '../chunk-OAH4IEQJ.js';
3
+ import '../chunk-UDW3DAP5.js';
3
4
  import '../chunk-ODEQTPFM.js';
@@ -1,4 +1,5 @@
1
- export { OrgNodeDisclosure, OrgNodeLabel, OrgNodeLead } from '../chunk-VCOELPCT.js';
2
- import '../chunk-B47YUQGM.js';
3
- import '../chunk-IA232OTU.js';
1
+ export { OrgNodeDisclosure, OrgNodeLabel, OrgNodeLead } from '../chunk-K7OS4O2U.js';
2
+ import '../chunk-J3IS2TOA.js';
3
+ import '../chunk-OAH4IEQJ.js';
4
+ import '../chunk-UDW3DAP5.js';
4
5
  import '../chunk-ODEQTPFM.js';
@@ -1,12 +1,13 @@
1
- export { OrgTable, OrgTableActions, OrgTableAdd, OrgTableName } from '../chunk-6SIG5I72.js';
1
+ export { OrgTable, OrgTableActions, OrgTableAdd, OrgTableName } from '../chunk-JB6AN4ZC.js';
2
2
  import '../chunk-SX2DFTQV.js';
3
3
  import '../chunk-S3BCVWTU.js';
4
- import '../chunk-B47YUQGM.js';
4
+ import '../chunk-J3IS2TOA.js';
5
5
  import '../chunk-53DVJCVW.js';
6
6
  import '../chunk-74WGARJE.js';
7
7
  import '../chunk-7RPGY3JE.js';
8
8
  import '../chunk-R25RGPUB.js';
9
9
  import '../chunk-4FQT6ZAY.js';
10
- import '../chunk-IA232OTU.js';
10
+ import '../chunk-OAH4IEQJ.js';
11
+ import '../chunk-UDW3DAP5.js';
11
12
  import '../chunk-BZFWDIV6.js';
12
13
  import '../chunk-ODEQTPFM.js';
@@ -1,5 +1,7 @@
1
- export { SegmentedControl } from '../chunk-N5KCGFWI.js';
2
- import '../chunk-DRHXRGB6.js';
1
+ import '../chunk-UI6HWAWE.js';
2
+ export { SegmentedControl } from '../chunk-LPHHDCN3.js';
3
+ import '../chunk-HEOVQZL7.js';
4
+ import '../chunk-CBOICT64.js';
3
5
  import '../chunk-BHHIIK3M.js';
4
6
  import '../chunk-BZFWDIV6.js';
5
7
  import '../chunk-ODEQTPFM.js';
@@ -1,4 +1,5 @@
1
- export { TabPanel, Tabs, tabId } from '../chunk-DRHXRGB6.js';
1
+ export { TabPanel, Tabs, tabId } from '../chunk-HEOVQZL7.js';
2
+ import '../chunk-CBOICT64.js';
2
3
  import '../chunk-BHHIIK3M.js';
3
4
  import '../chunk-BZFWDIV6.js';
4
5
  import '../chunk-ODEQTPFM.js';
@@ -36,6 +36,14 @@ export interface RovingOptions {
36
36
  * a refinement of it.
37
37
  */
38
38
  followFocus?: boolean | undefined;
39
+ /**
40
+ * How many options a row of a GRID holds, for options laid out in rows and
41
+ * columns (a picker of tiles): Up and Down then move a whole row, to the
42
+ * option above or below, and stop at the grid's edge rather than wrap into
43
+ * another column. Left and Right still walk the options in reading order.
44
+ * Unset, the options are one line.
45
+ */
46
+ columns?: number | undefined;
39
47
  }
40
48
  /**
41
49
  * Roving focus over a row of buttons: ONE TAB STOP for the row, the arrows to
@@ -59,7 +67,7 @@ export interface RovingOptions {
59
67
  * focus, so a move that lands on one drops focus on the page body and the
60
68
  * next arrow press does nothing at all.
61
69
  */
62
- export declare function useRoving(count: number, select: ((index: number) => void) | null, { followFocus }?: RovingOptions): {
70
+ export declare function useRoving(count: number, select: ((index: number) => void) | null, { followFocus, columns }?: RovingOptions): {
63
71
  buttons: import("react").RefObject<(HTMLButtonElement | null)[]>;
64
72
  onKeyDown: (event: KeyboardEvent<HTMLElement>, vertical: boolean) => void;
65
73
  onFocusAt: (index: number) => void;
@@ -1,10 +1,10 @@
1
- export { TagsInput } from '../chunk-DBUGBINU.js';
1
+ export { TagsInput } from '../chunk-MPXI6FM6.js';
2
2
  import '../chunk-LOECRMHA.js';
3
3
  import '../chunk-WIATRXEJ.js';
4
4
  import '../chunk-6MU7HNB4.js';
5
+ import '../chunk-RSAQOKH3.js';
5
6
  import '../chunk-7RPGY3JE.js';
6
7
  import '../chunk-R25RGPUB.js';
7
8
  import '../chunk-4FQT6ZAY.js';
8
- import '../chunk-RSAQOKH3.js';
9
9
  import '../chunk-BZFWDIV6.js';
10
10
  import '../chunk-ODEQTPFM.js';
@@ -1,7 +1,9 @@
1
- export { DensitySwitcher, ThemeSwitcher } from '../chunk-RHHGLTXJ.js';
1
+ export { DensitySwitcher, ThemeSwitcher } from '../chunk-X6K6OZ47.js';
2
2
  export { applyDensity, applyStoredPreferences, applyTheme, resolveTheme, useDensityPreference, useSystemTheme, useThemePreference } from '../chunk-K3OWD7BJ.js';
3
- import '../chunk-N5KCGFWI.js';
4
- import '../chunk-DRHXRGB6.js';
3
+ import '../chunk-UI6HWAWE.js';
4
+ import '../chunk-LPHHDCN3.js';
5
+ import '../chunk-HEOVQZL7.js';
6
+ import '../chunk-CBOICT64.js';
5
7
  import '../chunk-BHHIIK3M.js';
6
8
  import '../chunk-BZFWDIV6.js';
7
9
  import '../chunk-ODEQTPFM.js';
@@ -1,9 +1,9 @@
1
- export { DEFAULT_TIME_WINDOW_LABELS, TIME_WINDOW_SPANS, TimeWindowPicker, describeTimeWindow, isTimeWindowSet, parseTimeWindowDuration, resolveTimeWindow, timeWindowMatchesPreset } from '../chunk-HVPC2GHY.js';
1
+ export { DEFAULT_TIME_WINDOW_LABELS, TIME_WINDOW_SPANS, TimeWindowPicker, describeTimeWindow, isTimeWindowSet, parseTimeWindowDuration, resolveTimeWindow, timeWindowMatchesPreset } from '../chunk-IZHN5I3H.js';
2
2
  import '../chunk-SEFMO2EV.js';
3
- import '../chunk-PDUZO35I.js';
4
- import '../chunk-GXQ3B46I.js';
5
3
  import '../chunk-6MU7HNB4.js';
6
4
  import '../chunk-ZGX2DP7F.js';
5
+ import '../chunk-PDUZO35I.js';
6
+ import '../chunk-GXQ3B46I.js';
7
7
  import '../chunk-PQADV6P6.js';
8
8
  import '../chunk-7RPGY3JE.js';
9
9
  import '../chunk-R25RGPUB.js';
@@ -78,26 +78,18 @@
78
78
  import { type KeyboardEvent, type MouseEvent, type ReactNode, type Ref } from 'react';
79
79
  import { type CanvasGround, type CanvasLabels } from '../Canvas/index.js';
80
80
  import { type TreeConnectorShape, type TreeInput, type TreeItemAction, type LayoutRanks, type TreeModel, type TreeViewHandle } from '../Tree/index.js';
81
+ import type { NodeHue } from '../utils/nodeHue.js';
81
82
  /** A card of the layout: its id and the cards nested under it. */
82
83
  export interface TreeCardInput {
83
84
  id: string;
84
85
  children: TreeCardInput[];
85
86
  }
86
87
  /**
87
- * The six hues a card can be tinted with, and the connector arriving at it.
88
- *
89
- * DECORATIVE AND PER ENTITY, never a series: two cards sharing a hue say
90
- * nothing, so the palette is not measured for separability and the chart owes
91
- * no legend (`--color-node-*` in the tokens package says the same). It is what
92
- * an operator picks for one agent so they can find it again, and what a chart
93
- * with no such choice derives from a stable identity.
94
- *
95
- * A NAMED SET RATHER THAN A COLOUR. A caller that could hand in any colour
96
- * would hand in a literal, and the fill, the border and the ink of a tinted
97
- * card are measured steps of one hue rather than one value with alphas applied
98
- * by whoever drew it last.
88
+ * The hue a card is tinted with, and the connector arriving at it: one of the
89
+ * six an operator chooses an entity's hue from ([NodeHue]), so an agent's card
90
+ * wears the same hue as its avatar and its row.
99
91
  */
100
- export type TreeCardTone = 'purple' | 'cyan' | 'green' | 'amber' | 'rose' | 'blue';
92
+ export type TreeCardTone = NodeHue;
101
93
  /**
102
94
  * The props that make an element the pointer-only strip of controls beside a
103
95
  * node: see `TreeCardContext.actions`.