@danxbot/ui 24.4.0 → 25.0.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.
@@ -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,22 @@ 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"` below the `sm` breakpoint (640px) and the full rail above it,
63
+ * `false` (the default) never. Nine steps stacked is about 530px tall; this keeps the step's own content on the first screen.
55
64
  */
56
- orientation?: "horizontal" | "vertical";
65
+ compact?: boolean | "auto";
57
66
  /** The CURRENT step's content. */
58
67
  children?: ReactNode;
59
68
  className?: string;
60
69
  }
61
- export declare function Stepper({ label, steps, current, onCurrentChange, showControls, onFinish, backLabel, nextLabel, finishLabel, orientation, children, className, }: StepperProps): import("react").JSX.Element;
70
+ 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,16 @@ 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;
17
27
  /**
18
28
  * Why the flow cannot move on from here. Absent means it can.
19
29
  *
@@ -35,9 +45,9 @@ export interface Step {
35
45
  * What a step IS right now — derived from the steps and the cursor, never
36
46
  * stored.
37
47
  *
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
48
+ * Six, not two, because "finished", "you are here", "you left it on purpose",
49
+ * "you missed it", "not reached yet" and "this is what is stopping you" call for
50
+ * different next actions and one absence of action. Collapsing them to a boolean is what
41
51
  * produces a rail where a skipped step and an untouched one look identical.
42
52
  */
43
53
  export type StepStatus =
@@ -47,7 +57,9 @@ export type StepStatus =
47
57
  | "blocked"
48
58
  /** The cursor is on it. */
49
59
  | "current"
50
- /** Behind the cursor and not complete: passed over. */
60
+ /** `skipped: true` and not complete: left on purpose. Neutral, never a fault. DX-4963. */
61
+ | "skipped"
62
+ /** Behind the cursor, not complete and not marked `skipped`: passed over by accident. */
51
63
  | "incomplete"
52
64
  /** Ahead of the cursor. Not a fault — simply not reached. */
53
65
  | "upcoming";
@@ -65,6 +77,11 @@ export interface StepperProgress {
65
77
  total: number;
66
78
  /** How many steps are `complete`, anywhere in the flow. */
67
79
  complete: number;
68
- /** Behind the cursor and not complete. */
80
+ /**
81
+ * Behind the cursor, not complete and NOT marked `skipped`: the steps missed, the ones the red chip counts. (Renamed in meaning by
82
+ * DX-4963: a step the person skipped on purpose is `acknowledged`, not counted here.)
83
+ */
69
84
  skipped: number;
85
+ /** Steps marked `skipped` that are not complete, anywhere in the flow: left on purpose, counted in the neutral chip. DX-4963. */
86
+ acknowledged: number;
70
87
  }
@@ -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.0.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",