@danxbot/ui 2.2.2 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +16503 -15931
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/types/components/Button.d.ts +7 -1
- package/dist/types/components/IconButton.d.ts +56 -0
- package/dist/types/components/checklist/StatusChecklist.d.ts +37 -0
- package/dist/types/components/checklist/index.d.ts +3 -0
- package/dist/types/components/checklist/tally.d.ts +19 -0
- package/dist/types/components/checklist/types.d.ts +28 -0
- package/dist/types/components/drag-drop/context.d.ts +6 -2
- package/dist/types/components/drag-drop/recipe.d.ts +18 -0
- package/dist/types/components/drag-drop/shift.d.ts +45 -5
- package/dist/types/components/provenance/ProvenanceBadge.d.ts +11 -1
- package/dist/types/components/provenance/ProvenanceDisclosure.d.ts +46 -1
- package/dist/types/components/stepper/Stepper.d.ts +44 -0
- package/dist/types/components/stepper/derive.d.ts +48 -0
- package/dist/types/components/stepper/index.d.ts +3 -0
- package/dist/types/components/stepper/types.d.ts +70 -0
- package/dist/types/index.d.ts +4 -1
- package/package.json +2 -2
|
@@ -8,6 +8,8 @@ declare const button: import("tailwind-variants").TVReturnType<{
|
|
|
8
8
|
subtle: string[];
|
|
9
9
|
outline: string[];
|
|
10
10
|
ghost: string[];
|
|
11
|
+
"ghost-danger": string[];
|
|
12
|
+
"outline-danger": string[];
|
|
11
13
|
danger: string[];
|
|
12
14
|
"danger-subtle": string[];
|
|
13
15
|
link: string[];
|
|
@@ -34,6 +36,8 @@ declare const button: import("tailwind-variants").TVReturnType<{
|
|
|
34
36
|
subtle: string[];
|
|
35
37
|
outline: string[];
|
|
36
38
|
ghost: string[];
|
|
39
|
+
"ghost-danger": string[];
|
|
40
|
+
"outline-danger": string[];
|
|
37
41
|
danger: string[];
|
|
38
42
|
"danger-subtle": string[];
|
|
39
43
|
link: string[];
|
|
@@ -60,6 +64,8 @@ declare const button: import("tailwind-variants").TVReturnType<{
|
|
|
60
64
|
subtle: string[];
|
|
61
65
|
outline: string[];
|
|
62
66
|
ghost: string[];
|
|
67
|
+
"ghost-danger": string[];
|
|
68
|
+
"outline-danger": string[];
|
|
63
69
|
danger: string[];
|
|
64
70
|
"danger-subtle": string[];
|
|
65
71
|
link: string[];
|
|
@@ -99,5 +105,5 @@ export interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement>, Va
|
|
|
99
105
|
trailingIcon?: ReactNode;
|
|
100
106
|
ref?: Ref<HTMLButtonElement>;
|
|
101
107
|
}
|
|
102
|
-
export declare function Button({ className, variant, size, iconOnly, fullWidth, render, loading, leadingIcon, trailingIcon, disabled, children, onPointerDown, ref, ...props }: ButtonProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
108
|
+
export declare function Button({ className, variant, size, iconOnly, fullWidth, render, loading, leadingIcon, trailingIcon, disabled, children, onPointerDown, ref, "aria-disabled": ariaDisabled, ...props }: ButtonProps): import("react").ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
|
|
103
109
|
export { button as buttonVariants };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { ReactNode, Ref } from "react";
|
|
2
|
+
import { type ButtonProps } from "./Button";
|
|
3
|
+
/** Which `Button` variant backs each (variant, tone) pair. */
|
|
4
|
+
declare const VARIANT_FOR: {
|
|
5
|
+
readonly ghost: {
|
|
6
|
+
readonly neutral: "ghost";
|
|
7
|
+
readonly danger: "ghost-danger";
|
|
8
|
+
};
|
|
9
|
+
readonly subtle: {
|
|
10
|
+
readonly neutral: "subtle";
|
|
11
|
+
readonly danger: "danger-subtle";
|
|
12
|
+
};
|
|
13
|
+
readonly outline: {
|
|
14
|
+
readonly neutral: "outline";
|
|
15
|
+
readonly danger: "outline-danger";
|
|
16
|
+
};
|
|
17
|
+
readonly solid: {
|
|
18
|
+
readonly neutral: "solid";
|
|
19
|
+
readonly danger: "danger";
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
export type IconButtonVariant = keyof typeof VARIANT_FOR;
|
|
23
|
+
export type IconButtonTone = "neutral" | "danger";
|
|
24
|
+
export interface IconButtonProps extends Omit<ButtonProps, "children" | "iconOnly" | "leadingIcon" | "trailingIcon" | "variant" | "aria-label" | "disabled" | "aria-disabled"> {
|
|
25
|
+
/** The glyph. Rendered `aria-hidden` — the name comes from `label`. */
|
|
26
|
+
icon: ReactNode;
|
|
27
|
+
/**
|
|
28
|
+
* The accessible name, and the tooltip text. REQUIRED — an icon carries no
|
|
29
|
+
* text, so there is no other source for it.
|
|
30
|
+
*
|
|
31
|
+
* Name the ACTION and its object ("Delete Phase 2"), not the picture
|
|
32
|
+
* ("Trash"). It is read aloud in a list of controls where nothing else
|
|
33
|
+
* distinguishes one row's delete from another's.
|
|
34
|
+
*/
|
|
35
|
+
label: string;
|
|
36
|
+
/** Visual weight. Defaults to `ghost` — the right resting state in a row. */
|
|
37
|
+
variant?: IconButtonVariant;
|
|
38
|
+
/** `danger` makes the hover destructive. Resting state is unchanged. */
|
|
39
|
+
tone?: IconButtonTone;
|
|
40
|
+
/**
|
|
41
|
+
* Unavailable, AND WHY — there is no boolean form. The string is shown in
|
|
42
|
+
* the tooltip and announced as the control's description, so the refusal is
|
|
43
|
+
* never silent.
|
|
44
|
+
*/
|
|
45
|
+
disabledReason?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Suppress the tooltip. For the rare control already named in adjacent
|
|
48
|
+
* visible text, where a tooltip would only repeat it. The `aria-label` is
|
|
49
|
+
* unaffected — the name is never optional.
|
|
50
|
+
*/
|
|
51
|
+
hideTooltip?: boolean;
|
|
52
|
+
tooltipSide?: "top" | "bottom" | "left" | "right";
|
|
53
|
+
ref?: Ref<HTMLButtonElement>;
|
|
54
|
+
}
|
|
55
|
+
export declare function IconButton({ icon, label, variant, tone, size, disabledReason, hideTooltip, tooltipSide, className, onClick, ...props }: IconButtonProps): import("react").JSX.Element;
|
|
56
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import type { StatusOption } from "../StatusSelect";
|
|
3
|
+
import type { ChecklistItem, ChecklistState, ChecklistTally } from "./types";
|
|
4
|
+
export type { ChecklistItem, ChecklistState, ChecklistTally };
|
|
5
|
+
export interface StatusChecklistProps<Key extends string = string> {
|
|
6
|
+
/**
|
|
7
|
+
* What this list IS — "Evidence for the March filing".
|
|
8
|
+
*
|
|
9
|
+
* Names the group, so somebody landing on it by keyboard learns what the
|
|
10
|
+
* counts are counting. Required for the same reason `KanbanBoard.label` is.
|
|
11
|
+
*/
|
|
12
|
+
label: string;
|
|
13
|
+
/** The consumer's vocabulary, in the order the summary and groups read. */
|
|
14
|
+
states: readonly StatusOption<Key>[];
|
|
15
|
+
items: readonly ChecklistItem<Key>[];
|
|
16
|
+
/**
|
|
17
|
+
* `state` groups the rows under their state's heading; `given` renders them
|
|
18
|
+
* in the order supplied.
|
|
19
|
+
*
|
|
20
|
+
* GROUPED IS THE DEFAULT, and that is the opposite of what a checklist
|
|
21
|
+
* usually wants. A checklist you work down top to bottom should stay in its
|
|
22
|
+
* given order — but this control's stated job is to make the shape of the gap
|
|
23
|
+
* legible, and an interleaved list makes the reader do the sorting in their
|
|
24
|
+
* head while the summary above already claims to have done it for them.
|
|
25
|
+
* `given` is there for the case where the order is itself meaningful — a
|
|
26
|
+
* sequence, a priority, a filing order — because then regrouping destroys
|
|
27
|
+
* information the consumer put in deliberately.
|
|
28
|
+
*/
|
|
29
|
+
order?: "state" | "given";
|
|
30
|
+
/** Shown when `items` is empty. `EmptyState` supplies the shape. */
|
|
31
|
+
emptyTitle?: ReactNode;
|
|
32
|
+
emptyDescription?: ReactNode;
|
|
33
|
+
emptyAction?: ReactNode;
|
|
34
|
+
emptyIcon?: ReactNode;
|
|
35
|
+
className?: string;
|
|
36
|
+
}
|
|
37
|
+
export declare function StatusChecklist<Key extends string = string>({ label, states, items, order, emptyTitle, emptyDescription, emptyAction, emptyIcon, className, }: StatusChecklistProps<Key>): import("react").JSX.Element;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { StatusOption } from "../StatusSelect";
|
|
2
|
+
import type { ChecklistItem, ChecklistTally } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* Split `items` across the declared `states`, in the order the states were
|
|
5
|
+
* given.
|
|
6
|
+
*
|
|
7
|
+
* Every state appears in the result, INCLUDING EMPTY ONES. A zero is
|
|
8
|
+
* information — "nothing is blocking" is the single most useful thing this
|
|
9
|
+
* control ever says — and a chip that vanishes at zero is invisible at exactly
|
|
10
|
+
* the moment its emptiness is the news, while also making the summary row
|
|
11
|
+
* change width every time an item moves. The BODY is the other way round: see
|
|
12
|
+
* `StatusChecklist`.
|
|
13
|
+
*
|
|
14
|
+
* Throws rather than tolerating: an unknown state key, a duplicate state, a
|
|
15
|
+
* duplicate item id, or no states at all. Each of those renders as something
|
|
16
|
+
* plausible if allowed through — an item silently dropped from a list whose
|
|
17
|
+
* whole purpose is to be exhaustive is the worst failure this component has.
|
|
18
|
+
*/
|
|
19
|
+
export declare function tallyChecklist<Key extends string>(states: readonly StatusOption<Key>[], items: readonly ChecklistItem<Key>[]): ChecklistTally<Key>[];
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import type { StatusOption } from "../StatusSelect";
|
|
3
|
+
export type ChecklistState<Key extends string = string> = StatusOption<Key>;
|
|
4
|
+
export interface ChecklistItem<Key extends string = string> {
|
|
5
|
+
id: string;
|
|
6
|
+
/** What the item IS. The row's own text — never replaced by an aria-label. */
|
|
7
|
+
label: ReactNode;
|
|
8
|
+
/** Must be the `value` of one of the declared states. An unknown key throws. */
|
|
9
|
+
state: Key;
|
|
10
|
+
/** A second line: who it is with, when it was asked for, why it is missing. */
|
|
11
|
+
detail?: ReactNode;
|
|
12
|
+
/**
|
|
13
|
+
* A control for this row — "Request it", "Open", "Mark received".
|
|
14
|
+
*
|
|
15
|
+
* A slot rather than a `{label, onClick}` prop, for the same reason
|
|
16
|
+
* `RecordCard.badges` is one: whether the action is a button, a link, a menu
|
|
17
|
+
* or a spinner belongs to the surface, and every shape this prop could grow
|
|
18
|
+
* to cover would be a library release for a decision the consumer had
|
|
19
|
+
* already made.
|
|
20
|
+
*/
|
|
21
|
+
action?: ReactNode;
|
|
22
|
+
}
|
|
23
|
+
/** One state, its option, and everything in it — in the declared order. */
|
|
24
|
+
export interface ChecklistTally<Key extends string = string> {
|
|
25
|
+
option: StatusOption<Key>;
|
|
26
|
+
count: number;
|
|
27
|
+
items: ChecklistItem<Key>[];
|
|
28
|
+
}
|
|
@@ -14,8 +14,12 @@ export interface DragDropContextValue {
|
|
|
14
14
|
*/
|
|
15
15
|
instructionsId: string;
|
|
16
16
|
/**
|
|
17
|
-
* True while a `<DragDropOverlay>` is mounted, i.e. while
|
|
18
|
-
*
|
|
17
|
+
* True while a `<DragDropOverlay>` is mounted, i.e. while a portalled clone
|
|
18
|
+
* is carrying the card and the row itself should render as the hole it left.
|
|
19
|
+
*
|
|
20
|
+
* It selects WHICH of the two carries the card, never WHETHER one does: with
|
|
21
|
+
* no overlay the row follows the pointer under its own transform
|
|
22
|
+
* (`shift.ts#carriedOffset`). Either way the slot is vacated and closes.
|
|
19
23
|
*/
|
|
20
24
|
lifted: boolean;
|
|
21
25
|
registerOverlay: () => () => void;
|
|
@@ -21,6 +21,12 @@ export declare const dnd: import("tailwind-variants").TVReturnType<{
|
|
|
21
21
|
};
|
|
22
22
|
false: {};
|
|
23
23
|
};
|
|
24
|
+
carried: {
|
|
25
|
+
true: {
|
|
26
|
+
shift: string;
|
|
27
|
+
};
|
|
28
|
+
false: {};
|
|
29
|
+
};
|
|
24
30
|
mode: {
|
|
25
31
|
pointer: {
|
|
26
32
|
overlay: string;
|
|
@@ -61,6 +67,12 @@ export declare const dnd: import("tailwind-variants").TVReturnType<{
|
|
|
61
67
|
};
|
|
62
68
|
false: {};
|
|
63
69
|
};
|
|
70
|
+
carried: {
|
|
71
|
+
true: {
|
|
72
|
+
shift: string;
|
|
73
|
+
};
|
|
74
|
+
false: {};
|
|
75
|
+
};
|
|
64
76
|
mode: {
|
|
65
77
|
pointer: {
|
|
66
78
|
overlay: string;
|
|
@@ -101,6 +113,12 @@ export declare const dnd: import("tailwind-variants").TVReturnType<{
|
|
|
101
113
|
};
|
|
102
114
|
false: {};
|
|
103
115
|
};
|
|
116
|
+
carried: {
|
|
117
|
+
true: {
|
|
118
|
+
shift: string;
|
|
119
|
+
};
|
|
120
|
+
false: {};
|
|
121
|
+
};
|
|
104
122
|
mode: {
|
|
105
123
|
pointer: {
|
|
106
124
|
overlay: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ContainerId, DragAxis, DragState, LayoutSnapshot } from "../../lib/dnd";
|
|
1
|
+
import type { ContainerId, DragAxis, DragState, LayoutSnapshot, Point } from "../../lib/dnd";
|
|
2
2
|
export interface ContainerShift {
|
|
3
3
|
axis: DragAxis;
|
|
4
4
|
/** Items in this container with the carried one removed. */
|
|
@@ -26,14 +26,54 @@ export interface ContainerShift {
|
|
|
26
26
|
*/
|
|
27
27
|
markerShift: (restIndex: number) => number;
|
|
28
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* The carried item's own displacement from its resting box, in px — what makes
|
|
31
|
+
* the thing under the cursor BE the thing you picked up.
|
|
32
|
+
*
|
|
33
|
+
* WHY THIS EXISTS AT ALL. A `<DragDropOverlay>` is optional, and for a long
|
|
34
|
+
* while a board without one dragged nothing: the sibling gap opened correctly,
|
|
35
|
+
* the marker drew in the right place, and the row itself sat exactly where it
|
|
36
|
+
* had always been. Every automated check passed, because every one of them
|
|
37
|
+
* asserts against the ORDER a drop writes and the order was right — the defect
|
|
38
|
+
* was that there was no visual connection between the pointer and the thing it
|
|
39
|
+
* was moving, which is a fact about pixels and nothing but a browser can see
|
|
40
|
+
* it. So following the pointer is now what the engine does by DEFAULT, and an
|
|
41
|
+
* overlay is what a consumer adds when the card must escape its container
|
|
42
|
+
* rather than what it adds to make the card move at all.
|
|
43
|
+
*
|
|
44
|
+
* `grab` is where inside the box the press landed, so the card tracks the point
|
|
45
|
+
* that was actually pressed rather than snapping a corner to the cursor. The
|
|
46
|
+
* rest box comes from the same snapshot the shift is computed from — re-taken
|
|
47
|
+
* on scroll, resize and every auto-scroll frame — so the card stays under the
|
|
48
|
+
* cursor while the list scrolls beneath it.
|
|
49
|
+
*
|
|
50
|
+
* Null in keyboard mode: there is no pointer to follow, and a keyboard drag
|
|
51
|
+
* moves slot to slot with the marker saying where. That is not a fallback — it
|
|
52
|
+
* is a different question with a different honest answer.
|
|
53
|
+
*/
|
|
54
|
+
export declare function carriedOffset(layout: LayoutSnapshot | null, state: DragState): Point | null;
|
|
55
|
+
/**
|
|
56
|
+
* The carried item's follow offset as an inline style.
|
|
57
|
+
*
|
|
58
|
+
* A 2D `translate`, unlike `shiftStyle`'s axis-constrained one: the card is a
|
|
59
|
+
* held object rather than a row sliding along a list, and constraining it to
|
|
60
|
+
* the container's axis makes it slide off the cursor the moment the hand moves
|
|
61
|
+
* the other way.
|
|
62
|
+
*/
|
|
63
|
+
export declare function followStyle(offset: Point | null): {
|
|
64
|
+
translate: string;
|
|
65
|
+
};
|
|
29
66
|
/**
|
|
30
67
|
* Everything one container needs to render the shift, or null when no drag is
|
|
31
68
|
* in flight and nothing should move.
|
|
32
69
|
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
70
|
+
* WHETHER THE HOME SLOT CLOSES ASKS ONE QUESTION: has the card actually left
|
|
71
|
+
* it? Two different things can carry it away — a mounted `<DragDropOverlay>`
|
|
72
|
+
* (`lifted`), or the card following the pointer under its own transform
|
|
73
|
+
* (`carriedOffset`) — and either one empties the slot, so either one closes it.
|
|
74
|
+
* The reason this is not cosmetic runs the other way too: a KEYBOARD drag with
|
|
75
|
+
* no overlay has nothing carrying the card, so the card is still sitting in its
|
|
76
|
+
* own slot, and closing it there would slide a neighbour underneath it.
|
|
37
77
|
*/
|
|
38
78
|
export declare function containerShift(layout: LayoutSnapshot | null, state: DragState, container: ContainerId, lifted: boolean): ContainerShift | null;
|
|
39
79
|
/** A rect in viewport coordinates. */
|
|
@@ -1,12 +1,22 @@
|
|
|
1
1
|
import type { ProvenanceState } from "./types";
|
|
2
|
+
/** How much of the state the badge draws. The accessible name is the same either way. */
|
|
3
|
+
export type ProvenanceBadgeAppearance = "word" | "icon";
|
|
2
4
|
export interface ProvenanceBadgeProps {
|
|
3
5
|
state: ProvenanceState;
|
|
4
6
|
/** Render the badge even for states that are quiet by default. */
|
|
5
7
|
alwaysShow?: boolean;
|
|
8
|
+
/**
|
|
9
|
+
* `"word"` (default) draws the icon and the word. `"icon"` draws the glyph in
|
|
10
|
+
* the same coloured box and keeps the word as visually-hidden text, so the
|
|
11
|
+
* announced name does not change.
|
|
12
|
+
*
|
|
13
|
+
* `"icon"` also lifts the quiet rule — see the note at the top of this file.
|
|
14
|
+
*/
|
|
15
|
+
appearance?: ProvenanceBadgeAppearance;
|
|
6
16
|
size?: "sm" | "md";
|
|
7
17
|
className?: string;
|
|
8
18
|
}
|
|
9
|
-
export declare function ProvenanceBadge({ state, alwaysShow, size, className, }: ProvenanceBadgeProps): import("react").JSX.Element | null;
|
|
19
|
+
export declare function ProvenanceBadge({ state, alwaysShow, appearance, size, className, }: ProvenanceBadgeProps): import("react").JSX.Element | null;
|
|
10
20
|
/** The words this library uses for each state. Exported so a consumer's own
|
|
11
21
|
filters and legends read the same as its badges. */
|
|
12
22
|
export declare function provenanceStateLabel(state: ProvenanceState): string;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
2
|
import type { ProvenanceRecord } from "./types";
|
|
3
|
+
/** How much of the verification state the trigger draws. */
|
|
4
|
+
export type ProvenanceTriggerBadge = "icon" | "word" | "none";
|
|
3
5
|
export interface ProvenanceDisclosureProps {
|
|
4
6
|
record: ProvenanceRecord;
|
|
5
7
|
/**
|
|
@@ -14,6 +16,49 @@ export interface ProvenanceDisclosureProps {
|
|
|
14
16
|
emptyLabel?: string;
|
|
15
17
|
/** Shown in place of the value when the viewer may not see it. */
|
|
16
18
|
redactedLabel?: string;
|
|
19
|
+
/**
|
|
20
|
+
* How the state reads ON THE TRIGGER. The panel always shows icon + word.
|
|
21
|
+
*
|
|
22
|
+
* - `"word"` (default) — today's behaviour exactly, quiet rule included: the
|
|
23
|
+
* exceptions wear a worded badge and `verified` wears nothing.
|
|
24
|
+
* - `"icon"` — the glyph alone, in the same coloured box, for ALL FOUR states
|
|
25
|
+
* including `verified`. A dense table of values wants a legend, not four
|
|
26
|
+
* hundred sentences; the word is still announced (see below).
|
|
27
|
+
* - `"none"` — no badge at all, for a consumer drawing the state itself in an
|
|
28
|
+
* adjacent column. The state then leaves the accessible name too, because
|
|
29
|
+
* the name says what the trigger says and nothing more.
|
|
30
|
+
*/
|
|
31
|
+
triggerBadge?: ProvenanceTriggerBadge;
|
|
32
|
+
/**
|
|
33
|
+
* Let a long value wrap onto more lines instead of truncating.
|
|
34
|
+
*
|
|
35
|
+
* Off by default because the component's home is a dense table where a
|
|
36
|
+
* ragged row height is worse than an ellipsis. On by default would be wrong;
|
|
37
|
+
* unavailable was also wrong — a value clipped at `No — typed notes only, at
|
|
38
|
+
* gu…` in a 900px column is not a value, and there was no way in.
|
|
39
|
+
*/
|
|
40
|
+
valueWrap?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Draw something else in place of the value — an id chip, an avatar, a
|
|
43
|
+
* sparkline — and anchor the panel to THAT.
|
|
44
|
+
*
|
|
45
|
+
* NOT a whole-trigger slot, and the difference matters. This node becomes the
|
|
46
|
+
* CONTENT of the disclosure's own button; the button, its focus ring, its tap
|
|
47
|
+
* target and its accessible name stay with the component. A prop that took
|
|
48
|
+
* the control itself would hand a consumer all four obligations at once, and
|
|
49
|
+
* the observed result of consumers owning this one is a chip that announces a
|
|
50
|
+
* bare id ("FM-002") with no field, no value and no state — which is the
|
|
51
|
+
* exact defect this library has now shipped three times.
|
|
52
|
+
*
|
|
53
|
+
* Pass presentational markup. An interactive element here nests a control
|
|
54
|
+
* inside a control, which is invalid and unfocusable.
|
|
55
|
+
*
|
|
56
|
+
* The field, the state and the "show where this came from" affordance are
|
|
57
|
+
* still composed around it, so the announced name is the same as any other
|
|
58
|
+
* disclosure's. The dotted underline is dropped — a chip carries its own
|
|
59
|
+
* edges and does not want a second one.
|
|
60
|
+
*/
|
|
61
|
+
triggerContent?: ReactNode;
|
|
17
62
|
className?: string;
|
|
18
63
|
}
|
|
19
|
-
export declare function ProvenanceDisclosure({ record, actions, emptyLabel, redactedLabel, className, }: ProvenanceDisclosureProps): import("react").JSX.Element;
|
|
64
|
+
export declare function ProvenanceDisclosure({ record, actions, emptyLabel, redactedLabel, triggerBadge, valueWrap, triggerContent, className, }: ProvenanceDisclosureProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import type { Step, StepStatus, StepperProgress } from "./types";
|
|
3
|
+
export type { Step, StepStatus, StepperProgress };
|
|
4
|
+
export interface StepperProps {
|
|
5
|
+
/**
|
|
6
|
+
* What this flow IS — "Case intake", "Deployment".
|
|
7
|
+
*
|
|
8
|
+
* It names the ordered list, which is how somebody arriving at the rail
|
|
9
|
+
* learns what the sequence is for. Required rather than optional for the same
|
|
10
|
+
* reason `KanbanBoard.label` is: an unnamed list announces as "list" and
|
|
11
|
+
* gives nobody a reason to be in it.
|
|
12
|
+
*/
|
|
13
|
+
label: string;
|
|
14
|
+
steps: readonly Step[];
|
|
15
|
+
/** 0-based. Out of range throws — see `assertSteps`. */
|
|
16
|
+
current: number;
|
|
17
|
+
/**
|
|
18
|
+
* Move the cursor.
|
|
19
|
+
*
|
|
20
|
+
* ABSENT MAKES THE WHOLE RAIL A READ-OUT: no step is clickable and no
|
|
21
|
+
* forward/back control is drawn. The configuration is the switch, the same
|
|
22
|
+
* way `UseCaseCard` only becomes editable when handed `onStatusChange`. A
|
|
23
|
+
* consumer driving its own buttons omits this and keeps the rail.
|
|
24
|
+
*/
|
|
25
|
+
onCurrentChange?: (index: number) => void;
|
|
26
|
+
/**
|
|
27
|
+
* What the last step's forward control does. Absent means no control is drawn
|
|
28
|
+
* on the last step — a wizard whose final action lives in its own form.
|
|
29
|
+
*/
|
|
30
|
+
onFinish?: () => void;
|
|
31
|
+
backLabel?: string;
|
|
32
|
+
nextLabel?: string;
|
|
33
|
+
finishLabel?: string;
|
|
34
|
+
/**
|
|
35
|
+
* `vertical` stacks the rail beside long-form content. `horizontal` is the
|
|
36
|
+
* default because a sequence reads left to right, which is also the only
|
|
37
|
+
* layout in which the connector between two steps means anything.
|
|
38
|
+
*/
|
|
39
|
+
orientation?: "horizontal" | "vertical";
|
|
40
|
+
/** The CURRENT step's content. */
|
|
41
|
+
children?: ReactNode;
|
|
42
|
+
className?: string;
|
|
43
|
+
}
|
|
44
|
+
export declare function Stepper({ label, steps, current, onCurrentChange, onFinish, backLabel, nextLabel, finishLabel, orientation, children, className, }: StepperProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Step, StepStatus, StepperProgress } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Reject a flow that cannot be rendered honestly, loudly.
|
|
4
|
+
*
|
|
5
|
+
* Every one of these is unreachable through the component's own UI and silent
|
|
6
|
+
* if allowed through: an empty rail renders as a blank strip, an out-of-range
|
|
7
|
+
* cursor renders no current step at all, duplicate ids give React two elements
|
|
8
|
+
* with one key (which reconciles them into each other on the next change), and
|
|
9
|
+
* an empty `blocked` string disables the forward button while printing nothing
|
|
10
|
+
* beside it.
|
|
11
|
+
*/
|
|
12
|
+
export declare function assertSteps(steps: readonly Step[], current: number): void;
|
|
13
|
+
/**
|
|
14
|
+
* What one step IS, given where the cursor is.
|
|
15
|
+
*
|
|
16
|
+
* PRECEDENCE, and the first rule is the interesting one. `blocked` outranks
|
|
17
|
+
* everything, including `complete`, wherever the step sits. Data saying both
|
|
18
|
+
* is contradictory, and when a record contradicts itself the exception is what
|
|
19
|
+
* the reader needs — the same call `ProvenanceBadge` makes when it stays quiet
|
|
20
|
+
* on the ordinary case and loud on every other one. An affirmative that hides
|
|
21
|
+
* an obstruction is the worse of the two possible mistakes.
|
|
22
|
+
*
|
|
23
|
+
* Note that a `blocked` reason on a step OTHER than the current one still
|
|
24
|
+
* renders as blocked but gates nothing: only the current step's reason can stop
|
|
25
|
+
* forward movement (see `advanceBlockReason`). That is deliberate — a flow can
|
|
26
|
+
* legitimately want to say "and this one ahead needs a signature" without
|
|
27
|
+
* claiming that is why you are stuck right now.
|
|
28
|
+
*/
|
|
29
|
+
export declare function stepStatus(steps: readonly Step[], current: number, index: number): StepStatus;
|
|
30
|
+
/**
|
|
31
|
+
* Why forward movement is refused, or `null` when it is not.
|
|
32
|
+
*
|
|
33
|
+
* ONLY THE CURRENT STEP GATES. A reason on a step you are not standing on is
|
|
34
|
+
* information about that step, not a claim about this one.
|
|
35
|
+
*
|
|
36
|
+
* `null` is the only "not blocked" value — an empty string is rejected at
|
|
37
|
+
* `assertSteps` rather than treated as absent, so a falsy check here cannot
|
|
38
|
+
* turn a reason that failed to load into permission to proceed.
|
|
39
|
+
*/
|
|
40
|
+
export declare function advanceBlockReason(steps: readonly Step[], current: number): string | null;
|
|
41
|
+
/**
|
|
42
|
+
* Position and completion, as two numbers that are allowed to disagree.
|
|
43
|
+
*
|
|
44
|
+
* This exists so a consumer that genuinely wants a bar builds it from a named
|
|
45
|
+
* number instead of guessing which one a bar meant. The component itself draws
|
|
46
|
+
* no percentage — see the note on `Stepper`.
|
|
47
|
+
*/
|
|
48
|
+
export declare function stepperProgress(steps: readonly Step[], current: number): StepperProgress;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
export interface Step {
|
|
3
|
+
id: string;
|
|
4
|
+
/** Shown on the rail and spoken as the step's name. */
|
|
5
|
+
label: string;
|
|
6
|
+
/** What this step is for. One line, under the label. */
|
|
7
|
+
hint?: ReactNode;
|
|
8
|
+
/**
|
|
9
|
+
* Finished.
|
|
10
|
+
*
|
|
11
|
+
* ABSENT MEANS NOT COMPLETE. There is no third state, and none is invented:
|
|
12
|
+
* nobody has ever needed to record that they do not know whether a step was
|
|
13
|
+
* finished. This is the same call `RoadmapItem.built` makes about an absent
|
|
14
|
+
* track key, and it is what keeps `!step.complete` from having two readings.
|
|
15
|
+
*/
|
|
16
|
+
complete?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Why the flow cannot move on from here. Absent means it can.
|
|
19
|
+
*
|
|
20
|
+
* Written for the person who would have pressed the button — "two documents
|
|
21
|
+
* are still missing", not "invalid". It is rendered beside the forward
|
|
22
|
+
* control rather than only disabling it, because a dead button with no
|
|
23
|
+
* sentence next to it is indistinguishable from a broken one.
|
|
24
|
+
*
|
|
25
|
+
* AN EMPTY STRING THROWS, and that is a deliberate divergence from
|
|
26
|
+
* `KanbanLane.refusal`, which accepts one. There the reason is supporting
|
|
27
|
+
* detail on a lane that is already visibly refusing; here the sentence IS the
|
|
28
|
+
* mechanism — an empty one produces exactly the mute disabled button this
|
|
29
|
+
* prop exists to prevent, so it is rejected loudly instead of rendered as
|
|
30
|
+
* nothing.
|
|
31
|
+
*/
|
|
32
|
+
blocked?: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* What a step IS right now — derived from the steps and the cursor, never
|
|
36
|
+
* stored.
|
|
37
|
+
*
|
|
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
|
|
41
|
+
* produces a rail where a skipped step and an untouched one look identical.
|
|
42
|
+
*/
|
|
43
|
+
export type StepStatus =
|
|
44
|
+
/** `complete: true`. */
|
|
45
|
+
"complete"
|
|
46
|
+
/** Carries a `blocked` reason. Beats every other reading — see `stepStatus`. */
|
|
47
|
+
| "blocked"
|
|
48
|
+
/** The cursor is on it. */
|
|
49
|
+
| "current"
|
|
50
|
+
/** Behind the cursor and not complete: passed over. */
|
|
51
|
+
| "incomplete"
|
|
52
|
+
/** Ahead of the cursor. Not a fault — simply not reached. */
|
|
53
|
+
| "upcoming";
|
|
54
|
+
/**
|
|
55
|
+
* The two numbers a stepper header is tempted to average into one bar.
|
|
56
|
+
*
|
|
57
|
+
* `position` is where the cursor is; `complete` is how many are finished. They
|
|
58
|
+
* disagree the moment anybody moves past a step without finishing it, and
|
|
59
|
+
* `skipped` is that disagreement stated as a number rather than hidden inside
|
|
60
|
+
* a percentage.
|
|
61
|
+
*/
|
|
62
|
+
export interface StepperProgress {
|
|
63
|
+
/** 1-based, for reading: "Step 3 of 5". */
|
|
64
|
+
position: number;
|
|
65
|
+
total: number;
|
|
66
|
+
/** How many steps are `complete`, anywhere in the flow. */
|
|
67
|
+
complete: number;
|
|
68
|
+
/** Behind the cursor and not complete. */
|
|
69
|
+
skipped: number;
|
|
70
|
+
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export { Icon, type IconProps, type IconSize, type IconName } from "./components
|
|
|
13
13
|
export { registerIcon, registerIcons, getIcon, hasIcon, iconNames, type IconNode, type IconNodeChild, } from "./lib/icons";
|
|
14
14
|
export { coreIcons, type CoreIconName } from "./icons/data";
|
|
15
15
|
export { Button, buttonVariants, type ButtonProps } from "./components/Button";
|
|
16
|
+
export { IconButton, type IconButtonProps, type IconButtonVariant, type IconButtonTone, } from "./components/IconButton";
|
|
16
17
|
export { Badge, badgeVariants, type BadgeProps } from "./components/Badge";
|
|
17
18
|
export { Spinner, type SpinnerProps } from "./components/Spinner";
|
|
18
19
|
export { Skeleton, SkeletonText, LoadingOverlay, type SkeletonProps, type SkeletonTextProps, type LoadingOverlayProps, } from "./components/Loading";
|
|
@@ -41,6 +42,8 @@ export { RecordCard, type RecordCardProps, type RecordCardMetric, } from "./comp
|
|
|
41
42
|
export { Tabs, TabList, Tab, TabPanel, type TabsProps, type TabListProps, type TabProps, type TabPanelProps, } from "./components/Tabs";
|
|
42
43
|
export { Accordion, AccordionItem, type AccordionProps, type AccordionItemProps, } from "./components/Accordion";
|
|
43
44
|
export { Breadcrumb, Pagination, type BreadcrumbProps, type PaginationProps, type Crumb, } from "./components/Navigation";
|
|
45
|
+
export { Stepper, stepStatus, stepperProgress, advanceBlockReason, assertSteps, type StepperProps, type Step, type StepStatus, type StepperProgress, } from "./components/stepper";
|
|
46
|
+
export { StatusChecklist, tallyChecklist, type StatusChecklistProps, type ChecklistItem, type ChecklistState, type ChecklistTally, } from "./components/checklist";
|
|
44
47
|
export { Toggle, ToggleGroup, Toolbar, ToolbarSeparator, type ToggleProps, type ToggleGroupProps, type ToolbarProps, } from "./components/Toggle";
|
|
45
48
|
export { Separator, ScrollArea, Collapsible, EmptyState, Timeline, type SeparatorProps, type ScrollAreaProps, type CollapsibleProps, type EmptyStateProps, type TimelineProps, type TimelineItem, } from "./components/Surface";
|
|
46
49
|
export { PanelGroup, Panel, PanelResizer, type PanelGroupProps, type PanelProps, type PanelResizerProps, type PanelDirection, type PanelNarrowMode, } from "./components/Panel";
|
|
@@ -96,5 +99,5 @@ export { AmbiguousTimeError, addDays, addDuration, addMonths, atMidnight, atTime
|
|
|
96
99
|
export { allDayBandSegment, dayKey, daySlots, isAllDay, packBand, packLanes, snapFractionToInstant, timeSegments, timedBandSegment, type AllDayEvent, type BandInput, type BandOptions, type BandPlacement, type BandResult, type BandSegment, type CalendarEvent, type CalendarEventId, type CalendarView, type DaySlot, type DragKind, type EventDraft, type EventPalette, type LaneInput, type LaneOptions, type LanePlacement, type PaletteEntry, type TimeSegment, type TimedEvent, type VisibleRange, } from "./lib/calendar";
|
|
97
100
|
export { RBACProvider, useRBAC, AccountMenu, DevToolsPopover, RolePermissionMatrix, ProfilePage, RolesPermissionsPage, type RBACProviderProps, type RBACHookResult, type AccountMenuProps, type DevToolsPopoverProps, type RolePermissionMatrixProps, type Permission, type Role, type User, type Team, type TeamMembership, } from "./components/rbac";
|
|
98
101
|
export { UseCaseCard, RoadmapItemCard, RoadmapSwimlaneBoard, UseCaseLedgerPage, RoadmapPage, PhaseManager, TrackManager, deriveRoadmapItemStatus, isFullyBuilt, isUnbuilt, trackIds, trackProgress, toneForIndex, CATEGORY_TONES, type Domain, type Phase, type Track, type RoadmapItem, type RoadmapItemStatus, type UseCase, type UseCaseStatus, type UseCaseDecision, type UseCaseCardProps, type RoadmapItemCardProps, type RoadmapSwimlaneBoardProps, type UseCaseLedgerPageProps, type RoadmapPageProps, type PhaseManagerProps, type TrackManagerProps, } from "./components/roadmap";
|
|
99
|
-
export { ProvenanceDisclosure, ProvenanceBadge, ConfidenceMeter, provenanceStateLabel, confidenceBand, type ProvenanceRecord, type ProvenanceState, type ProvenanceSource, type ProvenanceCheck, type ProvenanceCall, type ProvenanceSignoff, type ConfidenceBand, type ProvenanceDisclosureProps, type ProvenanceBadgeProps, type ConfidenceMeterProps, } from "./components/provenance";
|
|
102
|
+
export { ProvenanceDisclosure, ProvenanceBadge, ConfidenceMeter, provenanceStateLabel, confidenceBand, type ProvenanceRecord, type ProvenanceState, type ProvenanceSource, type ProvenanceCheck, type ProvenanceCall, type ProvenanceSignoff, type ConfidenceBand, type ProvenanceDisclosureProps, type ProvenanceTriggerBadge, type ProvenanceBadgeProps, type ProvenanceBadgeAppearance, type ConfidenceMeterProps, } from "./components/provenance";
|
|
100
103
|
export { createSimStore, resetSimStores, useSimSettings, setSimSettings, getNetworkSpeed, getDataSource, simulateLatency, SimNetworkError, type SimStore, type SimStoreOptions, type SimSettings, type NetworkSpeed, type DataSource, type SimNamespace, } from "./lib/sim";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@danxbot/ui",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.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",
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
"audit:arrows": "node scripts/audit-arrows.mjs",
|
|
79
79
|
"audit:motion": "node scripts/audit-motion.mjs",
|
|
80
80
|
"audit:responsive": "node scripts/audit-responsive.mjs",
|
|
81
|
-
"audit:dnd": "node scripts/audit-dnd.mjs && node scripts/probe-dnd-sensors.mjs && node scripts/probe-dnd-a11y.mjs",
|
|
81
|
+
"audit:dnd": "node scripts/audit-dnd.mjs && node scripts/probe-dnd-sensors.mjs && node scripts/probe-dnd-a11y.mjs && node scripts/probe-drag-follow.mjs",
|
|
82
82
|
"audit:axtree": "node scripts/audit-axtree.mjs",
|
|
83
83
|
"audit:mutations": "node scripts/audit-mutations.mjs",
|
|
84
84
|
"audit:palette": "node scripts/audit-palette.mjs",
|