@crewlethq/ui 0.13.0 → 0.15.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 (76) hide show
  1. package/README.md +42 -0
  2. package/dist/AppShell/AppShell.d.ts +76 -11
  3. package/dist/AppShell/index.d.ts +1 -1
  4. package/dist/AppShell/index.js +2 -2
  5. package/dist/{AppShell-CEVLW4QG.css → AppShell-6QUD7NWM.css} +74 -1
  6. package/dist/AvatarPicker/index.js +4 -4
  7. package/dist/Canvas/index.js +3 -3
  8. package/dist/Charts/StackedColumns.d.ts +30 -7
  9. package/dist/Charts/index.d.ts +1 -1
  10. package/dist/Charts/index.js +1 -1
  11. package/dist/{Charts-JUERFLAR.css → Charts-JYW4X5ZL.css} +18 -1
  12. package/dist/CommandPalette/index.js +3 -3
  13. package/dist/DataTable/index.js +5 -5
  14. package/dist/DataView/index.js +9 -9
  15. package/dist/DateTimePicker/index.js +3 -3
  16. package/dist/{DateTimePicker-4AZBTODT.css → DateTimePicker-NJ6XH2TE.css} +4 -3
  17. package/dist/DescriptionList/DescriptionList.d.ts +9 -1
  18. package/dist/DescriptionList/index.js +1 -1
  19. package/dist/{DescriptionList-YYY3V3O6.css → DescriptionList-IXMRCSMK.css} +24 -0
  20. package/dist/FactList/index.js +3 -3
  21. package/dist/Layer/index.js +1 -1
  22. package/dist/Layer-J222IFNX.css +33 -0
  23. package/dist/Layout/index.js +1 -1
  24. package/dist/{Layout-2ZCV3IGF.css → Layout-ZBEGLXAE.css} +18 -0
  25. package/dist/ListInput/index.js +3 -3
  26. package/dist/MarkdownEditor/index.js +1 -1
  27. package/dist/Menu/index.js +2 -2
  28. package/dist/Modal/index.js +2 -2
  29. package/dist/{Modal-3YJ2GG2T.css → Modal-RQAYGG4L.css} +1 -1
  30. package/dist/OrgTable/index.js +5 -5
  31. package/dist/Popover/index.js +2 -2
  32. package/dist/Select/index.js +2 -2
  33. package/dist/{Select-XMZ44RWY.css → Select-2P7AWUE4.css} +32 -6
  34. package/dist/Shortcut/index.js +1 -1
  35. package/dist/Switcher/index.js +5 -5
  36. package/dist/TagsInput/index.js +3 -3
  37. package/dist/TimeWindowPicker/index.js +4 -4
  38. package/dist/{TimeWindowPicker-GBF4JDFI.css → TimeWindowPicker-BZ5HHATU.css} +5 -4
  39. package/dist/Toaster/Toaster.d.ts +6 -1
  40. package/dist/Toaster/index.js +2 -2
  41. package/dist/{Toaster-KZ7YE2HA.css → Toaster-EOOOTSJT.css} +82 -87
  42. package/dist/Toolbar/index.js +1 -1
  43. package/dist/Tooltip/index.js +2 -2
  44. package/dist/TreeCanvas/index.js +4 -4
  45. package/dist/TreeGrid/index.js +3 -3
  46. package/dist/{chunk-UZPHPW3Z.js → chunk-2GXTIK37.js} +4 -4
  47. package/dist/{chunk-RZ7RGECB.js → chunk-2OLCUNG7.js} +1 -1
  48. package/dist/{chunk-JDPAA2JU.js → chunk-2UU5IGZI.js} +2 -2
  49. package/dist/{chunk-B2CITO6R.js → chunk-7BZPYA5P.js} +3 -3
  50. package/dist/{chunk-2PZBIHRV.js → chunk-AMH67MLM.js} +2 -2
  51. package/dist/{chunk-6LXMLQUM.js → chunk-B2Z2CDM5.js} +2 -2
  52. package/dist/{chunk-O2ZDZZS7.js → chunk-BWRGFKJP.js} +3 -2
  53. package/dist/{chunk-75WOCYGC.js → chunk-DYHSQHAZ.js} +1 -1
  54. package/dist/{chunk-4FFHJBEN.js → chunk-EFNHOVC2.js} +1 -1
  55. package/dist/{chunk-XN4JBAN3.js → chunk-F2XSYBKH.js} +8 -2
  56. package/dist/{chunk-XFE5W2I4.js → chunk-FC4YTTFJ.js} +14 -4
  57. package/dist/{chunk-L3CTFFLZ.js → chunk-H3XOMT7W.js} +53 -9
  58. package/dist/{chunk-7RPGY3JE.js → chunk-HMPFGIWM.js} +1 -1
  59. package/dist/{chunk-HKGS67VG.js → chunk-IYZZL3MZ.js} +1 -1
  60. package/dist/{chunk-URYDN2KA.js → chunk-JI5AVQLA.js} +1 -1
  61. package/dist/{chunk-CF6DTETT.js → chunk-K4VORB64.js} +2 -2
  62. package/dist/{chunk-S3IENQ3E.js → chunk-LCF4WPYS.js} +3 -3
  63. package/dist/{chunk-4WNNEDKO.js → chunk-MLT2HBPN.js} +87 -74
  64. package/dist/{chunk-TFH6SYWB.js → chunk-NS7BVLL3.js} +1 -1
  65. package/dist/{chunk-LELD5KPA.js → chunk-QH3AKP2N.js} +22 -9
  66. package/dist/{chunk-WY2NLRZN.js → chunk-QV266R6G.js} +3 -3
  67. package/dist/{chunk-CQY5NTRS.js → chunk-QWOPX2MN.js} +1 -1
  68. package/dist/{chunk-53DVJCVW.js → chunk-VYOKRN2I.js} +1 -1
  69. package/dist/{chunk-W4ENKCXJ.js → chunk-ZAC7SKUN.js} +1 -1
  70. package/dist/generated/index.js +33 -33
  71. package/dist/index.js +33 -33
  72. package/dist/styles.css +279 -114
  73. package/package.json +3 -3
  74. package/dist/Layer-NAFSGCFA.css +0 -23
  75. package/dist/{chunk-LZP7FGT7.js → chunk-GARACZAH.js} +1 -1
  76. package/dist/{chunk-GG2QEZO2.js → chunk-JCO3SIST.js} +1 -1
package/README.md CHANGED
@@ -198,6 +198,48 @@ places:
198
198
  - A surface that pans or zooms dispatches `LAYER_REPOSITION_EVENT` on its host
199
199
  when the content beneath it moves, and every panel anchored inside follows.
200
200
 
201
+ ## Changes in 0.15.0
202
+
203
+ 0.15.0 gives the rail's foot a row that opens a panel, which is what the engine console's engine panel is built from. It also keeps an unread failure on screen, lets the column chart fill a stretched card, and wraps its legend on a narrow one.
204
+
205
+ **`AppShell.RailRow` opens a panel.** It hands its element to `ref`, and a row with `onClick` passes `aria-expanded`, `aria-haspopup` and `aria-controls` through to its button, so it is the trigger of a `Popover` or a `Menu` as it is. A row that opens something ends in an upward chevron, and keeps the hover's lift while its panel is open, drawn from `aria-expanded`. A row nothing presses refuses all three in its type, as it refuses `label`.
206
+
207
+ **`AppShell.RailRow` takes a `count`**: `{ value, label, mark?, tone? }` (`RailRowCount`), drawn after the words as a count in the nav is, and read as the end of the row's name ("Engine serving, 5 alarms"). `tone: 'warning'` draws the figure and its mark in the warning ink, which `@crewlethq/tokens` now holds to 4.5:1 on the rail and under the hover overlay in every theme.
208
+
209
+ **A control in the rail's foot is a row of the rail's own grammar.** A `RailRow` with `onClick` and no `detail`, and a control dropped into the foot, stand on the nav row's 30px step with its glyph gap, its compact medium words and its secondary ink, and the row's mark takes a nav glyph's 14px width, so its words start where the nav's words start. A row the rail only states keeps the status line's caption, and a row with a `detail` keeps the status block.
210
+
211
+ **`DescriptionList` takes `fit`**: the term column is as wide as its longest term, and the pairs stay side by side at every width, for a panel of its own width such as a popover.
212
+
213
+ **A `Stack` or an `Inline` drawn as a list** (`as="ul"` or `as="ol"`) takes back the browser's list margins, indent and markers, and stays a list to a screen reader.
214
+
215
+ **A `Popover` its own content closes hands focus back to its trigger**, as Escape does, when focus was inside the panel: the control that closed it goes with the panel, and focus used to fall to the page's body. A close while focus is elsewhere leaves it there.
216
+
217
+ **A panel opened from the open drawer is drawn above it.** A `LayerHost`'s target takes no z-index of its own any more, so every surface in it stacks by its own step in the layer band. It used to be a stacking context at the bottom of the band, which held everything inside it under the shell's open drawer: a popover or a dialog opened from the drawer, below the shell breakpoint, was drawn under the drawer.
218
+
219
+ **A sticky toast is never evicted.** `ToastProvider` kept its newest `max` toasts whatever they were, so the next one took away a failure nobody had read. Over `max`, the oldest toast that would have gone by itself goes now. A failure, a warning, a variant of your own that names no duration and any toast given `duration: 0` stay until they are dismissed, and when every toast held is sticky none goes: the stack holds more than `max` until the reader dismisses some, and the new toast is drawn too. A failure that can be raised again and again takes an `id`, so each repeat replaces its own strip.
220
+
221
+ **`StackedColumns` takes `height="fill"`.** In a card that a taller neighbour stretches, the chart grows into the spare height and spends all of it on the plot, so nothing opens between the dates and what stands under them. The figure flexes, its rows are `auto` / `minmax(minHeight, 1fr)` / `auto`, and the axis and the plot stand at the whole of the plot's row. `minHeight` is the plot's least height, 11.5rem by default, and its height wherever nothing stretches it. `StackedColumnsHeight` and `StackedColumnsLegend` are exported.
222
+
223
+ **A `StackedColumns` legend in the head wraps.** On a card too narrow for the heading and the legend side by side, the legend takes a row of its own under the heading, still flushed to the end, rather than standing beside the title as a column of one series a line. Where both fit, nothing moves.
224
+
225
+ What to change: a screen that leaned on `max` to clear old failures now keeps them until they are dismissed; give a repeated failure an `id`, and take one back with `useToast().dismiss(id)` once its condition clears. A test that reads a foot control's caption ink, its regular weight or its 34px height reads the nav row's. Everything else is new.
226
+
227
+ ## Changes in 0.14.0
228
+
229
+ 0.14.0 draws toasts as the first release did and quiets the pickers.
230
+
231
+ **Toasts are the first release's strip again**: a dark strip on `--color-surface-background` with the large shadow and the rim light, a 12px corner, a 20px mark, a slide in from the right, and the countdown as a wash behind the words that drains from the right. A variant spends its hue on its mark (the feedback ink step) and its wash (the feedback soft step) only, so a failure is a rose mark on a faint rose wash with a rose action, never red words on a red edge. Reduced motion keeps the strip still and draws no wash.
232
+
233
+ **A picker's boundary is a button's.** `Select`, `DateTimePicker` and `TimeWindowPicker` draw their trigger on `--color-border-strong`, as the secondary button does, and step to `--color-border-strong-hover` under the pointer. Text boxes, checkboxes and switches keep `--color-border-control` at 3:1, as do the typed boxes inside the pickers' panels.
234
+
235
+ **A `Select` list that leads with marks ends its rows with the tick**, so a swatch, an avatar or a glyph starts at the panel's edge. A list of words keeps the tick's column first.
236
+
237
+ **`--crewlet-select-menu-max-height` is the list's height.** The shared listbox cap of min(360px, 60vh) no longer overrides a taller panel; the panel keeps the 60vh cap on the window.
238
+
239
+ `@crewlethq/tokens`: Origin's dark `--color-border-default` is #2e2e30, and the comfortable density is 1.16 (it was 1.14), a shade larger at every gap, pad, row and control.
240
+
241
+ What to change: a test that reads a failure toast's red edge or red words, or a picker's control boundary, reads the new ones. Everything else is unchanged.
242
+
201
243
  ## Changes in 0.13.0
202
244
 
203
245
  0.13.0 adds the parts the engine console's themes, project switcher, inbox and knowledge base are built with, and calls the light and dark choice Mode.
@@ -37,7 +37,8 @@
37
37
  * because a rail translated out of view keeps every link in the tab order and
38
38
  * a keyboard reader walks through a dozen stops nobody can see.
39
39
  */
40
- import { type HTMLAttributes, type MouseEventHandler, type ReactNode, type Ref } from 'react';
40
+ import { type AriaAttributes, type HTMLAttributes, type MouseEventHandler, type ReactNode, type Ref } from 'react';
41
+ import type { Tone } from '../utils/tone.js';
41
42
  /** What the shell tells the components inside it. */
42
43
  interface AppShellContextValue {
43
44
  /** Whether the layout is below the shell breakpoint. */
@@ -101,7 +102,7 @@ export interface AppShellProps extends Omit<HTMLAttributes<HTMLDivElement>, 'tit
101
102
  export declare function AppShell({ sidebar, topbar, banner, footer, mainId, mainRef, fill, navigationKey, toggleLabel, skipLabel, className, style, children, ...rest }: AppShellProps): import("react").JSX.Element;
102
103
  export declare namespace AppShell {
103
104
  var Rail: typeof AppShellRail;
104
- var RailRow: typeof AppShellRailRow;
105
+ var RailRow: import("react").ForwardRefExoticComponent<AppShellRailRowProps & import("react").RefAttributes<HTMLElement>>;
105
106
  var Topbar: typeof AppShellTopbar;
106
107
  var Toggle: typeof AppShellToggle;
107
108
  }
@@ -119,6 +120,37 @@ export interface AppShellRailProps {
119
120
  }
120
121
  /** The rail's three regions: a head, a scrolling middle, and a foot. */
121
122
  export declare function AppShellRail({ header, footer, className, children }: AppShellRailProps): import("react").JSX.Element;
123
+ /**
124
+ * A figure at the end of a row in the foot, and what it counts.
125
+ *
126
+ * VALUES RATHER THAN AN ELEMENT, for the reason `NavItem`'s figures are
127
+ * values: the rail paints the figure, so its ink is held to its floor on
128
+ * every ground the row can have, the row a panel is open from included, and
129
+ * that is a fact about the rail rather than something a call site can be
130
+ * asked to know.
131
+ */
132
+ export interface RailRowCount {
133
+ /** The figure, drawn as given, so the caller decides its formatting. */
134
+ value: number | string;
135
+ /**
136
+ * What is counted, read after the figure as part of the row's name:
137
+ * `alarms` makes the engine's row "Engine serving, 5 alarms". Required,
138
+ * because a figure read with no word after it is a number nobody can place.
139
+ */
140
+ label: string;
141
+ /**
142
+ * A mark before the figure: the triangle beside a count of alarms.
143
+ * Decoration, because the label says the same thing in words.
144
+ */
145
+ mark?: ReactNode;
146
+ /**
147
+ * `warning` draws the figure and its mark in the warning ink, for a count
148
+ * of things that are wrong: the alarms standing on a node. The figure is
149
+ * never the only carrier, since its mark and its label say the same. Left
150
+ * out, it is the quiet figure a count in the nav is, in the tertiary ink.
151
+ */
152
+ tone?: Extract<Tone, 'neutral' | 'warning'> | undefined;
153
+ }
122
154
  /** What a row in the rail's foot holds, whether or not it is a control. */
123
155
  interface RailRowContent {
124
156
  /**
@@ -128,11 +160,19 @@ interface RailRowContent {
128
160
  */
129
161
  icon?: ReactNode;
130
162
  /**
131
- * A value at the end of the row: a count, a tag, a time. It stands beside
132
- * the words while both fit on the rail, and drops under them when they do
133
- * not, so it never takes the room the words need.
163
+ * A value at the end of the row: a tag, a time. It stands beside the words
164
+ * while both fit on the rail, and drops under them when they do not, so it
165
+ * never takes the room the words need. A figure with words that name it is
166
+ * `count`.
134
167
  */
135
168
  trailing?: ReactNode;
169
+ /**
170
+ * How many of something the row reports, as a figure after the words: the
171
+ * alarms standing on the engine. It is read as the end of the row's name
172
+ * (", 5 alarms") and hidden from assistive technology where it is drawn, so
173
+ * each reader is told it once.
174
+ */
175
+ count?: RailRowCount | undefined;
136
176
  /**
137
177
  * A second line under the row's words: "3 nodes · config epoch 42" under
138
178
  * "Engine healthy". Given one, the row is the design's STATUS BLOCK, drawn
@@ -148,23 +188,43 @@ interface RailRowContent {
148
188
  export interface StaticRailRowProps extends RailRowContent {
149
189
  onClick?: undefined;
150
190
  label?: undefined;
191
+ 'aria-expanded'?: undefined;
192
+ 'aria-haspopup'?: undefined;
193
+ 'aria-controls'?: undefined;
151
194
  }
152
195
  /** A row that opens something: the engine panel, an account menu. */
153
196
  export interface ActionRailRowProps extends RailRowContent {
154
197
  onClick: MouseEventHandler<HTMLButtonElement>;
155
198
  /**
156
199
  * Names the control where its own words are not a name: "engine connected"
157
- * names a state rather than what pressing it does.
200
+ * names a state rather than what pressing it does. It replaces the name the
201
+ * row's words and its count would give it, so it says the count too.
158
202
  */
159
203
  label?: string | undefined;
204
+ /**
205
+ * Whether the panel this row opens is open. A `Popover` or a `Menu` the row
206
+ * is the trigger of passes this and the two below, and the row draws its
207
+ * open state from it, so the picture and what a screen reader is told
208
+ * cannot come apart.
209
+ */
210
+ 'aria-expanded'?: boolean | undefined;
211
+ /**
212
+ * What the row opens. Given one, the row ends in a chevron pointing up,
213
+ * which is where a panel opened from the rail's foot stands.
214
+ */
215
+ 'aria-haspopup'?: AriaAttributes['aria-haspopup'];
216
+ /** The panel the row opens, while it is open. */
217
+ 'aria-controls'?: string | undefined;
160
218
  }
161
219
  /**
162
220
  * A row in the rail's foot.
163
221
  *
164
- * `label` is refused without `onClick` by the type rather than ignored at
165
- * runtime: `aria-label` on an element with no role is dropped by assistive
166
- * technology, so a name passed to a row nothing presses is a name nobody is
167
- * ever told, and a silent no-op is the shape a caller cannot debug.
222
+ * `label` and the three popup attributes are refused without `onClick` by the
223
+ * type rather than ignored at runtime: `aria-label` on an element with no role
224
+ * is dropped by assistive technology, and `aria-expanded` on one is a state of
225
+ * a control that does not exist, so either passed to a row nothing presses is
226
+ * something nobody is ever told, and a silent no-op is the shape a caller
227
+ * cannot debug.
168
228
  */
169
229
  export type AppShellRailRowProps = StaticRailRowProps | ActionRailRowProps;
170
230
  /**
@@ -183,8 +243,13 @@ export type AppShellRailRowProps = StaticRailRowProps | ActionRailRowProps;
183
243
  * a dropped-in control is a row in the rail rather than a control sitting on a
184
244
  * toolbar's inset. This is still the one to reach for, because it is also the
185
245
  * thing that decides whether the row is a control at all.
246
+ *
247
+ * A ROW THAT OPENS A PANEL IS THE PANEL'S TRIGGER, as it is: the element is
248
+ * handed to `ref`, and the popup attributes a `Popover` or a `Menu` gives its
249
+ * trigger reach the button, so the panel is anchored to the row and the row
250
+ * says whether it is open.
186
251
  */
187
- export declare function AppShellRailRow({ icon, trailing, detail, onClick, label, className, children }: AppShellRailRowProps): import("react").JSX.Element;
252
+ export declare const AppShellRailRow: import("react").ForwardRefExoticComponent<AppShellRailRowProps & import("react").RefAttributes<HTMLElement>>;
188
253
  export interface AppShellToggleProps {
189
254
  className?: string | undefined;
190
255
  }
@@ -1,3 +1,3 @@
1
1
  import './AppShell.css';
2
2
  export { AppShell, AppShellRail, AppShellRailRow, AppShellToggle, AppShellTopbar, useAppShell } from './AppShell.js';
3
- export type { ActionRailRowProps, AppShellContextValue, AppShellProps, AppShellRailProps, AppShellRailRowProps, AppShellToggleProps, AppShellTopbarProps, StaticRailRowProps, } from './AppShell.js';
3
+ export type { ActionRailRowProps, AppShellContextValue, AppShellProps, AppShellRailProps, AppShellRailRowProps, AppShellToggleProps, AppShellTopbarProps, RailRowCount, StaticRailRowProps, } from './AppShell.js';
@@ -1,7 +1,7 @@
1
- export { AppShell, AppShellRail, AppShellRailRow, AppShellToggle, AppShellTopbar, useAppShell } from '../chunk-L3CTFFLZ.js';
1
+ export { AppShell, AppShellRail, AppShellRailRow, AppShellToggle, AppShellTopbar, useAppShell } from '../chunk-H3XOMT7W.js';
2
2
  import '../chunk-IG75YMUN.js';
3
3
  import '../chunk-4FQT6ZAY.js';
4
- import '../chunk-7RPGY3JE.js';
4
+ import '../chunk-HMPFGIWM.js';
5
5
  import '../chunk-R25RGPUB.js';
6
6
  import '../chunk-BZFWDIV6.js';
7
7
  import '../chunk-ODEQTPFM.js';
@@ -215,7 +215,44 @@
215
215
  color var(--motion-duration-fast) var(--motion-easing-default);
216
216
  }
217
217
 
218
- .crewlet-app-shell__rail-row--action:hover {
218
+ /*
219
+ * A CONTROL IN THE FOOT IS A ROW OF THE RAIL'S OWN GRAMMAR: the nav row's 30px
220
+ * step, its glyph-to-word gap, its word size and weight, and its secondary ink
221
+ * lifting to the primary under the pointer, as Settings above it is drawn. So
222
+ * the engine's row under Settings reads as one more row of the rail rather
223
+ * than as a caption, its words start on the line the nav's words start on, and
224
+ * it keeps one height in every state it says: one line of the compact step.
225
+ * A status line the rail only states keeps the quieter caption above, and the
226
+ * status block keeps its card.
227
+ *
228
+ * Its mark takes a nav glyph's width, `sm` (14px), whatever the mark is, so a
229
+ * 7px status dot is centred where the glyph above it is centred and the words
230
+ * beside it start where "Settings" starts.
231
+ */
232
+ .crewlet-app-shell__rail-row--action:not(.crewlet-app-shell__rail-row--block),
233
+ .crewlet-app-shell__rail-foot > .crewlet-btn {
234
+ gap: calc(var(--spacing-2) + var(--spacing-1) / 2);
235
+ min-height: var(--size-nav-row);
236
+ padding-block: 0;
237
+ color: var(--color-text-secondary);
238
+ font-size: var(--font-size-compact);
239
+ font-weight: var(--font-weight-medium);
240
+ letter-spacing: var(--font-letter-spacing-snug);
241
+ line-height: var(--font-line-height-tight);
242
+ }
243
+
244
+ .crewlet-app-shell__rail-row--action:not(.crewlet-app-shell__rail-row--block) > .crewlet-app-shell__rail-row-icon {
245
+ min-width: 14px;
246
+ }
247
+
248
+ /*
249
+ * OPEN IS POINTED AT. The row a panel is open from keeps the hover's lift for
250
+ * as long as the panel is open, drawn from `aria-expanded` so the picture and
251
+ * what a screen reader is told cannot come apart, as the switcher's trigger
252
+ * draws it.
253
+ */
254
+ .crewlet-app-shell__rail-row--action:hover,
255
+ .crewlet-app-shell__rail-row--action[aria-expanded='true'] {
219
256
  background: var(--color-surface-hover);
220
257
  color: var(--color-text-primary);
221
258
  }
@@ -293,6 +330,42 @@
293
330
  flex: none;
294
331
  }
295
332
 
333
+ /*
334
+ * THE COUNT: how many of something the row reports, after its words, drawn as
335
+ * a count in the nav is: the caption step, tabular figures so a count that
336
+ * ticks up does not move the words beside it, and a mark half a step off the
337
+ * figure. It is the tertiary step, as the nav's is, unless what it counts is
338
+ * wrong: a warning count is the warning ink, figure and mark together, which
339
+ * @crewlethq/tokens holds to 4.5:1 on the rail and under the hover overlay
340
+ * (RAIL_PAINTS), so on the row a panel is open from too.
341
+ */
342
+ .crewlet-app-shell__rail-row-count {
343
+ display: inline-flex;
344
+ align-items: center;
345
+ flex: none;
346
+ gap: calc(var(--spacing-1) + 1px);
347
+ color: var(--color-text-tertiary);
348
+ font-size: var(--font-size-2xs);
349
+ font-variant-numeric: tabular-nums;
350
+ }
351
+
352
+ .crewlet-app-shell__rail-row-count-mark {
353
+ display: inline-flex;
354
+ }
355
+
356
+ .crewlet-app-shell__rail-row-count--warning {
357
+ color: var(--color-feedback-warning-ink);
358
+ }
359
+
360
+ /* The chevron that says the row opens a panel, in the quiet step: a mark, not
361
+ a word, and it stays quiet while the row lifts, as the panel's own name is
362
+ what a reader is told. */
363
+ .crewlet-app-shell__rail-row-opens {
364
+ display: inline-flex;
365
+ flex: none;
366
+ color: var(--color-text-tertiary);
367
+ }
368
+
296
369
  /*
297
370
  * THE STATUS BLOCK: a row given a `detail` is the approved design's engine
298
371
  * status, its words over a second line, on the card rung inside the plain
@@ -1,14 +1,14 @@
1
- export { AvatarPicker } from '../chunk-4FFHJBEN.js';
1
+ export { AvatarPicker } from '../chunk-EFNHOVC2.js';
2
2
  import '../chunk-NXDEPUVG.js';
3
3
  import '../chunk-AYKXMIOR.js';
4
4
  import '../chunk-26PEPONN.js';
5
5
  import '../chunk-4LDTQWS7.js';
6
- import '../chunk-O2ZDZZS7.js';
6
+ import '../chunk-BWRGFKJP.js';
7
7
  import '../chunk-YXMCUKFI.js';
8
8
  import '../chunk-CBOICT64.js';
9
9
  import '../chunk-BHHIIK3M.js';
10
- import '../chunk-7RPGY3JE.js';
10
+ import '../chunk-HMPFGIWM.js';
11
11
  import '../chunk-R25RGPUB.js';
12
- import '../chunk-HI6Q2UXQ.js';
13
12
  import '../chunk-BZFWDIV6.js';
13
+ import '../chunk-HI6Q2UXQ.js';
14
14
  import '../chunk-ODEQTPFM.js';
@@ -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-2PZBIHRV.js';
2
- import '../chunk-53DVJCVW.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-AMH67MLM.js';
2
+ import '../chunk-VYOKRN2I.js';
3
3
  import '../chunk-OG6CL3EB.js';
4
4
  import '../chunk-4FQT6ZAY.js';
5
- import '../chunk-7RPGY3JE.js';
5
+ import '../chunk-HMPFGIWM.js';
6
6
  import '../chunk-R25RGPUB.js';
7
7
  import '../chunk-BZFWDIV6.js';
8
8
  import '../chunk-ODEQTPFM.js';
@@ -17,12 +17,24 @@ export interface StackedColumnsBucket {
17
17
  *
18
18
  * `below`, the default, under the dates. `head` at the END of the chart's head
19
19
  * row, top right, where the design's Spend card draws it beside the card's
20
- * title: pass that title as `head` and the two share one line. `none` draws no
21
- * legend, for a screen that names the series somewhere the chart cannot reach;
22
- * the chart is then that screen's to caption, and a stacked figure without its
23
- * legend is a picture of some numbers.
20
+ * title: pass that title as `head` and the two share one line wherever both
21
+ * fit, while on a card too narrow for both the legend drops to a row of its
22
+ * own under the title, still at the end. `none` draws no legend, for a screen
23
+ * that names the series somewhere the chart cannot reach; the chart is then
24
+ * that screen's to caption, and a stacked figure without its legend is a
25
+ * picture of some numbers.
24
26
  */
25
27
  export type StackedColumnsLegend = 'below' | 'head' | 'none';
28
+ /**
29
+ * How tall the plot is: a CSS length, or `fill`.
30
+ *
31
+ * `fill` is for a chart its container stretches, such as a card beside a
32
+ * taller one in a row of one height. The figure flexes into the height it is
33
+ * given and spends all of it on the plot, so the spare height opens inside
34
+ * the plot rather than as a band of nothing under the dates. Wherever nothing
35
+ * stretches it, the plot is `minHeight` tall.
36
+ */
37
+ export type StackedColumnsHeight = 'fill' | (string & {});
26
38
  export interface StackedColumnsProps {
27
39
  /**
28
40
  * Every series the figure CAN draw, in stacking order: the first stands on
@@ -46,8 +58,14 @@ export interface StackedColumnsProps {
46
58
  * row over the plot, with the legend at its end when `legend` is `head`.
47
59
  */
48
60
  head?: ReactNode;
49
- /** How tall the plot is, as a CSS length. */
50
- height?: string;
61
+ /** How tall the plot is, as a CSS length, or `fill`: see the type. Defaults to 11.5rem. */
62
+ height?: StackedColumnsHeight;
63
+ /**
64
+ * The least height of a `fill` plot, as a CSS length, which is its height
65
+ * wherever nothing stretches the figure. Defaults to 11.5rem, the height of
66
+ * a plot given none.
67
+ */
68
+ minHeight?: string;
51
69
  /** How a value reads out, on the scale and in the tooltip. Defaults to a compact number. */
52
70
  format?: (value: number) => string;
53
71
  /** How a bucket reads out, under the plot and in the tooltip. Defaults to the reader's date. */
@@ -105,8 +123,13 @@ export declare function niceScale(peak: number, steps?: number): {
105
123
  * under the dates or at the end of the chart's head, top right, as the
106
124
  * design's Spend card has it.
107
125
  *
126
+ * IT CAN TAKE THE HEIGHT IT IS GIVEN. Drawn at a fixed height in a card that a
127
+ * taller neighbour stretched, the plot stopped where its length said and the
128
+ * rest of the card was a band of nothing under the dates; `height="fill"`
129
+ * spends that height on the plot instead (see the type).
130
+ *
108
131
  * All of it is HTML positioned by style properties, so it holds a crisp 2px
109
132
  * gap and a true 4px corner at any width, which a stretched SVG cannot, and no
110
133
  * style element is ever drawn.
111
134
  */
112
- export declare function StackedColumns({ series, buckets, hidden, label, legend, head, height, format, formatTime, summary, className, }: StackedColumnsProps): import("react").JSX.Element;
135
+ export declare function StackedColumns({ series, buckets, hidden, label, legend, head, height, minHeight, format, formatTime, summary, className, }: StackedColumnsProps): import("react").JSX.Element;
@@ -11,7 +11,7 @@ export type { ActivityBucket, ActivityStripProps } from './ActivityStrip.js';
11
11
  export { TimeSeries, Sparkline } from './TimeSeries.js';
12
12
  export type { Series, SeriesPoint, SparklineProps, TimeSeriesProps } from './TimeSeries.js';
13
13
  export { StackedColumns, niceScale } from './StackedColumns.js';
14
- export type { StackedColumnsBucket, StackedColumnsProps, StackedColumnsSeries } from './StackedColumns.js';
14
+ export type { StackedColumnsBucket, StackedColumnsHeight, StackedColumnsLegend, StackedColumnsProps, StackedColumnsSeries, } from './StackedColumns.js';
15
15
  export { ChartTooltip } from './ChartTooltip.js';
16
16
  export type { ChartTooltipProps, ChartTooltipRow } from './ChartTooltip.js';
17
17
  export { useChartHover } from './useChartHover.js';
@@ -1,3 +1,3 @@
1
- export { ActivityStrip, BarList, ChartTooltip, DATA_COLORS, DATA_COLOR_OTHER, Legend, Sparkline, StackedBar, StackedColumns, TimeSeries, dataColor, niceScale, useChartHover } from '../chunk-4WNNEDKO.js';
1
+ export { ActivityStrip, BarList, ChartTooltip, DATA_COLORS, DATA_COLOR_OTHER, Legend, Sparkline, StackedBar, StackedColumns, TimeSeries, dataColor, niceScale, useChartHover } from '../chunk-MLT2HBPN.js';
2
2
  import '../chunk-BZFWDIV6.js';
3
3
  import '../chunk-ODEQTPFM.js';
@@ -405,6 +405,16 @@
405
405
  min-width: 0;
406
406
  }
407
407
 
408
+ /*
409
+ * A FILL CHART GROWS INTO THE HEIGHT IT IS GIVEN (`height="fill"`). The figure
410
+ * flexes, so in a card a taller neighbour stretches it takes the spare height,
411
+ * and its rows (a style property) spend all of it on the plot's row. Nowhere to
412
+ * grow, it is as tall as its content, the plot at its least.
413
+ */
414
+ .crewlet-stacked-columns--fill {
415
+ flex: 1 1 auto;
416
+ }
417
+
408
418
  /*
409
419
  * EACH WORD IS A BOX OF NO HEIGHT, spread from the top of the plot to its
410
420
  * baseline, with the word centred on it: so every word stands exactly on the
@@ -519,12 +529,19 @@
519
529
  * legend at its END, top right, where the design's Spend card draws it; the
520
530
  * legend is flushed to the end of that row and wraps from there. Below, the
521
531
  * legend starts under the axis, a step clear of the dates.
532
+ *
533
+ * ON A CARD TOO NARROW FOR BOTH, THE LEGEND TAKES A ROW OF ITS OWN, under the
534
+ * heading and still flushed to the end. Held on one line, the two shrank
535
+ * together and the legend stood beside the title as a column of one series a
536
+ * line. The rows stand a step apart, closer than the head stands to the plot,
537
+ * so the legend still reads as the head's.
522
538
  */
523
539
  .crewlet-stacked-columns__head {
524
540
  grid-column: 1 / -1;
525
541
  display: flex;
542
+ flex-wrap: wrap;
526
543
  align-items: flex-start;
527
- gap: var(--spacing-4);
544
+ gap: var(--spacing-2) var(--spacing-4);
528
545
  margin-bottom: var(--spacing-3);
529
546
  min-width: 0;
530
547
  }
@@ -1,5 +1,5 @@
1
- export { CommandPalette } from '../chunk-HKGS67VG.js';
2
- import '../chunk-CF6DTETT.js';
1
+ export { CommandPalette } from '../chunk-IYZZL3MZ.js';
2
+ import '../chunk-K4VORB64.js';
3
3
  import '../chunk-F73MC7EZ.js';
4
4
  import '../chunk-SMBKXWML.js';
5
5
  import '../chunk-FTEJPHBI.js';
@@ -7,7 +7,7 @@ import '../chunk-OG6CL3EB.js';
7
7
  import '../chunk-PQADV6P6.js';
8
8
  import '../chunk-4FQT6ZAY.js';
9
9
  import '../chunk-BHHIIK3M.js';
10
- import '../chunk-7RPGY3JE.js';
10
+ import '../chunk-HMPFGIWM.js';
11
11
  import '../chunk-R25RGPUB.js';
12
12
  import '../chunk-BZFWDIV6.js';
13
13
  import '../chunk-ODEQTPFM.js';
@@ -1,14 +1,14 @@
1
- export { ALL_ITEMS, CopyableCell, DATA_TABLE_LABELS, DataTable, RowActionsMenu } from '../chunk-WY2NLRZN.js';
2
- import '../chunk-TFH6SYWB.js';
1
+ export { ALL_ITEMS, CopyableCell, DATA_TABLE_LABELS, DataTable, RowActionsMenu } from '../chunk-QV266R6G.js';
2
+ import '../chunk-NS7BVLL3.js';
3
3
  import '../chunk-EUCC37WY.js';
4
- import '../chunk-YCTMKKRA.js';
4
+ import '../chunk-K4VORB64.js';
5
5
  import '../chunk-5VNUYO76.js';
6
- import '../chunk-CF6DTETT.js';
7
6
  import '../chunk-OG6CL3EB.js';
8
7
  import '../chunk-AV2DXAEL.js';
8
+ import '../chunk-YCTMKKRA.js';
9
9
  import '../chunk-PQADV6P6.js';
10
10
  import '../chunk-4FQT6ZAY.js';
11
- import '../chunk-7RPGY3JE.js';
11
+ import '../chunk-HMPFGIWM.js';
12
12
  import '../chunk-R25RGPUB.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-UZPHPW3Z.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-2GXTIK37.js';
2
2
  import '../chunk-HOXGBLEY.js';
3
3
  import '../chunk-3CZ7XAVY.js';
4
4
  import '../chunk-PGRPNDWM.js';
5
- import '../chunk-WY2NLRZN.js';
6
- import '../chunk-TFH6SYWB.js';
5
+ import '../chunk-QV266R6G.js';
6
+ import '../chunk-NS7BVLL3.js';
7
7
  import '../chunk-EUCC37WY.js';
8
- import '../chunk-JDPAA2JU.js';
9
- import '../chunk-YCTMKKRA.js';
10
- import '../chunk-5VNUYO76.js';
11
- import '../chunk-CF6DTETT.js';
8
+ import '../chunk-2UU5IGZI.js';
9
+ import '../chunk-K4VORB64.js';
12
10
  import '../chunk-F73MC7EZ.js';
13
11
  import '../chunk-SMBKXWML.js';
14
12
  import '../chunk-FTEJPHBI.js';
13
+ import '../chunk-5VNUYO76.js';
15
14
  import '../chunk-GXQ3B46I.js';
16
15
  import '../chunk-OG6CL3EB.js';
17
16
  import '../chunk-AV2DXAEL.js';
17
+ import '../chunk-YCTMKKRA.js';
18
18
  import '../chunk-PQADV6P6.js';
19
19
  import '../chunk-4FQT6ZAY.js';
20
- import '../chunk-O2ZDZZS7.js';
20
+ import '../chunk-BWRGFKJP.js';
21
21
  import '../chunk-BHHIIK3M.js';
22
- import '../chunk-7RPGY3JE.js';
22
+ import '../chunk-HMPFGIWM.js';
23
23
  import '../chunk-R25RGPUB.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-JDPAA2JU.js';
1
+ export { DEFAULT_DATE_TIME_PICKER_LABELS, DateTimePicker } from '../chunk-2UU5IGZI.js';
2
2
  import '../chunk-GXQ3B46I.js';
3
3
  import '../chunk-OG6CL3EB.js';
4
4
  import '../chunk-4FQT6ZAY.js';
5
- import '../chunk-O2ZDZZS7.js';
6
- import '../chunk-7RPGY3JE.js';
5
+ import '../chunk-BWRGFKJP.js';
6
+ import '../chunk-HMPFGIWM.js';
7
7
  import '../chunk-R25RGPUB.js';
8
8
  import '../chunk-BZFWDIV6.js';
9
9
  import '../chunk-ODEQTPFM.js';
@@ -1,7 +1,8 @@
1
1
  /*
2
2
  * DateTimePicker: a Select-shaped trigger over a calendar dialog.
3
3
  *
4
- * The trigger borrows the Select's geometry so a date box and a picker line
4
+ * The trigger borrows the Select's geometry and its button boundary
5
+ * (--color-border-strong; see Select.css) so a date box and a picker line
5
6
  * up in the same toolbar; the panel holds the shared CalendarGrid, so the
6
7
  * month looks and behaves the same here as in every other picker.
7
8
  */
@@ -17,7 +18,7 @@
17
18
  height. */
18
19
  padding: 0 var(--spacing-2) 0 var(--spacing-3);
19
20
  background: var(--color-surface-subtle);
20
- border: 1px solid var(--color-border-control);
21
+ border: 1px solid var(--color-border-strong);
21
22
  border-radius: var(--radius-md);
22
23
  color: var(--color-text-primary);
23
24
  font-family: inherit;
@@ -34,7 +35,7 @@
34
35
  }
35
36
 
36
37
  .crewlet-datetime:hover:not(:disabled) {
37
- border-color: var(--color-border-hover);
38
+ border-color: var(--color-border-strong-hover);
38
39
  }
39
40
 
40
41
  /*
@@ -4,6 +4,14 @@ export type DescriptionListEntry = readonly [term: ReactNode, detail: ReactNode]
4
4
  export interface DescriptionListProps extends HTMLAttributes<HTMLDListElement> {
5
5
  /** Tightens the rhythm for a panel that carries a dozen pairs. */
6
6
  dense?: boolean | undefined;
7
+ /**
8
+ * Sizes the term column to its longest term, and keeps each term beside its
9
+ * detail at every width: for a small panel whose terms are a word each
10
+ * ("Nodes", "Up"). The default column is 120px at the least and stacks on a
11
+ * narrow screen, which in a panel of a fixed width spends that width on the
12
+ * space after "Up" and stacks a list the panel had room to lay side by side.
13
+ */
14
+ fit?: boolean | undefined;
7
15
  /**
8
16
  * The pairs. Given as tuples so a caller can build them from a record
9
17
  * without inventing a key for each one; `DescriptionList.Item` children are
@@ -24,7 +32,7 @@ export interface DescriptionListProps extends HTMLAttributes<HTMLDListElement> {
24
32
  * Each pair is wrapped in a `div`, which HTML allows inside a `dl` and which
25
33
  * is what lets one pair be one grid row.
26
34
  */
27
- export declare function DescriptionList({ dense, items, className, children, ...rest }: DescriptionListProps): import("react").JSX.Element;
35
+ export declare function DescriptionList({ dense, fit, items, className, children, ...rest }: DescriptionListProps): import("react").JSX.Element;
28
36
  export declare namespace DescriptionList {
29
37
  var Item: typeof DescriptionListItem;
30
38
  }
@@ -1,2 +1,2 @@
1
- export { DescriptionList, DescriptionListItem } from '../chunk-XN4JBAN3.js';
1
+ export { DescriptionList, DescriptionListItem } from '../chunk-F2XSYBKH.js';
2
2
  import '../chunk-ODEQTPFM.js';
@@ -57,3 +57,27 @@
57
57
  margin-bottom: var(--spacing-2);
58
58
  }
59
59
  }
60
+
61
+ /*
62
+ * FIT: the term column is as wide as its longest term, and the pairs stay side
63
+ * by side at every width. It is for a panel of its own width, such as a
64
+ * popover, where the window's width says nothing about the room the list has:
65
+ * the narrow rule above is a question about the window, and a 260px panel is
66
+ * 260px on a phone and on a desktop alike. Its terms are a word each, so the
67
+ * column they take is a word wide and the details keep the rest.
68
+ *
69
+ * Written AFTER the narrow rule, which it overrides at the same weight, so
70
+ * nothing here has to outrank a media query.
71
+ */
72
+ .crewlet-description-list--fit {
73
+ grid-template-columns: max-content minmax(0, 1fr);
74
+ gap: var(--spacing-2) var(--spacing-4);
75
+ }
76
+
77
+ .crewlet-description-list--fit.crewlet-description-list--dense {
78
+ gap: var(--spacing-1) var(--spacing-3);
79
+ }
80
+
81
+ .crewlet-description-list--fit .crewlet-description-list__detail {
82
+ margin-bottom: 0;
83
+ }
@@ -1,6 +1,6 @@
1
- export { FactList } from '../chunk-URYDN2KA.js';
2
- import '../chunk-CQY5NTRS.js';
3
- import '../chunk-7RPGY3JE.js';
1
+ export { FactList } from '../chunk-JI5AVQLA.js';
2
+ import '../chunk-QWOPX2MN.js';
3
+ import '../chunk-HMPFGIWM.js';
4
4
  import '../chunk-R25RGPUB.js';
5
5
  import '../chunk-BZFWDIV6.js';
6
6
  import '../chunk-ODEQTPFM.js';