@meetreeve/ui 0.15.0 → 0.16.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/README.md +41 -0
- package/dist/stage-rail/index.d.mts +173 -0
- package/dist/stage-rail/index.d.ts +173 -0
- package/dist/stage-rail/index.js +3814 -0
- package/dist/stage-rail/index.mjs +3783 -0
- package/dist/tokens/index.d.mts +12 -1
- package/dist/tokens/index.d.ts +12 -1
- package/dist/tokens/index.js +8 -0
- package/dist/tokens/index.mjs +7 -0
- package/dist/tokens.css +5 -1
- package/package.json +7 -2
package/README.md
CHANGED
|
@@ -187,6 +187,47 @@ the host must define `--color-popover`, `--color-popover-foreground`,
|
|
|
187
187
|
`--color-border` and `--color-ring`, and Tailwind consumers must include this
|
|
188
188
|
package's `dist` as a `@source` (see ResponsiveHeader above).
|
|
189
189
|
|
|
190
|
+
## StageRail (DEV-13855)
|
|
191
|
+
|
|
192
|
+
Domain-free "flow of cards": cards joined by connectors, left to right.
|
|
193
|
+
|
|
194
|
+
```tsx
|
|
195
|
+
import { StageRail, StageCardShell, StageConnector, StageRailMini } from "@meetreeve/ui/stage-rail";
|
|
196
|
+
|
|
197
|
+
<StageRail
|
|
198
|
+
stages={steps}
|
|
199
|
+
getId={(s) => s.id}
|
|
200
|
+
leading={<TriggerCard />} // fixed: never reorders, nothing inserts before it
|
|
201
|
+
trailing={<ExitCard />} // fixed: nothing inserts after it
|
|
202
|
+
selectedId={selected}
|
|
203
|
+
onSelect={setSelected}
|
|
204
|
+
onInsertAt={(i) => insertStep(i)}
|
|
205
|
+
reorderable
|
|
206
|
+
onReorder={(from, to) => moveStep(from, to)}
|
|
207
|
+
editable={isDraft} // false: no +, no reorder
|
|
208
|
+
ruler={[{ label: "Start" }, ...steps.map((s) => ({ label: s.day })), { label: "End" }]}
|
|
209
|
+
renderCard={(s, i, ctx) => (
|
|
210
|
+
<StageCardShell selected={ctx.selected} dragging={ctx.dragging} dragHandle={ctx.reorderable}
|
|
211
|
+
onSelect={ctx.select} index={i + 1} className="w-64">
|
|
212
|
+
…
|
|
213
|
+
</StageCardShell>
|
|
214
|
+
)}
|
|
215
|
+
renderConnector={(prev, next, i, ctx) => ( // prev/next null = a fixed slot
|
|
216
|
+
<StageConnector label="2 days" onInsert={ctx.canInsert ? ctx.insert : undefined} dropActive={ctx.dropActive} />
|
|
217
|
+
)}
|
|
218
|
+
/>
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
- Reorder is opt-in and starts only from a `[data-stage-drag-handle]` (the
|
|
222
|
+
shell's `dragHandle`), so inputs and buttons in cards and connectors never
|
|
223
|
+
start a drag. Clicks and keys from interactive descendants never select.
|
|
224
|
+
- Styling uses the consumer's shadcn theme tokens (`bg-card`, `ring-primary`,
|
|
225
|
+
`ring-destructive`, `text-muted-foreground`, …), so light and dark follow the
|
|
226
|
+
host. Spacing reads `--mf-stage-*` with built-in fallbacks.
|
|
227
|
+
- Fit: measure `scrollRef` and feed `computeFitZoomFromExtent({ zoom, scrollWidth, clientWidth })`
|
|
228
|
+
back into `zoom`. It can only zoom out; to fit a rail that already fits, jump
|
|
229
|
+
to 1, re-measure, and correct down.
|
|
230
|
+
|
|
190
231
|
## Tokens
|
|
191
232
|
|
|
192
233
|
```ts
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode, Ref, HTMLAttributes } from 'react';
|
|
3
|
+
|
|
4
|
+
interface StageCardContext {
|
|
5
|
+
/** 0-based position in `stages`. */
|
|
6
|
+
index: number;
|
|
7
|
+
selected: boolean;
|
|
8
|
+
/** This card is the one being pointer-dragged. */
|
|
9
|
+
dragging: boolean;
|
|
10
|
+
/** Pointer / Alt+arrow reorder is live — render a drag handle (`StageCardShell dragHandle`). */
|
|
11
|
+
reorderable: boolean;
|
|
12
|
+
/** Calls `onSelect(getId(stage))`. Wire it to `StageCardShell onSelect`. */
|
|
13
|
+
select: () => void;
|
|
14
|
+
}
|
|
15
|
+
interface StageConnectorContext {
|
|
16
|
+
/** `editable` and `onInsertAt` is set. */
|
|
17
|
+
canInsert: boolean;
|
|
18
|
+
/** Calls `onInsertAt(i)`. */
|
|
19
|
+
insert: () => void;
|
|
20
|
+
/** A pointer drag would land a stage in this gap. */
|
|
21
|
+
dropActive: boolean;
|
|
22
|
+
}
|
|
23
|
+
interface StageRailProps<T> {
|
|
24
|
+
stages: T[];
|
|
25
|
+
getId: (stage: T) => string;
|
|
26
|
+
renderCard: (stage: T, index: number, ctx: StageCardContext) => ReactNode;
|
|
27
|
+
/**
|
|
28
|
+
* The link between two rendered slots. `prev`/`next` are null for a fixed
|
|
29
|
+
* `leading`/`trailing` slot; `index` is where an inserted stage would land.
|
|
30
|
+
* Return null for no gap. Defaults to an inline `StageConnector`.
|
|
31
|
+
*/
|
|
32
|
+
renderConnector?: (prev: T | null, next: T | null, index: number, ctx: StageConnectorContext) => ReactNode;
|
|
33
|
+
/** Fixed first slot (e.g. a trigger): never reorderable, nothing inserts before it. */
|
|
34
|
+
leading?: ReactNode;
|
|
35
|
+
/** Fixed last slot (e.g. an exit or an append target): nothing inserts after it. */
|
|
36
|
+
trailing?: ReactNode;
|
|
37
|
+
selectedId?: string | null;
|
|
38
|
+
onSelect?: (id: string) => void;
|
|
39
|
+
onInsertAt?: (index: number) => void;
|
|
40
|
+
/** Array-move semantics: `to` is the moved stage's final index. */
|
|
41
|
+
onReorder?: (from: number, to: number) => void;
|
|
42
|
+
/** Opt in to pointer (drag handle) and Alt+←/→ reorder. */
|
|
43
|
+
reorderable?: boolean;
|
|
44
|
+
/** false = read-only: no insert, no reorder. */
|
|
45
|
+
editable?: boolean;
|
|
46
|
+
/** One label per RENDERED slot, fixed slots included, drawn above it. */
|
|
47
|
+
ruler?: {
|
|
48
|
+
label: ReactNode;
|
|
49
|
+
}[];
|
|
50
|
+
/** CSS zoom on the track; pair with `computeFitZoomFromExtent` over `scrollRef`. */
|
|
51
|
+
zoom?: number;
|
|
52
|
+
/** The horizontal scroll element (measure scrollWidth/clientWidth for fit). */
|
|
53
|
+
scrollRef?: Ref<HTMLDivElement>;
|
|
54
|
+
className?: string;
|
|
55
|
+
"aria-label"?: string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* A horizontal "flow of cards": leading slot → stage cards → trailing slot,
|
|
59
|
+
* with connectors between every pair. Domain-free — cards and connectors are
|
|
60
|
+
* the consumer's render props. Snap-scrolls below md.
|
|
61
|
+
*/
|
|
62
|
+
declare function StageRail<T>({ stages, getId, renderCard, renderConnector, leading, trailing, selectedId, onSelect, onInsertAt, onReorder, reorderable, editable, ruler, zoom, scrollRef, className, "aria-label": ariaLabel, }: StageRailProps<T>): react.JSX.Element;
|
|
63
|
+
|
|
64
|
+
/** True when `target` is (inside) an interactive element nested in `root` — not `root` itself. */
|
|
65
|
+
declare function isInteractiveTarget(target: EventTarget | null, root: Element): boolean;
|
|
66
|
+
interface StageCardShellProps extends Omit<HTMLAttributes<HTMLDivElement>, "onSelect"> {
|
|
67
|
+
/** Click / Enter / Space on the card itself. Never fires from interactive descendants. */
|
|
68
|
+
onSelect?: () => void;
|
|
69
|
+
selected?: boolean;
|
|
70
|
+
disabled?: boolean;
|
|
71
|
+
/** Visual only — the body is never replaced. */
|
|
72
|
+
pending?: boolean;
|
|
73
|
+
/** Destructive ring; wins over `selected`. */
|
|
74
|
+
error?: boolean;
|
|
75
|
+
/** Dims the card while a drag (yours or StageRail's) is in flight. */
|
|
76
|
+
dragging?: boolean;
|
|
77
|
+
/** Show the visual drag handle (StageRail's pointer reorder grabs it; HTML5 consumers use `draggable`). */
|
|
78
|
+
dragHandle?: boolean;
|
|
79
|
+
/** Shown verbatim in the bottom-left dot (pass the 1-based number). Omitted when undefined. */
|
|
80
|
+
index?: number;
|
|
81
|
+
topLeft?: ReactNode;
|
|
82
|
+
topRight?: ReactNode;
|
|
83
|
+
/** Centred overlay revealed on card hover (and focus-within unless `overlayRevealOnFocus` is false). */
|
|
84
|
+
overlay?: ReactNode;
|
|
85
|
+
/** Also reveal `overlay` while focus is inside the card. false for bodies that hold focus (e.g. an iframe). */
|
|
86
|
+
overlayRevealOnFocus?: boolean;
|
|
87
|
+
/** Classes for the drag handle, merged last. */
|
|
88
|
+
handleClassName?: string;
|
|
89
|
+
/** Classes for the index dot, merged last. */
|
|
90
|
+
indexClassName?: string;
|
|
91
|
+
/** Bottom strip (e.g. an inline error). */
|
|
92
|
+
alert?: ReactNode;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* The frame every stage card shares: ONE root div (ref + rest props land on
|
|
96
|
+
* it, so Radix `asChild` triggers and IntersectionObserver refs work), the
|
|
97
|
+
* consumer's body full-bleed inside, and absolutely-positioned slots over it.
|
|
98
|
+
* Stateless; hover is CSS-only via the `group/card` name.
|
|
99
|
+
*/
|
|
100
|
+
declare const StageCardShell: react.ForwardRefExoticComponent<StageCardShellProps & react.RefAttributes<HTMLDivElement>>;
|
|
101
|
+
|
|
102
|
+
interface StageConnectorProps extends HTMLAttributes<HTMLElement> {
|
|
103
|
+
/** `inline` sits between cards; `append` is the tall end-of-rail target. */
|
|
104
|
+
variant?: "inline" | "append";
|
|
105
|
+
/** Without it (or when `disabled`) the inline `+` is not rendered and the append button is disabled. */
|
|
106
|
+
onInsert?: () => void;
|
|
107
|
+
disabled?: boolean;
|
|
108
|
+
/** Highlight as the live drop target (shows the inline `+` without hover). */
|
|
109
|
+
dropActive?: boolean;
|
|
110
|
+
/** Accessible name of the insert control. */
|
|
111
|
+
insertLabel?: string;
|
|
112
|
+
/** Inline: text / controls under the link (e.g. "2 days", an inline input). */
|
|
113
|
+
label?: ReactNode;
|
|
114
|
+
/** Inline: chip above the link (e.g. "38 waiting"). */
|
|
115
|
+
badge?: ReactNode;
|
|
116
|
+
/** Inline: 0–1 volume, scales the link's thickness (1px → 6px). */
|
|
117
|
+
weight?: number;
|
|
118
|
+
/** Append: the card height to match. Width is max(80, height * 0.45). */
|
|
119
|
+
height?: number;
|
|
120
|
+
/** Append: visible caption. */
|
|
121
|
+
appendText?: ReactNode;
|
|
122
|
+
/** Inline: show the `+` without hover on touch (hover:none) devices. */
|
|
123
|
+
touchAlwaysVisible?: boolean;
|
|
124
|
+
/** Inline: classes for the `+` button, merged last (its drop-active state included). */
|
|
125
|
+
insertClassName?: string;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* The link between two stage cards. Rest props (HTML5 onDragOver / onDrop …)
|
|
129
|
+
* land on the hit-area root. Inline with no label/badge/weight it is exactly
|
|
130
|
+
* the 36×36 hit area — zero extra size. Horizontal only.
|
|
131
|
+
*/
|
|
132
|
+
declare function StageConnector({ variant, onInsert, disabled, dropActive, insertLabel, label, badge, weight, height, appendText, touchAlwaysVisible, insertClassName, className, style, onClick, ...rest }: StageConnectorProps): react.JSX.Element;
|
|
133
|
+
|
|
134
|
+
interface StageRailMiniDot {
|
|
135
|
+
/** Names the stage in the accessible summary and the dot's tooltip. */
|
|
136
|
+
label: string;
|
|
137
|
+
key?: string;
|
|
138
|
+
/** Colour per kind, e.g. "bg-primary". */
|
|
139
|
+
className?: string;
|
|
140
|
+
/** Optional tiny icon; the dot grows to fit it. */
|
|
141
|
+
icon?: ReactNode;
|
|
142
|
+
}
|
|
143
|
+
/** Dot-sequence thumbnail of a rail for list rows: one dot per stage. */
|
|
144
|
+
declare function StageRailMini({ dots, className, "aria-label": ariaLabel, }: {
|
|
145
|
+
dots: StageRailMiniDot[];
|
|
146
|
+
className?: string;
|
|
147
|
+
"aria-label"?: string;
|
|
148
|
+
}): react.JSX.Element;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Zoom that fits a rail's content into its scroll viewport, derived from the
|
|
152
|
+
* scroller's REAL rendered extent (ported from the Studio chain, DEV-3681:
|
|
153
|
+
* a closed-form gap model no-opped on overflowing chains).
|
|
154
|
+
*
|
|
155
|
+
* `zoom` is the zoom the extent was rendered AT. Content scales linearly with
|
|
156
|
+
* zoom; the scroller's own horizontal padding (`pad`, StageRail's md+ px-8 =
|
|
157
|
+
* 64) doesn't, so both extents shed it before the ratio. Clamped to
|
|
158
|
+
* [min, max] and rounded to 2dp.
|
|
159
|
+
*
|
|
160
|
+
* Caveat: DOM scrollWidth floor-clamps at clientWidth, so content that already
|
|
161
|
+
* fits measures ratio 1 and this echoes `zoom` — it can only zoom OUT. To fit
|
|
162
|
+
* a fitting rail, jump to `max`, re-measure, and correct down if it overshot.
|
|
163
|
+
*/
|
|
164
|
+
declare function computeFitZoomFromExtent({ zoom, scrollWidth, clientWidth, pad, min, max, }: {
|
|
165
|
+
zoom: number;
|
|
166
|
+
scrollWidth: number;
|
|
167
|
+
clientWidth: number;
|
|
168
|
+
pad?: number;
|
|
169
|
+
min?: number;
|
|
170
|
+
max?: number;
|
|
171
|
+
}): number;
|
|
172
|
+
|
|
173
|
+
export { type StageCardContext, StageCardShell, type StageCardShellProps, StageConnector, type StageConnectorContext, type StageConnectorProps, StageRail, StageRailMini, type StageRailMiniDot, type StageRailProps, computeFitZoomFromExtent, isInteractiveTarget };
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode, Ref, HTMLAttributes } from 'react';
|
|
3
|
+
|
|
4
|
+
interface StageCardContext {
|
|
5
|
+
/** 0-based position in `stages`. */
|
|
6
|
+
index: number;
|
|
7
|
+
selected: boolean;
|
|
8
|
+
/** This card is the one being pointer-dragged. */
|
|
9
|
+
dragging: boolean;
|
|
10
|
+
/** Pointer / Alt+arrow reorder is live — render a drag handle (`StageCardShell dragHandle`). */
|
|
11
|
+
reorderable: boolean;
|
|
12
|
+
/** Calls `onSelect(getId(stage))`. Wire it to `StageCardShell onSelect`. */
|
|
13
|
+
select: () => void;
|
|
14
|
+
}
|
|
15
|
+
interface StageConnectorContext {
|
|
16
|
+
/** `editable` and `onInsertAt` is set. */
|
|
17
|
+
canInsert: boolean;
|
|
18
|
+
/** Calls `onInsertAt(i)`. */
|
|
19
|
+
insert: () => void;
|
|
20
|
+
/** A pointer drag would land a stage in this gap. */
|
|
21
|
+
dropActive: boolean;
|
|
22
|
+
}
|
|
23
|
+
interface StageRailProps<T> {
|
|
24
|
+
stages: T[];
|
|
25
|
+
getId: (stage: T) => string;
|
|
26
|
+
renderCard: (stage: T, index: number, ctx: StageCardContext) => ReactNode;
|
|
27
|
+
/**
|
|
28
|
+
* The link between two rendered slots. `prev`/`next` are null for a fixed
|
|
29
|
+
* `leading`/`trailing` slot; `index` is where an inserted stage would land.
|
|
30
|
+
* Return null for no gap. Defaults to an inline `StageConnector`.
|
|
31
|
+
*/
|
|
32
|
+
renderConnector?: (prev: T | null, next: T | null, index: number, ctx: StageConnectorContext) => ReactNode;
|
|
33
|
+
/** Fixed first slot (e.g. a trigger): never reorderable, nothing inserts before it. */
|
|
34
|
+
leading?: ReactNode;
|
|
35
|
+
/** Fixed last slot (e.g. an exit or an append target): nothing inserts after it. */
|
|
36
|
+
trailing?: ReactNode;
|
|
37
|
+
selectedId?: string | null;
|
|
38
|
+
onSelect?: (id: string) => void;
|
|
39
|
+
onInsertAt?: (index: number) => void;
|
|
40
|
+
/** Array-move semantics: `to` is the moved stage's final index. */
|
|
41
|
+
onReorder?: (from: number, to: number) => void;
|
|
42
|
+
/** Opt in to pointer (drag handle) and Alt+←/→ reorder. */
|
|
43
|
+
reorderable?: boolean;
|
|
44
|
+
/** false = read-only: no insert, no reorder. */
|
|
45
|
+
editable?: boolean;
|
|
46
|
+
/** One label per RENDERED slot, fixed slots included, drawn above it. */
|
|
47
|
+
ruler?: {
|
|
48
|
+
label: ReactNode;
|
|
49
|
+
}[];
|
|
50
|
+
/** CSS zoom on the track; pair with `computeFitZoomFromExtent` over `scrollRef`. */
|
|
51
|
+
zoom?: number;
|
|
52
|
+
/** The horizontal scroll element (measure scrollWidth/clientWidth for fit). */
|
|
53
|
+
scrollRef?: Ref<HTMLDivElement>;
|
|
54
|
+
className?: string;
|
|
55
|
+
"aria-label"?: string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* A horizontal "flow of cards": leading slot → stage cards → trailing slot,
|
|
59
|
+
* with connectors between every pair. Domain-free — cards and connectors are
|
|
60
|
+
* the consumer's render props. Snap-scrolls below md.
|
|
61
|
+
*/
|
|
62
|
+
declare function StageRail<T>({ stages, getId, renderCard, renderConnector, leading, trailing, selectedId, onSelect, onInsertAt, onReorder, reorderable, editable, ruler, zoom, scrollRef, className, "aria-label": ariaLabel, }: StageRailProps<T>): react.JSX.Element;
|
|
63
|
+
|
|
64
|
+
/** True when `target` is (inside) an interactive element nested in `root` — not `root` itself. */
|
|
65
|
+
declare function isInteractiveTarget(target: EventTarget | null, root: Element): boolean;
|
|
66
|
+
interface StageCardShellProps extends Omit<HTMLAttributes<HTMLDivElement>, "onSelect"> {
|
|
67
|
+
/** Click / Enter / Space on the card itself. Never fires from interactive descendants. */
|
|
68
|
+
onSelect?: () => void;
|
|
69
|
+
selected?: boolean;
|
|
70
|
+
disabled?: boolean;
|
|
71
|
+
/** Visual only — the body is never replaced. */
|
|
72
|
+
pending?: boolean;
|
|
73
|
+
/** Destructive ring; wins over `selected`. */
|
|
74
|
+
error?: boolean;
|
|
75
|
+
/** Dims the card while a drag (yours or StageRail's) is in flight. */
|
|
76
|
+
dragging?: boolean;
|
|
77
|
+
/** Show the visual drag handle (StageRail's pointer reorder grabs it; HTML5 consumers use `draggable`). */
|
|
78
|
+
dragHandle?: boolean;
|
|
79
|
+
/** Shown verbatim in the bottom-left dot (pass the 1-based number). Omitted when undefined. */
|
|
80
|
+
index?: number;
|
|
81
|
+
topLeft?: ReactNode;
|
|
82
|
+
topRight?: ReactNode;
|
|
83
|
+
/** Centred overlay revealed on card hover (and focus-within unless `overlayRevealOnFocus` is false). */
|
|
84
|
+
overlay?: ReactNode;
|
|
85
|
+
/** Also reveal `overlay` while focus is inside the card. false for bodies that hold focus (e.g. an iframe). */
|
|
86
|
+
overlayRevealOnFocus?: boolean;
|
|
87
|
+
/** Classes for the drag handle, merged last. */
|
|
88
|
+
handleClassName?: string;
|
|
89
|
+
/** Classes for the index dot, merged last. */
|
|
90
|
+
indexClassName?: string;
|
|
91
|
+
/** Bottom strip (e.g. an inline error). */
|
|
92
|
+
alert?: ReactNode;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* The frame every stage card shares: ONE root div (ref + rest props land on
|
|
96
|
+
* it, so Radix `asChild` triggers and IntersectionObserver refs work), the
|
|
97
|
+
* consumer's body full-bleed inside, and absolutely-positioned slots over it.
|
|
98
|
+
* Stateless; hover is CSS-only via the `group/card` name.
|
|
99
|
+
*/
|
|
100
|
+
declare const StageCardShell: react.ForwardRefExoticComponent<StageCardShellProps & react.RefAttributes<HTMLDivElement>>;
|
|
101
|
+
|
|
102
|
+
interface StageConnectorProps extends HTMLAttributes<HTMLElement> {
|
|
103
|
+
/** `inline` sits between cards; `append` is the tall end-of-rail target. */
|
|
104
|
+
variant?: "inline" | "append";
|
|
105
|
+
/** Without it (or when `disabled`) the inline `+` is not rendered and the append button is disabled. */
|
|
106
|
+
onInsert?: () => void;
|
|
107
|
+
disabled?: boolean;
|
|
108
|
+
/** Highlight as the live drop target (shows the inline `+` without hover). */
|
|
109
|
+
dropActive?: boolean;
|
|
110
|
+
/** Accessible name of the insert control. */
|
|
111
|
+
insertLabel?: string;
|
|
112
|
+
/** Inline: text / controls under the link (e.g. "2 days", an inline input). */
|
|
113
|
+
label?: ReactNode;
|
|
114
|
+
/** Inline: chip above the link (e.g. "38 waiting"). */
|
|
115
|
+
badge?: ReactNode;
|
|
116
|
+
/** Inline: 0–1 volume, scales the link's thickness (1px → 6px). */
|
|
117
|
+
weight?: number;
|
|
118
|
+
/** Append: the card height to match. Width is max(80, height * 0.45). */
|
|
119
|
+
height?: number;
|
|
120
|
+
/** Append: visible caption. */
|
|
121
|
+
appendText?: ReactNode;
|
|
122
|
+
/** Inline: show the `+` without hover on touch (hover:none) devices. */
|
|
123
|
+
touchAlwaysVisible?: boolean;
|
|
124
|
+
/** Inline: classes for the `+` button, merged last (its drop-active state included). */
|
|
125
|
+
insertClassName?: string;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* The link between two stage cards. Rest props (HTML5 onDragOver / onDrop …)
|
|
129
|
+
* land on the hit-area root. Inline with no label/badge/weight it is exactly
|
|
130
|
+
* the 36×36 hit area — zero extra size. Horizontal only.
|
|
131
|
+
*/
|
|
132
|
+
declare function StageConnector({ variant, onInsert, disabled, dropActive, insertLabel, label, badge, weight, height, appendText, touchAlwaysVisible, insertClassName, className, style, onClick, ...rest }: StageConnectorProps): react.JSX.Element;
|
|
133
|
+
|
|
134
|
+
interface StageRailMiniDot {
|
|
135
|
+
/** Names the stage in the accessible summary and the dot's tooltip. */
|
|
136
|
+
label: string;
|
|
137
|
+
key?: string;
|
|
138
|
+
/** Colour per kind, e.g. "bg-primary". */
|
|
139
|
+
className?: string;
|
|
140
|
+
/** Optional tiny icon; the dot grows to fit it. */
|
|
141
|
+
icon?: ReactNode;
|
|
142
|
+
}
|
|
143
|
+
/** Dot-sequence thumbnail of a rail for list rows: one dot per stage. */
|
|
144
|
+
declare function StageRailMini({ dots, className, "aria-label": ariaLabel, }: {
|
|
145
|
+
dots: StageRailMiniDot[];
|
|
146
|
+
className?: string;
|
|
147
|
+
"aria-label"?: string;
|
|
148
|
+
}): react.JSX.Element;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Zoom that fits a rail's content into its scroll viewport, derived from the
|
|
152
|
+
* scroller's REAL rendered extent (ported from the Studio chain, DEV-3681:
|
|
153
|
+
* a closed-form gap model no-opped on overflowing chains).
|
|
154
|
+
*
|
|
155
|
+
* `zoom` is the zoom the extent was rendered AT. Content scales linearly with
|
|
156
|
+
* zoom; the scroller's own horizontal padding (`pad`, StageRail's md+ px-8 =
|
|
157
|
+
* 64) doesn't, so both extents shed it before the ratio. Clamped to
|
|
158
|
+
* [min, max] and rounded to 2dp.
|
|
159
|
+
*
|
|
160
|
+
* Caveat: DOM scrollWidth floor-clamps at clientWidth, so content that already
|
|
161
|
+
* fits measures ratio 1 and this echoes `zoom` — it can only zoom OUT. To fit
|
|
162
|
+
* a fitting rail, jump to `max`, re-measure, and correct down if it overshot.
|
|
163
|
+
*/
|
|
164
|
+
declare function computeFitZoomFromExtent({ zoom, scrollWidth, clientWidth, pad, min, max, }: {
|
|
165
|
+
zoom: number;
|
|
166
|
+
scrollWidth: number;
|
|
167
|
+
clientWidth: number;
|
|
168
|
+
pad?: number;
|
|
169
|
+
min?: number;
|
|
170
|
+
max?: number;
|
|
171
|
+
}): number;
|
|
172
|
+
|
|
173
|
+
export { type StageCardContext, StageCardShell, type StageCardShellProps, StageConnector, type StageConnectorContext, type StageConnectorProps, StageRail, StageRailMini, type StageRailMiniDot, type StageRailProps, computeFitZoomFromExtent, isInteractiveTarget };
|