@danxbot/ui 2.3.0 → 2.5.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 +19014 -18145
- 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/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/node-canvas/NodeCanvas.d.ts +58 -0
- package/dist/types/components/node-canvas/index.d.ts +3 -0
- package/dist/types/components/node-canvas/layout.d.ts +17 -0
- package/dist/types/components/node-canvas/types.d.ts +113 -0
- package/dist/types/components/node-canvas/use-canvas-gestures.d.ts +39 -0
- package/dist/types/components/provenance/ProvenanceBadge.d.ts +11 -1
- package/dist/types/components/provenance/ProvenanceDisclosure.d.ts +46 -1
- package/dist/types/index.d.ts +3 -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 {};
|
|
@@ -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. */
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { CanvasNode, CanvasOrientation, NodeRenderer } from "./types";
|
|
2
|
+
export interface NodeCanvasProps<Extra = unknown> {
|
|
3
|
+
/** The whole tree. The canvas walks into it; it never mutates it. */
|
|
4
|
+
root: CanvasNode<Extra>;
|
|
5
|
+
/**
|
|
6
|
+
* What this canvas IS — "Org chart", "Dependency graph for the March build".
|
|
7
|
+
*
|
|
8
|
+
* Required for the same reason `StatusChecklist.label` and
|
|
9
|
+
* `KanbanBoard.label` are: it is the accessible name of the whole structure,
|
|
10
|
+
* and somebody landing on it by keyboard has nothing else to tell them what
|
|
11
|
+
* they are inside.
|
|
12
|
+
*/
|
|
13
|
+
label: string;
|
|
14
|
+
/**
|
|
15
|
+
* The node body. Receives the consumer's own node type and a context of
|
|
16
|
+
* purely structural facts.
|
|
17
|
+
*
|
|
18
|
+
* A RENDER PROP RATHER THAN CHILDREN-AS-A-FUNCTION, because a canvas draws
|
|
19
|
+
* MANY nodes and `children` reads as one. `<NodeCanvas>{(node) => …}` looks
|
|
20
|
+
* like a single child and is really a template invoked N times, which is the
|
|
21
|
+
* ambiguity this library already avoids elsewhere (`ProvenanceDisclosure`
|
|
22
|
+
* takes `actions`, `Chat` takes a `components` map). It is optional: the
|
|
23
|
+
* default draws the `label` the node already declares and nothing else, so
|
|
24
|
+
* the component is usable with no wiring and the default introduces no
|
|
25
|
+
* vocabulary of its own.
|
|
26
|
+
*/
|
|
27
|
+
renderNode?: NodeRenderer<Extra>;
|
|
28
|
+
/** Which way the chart grows. See `CanvasOrientation`. */
|
|
29
|
+
orientation?: CanvasOrientation;
|
|
30
|
+
/** Levels below the current root to draw. `1` is the root and its children. */
|
|
31
|
+
depth?: number;
|
|
32
|
+
/** Along-axis extent of a node that does not declare its own, in px. */
|
|
33
|
+
nodeWidth?: number;
|
|
34
|
+
/** Cross-axis extent of a node that does not declare its own, in px. */
|
|
35
|
+
nodeHeight?: number;
|
|
36
|
+
/** Height of the scrolling viewport. Any CSS length. */
|
|
37
|
+
height?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Fired after the canvas re-roots, with the trail from the ORIGINAL root.
|
|
40
|
+
*
|
|
41
|
+
* Observation, not control: the canvas owns where it is. A consumer that
|
|
42
|
+
* needs to restore a position across a reload stores this and remounts with
|
|
43
|
+
* a different `root`.
|
|
44
|
+
*/
|
|
45
|
+
onRootChange?: (node: CanvasNode<Extra>, path: CanvasNode<Extra>[]) => void;
|
|
46
|
+
/** Fired when a node drag commits. The offset is from its laid-out position. */
|
|
47
|
+
onNodeDragEnd?: (event: {
|
|
48
|
+
id: string;
|
|
49
|
+
offset: {
|
|
50
|
+
x: number;
|
|
51
|
+
y: number;
|
|
52
|
+
};
|
|
53
|
+
}) => void;
|
|
54
|
+
/** Nothing pans, drags or descends. Reading still works, including by keyboard. */
|
|
55
|
+
disabled?: boolean;
|
|
56
|
+
className?: string;
|
|
57
|
+
}
|
|
58
|
+
export declare function NodeCanvas<Extra = unknown>({ root, label, renderNode, orientation, depth, nodeWidth, nodeHeight, height, onRootChange, onNodeDragEnd, disabled, className, }: NodeCanvasProps<Extra>): import("react").JSX.Element;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { NodeCanvas, type NodeCanvasProps } from "./NodeCanvas";
|
|
2
|
+
export { LAYOUT_DEFAULTS, layoutTree, pathToNode } from "./layout";
|
|
3
|
+
export type { CanvasEdge, CanvasLayout, CanvasNode, CanvasOrientation, LayoutOptions, NodeRenderContext, NodeRenderer, PlacedNode, } from "./types";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { CanvasLayout, CanvasNode, LayoutOptions } from "./types";
|
|
2
|
+
export declare const LAYOUT_DEFAULTS: Required<LayoutOptions>;
|
|
3
|
+
/**
|
|
4
|
+
* Lay a tree out.
|
|
5
|
+
*
|
|
6
|
+
* Coordinates are plane-local and start at 0 on both axes: the caller decides
|
|
7
|
+
* where the plane sits and how much padding surrounds it.
|
|
8
|
+
*/
|
|
9
|
+
export declare function layoutTree<Extra>(root: CanvasNode<Extra>, options?: LayoutOptions): CanvasLayout<Extra>;
|
|
10
|
+
/**
|
|
11
|
+
* The ids from the ORIGINAL root down to `targetId`, inclusive.
|
|
12
|
+
*
|
|
13
|
+
* `null` when the id is not in the tree, which the canvas treats as a
|
|
14
|
+
* programming error rather than as an empty trail — a breadcrumb that silently
|
|
15
|
+
* renders nothing is how a broken `rootId` looks like a styling bug.
|
|
16
|
+
*/
|
|
17
|
+
export declare function pathToNode<Extra>(root: CanvasNode<Extra>, targetId: string): CanvasNode<Extra>[] | null;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* One node of the tree.
|
|
4
|
+
*
|
|
5
|
+
* `Extra` carries the consumer's own fields DOWN THE WHOLE TREE, so
|
|
6
|
+
* `renderNode` receives their type rather than ours plus a cast:
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* type Task = { owner: string; done: boolean };
|
|
10
|
+
* const root: CanvasNode<Task> = { id: "r", label: "Release", owner: "ada", done: false, children: [...] };
|
|
11
|
+
* <NodeCanvas root={root} renderNode={(node) => <span>{node.owner}</span>} />
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* Written as an intersection rather than an interface with a type parameter
|
|
15
|
+
* because the recursion has to carry `Extra` into `children` — an interface
|
|
16
|
+
* cannot refer to its own instantiation that way without a self-referencing
|
|
17
|
+
* constraint that every consumer then has to spell out.
|
|
18
|
+
*/
|
|
19
|
+
export type CanvasNode<Extra = unknown> = Extra & {
|
|
20
|
+
/** Stable across renders. Node positions, focus and drag offsets are keyed on it. */
|
|
21
|
+
id: string;
|
|
22
|
+
/**
|
|
23
|
+
* The accessible name, the breadcrumb text, and the default body.
|
|
24
|
+
*
|
|
25
|
+
* A plain string, not a `ReactNode`, and that is deliberate: it is read
|
|
26
|
+
* aloud and printed into a trail, and neither of those can do anything with
|
|
27
|
+
* an element tree. Rich content belongs in `renderNode`.
|
|
28
|
+
*/
|
|
29
|
+
label: string;
|
|
30
|
+
children?: readonly CanvasNode<Extra>[];
|
|
31
|
+
/** Along-axis extent for this node only, when it differs from the canvas default. */
|
|
32
|
+
width?: number;
|
|
33
|
+
/** Cross-axis extent for this node only, when it differs from the canvas default. */
|
|
34
|
+
height?: number;
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Which way the chart grows.
|
|
38
|
+
*
|
|
39
|
+
* `vertical` puts the root at the top with children below it — the shape most
|
|
40
|
+
* people picture. `horizontal` puts the root at the left with children to the
|
|
41
|
+
* right, which is what deep trees with long labels actually want: label text
|
|
42
|
+
* runs along the level axis in one and across it in the other, so a horizontal
|
|
43
|
+
* chart of the same tree is narrower and reads without truncation.
|
|
44
|
+
*/
|
|
45
|
+
export type CanvasOrientation = "vertical" | "horizontal";
|
|
46
|
+
/** A node with its box resolved, in plane coordinates. `x`/`y` are its TOP-LEFT. */
|
|
47
|
+
export interface PlacedNode<Extra = unknown> {
|
|
48
|
+
id: string;
|
|
49
|
+
node: CanvasNode<Extra>;
|
|
50
|
+
/** 0 for the node the canvas is currently rooted on. */
|
|
51
|
+
depth: number;
|
|
52
|
+
/** Null for the current root. Ids of nodes outside this view never appear. */
|
|
53
|
+
parentId: string | null;
|
|
54
|
+
x: number;
|
|
55
|
+
y: number;
|
|
56
|
+
width: number;
|
|
57
|
+
height: number;
|
|
58
|
+
/** How many children it has, whether or not this view is showing them. */
|
|
59
|
+
childCount: number;
|
|
60
|
+
/**
|
|
61
|
+
* It has children and this view is not drawing them — the node sits on the
|
|
62
|
+
* bottom row of the visible depth. The affordance to descend belongs here.
|
|
63
|
+
*/
|
|
64
|
+
hasHiddenChildren: boolean;
|
|
65
|
+
}
|
|
66
|
+
/** Parent → child, by id. Both ends are always present in `nodes`. */
|
|
67
|
+
export interface CanvasEdge {
|
|
68
|
+
from: string;
|
|
69
|
+
to: string;
|
|
70
|
+
}
|
|
71
|
+
export interface CanvasLayout<Extra = unknown> {
|
|
72
|
+
nodes: PlacedNode<Extra>[];
|
|
73
|
+
edges: CanvasEdge[];
|
|
74
|
+
/** Extent of the laid-out nodes. The plane is this plus padding on each side. */
|
|
75
|
+
width: number;
|
|
76
|
+
height: number;
|
|
77
|
+
}
|
|
78
|
+
export interface LayoutOptions {
|
|
79
|
+
/** Along-axis extent of a node that does not declare its own. */
|
|
80
|
+
nodeWidth?: number;
|
|
81
|
+
/** Cross-axis extent of a node that does not declare its own. */
|
|
82
|
+
nodeHeight?: number;
|
|
83
|
+
/** Clear space between two adjacent nodes on the same level. */
|
|
84
|
+
siblingGap?: number;
|
|
85
|
+
/** Clear space between one level and the next. */
|
|
86
|
+
levelGap?: number;
|
|
87
|
+
orientation?: CanvasOrientation;
|
|
88
|
+
/**
|
|
89
|
+
* How many levels BELOW the root to draw. `1` shows the root and its
|
|
90
|
+
* children; `0` shows the root alone.
|
|
91
|
+
*/
|
|
92
|
+
depth?: number;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* What `renderNode` is told about the node it is drawing.
|
|
96
|
+
*
|
|
97
|
+
* Every field is structural — a fact about the node's place in the tree or in
|
|
98
|
+
* the current interaction. None of them is a fact about what the node is.
|
|
99
|
+
*/
|
|
100
|
+
export interface NodeRenderContext {
|
|
101
|
+
/** 0 for the node the canvas is rooted on. */
|
|
102
|
+
depth: number;
|
|
103
|
+
isRoot: boolean;
|
|
104
|
+
childCount: number;
|
|
105
|
+
hasChildren: boolean;
|
|
106
|
+
/** Children exist and this view stops short of them — clicking descends. */
|
|
107
|
+
hasHiddenChildren: boolean;
|
|
108
|
+
/** This node carries the canvas's single tab stop. */
|
|
109
|
+
isFocused: boolean;
|
|
110
|
+
/** A pointer is carrying this node right now. */
|
|
111
|
+
isDragging: boolean;
|
|
112
|
+
}
|
|
113
|
+
export type NodeRenderer<Extra = unknown> = (node: CanvasNode<Extra>, context: NodeRenderContext) => ReactNode;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Point } from "@/lib/dnd/types";
|
|
2
|
+
/** Plane-local box of a node, as the layout placed it. */
|
|
3
|
+
export interface NodeBox {
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
}
|
|
9
|
+
export interface CanvasGestureOptions {
|
|
10
|
+
/** Where a node sits before any drag offset. Null for an id not on screen. */
|
|
11
|
+
layoutBoxOf: (id: string) => NodeBox | null;
|
|
12
|
+
/** Extent of the scrolled plane. Node positions are clamped inside it. */
|
|
13
|
+
planeSize: {
|
|
14
|
+
width: number;
|
|
15
|
+
height: number;
|
|
16
|
+
};
|
|
17
|
+
/** A press that released without activating — the click that descends. */
|
|
18
|
+
onNodeClick: (id: string) => void;
|
|
19
|
+
/** A drag that committed. Offsets stay owned here either way. */
|
|
20
|
+
onNodeDragEnd?: (event: {
|
|
21
|
+
id: string;
|
|
22
|
+
offset: Point;
|
|
23
|
+
}) => void;
|
|
24
|
+
disabled?: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface CanvasGestures {
|
|
27
|
+
/** Drag offsets from the layout position, by node id. */
|
|
28
|
+
offsets: Readonly<Record<string, Point>>;
|
|
29
|
+
/** The node a pointer is currently carrying, or null. */
|
|
30
|
+
draggingId: string | null;
|
|
31
|
+
panning: boolean;
|
|
32
|
+
/** Ref callback for the scroll viewport. Stable — see the note at its use. */
|
|
33
|
+
bindViewport: (node: HTMLDivElement | null) => void;
|
|
34
|
+
/** Ref callback for one node's element. Stable per id. */
|
|
35
|
+
bindNode: (id: string) => (node: HTMLElement | null) => void;
|
|
36
|
+
/** Drop every offset — called when the layout underneath them changes. */
|
|
37
|
+
clearOffsets: () => void;
|
|
38
|
+
}
|
|
39
|
+
export declare function useCanvasGestures(options: CanvasGestureOptions): CanvasGestures;
|
|
@@ -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;
|
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";
|
|
@@ -98,5 +99,6 @@ export { AmbiguousTimeError, addDays, addDuration, addMonths, atMidnight, atTime
|
|
|
98
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";
|
|
99
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";
|
|
100
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";
|
|
101
|
-
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";
|
|
102
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";
|
|
104
|
+
export { NodeCanvas, LAYOUT_DEFAULTS, layoutTree, pathToNode, type NodeCanvasProps, type CanvasEdge, type CanvasLayout, type CanvasNode, type CanvasOrientation, type LayoutOptions, type NodeRenderContext, type NodeRenderer, type PlacedNode, } from "./components/node-canvas";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@danxbot/ui",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.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 && node scripts/probe-drag-overflow.mjs && node scripts/probe-node-canvas.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",
|