@danxbot/ui 24.4.0 → 25.1.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.
@@ -70,6 +70,18 @@ export interface SettingRowBaseProps {
70
70
  * applying yet.
71
71
  */
72
72
  effect?: ReactNode;
73
+ /**
74
+ * Where the control sits. DX-4968.
75
+ *
76
+ * `inline` (the default): beside the text from `sm` (640px) up, under it below. Right for a switch, a select or a short input,
77
+ * which keeps its own width at the row's trailing edge.
78
+ *
79
+ * `stacked`: ALWAYS under the text, the full width of the row. Use it for a control whose value is long and must be seen or
80
+ * copied whole, such as a `CopyValue` holding a URL. Beside the text, a control that cannot shrink takes the row's whole width and
81
+ * leaves the label and description a word-per-line sliver (or runs past the card edge); stacked gives the value box the width
82
+ * to truncate or wrap inside, with the copy button still in view.
83
+ */
84
+ layout?: "inline" | "stacked";
73
85
  /**
74
86
  * Right-aligned indicator — a `Badge` showing the setting's current derived
75
87
  * state, most often. Rendered beside the control, not inside it, so it
@@ -0,0 +1,49 @@
1
+ export interface ToggleMatrixRow {
2
+ id: string;
3
+ label: string;
4
+ /** More about the row. Printed under the label by default, or in a tooltip on it with `rowDescription="tooltip"`. */
5
+ description?: string;
6
+ /** A heading the row sits under. Headings appear only when at least one row names one; rows with none then sit under "Other". */
7
+ group?: string;
8
+ }
9
+ export interface ToggleMatrixColumn {
10
+ id: string;
11
+ label: string;
12
+ /** Present: the column cannot be edited (a lock appears in the header of an editable matrix, named by this text). */
13
+ lockedReason?: string;
14
+ }
15
+ export type ToggleMatrixCell = {
16
+ state: "on" | "off"; /** This one cell is being saved: a spinner, and the press is refused. */
17
+ busy?: boolean;
18
+ } | {
19
+ state: "unavailable"; /** Why this pair cannot be switched. Printed in the cell. */
20
+ reason: string;
21
+ };
22
+ export interface ToggleMatrixProps {
23
+ /** Screen-reader caption: what the grid is. */
24
+ caption: string;
25
+ /** Header of the row-label column. */
26
+ rowHeader: string;
27
+ rows: readonly ToggleMatrixRow[];
28
+ columns: readonly ToggleMatrixColumn[];
29
+ /** The state of the cell where a row and a column cross. */
30
+ cell: (rowId: string, columnId: string) => ToggleMatrixCell;
31
+ /** Draws no control anywhere. Default `false`. */
32
+ readOnly?: boolean;
33
+ /** A cell was pressed; `next` is the NEW value to save. */
34
+ onChange?: (rowId: string, columnId: string, next: boolean) => void;
35
+ /** Turns on the header checkbox that sets a whole column. `rowIds` are the switchable rows whose value differs from `next`. */
36
+ onColumnChange?: (columnId: string, next: boolean, rowIds: string[]) => void;
37
+ /** `inline` (default) prints a row's description under its label; `tooltip` keeps the label alone and shows it on hover or focus. */
38
+ rowDescription?: "inline" | "tooltip";
39
+ /** Tighter cell padding and wrapping column headers, for a phone or a grid of few columns. Default `false`. */
40
+ dense?: boolean;
41
+ /** The sentence a screen reader gets for a cell. Default: "<column>: <row> on|off". */
42
+ cellLabel?: (row: ToggleMatrixRow, column: ToggleMatrixColumn, on: boolean) => string;
43
+ /** Heading for rows with no `group` when others have one. Default: the catalog's "Other". */
44
+ otherGroupLabel?: string;
45
+ /** Names the header checkbox of a column. Default: the catalog's "Set every switch in <column>". */
46
+ columnSetLabel?: (column: ToggleMatrixColumn) => string;
47
+ className?: string;
48
+ }
49
+ export declare function ToggleMatrix({ caption, rowHeader, rows, columns, cell, readOnly, onChange, onColumnChange, rowDescription, dense, cellLabel, otherGroupLabel, columnSetLabel, className, }: ToggleMatrixProps): import("react").JSX.Element;
@@ -4,14 +4,5 @@ export interface PermissionSection {
4
4
  label: string | undefined;
5
5
  items: Permission[];
6
6
  }
7
- /**
8
- * Buckets permissions by `category`, preserving first-seen order.
9
- *
10
- * Grouping is opt-in as a WHOLE, not per-row: if not a single permission in
11
- * the set carries a `category`, this returns one ungrouped section rather
12
- * than inventing an "Uncategorised" heading nobody asked to see. A consumer
13
- * who supplies categories for some permissions and not others gets an
14
- * explicit "Other" bucket for the rest, because at that point the absence of
15
- * a category on a handful of rows is itself information worth a heading.
16
- */
7
+ /** Buckets permissions by `category` (the grouping rule is `groupInOrder`'s, shared with `ToggleMatrix`). */
17
8
  export declare function groupByCategory(permissions: Permission[], otherLabel: string): PermissionSection[];
@@ -49,13 +49,23 @@ export interface StepperProps {
49
49
  nextLabel?: string;
50
50
  finishLabel?: string;
51
51
  /**
52
- * `vertical` stacks the rail beside long-form content. `horizontal` is the
52
+ * `vertical` stacks the rail above long-form content. `horizontal` is the
53
53
  * default because a sequence reads left to right, which is also the only
54
54
  * layout in which the connector between two steps means anything.
55
+ *
56
+ * DX-4963: `side` puts the rail in a column BESIDE the content from the `lg` breakpoint (1024px) up, where a long flow
57
+ * (nine steps) reads best and every label is whole, and stacks it above the content like `vertical` below that.
58
+ */
59
+ orientation?: "horizontal" | "vertical" | "side";
60
+ /**
61
+ * DX-4963 - the one-line form for a narrow screen: "Step 3 of 9: Project" in a button that opens the full list under it (and
62
+ * closes again when the step changes). `true` always, `"auto"` wherever the full rail would not fit (below the `sm` breakpoint, 640px; with
63
+ * `orientation="side"` below `lg`, 1024px, DX-4968: between the two the stacked list would push the step's own content off the first
64
+ * screen), `false` (the default) never. Nine steps stacked is about 530px tall; this keeps the step's own content on the first screen.
55
65
  */
56
- orientation?: "horizontal" | "vertical";
66
+ compact?: boolean | "auto";
57
67
  /** The CURRENT step's content. */
58
68
  children?: ReactNode;
59
69
  className?: string;
60
70
  }
61
- export declare function Stepper({ label, steps, current, onCurrentChange, showControls, onFinish, backLabel, nextLabel, finishLabel, orientation, children, className, }: StepperProps): import("react").JSX.Element;
71
+ export declare function Stepper({ label, steps, current, onCurrentChange, showControls, onFinish, backLabel, nextLabel, finishLabel, orientation, compact, children, className, }: StepperProps): import("react").JSX.Element;
@@ -14,6 +14,27 @@ export interface Step {
14
14
  * track key, and it is what keeps `!step.complete` from having two readings.
15
15
  */
16
16
  complete?: boolean;
17
+ /**
18
+ * Passed on purpose without doing it: an optional step the person chose to leave, or one that was acknowledged and not filled in.
19
+ * DX-4963.
20
+ *
21
+ * It is NOT a fault. A step behind the cursor that is merely `incomplete` is the one thing a rail marks in danger red, because
22
+ * something was missed; a `skipped` step was a decision, so it gets a grey marker, its own spoken word, and a neutral chip, and it
23
+ * is never counted in the red one. `complete` outranks it (a step that was skipped and then done is done), and `blocked` and the
24
+ * cursor outrank both. Like `complete`, absent means false.
25
+ */
26
+ skipped?: boolean;
27
+ /**
28
+ * Done, but there is nothing a server could test, so it cannot be called a tested success. DX-4968.
29
+ *
30
+ * The VALUE is the words, supplied by the caller ("Saved, not tested", "Confirmed when the token is saved"): the library cannot
31
+ * know what a flow's steps are for, and "skipped" would be false for a step that was done. The words are printed under the label
32
+ * and spoken as the step's state. It is its own neutral state: a grey marker with its own glyph, never the green of a tested
33
+ * result, never the red of a missed step, and counted in neither chip (`StepperProgress.unverified` carries the number for a
34
+ * caller that wants it). `complete` outranks it, and the cursor and `blocked` outrank both; it outranks `skipped`.
35
+ * An empty string throws, for the same reason an empty `blocked` does: the words ARE the spoken state.
36
+ */
37
+ unverified?: string;
17
38
  /**
18
39
  * Why the flow cannot move on from here. Absent means it can.
19
40
  *
@@ -35,9 +56,9 @@ export interface Step {
35
56
  * What a step IS right now — derived from the steps and the cursor, never
36
57
  * stored.
37
58
  *
38
- * Five, not two, because "finished", "you are here", "you skipped it", "not
39
- * reached yet" and "this is what is stopping you" call for four different
40
- * next actions and one absence of action. Collapsing them to a boolean is what
59
+ * Seven, not two, because "finished", "you are here", "done but unproven", "you left it on purpose",
60
+ * "you missed it", "not reached yet" and "this is what is stopping you" call for
61
+ * different next actions and one absence of action. Collapsing them to a boolean is what
41
62
  * produces a rail where a skipped step and an untouched one look identical.
42
63
  */
43
64
  export type StepStatus =
@@ -47,7 +68,11 @@ export type StepStatus =
47
68
  | "blocked"
48
69
  /** The cursor is on it. */
49
70
  | "current"
50
- /** Behind the cursor and not complete: passed over. */
71
+ /** Carries `unverified` words and is not complete: done, with no result to show. Neutral, never a fault. DX-4968. */
72
+ | "unverified"
73
+ /** `skipped: true` and not complete: left on purpose. Neutral, never a fault. DX-4963. */
74
+ | "skipped"
75
+ /** Behind the cursor, not complete and marked neither `skipped` nor `unverified`: passed over by accident. */
51
76
  | "incomplete"
52
77
  /** Ahead of the cursor. Not a fault — simply not reached. */
53
78
  | "upcoming";
@@ -65,6 +90,13 @@ export interface StepperProgress {
65
90
  total: number;
66
91
  /** How many steps are `complete`, anywhere in the flow. */
67
92
  complete: number;
68
- /** Behind the cursor and not complete. */
93
+ /**
94
+ * Behind the cursor, not complete and marked neither `skipped` nor `unverified`: the steps missed, the ones the red chip counts. (Renamed in meaning by
95
+ * DX-4963: a step the person skipped on purpose is `acknowledged`, not counted here.)
96
+ */
69
97
  skipped: number;
98
+ /** Steps marked `skipped` that are not complete, anywhere in the flow: left on purpose, counted in the neutral chip. DX-4963. */
99
+ acknowledged: number;
100
+ /** Steps carrying `unverified` words that are not complete, anywhere in the flow: done, with nothing to test. Counted in no chip. DX-4968. */
101
+ unverified: number;
70
102
  }
@@ -37,6 +37,7 @@ export { DescriptionList, DescriptionListItem, type DescriptionListProps, type D
37
37
  export { ConnectionCard, type ConnectionCardProps, type ConnectionHealth, } from "./components/ConnectionCard";
38
38
  export { Checkbox, Switch, Radio, RadioGroup, CheckboxField, SwitchField, RadioField, RadioCard, type CheckboxProps, type SwitchProps, type RadioProps, type RadioGroupProps, type CheckboxFieldProps, type SwitchFieldProps, type RadioFieldProps, type RadioCardProps, } from "./components/Choice";
39
39
  export { TriStateSwitch, type TriStateSwitchProps, type TriStateSwitchSize, } from "./components/TriStateSwitch";
40
+ export { ToggleMatrix, type ToggleMatrixProps, type ToggleMatrixRow, type ToggleMatrixColumn, type ToggleMatrixCell, } from "./components/ToggleMatrix";
40
41
  export { Dialog, DialogClose, AlertDialog, type DialogProps, type AlertDialogProps, } from "./components/Dialog";
41
42
  export { Popover, PopoverClose, Tooltip, TooltipProvider, type PopoverProps, type TooltipProps, } from "./components/Popover";
42
43
  export { Toaster, ToastProvider, useToast, type ToasterProps, type ToastProviderProps, type ToastOptions, type ToastTone, } from "./components/Toast";
@@ -0,0 +1,13 @@
1
+ export interface OrderedSection<T> {
2
+ /** `undefined` when nothing in the set names a group. */
3
+ label: string | undefined;
4
+ items: T[];
5
+ }
6
+ /**
7
+ * Buckets items by their group, preserving first-seen order.
8
+ *
9
+ * Grouping is opt-in as a WHOLE, not per item: if not one item names a group this returns one ungrouped section rather than inventing
10
+ * an "Uncategorised" heading nobody asked to see. When some items name a group and others do not, the rest go under `otherLabel`,
11
+ * because at that point the absence of a group on a few items is itself information worth a heading.
12
+ */
13
+ export declare function groupInOrder<T>(items: readonly T[], groupOf: (item: T) => string | undefined, otherLabel: string): OrderedSection<T>[];
@@ -184,8 +184,16 @@ export interface AuthProvenanceFlowsStrings {
184
184
  stepper: {
185
185
  /** Header above the rail. */
186
186
  stepOf: (positionText: string, totalText: string) => string;
187
- /** Chip counting steps behind the cursor that are not complete. */
187
+ /** Chip counting steps behind the cursor that are not complete and were not skipped on purpose (the red one). DX-4963: was `skipped`. */
188
+ missed: (n: number, nText: string) => string;
189
+ /** Chip counting steps the person skipped on purpose (the neutral one). DX-4963. */
188
190
  skipped: (n: number, nText: string) => string;
191
+ /** The compact (phone) form's one line: the position text, then the current step's label. DX-4963. */
192
+ compactSummary: (positionText: string, stepLabel: string) => string;
193
+ /** Screen-reader text of the compact form's button while the full list is closed. DX-4963. */
194
+ showSteps: string;
195
+ /** Screen-reader text of the compact form's button while the full list is open. DX-4963. */
196
+ hideSteps: string;
189
197
  /** Back button (a caller's `backLabel` replaces it). */
190
198
  back: string;
191
199
  /** Next button (a caller's `nextLabel` replaces it). */
@@ -200,8 +208,10 @@ export interface AuthProvenanceFlowsStrings {
200
208
  blocked: string;
201
209
  /** The step the cursor is on. */
202
210
  current: string;
203
- /** Behind the cursor and not finished. */
211
+ /** Behind the cursor, not finished and not skipped on purpose. DX-4963: was "skipped". */
204
212
  incomplete: string;
213
+ /** Skipped on purpose (a neutral state, not a fault). DX-4963. */
214
+ skipped: string;
205
215
  /** Ahead of the cursor. */
206
216
  upcoming: string;
207
217
  };
@@ -538,6 +538,19 @@ export interface RbacStrings {
538
538
  /** The sentence a screen reader gets for a cell, saying whether the role holds the permission. */
539
539
  cell: (roleLabel: string, permissionLabel: string, granted: boolean) => string;
540
540
  };
541
+ /** `ToggleMatrix` (DX-4963), the grid `RolePermissionMatrix` is built on. */
542
+ toggleMatrix: {
543
+ /** The sentence a screen reader gets for a cell when the consumer gives none, saying whether the column has the row switched on. */
544
+ cell: (columnLabel: string, rowLabel: string, on: boolean) => string;
545
+ /** The muted badge in a cell that cannot be switched; the reason is printed under it. */
546
+ unavailable: string;
547
+ /** Accessible name of the checkbox in a column header that sets every switch in the column. */
548
+ setColumn: (columnLabel: string) => string;
549
+ /** Heading for rows with no group, when other rows have one. */
550
+ otherGroup: string;
551
+ /** Accessible name of the spinner in a cell that is being saved. */
552
+ busy: string;
553
+ };
541
554
  /** `RolesPermissionsPage`. */
542
555
  rolesPermissionsPage: {
543
556
  /** The page heading. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danxbot/ui",
3
- "version": "24.4.0",
3
+ "version": "25.1.0",
4
4
  "type": "module",
5
5
  "description": "Danxbot — a domain-agnostic React design system with motion as a first-class primitive.",
6
6
  "license": "MIT",