@luciole-sh/flow-graph 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +671 -2
- package/dist/Flow.d.ts +41 -0
- package/dist/Flow.d.ts.map +1 -0
- package/dist/Flow.js +489 -0
- package/dist/Flow.js.map +1 -0
- package/dist/components.d.ts +28 -0
- package/dist/components.d.ts.map +1 -0
- package/dist/components.js +100 -0
- package/dist/components.js.map +1 -0
- package/dist/frame.d.ts +68 -0
- package/dist/frame.d.ts.map +1 -0
- package/dist/frame.js +136 -0
- package/dist/frame.js.map +1 -0
- package/dist/geometry.d.ts +60 -0
- package/dist/geometry.d.ts.map +1 -0
- package/dist/geometry.js +205 -0
- package/dist/geometry.js.map +1 -0
- package/dist/hooks.d.ts +56 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +65 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/keymap.d.ts +11 -0
- package/dist/keymap.d.ts.map +1 -0
- package/dist/keymap.js +42 -0
- package/dist/keymap.js.map +1 -0
- package/dist/navigation.d.ts +32 -0
- package/dist/navigation.d.ts.map +1 -0
- package/dist/navigation.js +68 -0
- package/dist/navigation.js.map +1 -0
- package/dist/nodes.d.ts +18 -0
- package/dist/nodes.d.ts.map +1 -0
- package/dist/nodes.js +46 -0
- package/dist/nodes.js.map +1 -0
- package/dist/raster.d.ts +112 -0
- package/dist/raster.d.ts.map +1 -0
- package/dist/raster.js +370 -0
- package/dist/raster.js.map +1 -0
- package/dist/store.d.ts +104 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +186 -0
- package/dist/store.js.map +1 -0
- package/dist/theme.d.ts +25 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +39 -0
- package/dist/theme.js.map +1 -0
- package/dist/types.d.ts +140 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/vendor/xyflow/LICENSE +21 -0
- package/dist/vendor/xyflow/bezier.d.ts +26 -0
- package/dist/vendor/xyflow/bezier.d.ts.map +1 -0
- package/dist/vendor/xyflow/bezier.js +47 -0
- package/dist/vendor/xyflow/bezier.js.map +1 -0
- package/dist/vendor/xyflow/changes.d.ts +9 -0
- package/dist/vendor/xyflow/changes.d.ts.map +1 -0
- package/dist/vendor/xyflow/changes.js +133 -0
- package/dist/vendor/xyflow/changes.js.map +1 -0
- package/dist/vendor/xyflow/smoothstep.d.ts +17 -0
- package/dist/vendor/xyflow/smoothstep.d.ts.map +1 -0
- package/dist/vendor/xyflow/smoothstep.js +166 -0
- package/dist/vendor/xyflow/smoothstep.js.map +1 -0
- package/package.json +61 -4
- package/src/Flow.tsx +684 -0
- package/src/components.tsx +180 -0
- package/src/frame.ts +203 -0
- package/src/geometry.ts +274 -0
- package/src/hooks.tsx +121 -0
- package/src/index.ts +21 -0
- package/src/keymap.tsx +45 -0
- package/src/navigation.ts +86 -0
- package/src/nodes.tsx +86 -0
- package/src/raster.ts +453 -0
- package/src/store.ts +240 -0
- package/src/theme.ts +61 -0
- package/src/types.ts +130 -0
- package/src/vendor/xyflow/LICENSE +21 -0
- package/src/vendor/xyflow/README.md +20 -0
- package/src/vendor/xyflow/bezier.ts +102 -0
- package/src/vendor/xyflow/changes.ts +177 -0
- package/src/vendor/xyflow/smoothstep.ts +219 -0
- package/tsconfig.json +22 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "@opentui/react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef } from "react";
|
|
3
|
+
import { RGBA } from "@opentui/core";
|
|
4
|
+
import { absolutePositions, flowBounds, toFlow } from "./geometry.js";
|
|
5
|
+
import { useStore, useStoreVersion } from "./hooks.js";
|
|
6
|
+
import { drawMiniMap, Grid } from "./raster.js";
|
|
7
|
+
import { roleColor, useFlowTheme } from "./theme.js";
|
|
8
|
+
const PANEL_Z = 100_000;
|
|
9
|
+
const DEFAULT_GAP = { x: 8, y: 4 };
|
|
10
|
+
const MINIMAP_WIDTH = 24;
|
|
11
|
+
const MINIMAP_HEIGHT = 8;
|
|
12
|
+
/** Marks every `gap` flow cells, under the edges: dots, grid lines, or crosses. */
|
|
13
|
+
export function Background({ variant = "dots", gap = DEFAULT_GAP, color, }) {
|
|
14
|
+
const store = useStore();
|
|
15
|
+
const { x, y } = gap;
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
store.setBackground({ variant, gap: { x, y }, color });
|
|
18
|
+
return () => store.setBackground(null);
|
|
19
|
+
}, [store, variant, x, y, color]);
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
/** Content over the canvas, in a corner or centered on an edge. */
|
|
23
|
+
export function Panel({ position = "top-left", children, }) {
|
|
24
|
+
const [vertical, horizontal] = position.split("-");
|
|
25
|
+
const place = {
|
|
26
|
+
...(vertical === "top" ? { top: 0 } : { bottom: 0 }),
|
|
27
|
+
...(horizontal === "left"
|
|
28
|
+
? { left: 0 }
|
|
29
|
+
: horizontal === "right"
|
|
30
|
+
? { right: 0 }
|
|
31
|
+
: { left: 0, right: 0, alignItems: "center" }),
|
|
32
|
+
};
|
|
33
|
+
// A click on a panel is its own: it neither selects nor pans the canvas.
|
|
34
|
+
return (_jsx("box", { position: "absolute", zIndex: PANEL_Z, flexDirection: "column", ...place, onMouseDown: (event) => event.stopPropagation(), children: children }));
|
|
35
|
+
}
|
|
36
|
+
/** Zoom in, zoom out, fit, and the current level. */
|
|
37
|
+
export function Controls({ position = "bottom-left" }) {
|
|
38
|
+
const store = useStoreVersion();
|
|
39
|
+
const theme = useFlowTheme();
|
|
40
|
+
const button = (label, action) => (_jsx("text", { selectable: false, fg: theme.text, bg: theme.labelBg, onMouseDown: (event) => {
|
|
41
|
+
event.stopPropagation();
|
|
42
|
+
action();
|
|
43
|
+
}, children: ` ${label} ` }));
|
|
44
|
+
return (_jsx(Panel, { position: position, children: _jsxs("box", { flexDirection: "row", gap: 1, backgroundColor: theme.panelBg, children: [button("+", () => store.zoom(1)), button("-", () => store.zoom(-1)), button("fit", () => store.fitView()), _jsx("text", { selectable: false, fg: theme.muted, children: store.detail })] }) }));
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Every node in braille, and the part in view outlined. A click moves the view there.
|
|
48
|
+
*/
|
|
49
|
+
export function MiniMap({ position = "bottom-right", width = MINIMAP_WIDTH, height = MINIMAP_HEIGHT, }) {
|
|
50
|
+
const store = useStoreVersion();
|
|
51
|
+
const theme = useFlowTheme();
|
|
52
|
+
const box = useRef(null);
|
|
53
|
+
const grid = new Grid(width, height);
|
|
54
|
+
const view = (() => {
|
|
55
|
+
const topLeft = toFlow({ x: 0, y: 0 }, store.viewport);
|
|
56
|
+
return {
|
|
57
|
+
...topLeft,
|
|
58
|
+
width: store.size.width / store.viewport.zoom,
|
|
59
|
+
height: store.size.height / store.viewport.zoom,
|
|
60
|
+
};
|
|
61
|
+
})();
|
|
62
|
+
const nodes = flowBounds(store.nodes, store.full) ?? view;
|
|
63
|
+
// The world: every node and the view.
|
|
64
|
+
const x0 = Math.min(nodes.x, view.x);
|
|
65
|
+
const y0 = Math.min(nodes.y, view.y);
|
|
66
|
+
const world = {
|
|
67
|
+
x: x0,
|
|
68
|
+
y: y0,
|
|
69
|
+
width: Math.max(nodes.x + nodes.width, view.x + view.width) - x0,
|
|
70
|
+
height: Math.max(nodes.y + nodes.height, view.y + view.height) - y0,
|
|
71
|
+
};
|
|
72
|
+
const positions = absolutePositions(store.nodes);
|
|
73
|
+
const rects = store.nodes
|
|
74
|
+
.filter((n) => !n.hidden && n.type !== "group")
|
|
75
|
+
.map((n) => {
|
|
76
|
+
const position = positions.get(n.id) ?? n.position;
|
|
77
|
+
const one = flowBounds([{ ...n, parentId: undefined, position }], store.full);
|
|
78
|
+
const role = n.selected ? "selected" : "edge";
|
|
79
|
+
return {
|
|
80
|
+
rect: one ?? { x: 0, y: 0, width: 0, height: 0 },
|
|
81
|
+
role,
|
|
82
|
+
color: n.selected ? undefined : n.color,
|
|
83
|
+
};
|
|
84
|
+
});
|
|
85
|
+
const toWorld = drawMiniMap(grid, world, rects, view);
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
box.current?.requestRender();
|
|
88
|
+
});
|
|
89
|
+
return (_jsx(Panel, { position: position, children: _jsx("box", { ref: box, width: width, height: height, backgroundColor: theme.panelBg, onMouseDown: (event) => {
|
|
90
|
+
event.stopPropagation();
|
|
91
|
+
const at = box.current;
|
|
92
|
+
if (!at)
|
|
93
|
+
return;
|
|
94
|
+
store.setCenter(toWorld({ x: event.x - at.x, y: event.y - at.y }));
|
|
95
|
+
}, renderAfter: function (buffer) {
|
|
96
|
+
for (const [x, y, cell] of grid.entries())
|
|
97
|
+
buffer.setCellWithAlphaBlending(this.x + x, this.y + y, cell.char, RGBA.fromHex(cell.color ?? roleColor(theme, cell.role)), RGBA.fromHex(theme.panelBg));
|
|
98
|
+
} }) }));
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=components.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"components.js","sourceRoot":"","sources":["../src/components.tsx"],"names":[],"mappings":"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"}
|
package/dist/frame.d.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One frame of the canvas under its nodes: edges, labels, markers, handles, the
|
|
3
|
+
* connection being made and the background, composed into a grid. And the reverse: what
|
|
4
|
+
* is at a canvas cell. Pure, so that a frame can be printed and compared in tests.
|
|
5
|
+
*/
|
|
6
|
+
import { type Anchor, type Measured, type Placed, type Size } from "./geometry.ts";
|
|
7
|
+
import { Grid, type BackgroundVariant, type EdgeStyle } from "./raster.ts";
|
|
8
|
+
import type { Edge, HandleSpec, Node, Position, Viewport, XY } from "./types.ts";
|
|
9
|
+
/**
|
|
10
|
+
* A custom edge type: the corner points of its path from the source anchor cell to the
|
|
11
|
+
* target's, drawn with box characters like a step edge.
|
|
12
|
+
*/
|
|
13
|
+
export type EdgeRoute = (params: {
|
|
14
|
+
edge: Edge;
|
|
15
|
+
source: XY;
|
|
16
|
+
sourcePosition: Position;
|
|
17
|
+
target: XY;
|
|
18
|
+
targetPosition: Position;
|
|
19
|
+
}) => XY[];
|
|
20
|
+
/** An edge type: a built-in style, or a route. */
|
|
21
|
+
export type EdgeType = EdgeStyle | EdgeRoute;
|
|
22
|
+
export declare const CONNECTION_ID = "__connection";
|
|
23
|
+
export type FrameInput = {
|
|
24
|
+
size: Size;
|
|
25
|
+
viewport: Viewport;
|
|
26
|
+
nodes: readonly Node[];
|
|
27
|
+
edges: readonly Edge[];
|
|
28
|
+
measured: ReadonlyMap<string, Measured>;
|
|
29
|
+
handles?: ReadonlyMap<string, ReadonlyMap<string, HandleSpec>>;
|
|
30
|
+
background?: {
|
|
31
|
+
variant: BackgroundVariant;
|
|
32
|
+
gap: XY;
|
|
33
|
+
} | null;
|
|
34
|
+
connecting?: {
|
|
35
|
+
source: Anchor;
|
|
36
|
+
pointer?: XY;
|
|
37
|
+
target?: string;
|
|
38
|
+
} | null;
|
|
39
|
+
edgeTypes?: Readonly<Record<string, EdgeType>>;
|
|
40
|
+
defaultEdgeType?: string;
|
|
41
|
+
/** Curves and slanted lines in braille; without, they are drawn as smoothstep edges. */
|
|
42
|
+
braille?: boolean;
|
|
43
|
+
/** Animation step: advances the dashes of animated edges. */
|
|
44
|
+
phase?: number;
|
|
45
|
+
};
|
|
46
|
+
export type Frame = {
|
|
47
|
+
grid: Grid;
|
|
48
|
+
placed: Placed[];
|
|
49
|
+
anchors: Map<string, Anchor[]>;
|
|
50
|
+
};
|
|
51
|
+
export declare function composeFrame(input: FrameInput): Frame;
|
|
52
|
+
export type Hit = {
|
|
53
|
+
kind: "handle";
|
|
54
|
+
anchor: Anchor;
|
|
55
|
+
} | {
|
|
56
|
+
kind: "node";
|
|
57
|
+
node: Node;
|
|
58
|
+
} | {
|
|
59
|
+
kind: "edge";
|
|
60
|
+
id: string;
|
|
61
|
+
} | {
|
|
62
|
+
kind: "pane";
|
|
63
|
+
};
|
|
64
|
+
/** What is at canvas cell `at`: a source handle, a node (topmost first), an edge, or none. */
|
|
65
|
+
export declare function hitTest(frame: Frame, at: XY): Hit;
|
|
66
|
+
/** Where a connection dropped at `at` ends: a target handle, or a node's first target. */
|
|
67
|
+
export declare function dropTarget(frame: Frame, at: XY, source: Anchor): Anchor | undefined;
|
|
68
|
+
//# sourceMappingURL=frame.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame.d.ts","sourceRoot":"","sources":["../src/frame.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAML,KAAK,MAAM,EACX,KAAK,QAAQ,EACb,KAAK,MAAM,EACX,KAAK,IAAI,EACV,MAAM,eAAe,CAAC;AACvB,OAAO,EAIL,IAAI,EACJ,KAAK,iBAAiB,EAEtB,KAAK,SAAS,EACf,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,YAAY,CAAC;AAEjF;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,MAAM,EAAE;IAC/B,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,EAAE,CAAC;IACX,cAAc,EAAE,QAAQ,CAAC;IACzB,MAAM,EAAE,EAAE,CAAC;IACX,cAAc,EAAE,QAAQ,CAAC;CAC1B,KAAK,EAAE,EAAE,CAAC;AACX,kDAAkD;AAClD,MAAM,MAAM,QAAQ,GAAG,SAAS,GAAG,SAAS,CAAC;AAG7C,eAAO,MAAM,aAAa,iBAAiB,CAAC;AAI5C,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,IAAI,CAAC;IACX,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,SAAS,IAAI,EAAE,CAAC;IACvB,KAAK,EAAE,SAAS,IAAI,EAAE,CAAC;IACvB,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACxC,OAAO,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAC/D,UAAU,CAAC,EAAE;QAAE,OAAO,EAAE,iBAAiB,CAAC;QAAC,GAAG,EAAE,EAAE,CAAA;KAAE,GAAG,IAAI,CAAC;IAC5D,UAAU,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,EAAE,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACtE,SAAS,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,wFAAwF;IACxF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG;IAClB,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CAChC,CAAC;AAEF,wBAAgB,YAAY,CAAC,KAAK,EAAE,UAAU,GAAG,KAAK,CA+DrD;AA6BD,MAAM,MAAM,GAAG,GACX;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,IAAI,CAAA;CAAE,GAC5B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC5B;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAErB,8FAA8F;AAC9F,wBAAgB,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,GAAG,GAAG,CAcjD;AAED,0FAA0F;AAC1F,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAiBnF"}
|
package/dist/frame.js
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One frame of the canvas under its nodes: edges, labels, markers, handles, the
|
|
3
|
+
* connection being made and the background, composed into a grid. And the reverse: what
|
|
4
|
+
* is at a canvas cell. Pure, so that a frame can be printed and compared in tests.
|
|
5
|
+
*/
|
|
6
|
+
import { anchorsOf, contains, detailFor, pickAnchor, placeNodes, } from "./geometry.js";
|
|
7
|
+
import { drawBackground, drawEdge, drawLabel, Grid, } from "./raster.js";
|
|
8
|
+
const BUILTIN_STYLES = new Set(["smoothstep", "step", "straight", "bezier"]);
|
|
9
|
+
export const CONNECTION_ID = "__connection";
|
|
10
|
+
const SOURCE_HANDLE = "●";
|
|
11
|
+
const TARGET_HANDLE = "○";
|
|
12
|
+
export function composeFrame(input) {
|
|
13
|
+
const detail = detailFor(input.viewport.zoom);
|
|
14
|
+
const placed = placeNodes(input.nodes, input.viewport, input.measured);
|
|
15
|
+
const anchors = new Map(placed.map((p) => [
|
|
16
|
+
p.node.id,
|
|
17
|
+
anchorsOf(p, [...(input.handles?.get(p.node.id)?.values() ?? [])], detail),
|
|
18
|
+
]));
|
|
19
|
+
const grid = new Grid(input.size.width, input.size.height);
|
|
20
|
+
const labels = [];
|
|
21
|
+
// Selected edges last: their color wins where lines share a cell.
|
|
22
|
+
const rank = (e) => (e.selected ? 2 : e.animated ? 1 : 0);
|
|
23
|
+
const edges = [...input.edges].filter((e) => !e.hidden).sort((a, b) => rank(a) - rank(b));
|
|
24
|
+
for (const edge of edges) {
|
|
25
|
+
const source = pickAnchor(anchors.get(edge.source) ?? [], "source", edge.sourceHandle);
|
|
26
|
+
const target = pickAnchor(anchors.get(edge.target) ?? [], "target", edge.targetHandle);
|
|
27
|
+
if (!source || !target)
|
|
28
|
+
continue;
|
|
29
|
+
const draw = edgeDraw(edge, source, target, input);
|
|
30
|
+
const at = drawEdge(grid, draw);
|
|
31
|
+
if (edge.label)
|
|
32
|
+
labels.push({ at, text: edge.label, owner: edge.id });
|
|
33
|
+
}
|
|
34
|
+
const connecting = input.connecting;
|
|
35
|
+
if (connecting) {
|
|
36
|
+
const target = connecting.target
|
|
37
|
+
? pickAnchor(anchors.get(connecting.target) ?? [], "target", null)
|
|
38
|
+
: undefined;
|
|
39
|
+
const pointer = connecting.pointer;
|
|
40
|
+
const end = target?.cell ?? pointer;
|
|
41
|
+
if (end) {
|
|
42
|
+
const targetPosition = target?.position ?? (end.x >= connecting.source.cell.x ? "left" : "right");
|
|
43
|
+
drawEdge(grid, {
|
|
44
|
+
id: CONNECTION_ID,
|
|
45
|
+
style: "smoothstep",
|
|
46
|
+
source: connecting.source.cell,
|
|
47
|
+
sourcePosition: connecting.source.position,
|
|
48
|
+
target: end,
|
|
49
|
+
targetPosition,
|
|
50
|
+
role: "handle",
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
// Where it can end: every other node's targets.
|
|
54
|
+
for (const [id, list] of anchors)
|
|
55
|
+
if (id !== connecting.source.nodeId)
|
|
56
|
+
for (const a of list)
|
|
57
|
+
if (a.type === "target" && !(target && a === target))
|
|
58
|
+
grid.set(a.cell.x, a.cell.y, { char: TARGET_HANDLE, role: "handle" });
|
|
59
|
+
}
|
|
60
|
+
// The selected nodes' sources: where a connection starts with the mouse.
|
|
61
|
+
for (const p of placed)
|
|
62
|
+
if (p.node.selected && p.node.connectable !== false)
|
|
63
|
+
for (const a of anchors.get(p.node.id) ?? [])
|
|
64
|
+
if (a.type === "source" && !grid.get(a.cell.x, a.cell.y))
|
|
65
|
+
grid.set(a.cell.x, a.cell.y, { char: SOURCE_HANDLE, role: "handle" });
|
|
66
|
+
for (const label of labels)
|
|
67
|
+
drawLabel(grid, label.at, label.text, label.owner);
|
|
68
|
+
grid.resolve(input.phase ?? 0);
|
|
69
|
+
if (input.background)
|
|
70
|
+
drawBackground(grid, input.viewport, input.background.variant, input.background.gap);
|
|
71
|
+
return { grid, placed, anchors };
|
|
72
|
+
}
|
|
73
|
+
function edgeDraw(edge, source, target, input) {
|
|
74
|
+
const name = edge.type ?? input.defaultEdgeType ?? "smoothstep";
|
|
75
|
+
const type = input.edgeTypes?.[name] ?? (BUILTIN_STYLES.has(name) ? name : "smoothstep");
|
|
76
|
+
const base = {
|
|
77
|
+
id: edge.id,
|
|
78
|
+
source: source.cell,
|
|
79
|
+
sourcePosition: source.position,
|
|
80
|
+
target: target.cell,
|
|
81
|
+
targetPosition: target.position,
|
|
82
|
+
label: edge.label,
|
|
83
|
+
animated: edge.animated,
|
|
84
|
+
selected: edge.selected,
|
|
85
|
+
markerEnd: edge.markerEnd !== "none",
|
|
86
|
+
markerStart: edge.markerStart === "arrow",
|
|
87
|
+
color: edge.color,
|
|
88
|
+
};
|
|
89
|
+
if (typeof type === "function")
|
|
90
|
+
return { ...base, style: "step", points: type({ edge, ...base }) };
|
|
91
|
+
const style = type === "smoothstep" || type === "step" || type === "straight" || type === "bezier"
|
|
92
|
+
? type
|
|
93
|
+
: "smoothstep";
|
|
94
|
+
// Without braille, curves fall back to the orthogonal path.
|
|
95
|
+
const curved = style === "bezier" || style === "straight";
|
|
96
|
+
return { ...base, style: curved && input.braille === false ? "smoothstep" : style };
|
|
97
|
+
}
|
|
98
|
+
/** What is at canvas cell `at`: a source handle, a node (topmost first), an edge, or none. */
|
|
99
|
+
export function hitTest(frame, at) {
|
|
100
|
+
for (const list of frame.anchors.values())
|
|
101
|
+
for (const anchor of list)
|
|
102
|
+
if (anchor.type === "source" && anchor.cell.x === at.x && anchor.cell.y === at.y) {
|
|
103
|
+
const node = frame.placed.find((p) => p.node.id === anchor.nodeId)?.node;
|
|
104
|
+
if (node?.connectable !== false)
|
|
105
|
+
return { kind: "handle", anchor };
|
|
106
|
+
}
|
|
107
|
+
for (let i = frame.placed.length - 1; i >= 0; i--) {
|
|
108
|
+
const p = frame.placed[i];
|
|
109
|
+
if (p && contains(p.rect, at))
|
|
110
|
+
return { kind: "node", node: p.node };
|
|
111
|
+
}
|
|
112
|
+
const owner = frame.grid.get(at.x, at.y)?.owner;
|
|
113
|
+
if (owner && owner !== CONNECTION_ID)
|
|
114
|
+
return { kind: "edge", id: owner };
|
|
115
|
+
return { kind: "pane" };
|
|
116
|
+
}
|
|
117
|
+
/** Where a connection dropped at `at` ends: a target handle, or a node's first target. */
|
|
118
|
+
export function dropTarget(frame, at, source) {
|
|
119
|
+
for (const list of frame.anchors.values())
|
|
120
|
+
for (const anchor of list)
|
|
121
|
+
if (anchor.type === "target" &&
|
|
122
|
+
anchor.nodeId !== source.nodeId &&
|
|
123
|
+
anchor.cell.x === at.x &&
|
|
124
|
+
anchor.cell.y === at.y)
|
|
125
|
+
return anchor;
|
|
126
|
+
for (let i = frame.placed.length - 1; i >= 0; i--) {
|
|
127
|
+
const p = frame.placed[i];
|
|
128
|
+
if (!p || p.node.id === source.nodeId || !contains(p.rect, at))
|
|
129
|
+
continue;
|
|
130
|
+
if (p.node.type === "group")
|
|
131
|
+
continue;
|
|
132
|
+
return pickAnchor(frame.anchors.get(p.node.id) ?? [], "target", null);
|
|
133
|
+
}
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=frame.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frame.js","sourceRoot":"","sources":["../src/frame.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where things are on the canvas: flow coordinates (cells at zoom 1) to canvas cells,
|
|
3
|
+
* semantic zoom, node rectangles, handle anchors, fitting the view. Pure functions.
|
|
4
|
+
*/
|
|
5
|
+
import type { Detail, HandleSpec, HandleType, Node, Position, Rect, Viewport, XY } from "./types.ts";
|
|
6
|
+
export declare const ZOOMS: readonly [1, 0.5, 0.25];
|
|
7
|
+
export declare function detailFor(zoom: number): Detail;
|
|
8
|
+
/** The next zoom level in (`+1`) or out (`-1`), or the same one at either end. */
|
|
9
|
+
export declare function stepZoom(zoom: number, direction: 1 | -1): number;
|
|
10
|
+
/** Zooms to `zoom` keeping the flow point under canvas cell `anchor` where it is. */
|
|
11
|
+
export declare function zoomAround(viewport: Viewport, zoom: number, anchor: XY): Viewport;
|
|
12
|
+
export declare const toCanvas: (point: XY, viewport: Viewport) => XY;
|
|
13
|
+
export declare const toFlow: (point: XY, viewport: Viewport) => XY;
|
|
14
|
+
export declare const labelOf: (node: Node) => string;
|
|
15
|
+
/** Where each node is in flow coordinates, its parents' positions added. */
|
|
16
|
+
export declare function absolutePositions(nodes: readonly Node[]): Map<string, XY>;
|
|
17
|
+
export type Size = {
|
|
18
|
+
width: number;
|
|
19
|
+
height: number;
|
|
20
|
+
};
|
|
21
|
+
/** A rendered size and the detail it was rendered at. */
|
|
22
|
+
export type Measured = Size & {
|
|
23
|
+
detail: Detail;
|
|
24
|
+
};
|
|
25
|
+
/** The size a node takes at `detail` before it is measured. */
|
|
26
|
+
export declare function estimateSize(node: Node, detail: Detail, zoom?: number): Size;
|
|
27
|
+
export type Placed = {
|
|
28
|
+
node: Node;
|
|
29
|
+
/** In canvas cells. */
|
|
30
|
+
rect: Rect;
|
|
31
|
+
/** Drawing order: groups under their children, the selection over the rest. */
|
|
32
|
+
z: number;
|
|
33
|
+
};
|
|
34
|
+
/** Each visible node's rectangle on the canvas, in drawing order. */
|
|
35
|
+
export declare function placeNodes(nodes: readonly Node[], viewport: Viewport, measured: ReadonlyMap<string, Measured>): Placed[];
|
|
36
|
+
/** The flow-coordinate bounds of `nodes` at full detail, or null when there are none. */
|
|
37
|
+
export declare function flowBounds(nodes: readonly Node[], measured: ReadonlyMap<string, Measured>): Rect | null;
|
|
38
|
+
/** The closest zoom level at which `bounds` fits `canvas`, centered. */
|
|
39
|
+
export declare function fitViewport(bounds: Rect | null, canvas: Size, padding?: number): Viewport;
|
|
40
|
+
/** The smallest pan that brings `rect` (canvas cells) into `canvas`, `margin` cells in. */
|
|
41
|
+
export declare function panToShow(viewport: Viewport, rect: Rect, canvas: Size, margin?: number): Viewport;
|
|
42
|
+
export declare const contains: (rect: Rect, point: XY) => boolean;
|
|
43
|
+
export type Anchor = {
|
|
44
|
+
nodeId: string;
|
|
45
|
+
handle: string | null;
|
|
46
|
+
type: HandleType;
|
|
47
|
+
position: Position;
|
|
48
|
+
/** The cell just outside the node's border, where the edge starts or ends. */
|
|
49
|
+
cell: XY;
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Each handle's anchor cell: `handles` as the node declared them, or one source and one
|
|
53
|
+
* target on the node's `sourcePosition`/`targetPosition`. Handles sharing a side are
|
|
54
|
+
* spread along it.
|
|
55
|
+
*/
|
|
56
|
+
export declare function anchorsOf(placed: Placed, handles: readonly HandleSpec[] | undefined, detail: Detail): Anchor[];
|
|
57
|
+
/** The anchor an edge uses at one end: its named handle, else the first of that type. */
|
|
58
|
+
export declare function pickAnchor(anchors: readonly Anchor[], type: HandleType, handle: string | null | undefined): Anchor | undefined;
|
|
59
|
+
export declare const opposite: Record<Position, Position>;
|
|
60
|
+
//# sourceMappingURL=geometry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geometry.d.ts","sourceRoot":"","sources":["../src/geometry.ts"],"names":[],"mappings":"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"}
|
package/dist/geometry.js
ADDED
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/** The zoom levels, from closest to farthest. Each draws nodes with less detail. */
|
|
2
|
+
const HALF = 0.5;
|
|
3
|
+
const QUARTER = 0.25;
|
|
4
|
+
export const ZOOMS = [1, HALF, QUARTER];
|
|
5
|
+
const DETAILS = ["full", "compact", "dot"];
|
|
6
|
+
const FIT_PADDING = 2;
|
|
7
|
+
/** A node that was never measured: its label in a bordered box. */
|
|
8
|
+
const BORDER_AND_PADDING = 4;
|
|
9
|
+
const DEFAULT_HEIGHT = 3;
|
|
10
|
+
const MIN_LABEL = 4;
|
|
11
|
+
export function detailFor(zoom) {
|
|
12
|
+
const index = ZOOMS.findIndex((z) => zoom >= z);
|
|
13
|
+
return DETAILS[index < 0 ? DETAILS.length - 1 : index] ?? "dot";
|
|
14
|
+
}
|
|
15
|
+
/** The next zoom level in (`+1`) or out (`-1`), or the same one at either end. */
|
|
16
|
+
export function stepZoom(zoom, direction) {
|
|
17
|
+
const index = ZOOMS.findIndex((z) => zoom >= z);
|
|
18
|
+
const current = index < 0 ? ZOOMS.length - 1 : index;
|
|
19
|
+
const next = Math.min(ZOOMS.length - 1, Math.max(0, current - direction));
|
|
20
|
+
return ZOOMS[next] ?? zoom;
|
|
21
|
+
}
|
|
22
|
+
/** Zooms to `zoom` keeping the flow point under canvas cell `anchor` where it is. */
|
|
23
|
+
export function zoomAround(viewport, zoom, anchor) {
|
|
24
|
+
const flow = toFlow(anchor, viewport);
|
|
25
|
+
return {
|
|
26
|
+
x: Math.round(anchor.x - flow.x * zoom),
|
|
27
|
+
y: Math.round(anchor.y - flow.y * zoom),
|
|
28
|
+
zoom,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export const toCanvas = (point, viewport) => ({
|
|
32
|
+
x: Math.round(point.x * viewport.zoom + viewport.x),
|
|
33
|
+
y: Math.round(point.y * viewport.zoom + viewport.y),
|
|
34
|
+
});
|
|
35
|
+
export const toFlow = (point, viewport) => ({
|
|
36
|
+
x: (point.x - viewport.x) / viewport.zoom,
|
|
37
|
+
y: (point.y - viewport.y) / viewport.zoom,
|
|
38
|
+
});
|
|
39
|
+
export const labelOf = (node) => typeof node.data.label === "string" ? node.data.label : node.id;
|
|
40
|
+
/** Where each node is in flow coordinates, its parents' positions added. */
|
|
41
|
+
export function absolutePositions(nodes) {
|
|
42
|
+
const byId = new Map(nodes.map((node) => [node.id, node]));
|
|
43
|
+
const positions = new Map();
|
|
44
|
+
const resolve = (node, seen) => {
|
|
45
|
+
const known = positions.get(node.id);
|
|
46
|
+
if (known)
|
|
47
|
+
return known;
|
|
48
|
+
const parent = node.parentId ? byId.get(node.parentId) : undefined;
|
|
49
|
+
// A cycle of parents is ignored rather than followed.
|
|
50
|
+
const origin = parent && !seen.has(parent.id) ? resolve(parent, new Set(seen).add(node.id)) : { x: 0, y: 0 };
|
|
51
|
+
const position = { x: origin.x + node.position.x, y: origin.y + node.position.y };
|
|
52
|
+
positions.set(node.id, position);
|
|
53
|
+
return position;
|
|
54
|
+
};
|
|
55
|
+
for (const node of nodes)
|
|
56
|
+
resolve(node, new Set([node.id]));
|
|
57
|
+
return positions;
|
|
58
|
+
}
|
|
59
|
+
/** The size a node takes at `detail` before it is measured. */
|
|
60
|
+
export function estimateSize(node, detail, zoom = 1) {
|
|
61
|
+
if (node.type === "group" || (node.width !== undefined && node.height !== undefined)) {
|
|
62
|
+
const width = node.width ?? MIN_LABEL;
|
|
63
|
+
const height = node.height ?? DEFAULT_HEIGHT;
|
|
64
|
+
return detail === "full"
|
|
65
|
+
? { width, height }
|
|
66
|
+
: {
|
|
67
|
+
width: Math.max(2, Math.round(width * zoom)),
|
|
68
|
+
height: Math.max(1, Math.round(height * zoom)),
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
const label = Math.max(MIN_LABEL, labelOf(node).length);
|
|
72
|
+
if (detail === "dot")
|
|
73
|
+
return { width: 1, height: 1 };
|
|
74
|
+
if (detail === "compact")
|
|
75
|
+
return { width: label + 2, height: 1 };
|
|
76
|
+
return { width: label + BORDER_AND_PADDING, height: DEFAULT_HEIGHT };
|
|
77
|
+
}
|
|
78
|
+
const GROUP_Z = -1;
|
|
79
|
+
const SELECTED_Z = 1000;
|
|
80
|
+
/** Each visible node's rectangle on the canvas, in drawing order. */
|
|
81
|
+
export function placeNodes(nodes, viewport, measured) {
|
|
82
|
+
const detail = detailFor(viewport.zoom);
|
|
83
|
+
const positions = absolutePositions(nodes);
|
|
84
|
+
const placed = [];
|
|
85
|
+
for (const node of nodes) {
|
|
86
|
+
if (node.hidden)
|
|
87
|
+
continue;
|
|
88
|
+
const at = toCanvas(positions.get(node.id) ?? node.position, viewport);
|
|
89
|
+
const size = measured.get(node.id);
|
|
90
|
+
const { width, height } = size && size.detail === detail ? size : estimateSize(node, detail, viewport.zoom);
|
|
91
|
+
const z = (node.zIndex ?? 0) + (node.type === "group" ? GROUP_Z : 0) + (node.selected ? SELECTED_Z : 0);
|
|
92
|
+
placed.push({ node, rect: { x: at.x, y: at.y, width, height }, z });
|
|
93
|
+
}
|
|
94
|
+
// Stable: equal z keeps the application's order.
|
|
95
|
+
return placed.sort((a, b) => a.z - b.z);
|
|
96
|
+
}
|
|
97
|
+
/** The flow-coordinate bounds of `nodes` at full detail, or null when there are none. */
|
|
98
|
+
export function flowBounds(nodes, measured) {
|
|
99
|
+
const positions = absolutePositions(nodes);
|
|
100
|
+
let bounds = null;
|
|
101
|
+
for (const node of nodes) {
|
|
102
|
+
if (node.hidden)
|
|
103
|
+
continue;
|
|
104
|
+
const at = positions.get(node.id) ?? node.position;
|
|
105
|
+
const size = measured.get(node.id);
|
|
106
|
+
const { width, height } = size?.detail === "full" ? size : estimateSize(node, "full");
|
|
107
|
+
const box = { x0: at.x, y0: at.y, x1: at.x + width, y1: at.y + height };
|
|
108
|
+
bounds = bounds
|
|
109
|
+
? {
|
|
110
|
+
x0: Math.min(bounds.x0, box.x0),
|
|
111
|
+
y0: Math.min(bounds.y0, box.y0),
|
|
112
|
+
x1: Math.max(bounds.x1, box.x1),
|
|
113
|
+
y1: Math.max(bounds.y1, box.y1),
|
|
114
|
+
}
|
|
115
|
+
: box;
|
|
116
|
+
}
|
|
117
|
+
return (bounds && {
|
|
118
|
+
x: bounds.x0,
|
|
119
|
+
y: bounds.y0,
|
|
120
|
+
width: bounds.x1 - bounds.x0,
|
|
121
|
+
height: bounds.y1 - bounds.y0,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
/** The closest zoom level at which `bounds` fits `canvas`, centered. */
|
|
125
|
+
export function fitViewport(bounds, canvas, padding = FIT_PADDING) {
|
|
126
|
+
if (!bounds)
|
|
127
|
+
return { x: padding, y: padding, zoom: 1 };
|
|
128
|
+
const zoom = ZOOMS.find((z) => bounds.width * z <= canvas.width - padding * 2 &&
|
|
129
|
+
bounds.height * z <= canvas.height - padding * 2) ?? ZOOMS[ZOOMS.length - 1];
|
|
130
|
+
const z = zoom ?? 1;
|
|
131
|
+
return {
|
|
132
|
+
x: Math.round((canvas.width - bounds.width * z) / 2 - bounds.x * z),
|
|
133
|
+
y: Math.round((canvas.height - bounds.height * z) / 2 - bounds.y * z),
|
|
134
|
+
zoom: z,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
/** The smallest pan that brings `rect` (canvas cells) into `canvas`, `margin` cells in. */
|
|
138
|
+
export function panToShow(viewport, rect, canvas, margin = 1) {
|
|
139
|
+
const shift = (start, length, size) => {
|
|
140
|
+
if (length + margin * 2 > size)
|
|
141
|
+
return -start + margin;
|
|
142
|
+
if (start < margin)
|
|
143
|
+
return margin - start;
|
|
144
|
+
if (start + length > size - margin)
|
|
145
|
+
return size - margin - (start + length);
|
|
146
|
+
return 0;
|
|
147
|
+
};
|
|
148
|
+
const dx = shift(rect.x, rect.width, canvas.width);
|
|
149
|
+
const dy = shift(rect.y, rect.height, canvas.height);
|
|
150
|
+
return dx === 0 && dy === 0 ? viewport : { ...viewport, x: viewport.x + dx, y: viewport.y + dy };
|
|
151
|
+
}
|
|
152
|
+
export const contains = (rect, point) => point.x >= rect.x &&
|
|
153
|
+
point.x < rect.x + rect.width &&
|
|
154
|
+
point.y >= rect.y &&
|
|
155
|
+
point.y < rect.y + rect.height;
|
|
156
|
+
/**
|
|
157
|
+
* Each handle's anchor cell: `handles` as the node declared them, or one source and one
|
|
158
|
+
* target on the node's `sourcePosition`/`targetPosition`. Handles sharing a side are
|
|
159
|
+
* spread along it.
|
|
160
|
+
*/
|
|
161
|
+
export function anchorsOf(placed, handles, detail) {
|
|
162
|
+
const { node, rect } = placed;
|
|
163
|
+
const specs = handles && handles.length > 0
|
|
164
|
+
? handles
|
|
165
|
+
: [
|
|
166
|
+
...(node.type === "input" || node.type === "group"
|
|
167
|
+
? []
|
|
168
|
+
: [{ id: null, type: "target", position: node.targetPosition ?? "left" }]),
|
|
169
|
+
...(node.type === "output" || node.type === "group"
|
|
170
|
+
? []
|
|
171
|
+
: [{ id: null, type: "source", position: node.sourcePosition ?? "right" }]),
|
|
172
|
+
];
|
|
173
|
+
// At `dot` the node is one cell: every handle is on it, whatever its side.
|
|
174
|
+
const bySide = new Map();
|
|
175
|
+
for (const spec of specs)
|
|
176
|
+
bySide.set(spec.position, [...(bySide.get(spec.position) ?? []), spec]);
|
|
177
|
+
const anchors = [];
|
|
178
|
+
for (const [position, list] of bySide)
|
|
179
|
+
list.forEach((spec, index) => {
|
|
180
|
+
const along = (length) => detail === "dot" ? 0 : Math.floor(((index + 1) * length) / (list.length + 1) - 1 / 2);
|
|
181
|
+
const midX = rect.x + Math.max(0, Math.min(rect.width - 1, along(rect.width)));
|
|
182
|
+
const midY = rect.y + Math.max(0, Math.min(rect.height - 1, along(rect.height)));
|
|
183
|
+
const cell = position === "left"
|
|
184
|
+
? { x: rect.x - 1, y: midY }
|
|
185
|
+
: position === "right"
|
|
186
|
+
? { x: rect.x + rect.width, y: midY }
|
|
187
|
+
: position === "top"
|
|
188
|
+
? { x: midX, y: rect.y - 1 }
|
|
189
|
+
: { x: midX, y: rect.y + rect.height };
|
|
190
|
+
anchors.push({ nodeId: node.id, handle: spec.id, type: spec.type, position, cell });
|
|
191
|
+
});
|
|
192
|
+
return anchors;
|
|
193
|
+
}
|
|
194
|
+
/** The anchor an edge uses at one end: its named handle, else the first of that type. */
|
|
195
|
+
export function pickAnchor(anchors, type, handle) {
|
|
196
|
+
const ofType = anchors.filter((a) => a.type === type);
|
|
197
|
+
return (handle ? ofType.find((a) => a.handle === handle) : undefined) ?? ofType[0];
|
|
198
|
+
}
|
|
199
|
+
export const opposite = {
|
|
200
|
+
left: "right",
|
|
201
|
+
right: "left",
|
|
202
|
+
top: "bottom",
|
|
203
|
+
bottom: "top",
|
|
204
|
+
};
|
|
205
|
+
//# sourceMappingURL=geometry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geometry.js","sourceRoot":"","sources":["../src/geometry.ts"],"names":[],"mappings":"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"}
|