panelui-web 0.0.0-stage → 0.2.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 +43 -2
- package/dist/components/bar-picker/index.d.ts +61 -0
- package/dist/components/bar-picker/index.js +139 -0
- package/dist/components/card/index.d.ts +107 -0
- package/dist/components/card/index.js +88 -0
- package/dist/components/command-dock/index.d.ts +118 -0
- package/dist/components/command-dock/index.js +239 -0
- package/dist/components/day-grid/index.d.ts +87 -0
- package/dist/components/day-grid/index.js +251 -0
- package/dist/components/feedback/index.d.ts +135 -0
- package/dist/components/feedback/index.js +283 -0
- package/dist/components/flow/flow-paths.d.ts +94 -0
- package/dist/components/flow/flow-paths.js +270 -0
- package/dist/components/flow/index.d.ts +235 -0
- package/dist/components/flow/index.js +597 -0
- package/dist/components/frame/index.d.ts +189 -0
- package/dist/components/frame/index.js +181 -0
- package/dist/components/kpi/index.d.ts +211 -0
- package/dist/components/kpi/index.js +243 -0
- package/dist/components/lane-board/index.d.ts +125 -0
- package/dist/components/lane-board/index.js +691 -0
- package/dist/components/planet/index.d.ts +132 -0
- package/dist/components/planet/index.js +653 -0
- package/dist/components/planet/land.d.ts +8 -0
- package/dist/components/planet/land.js +122 -0
- package/dist/components/range-meter/index.d.ts +70 -0
- package/dist/components/range-meter/index.js +170 -0
- package/dist/components/rolling-number/index.d.ts +46 -0
- package/dist/components/rolling-number/index.js +81 -0
- package/dist/components/sheet/index.d.ts +148 -0
- package/dist/components/sheet/index.js +330 -0
- package/dist/components/tilt-card/index.d.ts +60 -0
- package/dist/components/tilt-card/index.js +114 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +15 -0
- package/dist/lib/cn.d.ts +3 -0
- package/dist/lib/cn.js +6 -0
- package/package.json +72 -4
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Edge geometry for Flow.
|
|
3
|
+
*
|
|
4
|
+
* Everything here is plain arithmetic on plain numbers: where on a node's face
|
|
5
|
+
* an edge attaches, which faces two nodes should use when nobody has said, and
|
|
6
|
+
* the path between two anchors in each of the four routings. It knows nothing
|
|
7
|
+
* about React or the page, which is what lets it be tested by itself.
|
|
8
|
+
*
|
|
9
|
+
* Kept out of `index.tsx` so the component file stays about components. Named
|
|
10
|
+
* `flow-paths` and not `paths`, because a copied component lands beside others
|
|
11
|
+
* and `paths.ts` would be a land grab on a very common name.
|
|
12
|
+
*/
|
|
13
|
+
/** The outward unit normal of a face — which way an edge sets off. */
|
|
14
|
+
export function sideNormal(side) {
|
|
15
|
+
if (side === 'left')
|
|
16
|
+
return { x: -1, y: 0 };
|
|
17
|
+
if (side === 'right')
|
|
18
|
+
return { x: 1, y: 0 };
|
|
19
|
+
if (side === 'top')
|
|
20
|
+
return { x: 0, y: -1 };
|
|
21
|
+
return { x: 0, y: 1 };
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Where on a face an edge attaches. `offset` runs 0–1 along the face, so two
|
|
25
|
+
* handles on the same side can sit apart without either knowing about the other.
|
|
26
|
+
*/
|
|
27
|
+
export function anchorOf(rect, side, offset) {
|
|
28
|
+
if (side === 'top') {
|
|
29
|
+
return { x: rect.x + rect.width * offset, y: rect.y };
|
|
30
|
+
}
|
|
31
|
+
if (side === 'bottom') {
|
|
32
|
+
return { x: rect.x + rect.width * offset, y: rect.y + rect.height };
|
|
33
|
+
}
|
|
34
|
+
if (side === 'left') {
|
|
35
|
+
return { x: rect.x, y: rect.y + rect.height * offset };
|
|
36
|
+
}
|
|
37
|
+
return { x: rect.x + rect.width, y: rect.y + rect.height * offset };
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Pushes an anchor out along its own face's normal.
|
|
41
|
+
*
|
|
42
|
+
* For an end attached to something that draws its own border: landing exactly
|
|
43
|
+
* on the border puts the line under the stroke, where it reads as stopping
|
|
44
|
+
* short rather than as arriving.
|
|
45
|
+
*/
|
|
46
|
+
export function standOff(point, side, by) {
|
|
47
|
+
if (by === 0)
|
|
48
|
+
return point;
|
|
49
|
+
const normal = sideNormal(side);
|
|
50
|
+
return { x: point.x + normal.x * by, y: point.y + normal.y * by };
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The faces two nodes should use when nobody has said. Whichever axis they are
|
|
54
|
+
* further apart on wins, so nodes side by side connect left-to-right and nodes
|
|
55
|
+
* stacked connect top-to-bottom — and the edge changes its mind as they are
|
|
56
|
+
* dragged past each other, which is what makes a hand-arranged graph stay
|
|
57
|
+
* readable without anyone re-specifying anything.
|
|
58
|
+
*/
|
|
59
|
+
export function autoSides(from, to) {
|
|
60
|
+
const dx = to.x + to.width / 2 - (from.x + from.width / 2);
|
|
61
|
+
const dy = to.y + to.height / 2 - (from.y + from.height / 2);
|
|
62
|
+
if (Math.abs(dx) > Math.abs(dy)) {
|
|
63
|
+
return dx >= 0 ? { from: 'right', to: 'left' } : { from: 'left', to: 'right' };
|
|
64
|
+
}
|
|
65
|
+
return dy >= 0 ? { from: 'bottom', to: 'top' } : { from: 'top', to: 'bottom' };
|
|
66
|
+
}
|
|
67
|
+
/** A line, for a graph where the routing is not the point. */
|
|
68
|
+
export function straightPath(from, to) {
|
|
69
|
+
return `M${from.x},${from.y} L${to.x},${to.y}`;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* How far a bezier's control point sits from its anchor.
|
|
73
|
+
*
|
|
74
|
+
* With room between the two faces it is half the gap, which gives the familiar
|
|
75
|
+
* S. When they overlap — the target is *behind* the source — the gap is
|
|
76
|
+
* negative and half of it would fold the curve inside out, so the offset grows
|
|
77
|
+
* with the square root of the overlap instead: enough to bulge the curve clear
|
|
78
|
+
* of the node, never enough to run away as the overlap grows.
|
|
79
|
+
*/
|
|
80
|
+
function controlOffset(distance, curvature) {
|
|
81
|
+
if (distance >= 0)
|
|
82
|
+
return 0.5 * distance;
|
|
83
|
+
return curvature * 25 * Math.sqrt(-distance);
|
|
84
|
+
}
|
|
85
|
+
function controlPoint(point, side, other, curvature) {
|
|
86
|
+
if (side === 'left') {
|
|
87
|
+
return { x: point.x - controlOffset(point.x - other.x, curvature), y: point.y };
|
|
88
|
+
}
|
|
89
|
+
if (side === 'right') {
|
|
90
|
+
return { x: point.x + controlOffset(other.x - point.x, curvature), y: point.y };
|
|
91
|
+
}
|
|
92
|
+
if (side === 'top') {
|
|
93
|
+
return { x: point.x, y: point.y - controlOffset(point.y - other.y, curvature) };
|
|
94
|
+
}
|
|
95
|
+
return { x: point.x, y: point.y + controlOffset(other.y - point.y, curvature) };
|
|
96
|
+
}
|
|
97
|
+
/** A cubic curve leaving and arriving perpendicular to each face. */
|
|
98
|
+
export function bezierPath(from, fromSide, to, toSide, curvature) {
|
|
99
|
+
const c1 = controlPoint(from, fromSide, to, curvature);
|
|
100
|
+
const c2 = controlPoint(to, toSide, from, curvature);
|
|
101
|
+
return `M${from.x},${from.y} C${c1.x},${c1.y} ${c2.x},${c2.y} ${to.x},${to.y}`;
|
|
102
|
+
}
|
|
103
|
+
function distanceBetween(a, b) {
|
|
104
|
+
const dx = b.x - a.x;
|
|
105
|
+
const dy = b.y - a.y;
|
|
106
|
+
return Math.sqrt(dx * dx + dy * dy);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* One corner of a stepped path, rounded.
|
|
110
|
+
*
|
|
111
|
+
* The radius is capped at half of the shorter of the two segments meeting here,
|
|
112
|
+
* so a corner between two short runs tucks in rather than overshooting into the
|
|
113
|
+
* segment beyond it and drawing a path that doubles back.
|
|
114
|
+
*/
|
|
115
|
+
function bend(a, b, c, radius) {
|
|
116
|
+
const size = Math.min(distanceBetween(a, b) / 2, distanceBetween(b, c) / 2, radius);
|
|
117
|
+
// Three collinear points are not a corner.
|
|
118
|
+
if ((a.x === b.x && b.x === c.x) || (a.y === b.y && b.y === c.y)) {
|
|
119
|
+
return `L${b.x},${b.y}`;
|
|
120
|
+
}
|
|
121
|
+
if (a.y === b.y) {
|
|
122
|
+
const xDir = a.x < c.x ? -1 : 1;
|
|
123
|
+
const yDir = a.y < c.y ? 1 : -1;
|
|
124
|
+
return `L${b.x + size * xDir},${b.y}Q${b.x},${b.y} ${b.x},${b.y + size * yDir}`;
|
|
125
|
+
}
|
|
126
|
+
const xDir = a.x < c.x ? 1 : -1;
|
|
127
|
+
const yDir = a.y < c.y ? -1 : 1;
|
|
128
|
+
return `L${b.x},${b.y + size * yDir}Q${b.x},${b.y} ${b.x + size * xDir},${b.y}`;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* An orthogonal route with rounded corners — the one that reads as wiring.
|
|
132
|
+
*
|
|
133
|
+
* Both ends first step `gap` points straight out along their own face, so the
|
|
134
|
+
* edge leaves the node square-on instead of grazing its corner. From there the
|
|
135
|
+
* two are joined by a single dog-leg, split across the axis they are further
|
|
136
|
+
* apart on.
|
|
137
|
+
*
|
|
138
|
+
* `radius` of 0 gives hard corners, which is the stepped variant.
|
|
139
|
+
*/
|
|
140
|
+
export function smoothStepPath(from, fromSide, to, toSide, radius, gap) {
|
|
141
|
+
const fromNormal = sideNormal(fromSide);
|
|
142
|
+
const toNormal = sideNormal(toSide);
|
|
143
|
+
let fromGap = {
|
|
144
|
+
x: from.x + fromNormal.x * gap,
|
|
145
|
+
y: from.y + fromNormal.y * gap,
|
|
146
|
+
};
|
|
147
|
+
let toGap = { x: to.x + toNormal.x * gap, y: to.y + toNormal.y * gap };
|
|
148
|
+
// The axis the two gap points are further apart on is the one the dog-leg
|
|
149
|
+
// travels along.
|
|
150
|
+
const horizontal = Math.abs(toGap.x - fromGap.x) > Math.abs(toGap.y - fromGap.y);
|
|
151
|
+
const facing = (fromNormal.x !== 0 && toNormal.x !== 0 && fromNormal.x !== toNormal.x) ||
|
|
152
|
+
(fromNormal.y !== 0 && toNormal.y !== 0 && fromNormal.y !== toNormal.y);
|
|
153
|
+
let middle;
|
|
154
|
+
if (facing) {
|
|
155
|
+
// Faces pointing at each other: meet in the middle of the run between them.
|
|
156
|
+
const midX = (fromGap.x + toGap.x) / 2;
|
|
157
|
+
const midY = (fromGap.y + toGap.y) / 2;
|
|
158
|
+
middle =
|
|
159
|
+
fromNormal.x !== 0
|
|
160
|
+
? [
|
|
161
|
+
{ x: midX, y: fromGap.y },
|
|
162
|
+
{ x: midX, y: toGap.y },
|
|
163
|
+
]
|
|
164
|
+
: [
|
|
165
|
+
{ x: fromGap.x, y: midY },
|
|
166
|
+
{ x: toGap.x, y: midY },
|
|
167
|
+
];
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
// Faces pointing the same way, or at right angles: one corner is enough.
|
|
171
|
+
// Which of the two possible corners depends on the travelling axis.
|
|
172
|
+
middle = horizontal ? [{ x: toGap.x, y: fromGap.y }] : [{ x: fromGap.x, y: toGap.y }];
|
|
173
|
+
// Two handles on the same face, closer together than the gap: the gap
|
|
174
|
+
// points sit between the anchors and the route folds back over itself.
|
|
175
|
+
// Push them out far enough to clear.
|
|
176
|
+
if (fromSide === toSide) {
|
|
177
|
+
const axis = fromNormal.x !== 0 ? 'x' : 'y';
|
|
178
|
+
const apart = Math.abs(from[axis] - to[axis]);
|
|
179
|
+
if (apart <= gap) {
|
|
180
|
+
const push = Math.min(gap - 1, gap - apart);
|
|
181
|
+
if (axis === 'x') {
|
|
182
|
+
fromGap = { x: fromGap.x + fromNormal.x * push, y: fromGap.y };
|
|
183
|
+
toGap = { x: toGap.x + toNormal.x * push, y: toGap.y };
|
|
184
|
+
middle = [{ x: Math.max(fromGap.x, toGap.x), y: fromGap.y }];
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
fromGap = { x: fromGap.x, y: fromGap.y + fromNormal.y * push };
|
|
188
|
+
toGap = { x: toGap.x, y: toGap.y + toNormal.y * push };
|
|
189
|
+
middle = [{ x: fromGap.x, y: Math.max(fromGap.y, toGap.y) }];
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
const points = [from, fromGap, ...middle, toGap, to];
|
|
195
|
+
// Drop points that repeat the one before them — a duplicate reads as a
|
|
196
|
+
// zero-length segment and makes the bend either side of it collapse.
|
|
197
|
+
const route = [];
|
|
198
|
+
for (let i = 0; i < points.length; i += 1) {
|
|
199
|
+
const point = points[i];
|
|
200
|
+
const previous = route[route.length - 1];
|
|
201
|
+
if (previous && previous.x === point.x && previous.y === point.y)
|
|
202
|
+
continue;
|
|
203
|
+
route.push(point);
|
|
204
|
+
}
|
|
205
|
+
if (route.length < 2)
|
|
206
|
+
return `M${from.x},${from.y}`;
|
|
207
|
+
let d = `M${route[0].x},${route[0].y}`;
|
|
208
|
+
for (let i = 1; i < route.length - 1; i += 1) {
|
|
209
|
+
d +=
|
|
210
|
+
radius > 0
|
|
211
|
+
? bend(route[i - 1], route[i], route[i + 1], radius)
|
|
212
|
+
: `L${route[i].x},${route[i].y}`;
|
|
213
|
+
}
|
|
214
|
+
const last = route[route.length - 1];
|
|
215
|
+
d += `L${last.x},${last.y}`;
|
|
216
|
+
return d;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* The `d` string for an edge between two anchors, in whichever shape was asked
|
|
220
|
+
* for. One entry point, so an edge's path is a single call.
|
|
221
|
+
*/
|
|
222
|
+
export function edgePath(variant, from, fromSide, to, toSide, curvature, radius, gap) {
|
|
223
|
+
if (variant === 'straight')
|
|
224
|
+
return straightPath(from, to);
|
|
225
|
+
if (variant === 'bezier')
|
|
226
|
+
return bezierPath(from, fromSide, to, toSide, curvature);
|
|
227
|
+
return smoothStepPath(from, fromSide, to, toSide, variant === 'step' ? 0 : radius, gap);
|
|
228
|
+
}
|
|
229
|
+
/** Length of an edge's bounding diagonal — enough to size a dash cycle by. */
|
|
230
|
+
export function edgeSpan(from, to) {
|
|
231
|
+
return distanceBetween(from, to);
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* The arrowhead at an edge's target, as its own closed path.
|
|
235
|
+
*
|
|
236
|
+
* SVG has `marker-end` for exactly this, and it is the obvious way to do it.
|
|
237
|
+
* It is not used, because a path carrying a marker reference stops picking up
|
|
238
|
+
* new geometry on re-render — the arrow-bearing edges freeze where they were
|
|
239
|
+
* first drawn while arrow-less ones follow their nodes. Drawing the triangle
|
|
240
|
+
* as an ordinary path costs nine numbers and behaves.
|
|
241
|
+
*
|
|
242
|
+
* `dirX`/`dirY` is the unit direction of travel *into* the target.
|
|
243
|
+
*/
|
|
244
|
+
export function arrowHeadPath(tip, dirX, dirY, size) {
|
|
245
|
+
const length = Math.sqrt(dirX * dirX + dirY * dirY) || 1;
|
|
246
|
+
const ux = dirX / length;
|
|
247
|
+
const uy = dirY / length;
|
|
248
|
+
// The perpendicular, for the two back corners.
|
|
249
|
+
const px = -uy;
|
|
250
|
+
const py = ux;
|
|
251
|
+
const baseX = tip.x - ux * size;
|
|
252
|
+
const baseY = tip.y - uy * size;
|
|
253
|
+
const half = size * 0.45;
|
|
254
|
+
return (`M${tip.x},${tip.y} ` +
|
|
255
|
+
`L${baseX + px * half},${baseY + py * half} ` +
|
|
256
|
+
`L${baseX - px * half},${baseY - py * half} Z`);
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Which way an edge is travelling as it arrives. Every routing but `straight`
|
|
260
|
+
* comes in perpendicular to the target's face, so the face decides it; a
|
|
261
|
+
* straight line comes in along itself.
|
|
262
|
+
*/
|
|
263
|
+
export function arrivalDirection(variant, from, to, toSide) {
|
|
264
|
+
if (variant === 'straight') {
|
|
265
|
+
return { x: to.x - from.x, y: to.y - from.y };
|
|
266
|
+
}
|
|
267
|
+
const normal = sideNormal(toSide);
|
|
268
|
+
// The face points outward; the edge arrives against it.
|
|
269
|
+
return { x: -normal.x, y: -normal.y };
|
|
270
|
+
}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flow — a canvas of nodes joined by edges, that you pan, zoom and rearrange.
|
|
3
|
+
*
|
|
4
|
+
* ```tsx
|
|
5
|
+
* <Flow>
|
|
6
|
+
* <Flow.Background variant="dots" />
|
|
7
|
+
* <Flow.Node id="source" position={{ x: 24, y: 40 }}>…</Flow.Node>
|
|
8
|
+
* <Flow.Node id="build" position={{ x: 24, y: 200 }}>…</Flow.Node>
|
|
9
|
+
* <Flow.Edge from="source" to="build" dashed animated arrow />
|
|
10
|
+
* <Flow.Controls />
|
|
11
|
+
* </Flow>
|
|
12
|
+
* ```
|
|
13
|
+
*
|
|
14
|
+
* ## The same parts as the app
|
|
15
|
+
*
|
|
16
|
+
* The parts and their props are the app library's Flow, so a graph written
|
|
17
|
+
* for one reads the same in the other. What differs is the hand: here the
|
|
18
|
+
* pane is dragged with a mouse, zoomed with a pinch or with Control and the
|
|
19
|
+
* wheel, and every node can be reached and moved from the keyboard.
|
|
20
|
+
*
|
|
21
|
+
* ## Where the positions live
|
|
22
|
+
*
|
|
23
|
+
* A node's `position` is where it starts. From then on the canvas holds it:
|
|
24
|
+
* a drag moves it there, and `onNodeDragEnd` says where it came to rest. Pass
|
|
25
|
+
* a new `position` and the node goes to it, which is how nodes are driven
|
|
26
|
+
* from outside.
|
|
27
|
+
*
|
|
28
|
+
* Edges are drawn from the boxes of the nodes they join, measured off the
|
|
29
|
+
* page. An edge therefore follows a node whatever is inside it, and redraws
|
|
30
|
+
* as either end is dragged.
|
|
31
|
+
*
|
|
32
|
+
* ## Three gestures, one canvas
|
|
33
|
+
*
|
|
34
|
+
* The pane pans, a node drags, and a handle draws a new connection. Each is
|
|
35
|
+
* taken by the innermost thing under the pointer, which is what a hand
|
|
36
|
+
* expects.
|
|
37
|
+
*/
|
|
38
|
+
import { type ComponentProps, type ReactNode } from 'react';
|
|
39
|
+
import { type FlowPoint, type FlowRect, type FlowSide } from './flow-paths.js';
|
|
40
|
+
export type FlowEdgeVariant = 'bezier' | 'smoothstep' | 'step' | 'straight';
|
|
41
|
+
/** Which of the theme's roles an edge is drawn in. */
|
|
42
|
+
export type FlowColor = 'primary' | 'info' | 'success' | 'warning' | 'destructive';
|
|
43
|
+
/** Where the canvas is looking: how far it is panned, and how far zoomed. */
|
|
44
|
+
export interface FlowViewport {
|
|
45
|
+
x: number;
|
|
46
|
+
y: number;
|
|
47
|
+
zoom: number;
|
|
48
|
+
}
|
|
49
|
+
export interface FlowNodePosition {
|
|
50
|
+
x: number;
|
|
51
|
+
y: number;
|
|
52
|
+
}
|
|
53
|
+
/** One end of an edge: a node, and optionally one of its handles by `id`. */
|
|
54
|
+
export interface FlowEndpoint {
|
|
55
|
+
node: string;
|
|
56
|
+
handle?: string;
|
|
57
|
+
}
|
|
58
|
+
export type FlowEndpointReference = string | FlowEndpoint;
|
|
59
|
+
/** What `onConnect` is handed when a connection lands. */
|
|
60
|
+
export interface FlowConnection {
|
|
61
|
+
/** Node the drag started from. */
|
|
62
|
+
source: string;
|
|
63
|
+
/** Handle it started from, when that handle has an `id`. */
|
|
64
|
+
sourceHandle?: string;
|
|
65
|
+
/** Node it was dropped on. */
|
|
66
|
+
target: string;
|
|
67
|
+
/** Handle it was dropped on, when it landed on one with an `id`. */
|
|
68
|
+
targetHandle?: string;
|
|
69
|
+
}
|
|
70
|
+
export interface FlowProps extends Omit<ComponentProps<'div'>, 'children'> {
|
|
71
|
+
/** Where the canvas looks to begin with. */
|
|
72
|
+
defaultViewport?: FlowViewport;
|
|
73
|
+
/** The furthest out it can be zoomed. */
|
|
74
|
+
minZoom?: number;
|
|
75
|
+
/** The furthest in it can be zoomed. */
|
|
76
|
+
maxZoom?: number;
|
|
77
|
+
/** Whether dragging the pane pans it. */
|
|
78
|
+
panOnDrag?: boolean;
|
|
79
|
+
/** Whether a pinch, or Control with the wheel, zooms it. */
|
|
80
|
+
zoomOnPinch?: boolean;
|
|
81
|
+
/** Fits every node into view once they have been measured. */
|
|
82
|
+
fitViewOnMount?: boolean;
|
|
83
|
+
/** The room left round the nodes when fitting them, in pixels. */
|
|
84
|
+
fitViewPadding?: number;
|
|
85
|
+
/** Called as the canvas is panned or zoomed. */
|
|
86
|
+
onViewportChange?: (viewport: FlowViewport) => void;
|
|
87
|
+
/** Called with a node's new position when a drag or a key press has moved it. */
|
|
88
|
+
onNodeDragEnd?: (id: string, position: FlowNodePosition) => void;
|
|
89
|
+
/** Called when a connection drawn from a handle lands on another node. */
|
|
90
|
+
onConnect?: (connection: FlowConnection) => void;
|
|
91
|
+
/** Decides whether a connection may land. Without it, any two different nodes may be joined. */
|
|
92
|
+
isValidConnection?: (connection: FlowConnection) => boolean;
|
|
93
|
+
/** What a screen reader calls the canvas. */
|
|
94
|
+
label?: string;
|
|
95
|
+
children?: ReactNode;
|
|
96
|
+
}
|
|
97
|
+
declare function FlowRoot({ defaultViewport, minZoom, maxZoom, panOnDrag, zoomOnPinch, fitViewOnMount, fitViewPadding, onViewportChange, onNodeDragEnd, onConnect, isValidConnection, label, className, children, onKeyDown, ...props }: FlowProps): import("react").JSX.Element;
|
|
98
|
+
declare namespace FlowRoot {
|
|
99
|
+
var displayName: string;
|
|
100
|
+
}
|
|
101
|
+
export interface FlowBackgroundProps {
|
|
102
|
+
/** Dots, a grid of lines, small crosses, or nothing. */
|
|
103
|
+
variant?: 'dots' | 'lines' | 'cross' | 'none';
|
|
104
|
+
/** The distance from one mark to the next, in pixels at a zoom of 1. */
|
|
105
|
+
gap?: number;
|
|
106
|
+
/** How big a mark is: a dot's radius, a line's thickness, half a cross's arm. */
|
|
107
|
+
size?: number;
|
|
108
|
+
className?: string;
|
|
109
|
+
}
|
|
110
|
+
/** The pattern behind the graph, which moves and scales with it. */
|
|
111
|
+
declare function FlowBackground({ variant, gap, size, className }: FlowBackgroundProps): import("react").ReactPortal | null;
|
|
112
|
+
declare namespace FlowBackground {
|
|
113
|
+
var displayName: string;
|
|
114
|
+
}
|
|
115
|
+
export interface FlowNodeProps extends Omit<ComponentProps<'div'>, 'id'> {
|
|
116
|
+
/** What edges and `onNodeDragEnd` call this node. */
|
|
117
|
+
id: string;
|
|
118
|
+
/** Where its top left corner is, on the graph. */
|
|
119
|
+
position: FlowNodePosition;
|
|
120
|
+
/** Whether it can be dragged and moved with the arrow keys. */
|
|
121
|
+
draggable?: boolean;
|
|
122
|
+
/** Draws it as the one that has been picked. */
|
|
123
|
+
selected?: boolean;
|
|
124
|
+
/** Called when it is pressed without being dragged, or with Enter. */
|
|
125
|
+
onPress?: () => void;
|
|
126
|
+
/** Called when Delete or Backspace is pressed on it. */
|
|
127
|
+
onDelete?: () => void;
|
|
128
|
+
/** How far one arrow key press moves it, in pixels. Shift moves four times as far. */
|
|
129
|
+
moveStep?: number;
|
|
130
|
+
}
|
|
131
|
+
/** A box on the graph. Whatever is inside it is yours. */
|
|
132
|
+
declare function FlowNode({ id, position, draggable, selected, onPress, onDelete, moveStep, className, style, children, ...props }: FlowNodeProps): import("react").JSX.Element;
|
|
133
|
+
declare namespace FlowNode {
|
|
134
|
+
var displayName: string;
|
|
135
|
+
}
|
|
136
|
+
export interface FlowGroupProps extends FlowNodeProps {
|
|
137
|
+
/** Written in the corner of the group. */
|
|
138
|
+
label?: ReactNode;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* A dashed box round a few things that belong together. It is a node like any
|
|
142
|
+
* other: it is dragged as one, and an edge can be joined to it.
|
|
143
|
+
*/
|
|
144
|
+
declare function FlowGroup({ id, position, draggable, selected: _selected, onPress, onDelete, moveStep, label, className, style, children, ...props }: FlowGroupProps): import("react").JSX.Element;
|
|
145
|
+
declare namespace FlowGroup {
|
|
146
|
+
var displayName: string;
|
|
147
|
+
}
|
|
148
|
+
export interface FlowHandleProps extends Omit<ComponentProps<'span'>, 'id'> {
|
|
149
|
+
/** A name for this handle, so an edge can be joined to it and not only to the node. */
|
|
150
|
+
id?: string;
|
|
151
|
+
/** Which face of the node it sits on. */
|
|
152
|
+
position?: FlowSide;
|
|
153
|
+
/** How far along that face, from 0 to 1. */
|
|
154
|
+
offset?: number;
|
|
155
|
+
}
|
|
156
|
+
/** A point on a node's edge that a connection can be drawn from, or dropped on. */
|
|
157
|
+
declare function FlowHandle({ id, position, offset, className, style, ...props }: FlowHandleProps): import("react").JSX.Element;
|
|
158
|
+
declare namespace FlowHandle {
|
|
159
|
+
var displayName: string;
|
|
160
|
+
}
|
|
161
|
+
export interface FlowEdgeProps {
|
|
162
|
+
/** Where it leaves from: a node's `id`, or `{ node, handle }`. */
|
|
163
|
+
from: FlowEndpointReference;
|
|
164
|
+
/** Where it arrives. */
|
|
165
|
+
to: FlowEndpointReference;
|
|
166
|
+
/** A curve, a rounded right-angled route, a square one, or a straight line. */
|
|
167
|
+
variant?: FlowEdgeVariant;
|
|
168
|
+
/** Sets the dashes marching towards the target. */
|
|
169
|
+
animated?: boolean;
|
|
170
|
+
/** Draws it dashed. */
|
|
171
|
+
dashed?: boolean;
|
|
172
|
+
/** One of the theme's roles. Without it the edge is a quiet grey. */
|
|
173
|
+
color?: FlowColor;
|
|
174
|
+
/** How thick the line is, in pixels at a zoom of 1. */
|
|
175
|
+
width?: number;
|
|
176
|
+
/** Draws an arrowhead where it arrives. */
|
|
177
|
+
arrow?: boolean;
|
|
178
|
+
/** The face it leaves from. Worked out from where the two nodes are when left out. */
|
|
179
|
+
fromSide?: FlowSide;
|
|
180
|
+
/** The face it arrives at. */
|
|
181
|
+
toSide?: FlowSide;
|
|
182
|
+
/** How round the corners of a `smoothstep` route are. */
|
|
183
|
+
radius?: number;
|
|
184
|
+
/** How far a routed edge runs straight out of a node before it turns. */
|
|
185
|
+
gap?: number;
|
|
186
|
+
/** How far a `bezier` bulges when its target is behind its source. */
|
|
187
|
+
curvature?: number;
|
|
188
|
+
}
|
|
189
|
+
/** A line from one node to another, which follows them as they move. */
|
|
190
|
+
declare function FlowEdge({ from, to, variant, animated, dashed, color, width, arrow, fromSide, toSide, radius, gap, curvature, }: FlowEdgeProps): import("react").JSX.Element | null;
|
|
191
|
+
declare namespace FlowEdge {
|
|
192
|
+
var displayName: string;
|
|
193
|
+
}
|
|
194
|
+
type FlowCorner = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
|
|
195
|
+
export interface FlowControlsProps extends Omit<ComponentProps<'div'>, 'children'> {
|
|
196
|
+
/** Shows the two zoom buttons. */
|
|
197
|
+
zoom?: boolean;
|
|
198
|
+
/** Shows the button that fits every node into view. */
|
|
199
|
+
fit?: boolean;
|
|
200
|
+
/** Shows the button that locks the canvas against panning, zooming and dragging. */
|
|
201
|
+
lock?: boolean;
|
|
202
|
+
/** How much one press of a zoom button zooms. */
|
|
203
|
+
step?: number;
|
|
204
|
+
/** Which corner of the canvas they sit in. */
|
|
205
|
+
position?: FlowCorner;
|
|
206
|
+
}
|
|
207
|
+
/** Buttons for what a pinch and a drag do, for anyone without either. */
|
|
208
|
+
declare function FlowControls({ zoom, fit, lock, step, position, className, ...props }: FlowControlsProps): import("react").ReactPortal | null;
|
|
209
|
+
declare namespace FlowControls {
|
|
210
|
+
var displayName: string;
|
|
211
|
+
}
|
|
212
|
+
export interface FlowMiniMapProps extends Omit<ComponentProps<'div'>, 'children'> {
|
|
213
|
+
/** How wide the map is, in pixels. */
|
|
214
|
+
width?: number;
|
|
215
|
+
/** How tall the map is, in pixels. */
|
|
216
|
+
height?: number;
|
|
217
|
+
/** Which corner of the canvas it sits in. */
|
|
218
|
+
position?: FlowCorner;
|
|
219
|
+
}
|
|
220
|
+
/** The whole graph, small, with the part in view marked on it. */
|
|
221
|
+
declare function FlowMiniMap({ width, height, position, className, style, ...props }: FlowMiniMapProps): import("react").ReactPortal | null;
|
|
222
|
+
declare namespace FlowMiniMap {
|
|
223
|
+
var displayName: string;
|
|
224
|
+
}
|
|
225
|
+
export declare const Flow: typeof FlowRoot & {
|
|
226
|
+
Background: typeof FlowBackground;
|
|
227
|
+
Node: typeof FlowNode;
|
|
228
|
+
Handle: typeof FlowHandle;
|
|
229
|
+
Edge: typeof FlowEdge;
|
|
230
|
+
Group: typeof FlowGroup;
|
|
231
|
+
Controls: typeof FlowControls;
|
|
232
|
+
MiniMap: typeof FlowMiniMap;
|
|
233
|
+
};
|
|
234
|
+
export { FlowBackground, FlowNode, FlowHandle, FlowEdge, FlowGroup, FlowControls, FlowMiniMap };
|
|
235
|
+
export type { FlowSide, FlowRect, FlowPoint };
|