@draftably/runtime 0.2.0 → 0.3.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 +13 -0
- package/dist/assets/render.worker-dvseyGmC.js +8310 -0
- package/dist/compile-Csfz4rk4.js +7267 -0
- package/dist/{font-data-tnqJ-kTK.js → font-data-DLXJur0j.js} +1 -1
- package/dist/graph.js +669 -0
- package/dist/index.js +5 -4
- package/dist/render-Dgo42PR4.js +1146 -0
- package/dist/types/src/dsl/compile.d.ts +13 -0
- package/dist/types/src/dsl/corridors.d.ts +38 -0
- package/dist/types/src/graph-api/core.d.ts +125 -0
- package/dist/types/src/graph-api/cytoscape.d.ts +48 -0
- package/dist/types/src/graph-api/dagre.d.ts +33 -0
- package/dist/types/src/graph-api/elk.d.ts +91 -0
- package/dist/types/src/graph-api/index.d.ts +60 -0
- package/dist/types/src/graph-api/react-flow.d.ts +100 -0
- package/dist/types/src/graph-api/transform.d.ts +6 -0
- package/dist/types/src/model/types.d.ts +9 -0
- package/dist/viewer.js +31 -29
- package/package.json +5 -1
- package/dist/assets/render.worker-fWW85Tf9.js +0 -7661
- package/dist/render-ZzhO-2H6.js +0 -7676
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type ResolvedAppearance } from '../model/appearance.js';
|
|
2
2
|
import type { CellsChrome, Lane, SequenceLayout } from '../model/types.js';
|
|
3
|
+
import { type Planned } from './corridors.js';
|
|
3
4
|
import { GROUP_HEADER, GROUP_INSET, contentOrigin } from './frame.js';
|
|
4
5
|
import { type Model, type ModelEdge, type ModelLayout, type ModelObject } from './syntax.js';
|
|
5
6
|
/** The single render context. Browser window size changes the camera, never the layout. */
|
|
@@ -44,6 +45,8 @@ export interface Diagnostic {
|
|
|
44
45
|
/** A connection as the file declares it, plus the lane a fold's wrap edge returns along. */
|
|
45
46
|
export interface SceneEdge extends ModelEdge {
|
|
46
47
|
lane?: Lane;
|
|
48
|
+
/** A forward line's route, planned from its scope's ranks and corridors (`planRoutes`). */
|
|
49
|
+
plan?: Planned;
|
|
47
50
|
/** A sequence message: the height of its row; it is drawn straight between lifelines there. */
|
|
48
51
|
row?: number;
|
|
49
52
|
}
|
|
@@ -149,6 +152,16 @@ export declare function crossings(paths: Array<Array<{
|
|
|
149
152
|
}>>): number;
|
|
150
153
|
/** The order of up to six items that scores fewest crossings; the first such, from `items`. */
|
|
151
154
|
export declare function fewestCrossings<T>(items: T[], score: (order: T[]) => number): T[];
|
|
155
|
+
/**
|
|
156
|
+
* The corridors a `flow` scope keeps for lines that skip ranks: the ranks with their stand-ins,
|
|
157
|
+
* each line's stand-ins by its index in the scope's pairs, and each stand-in's place across the
|
|
158
|
+
* run, in the scope's coordinates.
|
|
159
|
+
*/
|
|
160
|
+
export interface Corridors {
|
|
161
|
+
order: string[][];
|
|
162
|
+
chains: Map<number, string[]>;
|
|
163
|
+
across: Map<string, number>;
|
|
164
|
+
}
|
|
152
165
|
/**
|
|
153
166
|
* Lay out a model. `arranged` holds world positions from layout engines; scopes that an engine
|
|
154
167
|
* governs take their children's relative placement from it instead of their built-in recipe.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Routes for a `flow` scope's forward lines, planned from its ranks as a layered layout routes its
|
|
3
|
+
* edges: out of the source's trailing side, along a track in each gap the line turns in, down a
|
|
4
|
+
* corridor through each rank it skips, and into the target's leading side. The ranks' order already
|
|
5
|
+
* keeps crossings few, so the plan only has to place ports and order each gap's tracks. The router
|
|
6
|
+
* takes a planned route as it is when it clears every box.
|
|
7
|
+
*/
|
|
8
|
+
import type { Point, Rect } from '../model/types.js';
|
|
9
|
+
export interface PlanLine {
|
|
10
|
+
id: string;
|
|
11
|
+
/** Source, the stand-ins of the ranks it skips, target. */
|
|
12
|
+
chain: string[];
|
|
13
|
+
}
|
|
14
|
+
export interface Planned {
|
|
15
|
+
points: Point[];
|
|
16
|
+
fromOffset: number;
|
|
17
|
+
toOffset: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Space between ports on one side and between neighbouring tracks in a gap, as the router keeps
|
|
21
|
+
* them: ports `max(portGap, edgeGap)` apart and tracks `edgeGap` apart.
|
|
22
|
+
*/
|
|
23
|
+
export interface Spacing {
|
|
24
|
+
port: number;
|
|
25
|
+
track: number;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Plans each line of `lines`. `order` is the ranks with stand-ins, `box` each real member's drawn
|
|
29
|
+
* box and `across` each stand-in's place across the run, all in drawing coordinates. Lines that
|
|
30
|
+
* cannot be planned (a member without a box) are left out.
|
|
31
|
+
*/
|
|
32
|
+
export declare function planRoutes(axis: 'down' | 'right', order: string[][], lines: PlanLine[], box: (id: string) => Rect | undefined, across: (id: string) => number | undefined, spacing?: Spacing): Map<string, Planned>;
|
|
33
|
+
/**
|
|
34
|
+
* The room each gap between ranks needs for the tracks `planRoutes` lays in it: a standoff from
|
|
35
|
+
* the boxes either side and a pitch between tracks, by gap index; a gap with no track is absent.
|
|
36
|
+
* `box` may be a member's slot: only its place across the run counts.
|
|
37
|
+
*/
|
|
38
|
+
export declare function trackRoom(axis: 'down' | 'right', order: string[][], lines: PlanLine[], box: (id: string) => Rect | undefined, across: (id: string) => number | undefined, spacing?: Spacing): number[];
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import type { Point, RoutingSettings, Side } from '../model/types.js';
|
|
2
|
+
export type Shape = 'box' | 'pill' | 'circle' | 'diamond' | 'text';
|
|
3
|
+
/** How a scope arranges its children: a recipe, or a layout engine as `engine:<name>`. */
|
|
4
|
+
export type Arrange = 'flow' | 'row' | 'column' | 'lanes' | 'sequence' | `engine:${string}`;
|
|
5
|
+
/**
|
|
6
|
+
* How hard the router works. `full` repairs crossings and evens out lanes; `quick` routes each
|
|
7
|
+
* line once. `auto` (the default) routes quickly first, and fully when that will stay fast.
|
|
8
|
+
*/
|
|
9
|
+
export type Quality = 'auto' | 'full' | 'quick';
|
|
10
|
+
export interface RoutingOptions extends Partial<RoutingSettings> {
|
|
11
|
+
quality?: Quality;
|
|
12
|
+
}
|
|
13
|
+
export interface NodeIn {
|
|
14
|
+
id: string;
|
|
15
|
+
label?: string;
|
|
16
|
+
parent?: string;
|
|
17
|
+
shape?: Shape;
|
|
18
|
+
/** Fixed size, kept within 40–1200 by 24–1200. Without one, the box fits its label. */
|
|
19
|
+
width?: number;
|
|
20
|
+
height?: number;
|
|
21
|
+
}
|
|
22
|
+
export interface GroupIn {
|
|
23
|
+
id: string;
|
|
24
|
+
label?: string;
|
|
25
|
+
parent?: string;
|
|
26
|
+
/** How the group arranges its own children; `column` by default. */
|
|
27
|
+
arrange?: Arrange;
|
|
28
|
+
direction?: 'right' | 'down';
|
|
29
|
+
gap?: number;
|
|
30
|
+
}
|
|
31
|
+
export interface EdgeIn {
|
|
32
|
+
/** Unique among edges. Without one, the edge is `e1`, `e2`, … by position. */
|
|
33
|
+
id?: string;
|
|
34
|
+
source: string;
|
|
35
|
+
target: string;
|
|
36
|
+
label?: string;
|
|
37
|
+
dashed?: boolean;
|
|
38
|
+
sourceSide?: Side;
|
|
39
|
+
targetSide?: Side;
|
|
40
|
+
}
|
|
41
|
+
export interface GraphIn {
|
|
42
|
+
nodes: NodeIn[];
|
|
43
|
+
groups?: GroupIn[];
|
|
44
|
+
edges?: EdgeIn[];
|
|
45
|
+
/** How the top level is arranged; `flow` by default. */
|
|
46
|
+
arrange?: Arrange;
|
|
47
|
+
direction?: 'right' | 'down';
|
|
48
|
+
gap?: number;
|
|
49
|
+
fit?: 'wide' | 'slide' | 'square' | 'page' | 'tall';
|
|
50
|
+
/**
|
|
51
|
+
* `auto` (the default) folds a long `flow` into rows, like lines of text, when it is much
|
|
52
|
+
* wider than a 1100×720 page; `never` keeps one row.
|
|
53
|
+
*/
|
|
54
|
+
fold?: 'auto' | 'never';
|
|
55
|
+
routing?: RoutingOptions;
|
|
56
|
+
}
|
|
57
|
+
export interface Box {
|
|
58
|
+
x: number;
|
|
59
|
+
y: number;
|
|
60
|
+
width: number;
|
|
61
|
+
height: number;
|
|
62
|
+
}
|
|
63
|
+
export interface PlacedBox extends Box {
|
|
64
|
+
parent?: string;
|
|
65
|
+
}
|
|
66
|
+
export interface EdgeOut {
|
|
67
|
+
source: string;
|
|
68
|
+
target: string;
|
|
69
|
+
sourceSide: Side;
|
|
70
|
+
targetSide: Side;
|
|
71
|
+
/** From the source's outline to the target's. The host draws the arrowhead at the last point. */
|
|
72
|
+
points: Point[];
|
|
73
|
+
/** SVG path data with the rounded corners draftably draws. */
|
|
74
|
+
path: string;
|
|
75
|
+
/** The label's box. Draw a backing behind it: other lines may pass under it. */
|
|
76
|
+
label: Box | null;
|
|
77
|
+
/** True when the router found no clear way and drew a fallback line. */
|
|
78
|
+
blocked: boolean;
|
|
79
|
+
}
|
|
80
|
+
export interface Routed {
|
|
81
|
+
edges: Record<string, EdgeOut>;
|
|
82
|
+
/** The router mode that drew the lines. */
|
|
83
|
+
quality: 'full' | 'quick';
|
|
84
|
+
warnings: string[];
|
|
85
|
+
}
|
|
86
|
+
export interface LayoutResult extends Routed {
|
|
87
|
+
nodes: Record<string, PlacedBox>;
|
|
88
|
+
groups: Record<string, PlacedBox>;
|
|
89
|
+
/** Everything drawn: boxes, lines and labels. */
|
|
90
|
+
bounds: Box;
|
|
91
|
+
/** The `.draft` file this graph is. Open it in the viewer, or pass it to `renderSvg`. */
|
|
92
|
+
draft: string;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* `auto` routes fully when the quick routes predict a full pass within the budget. The full
|
|
96
|
+
* pass reroutes each line with a crossing or crowded lane against all the others, so its cost
|
|
97
|
+
* grows with lines times conflicts; this limit keeps it near the 1 s load budget.
|
|
98
|
+
*/
|
|
99
|
+
export declare const AUTO_FULL_LIMIT = 1200;
|
|
100
|
+
/** Place and route a graph the way a `.draft` file with the same content draws. */
|
|
101
|
+
export declare function layout(graph: GraphIn): Promise<LayoutResult>;
|
|
102
|
+
/**
|
|
103
|
+
* `layout` without a promise, for callers that cannot wait, such as a stand-in for a synchronous
|
|
104
|
+
* library. It cannot run a layout engine (`engine:` arrangements) or `fit`, which need `layout`.
|
|
105
|
+
*/
|
|
106
|
+
export declare function layoutSync(graph: GraphIn): LayoutResult;
|
|
107
|
+
export interface PlacedNodeIn extends Box {
|
|
108
|
+
id: string;
|
|
109
|
+
parent?: string;
|
|
110
|
+
shape?: Shape;
|
|
111
|
+
}
|
|
112
|
+
export interface PlacedGroupIn extends Box {
|
|
113
|
+
id: string;
|
|
114
|
+
parent?: string;
|
|
115
|
+
/** The title, so lines keep out of its band at the top of the group. */
|
|
116
|
+
label?: string;
|
|
117
|
+
}
|
|
118
|
+
export interface RouteIn {
|
|
119
|
+
nodes: PlacedNodeIn[];
|
|
120
|
+
groups?: PlacedGroupIn[];
|
|
121
|
+
edges: EdgeIn[];
|
|
122
|
+
routing?: RoutingOptions;
|
|
123
|
+
}
|
|
124
|
+
/** Route lines between boxes the caller placed. Nothing moves. */
|
|
125
|
+
export declare function route(graph: RouteIn): Routed;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A Cytoscape.js layout: `cytoscape.use(draftablyLayout)`, then
|
|
3
|
+
* `cy.layout({ name: 'draftably' }).run()`. It places nodes with draftably's layout. Cytoscape
|
|
4
|
+
* draws edges itself; the routed lines are on `layout.result` for an app that draws its own.
|
|
5
|
+
*/
|
|
6
|
+
import { type RoutingOptions } from './core.js';
|
|
7
|
+
/** The parts of a Cytoscape collection element this layout reads. */
|
|
8
|
+
interface CyElement {
|
|
9
|
+
id(): string;
|
|
10
|
+
data(key: string): unknown;
|
|
11
|
+
isParent(): boolean;
|
|
12
|
+
parent(): {
|
|
13
|
+
length: number;
|
|
14
|
+
id(): string;
|
|
15
|
+
};
|
|
16
|
+
isNode(): boolean;
|
|
17
|
+
outerWidth(): number;
|
|
18
|
+
outerHeight(): number;
|
|
19
|
+
source(): {
|
|
20
|
+
id(): string;
|
|
21
|
+
};
|
|
22
|
+
target(): {
|
|
23
|
+
id(): string;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
interface CyCollection {
|
|
27
|
+
nodes(): CyElement[] & {
|
|
28
|
+
layoutPositions(layout: unknown, options: object, at: (n: CyElement) => {
|
|
29
|
+
x: number;
|
|
30
|
+
y: number;
|
|
31
|
+
}): void;
|
|
32
|
+
};
|
|
33
|
+
edges(): CyElement[];
|
|
34
|
+
}
|
|
35
|
+
export interface CytoscapeLayoutOptions {
|
|
36
|
+
name: 'draftably';
|
|
37
|
+
eles: CyCollection;
|
|
38
|
+
cy: unknown;
|
|
39
|
+
direction?: 'right' | 'down';
|
|
40
|
+
gap?: number;
|
|
41
|
+
routing?: RoutingOptions;
|
|
42
|
+
fit?: boolean;
|
|
43
|
+
padding?: number;
|
|
44
|
+
animate?: boolean;
|
|
45
|
+
}
|
|
46
|
+
/** The Cytoscape extension: pass it to `cytoscape.use`. */
|
|
47
|
+
export declare function draftablyLayout(cytoscape: (type: 'layout', name: string, impl: unknown) => void): void;
|
|
48
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A stand-in for `dagre.layout(g)`: it reads a graphlib graph and writes the results back into
|
|
3
|
+
* it the way dagre does, so code that reads `g.node(v).x` or `g.edge(e).points` keeps working.
|
|
4
|
+
* Node `x` and `y` are centres; edge `points` run from outline to outline; the graph gets `width`
|
|
5
|
+
* and `height`. Clusters (compound parents) are groups and get a box too.
|
|
6
|
+
*/
|
|
7
|
+
import { type LayoutResult, type RoutingOptions } from './core.js';
|
|
8
|
+
type Label = {
|
|
9
|
+
[key: string]: unknown;
|
|
10
|
+
};
|
|
11
|
+
/** The graphlib `Graph` methods this reads, from `@dagrejs/graphlib` or `dagre.graphlib`. */
|
|
12
|
+
export interface DagreGraph {
|
|
13
|
+
nodes(): string[];
|
|
14
|
+
node(v: string): Label | undefined;
|
|
15
|
+
edges(): Array<{
|
|
16
|
+
v: string;
|
|
17
|
+
w: string;
|
|
18
|
+
name?: string;
|
|
19
|
+
}>;
|
|
20
|
+
edge(e: {
|
|
21
|
+
v: string;
|
|
22
|
+
w: string;
|
|
23
|
+
name?: string;
|
|
24
|
+
}): Label | undefined;
|
|
25
|
+
graph(): Label | undefined;
|
|
26
|
+
parent?(v: string): string | undefined | void;
|
|
27
|
+
children?(v?: string): string[] | undefined;
|
|
28
|
+
}
|
|
29
|
+
/** Lay out a graphlib graph in place, as `dagre.layout(g)` does. Returns the full result too. */
|
|
30
|
+
export declare function dagreLayout(g: DagreGraph, options?: {
|
|
31
|
+
routing?: RoutingOptions;
|
|
32
|
+
}): LayoutResult;
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ELK JSON in, ELK JSON out, so `new DraftablyELK().layout(graph)` can stand in for
|
|
3
|
+
* `new ELK().layout(graph)` from elkjs. A node with children is a group. Coordinates come back as
|
|
4
|
+
* elkjs gives them: a node's x and y relative to its parent; an edge's sections and labels relative
|
|
5
|
+
* to its `container`, the nearest node that holds both of its ends, which is set on each edge.
|
|
6
|
+
*/
|
|
7
|
+
import { type GraphIn, type LayoutResult } from './core.js';
|
|
8
|
+
export interface ElkLabel {
|
|
9
|
+
id?: string;
|
|
10
|
+
text?: string;
|
|
11
|
+
x?: number;
|
|
12
|
+
y?: number;
|
|
13
|
+
width?: number;
|
|
14
|
+
height?: number;
|
|
15
|
+
}
|
|
16
|
+
export interface ElkPort {
|
|
17
|
+
id: string;
|
|
18
|
+
x?: number;
|
|
19
|
+
y?: number;
|
|
20
|
+
width?: number;
|
|
21
|
+
height?: number;
|
|
22
|
+
layoutOptions?: Record<string, string>;
|
|
23
|
+
}
|
|
24
|
+
export interface ElkPoint {
|
|
25
|
+
x: number;
|
|
26
|
+
y: number;
|
|
27
|
+
}
|
|
28
|
+
export interface ElkEdgeSection {
|
|
29
|
+
id: string;
|
|
30
|
+
startPoint: ElkPoint;
|
|
31
|
+
endPoint: ElkPoint;
|
|
32
|
+
bendPoints?: ElkPoint[];
|
|
33
|
+
incomingShape?: string;
|
|
34
|
+
outgoingShape?: string;
|
|
35
|
+
}
|
|
36
|
+
export interface ElkEdge {
|
|
37
|
+
id: string;
|
|
38
|
+
sources: string[];
|
|
39
|
+
targets: string[];
|
|
40
|
+
labels?: ElkLabel[];
|
|
41
|
+
sections?: ElkEdgeSection[];
|
|
42
|
+
container?: string;
|
|
43
|
+
layoutOptions?: Record<string, string>;
|
|
44
|
+
}
|
|
45
|
+
export interface ElkNode {
|
|
46
|
+
id: string;
|
|
47
|
+
x?: number;
|
|
48
|
+
y?: number;
|
|
49
|
+
width?: number;
|
|
50
|
+
height?: number;
|
|
51
|
+
children?: ElkNode[];
|
|
52
|
+
ports?: ElkPort[];
|
|
53
|
+
edges?: ElkEdge[];
|
|
54
|
+
labels?: ElkLabel[];
|
|
55
|
+
layoutOptions?: Record<string, string>;
|
|
56
|
+
}
|
|
57
|
+
export interface ElkInput {
|
|
58
|
+
graph: GraphIn;
|
|
59
|
+
warnings: string[];
|
|
60
|
+
/** For each ELK edge, the IDs of its pieces: one per source and target pair. */
|
|
61
|
+
pieces: Map<string, string[]>;
|
|
62
|
+
/** Whether the drawing is mirrored afterwards, for `LEFT` and `UP`. */
|
|
63
|
+
mirror?: 'x' | 'y';
|
|
64
|
+
}
|
|
65
|
+
export declare function fromElk(root: ElkNode, extra?: Record<string, string>): ElkInput;
|
|
66
|
+
export declare function toElk(root: ElkNode, out: LayoutResult, { pieces }: ElkInput): ElkNode;
|
|
67
|
+
/** Lay out an ELK graph with draftably and return it as elkjs would. */
|
|
68
|
+
export declare function layoutElk(root: ElkNode, extra?: Record<string, string>, common?: Partial<GraphIn>): Promise<{
|
|
69
|
+
elk: ElkNode;
|
|
70
|
+
result: LayoutResult;
|
|
71
|
+
}>;
|
|
72
|
+
/**
|
|
73
|
+
* A stand-in for elkjs's `ELK` class: the same `layout(graph, { layoutOptions })` call, with
|
|
74
|
+
* draftably's layout and router. Options draftably does not use are listed in `warnings`.
|
|
75
|
+
*/
|
|
76
|
+
export declare class DraftablyELK {
|
|
77
|
+
private options;
|
|
78
|
+
/** Warnings from the last `layout` call, such as ELK options that were not used. */
|
|
79
|
+
warnings: string[];
|
|
80
|
+
constructor(options?: {
|
|
81
|
+
defaultLayoutOptions?: Record<string, string>;
|
|
82
|
+
});
|
|
83
|
+
layout(graph: ElkNode, args?: {
|
|
84
|
+
layoutOptions?: Record<string, string>;
|
|
85
|
+
}): Promise<ElkNode>;
|
|
86
|
+
knownLayoutAlgorithms(): Promise<{
|
|
87
|
+
id: string;
|
|
88
|
+
name: string;
|
|
89
|
+
}[]>;
|
|
90
|
+
terminateWorker(): void;
|
|
91
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Draftably's layout and router for graphs from any tool: `@draftably/runtime/graph`.
|
|
3
|
+
*
|
|
4
|
+
* const placed = await layout({ nodes, edges }); // draftably's own shape
|
|
5
|
+
* const { reactFlow } = await layout({ reactFlow: { nodes, edges } });
|
|
6
|
+
* const lines = route({ nodes: placedBoxes, edges }); // lines only
|
|
7
|
+
*
|
|
8
|
+
* A keyed call returns the same shape it took, under the same key.
|
|
9
|
+
*/
|
|
10
|
+
import { type GraphIn, type LayoutResult, type RouteIn, type Routed, type RoutingOptions } from './core.js';
|
|
11
|
+
import { type FlowEdge, type FlowEdgeOut, type FlowGraph, type FlowNode, type FlowNodeOut, type FlowOptions, type SvelteFlowNodeOut } from './react-flow.js';
|
|
12
|
+
import { type ElkNode } from './elk.js';
|
|
13
|
+
export { AUTO_FULL_LIMIT, layoutSync } from './core.js';
|
|
14
|
+
export { DraftablyELK } from './elk.js';
|
|
15
|
+
export { dagreLayout } from './dagre.js';
|
|
16
|
+
export { draftablyLayout } from './cytoscape.js';
|
|
17
|
+
export type { ElkEdge, ElkEdgeSection, ElkLabel, ElkNode, ElkPort } from './elk.js';
|
|
18
|
+
export type { DagreGraph } from './dagre.js';
|
|
19
|
+
export type { CytoscapeLayoutOptions } from './cytoscape.js';
|
|
20
|
+
export type * from './core.js';
|
|
21
|
+
export type { DraftablyEdgeData, FlowEdge, FlowEdgeOut, FlowGraph, FlowNode, FlowNodeOut, FlowOptions, SvelteFlowNodeOut, } from './react-flow.js';
|
|
22
|
+
/** Settings a keyed call takes beside its graph. */
|
|
23
|
+
export type Common = Pick<GraphIn, 'arrange' | 'direction' | 'gap' | 'fit' | 'fold' | 'routing'>;
|
|
24
|
+
type FlowLayout<N extends FlowNode, E extends FlowEdge> = FlowGraph<FlowNodeOut<N>, FlowEdgeOut<E>>;
|
|
25
|
+
type SvelteLayout<N extends FlowNode, E extends FlowEdge> = FlowGraph<SvelteFlowNodeOut<N>, FlowEdgeOut<E>>;
|
|
26
|
+
type FlowRouted<N extends FlowNode, E extends FlowEdge> = FlowGraph<N, FlowEdgeOut<E>>;
|
|
27
|
+
export declare function layout(graph: GraphIn): Promise<LayoutResult>;
|
|
28
|
+
export declare function layout<N extends FlowNode, E extends FlowEdge>(input: {
|
|
29
|
+
reactFlow: FlowGraph<N, E>;
|
|
30
|
+
} & FlowOptions & Common): Promise<{
|
|
31
|
+
reactFlow: FlowLayout<N, E>;
|
|
32
|
+
result: LayoutResult;
|
|
33
|
+
}>;
|
|
34
|
+
export declare function layout<N extends FlowNode, E extends FlowEdge>(input: {
|
|
35
|
+
svelteFlow: FlowGraph<N, E>;
|
|
36
|
+
} & FlowOptions & Common): Promise<{
|
|
37
|
+
svelteFlow: SvelteLayout<N, E>;
|
|
38
|
+
result: LayoutResult;
|
|
39
|
+
}>;
|
|
40
|
+
export declare function layout(input: {
|
|
41
|
+
elk: ElkNode;
|
|
42
|
+
} & Common): Promise<{
|
|
43
|
+
elk: ElkNode;
|
|
44
|
+
result: LayoutResult;
|
|
45
|
+
}>;
|
|
46
|
+
export declare function route(graph: RouteIn): Routed;
|
|
47
|
+
export declare function route<N extends FlowNode, E extends FlowEdge>(input: {
|
|
48
|
+
reactFlow: FlowGraph<N, E>;
|
|
49
|
+
routing?: RoutingOptions;
|
|
50
|
+
} & FlowOptions): {
|
|
51
|
+
reactFlow: FlowRouted<N, E>;
|
|
52
|
+
result: Routed;
|
|
53
|
+
};
|
|
54
|
+
export declare function route<N extends FlowNode, E extends FlowEdge>(input: {
|
|
55
|
+
svelteFlow: FlowGraph<N, E>;
|
|
56
|
+
routing?: RoutingOptions;
|
|
57
|
+
} & FlowOptions): {
|
|
58
|
+
svelteFlow: FlowRouted<N, E>;
|
|
59
|
+
result: Routed;
|
|
60
|
+
};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* React Flow (and Svelte Flow, which shares its node and edge shape) in, the same shape out.
|
|
3
|
+
* Nodes come back with `position` relative to their parent, as sub-flows expect, and a size.
|
|
4
|
+
* Edges keep their fields and gain `type: 'draftably'` (unless they have a type) and
|
|
5
|
+
* `data.draftably`: the routed path and label box that `DraftablyEdge` draws.
|
|
6
|
+
*/
|
|
7
|
+
import type { EdgeOut, GraphIn, LayoutResult, RouteIn, Routed, Shape } from './core.js';
|
|
8
|
+
import type { Side } from '../model/types.js';
|
|
9
|
+
/**
|
|
10
|
+
* The fields of a React Flow 11 or 12 node that layout reads; other fields pass through. No index
|
|
11
|
+
* signature, so React Flow's own `Node` and `Edge` types fit.
|
|
12
|
+
*/
|
|
13
|
+
export interface FlowNode {
|
|
14
|
+
id: string;
|
|
15
|
+
position?: {
|
|
16
|
+
x: number;
|
|
17
|
+
y: number;
|
|
18
|
+
};
|
|
19
|
+
data?: {
|
|
20
|
+
label?: unknown;
|
|
21
|
+
[key: string]: unknown;
|
|
22
|
+
};
|
|
23
|
+
type?: string;
|
|
24
|
+
parentId?: string;
|
|
25
|
+
/** React Flow 11's name for `parentId`. */
|
|
26
|
+
parentNode?: string;
|
|
27
|
+
width?: number | null;
|
|
28
|
+
height?: number | null;
|
|
29
|
+
measured?: {
|
|
30
|
+
width?: number;
|
|
31
|
+
height?: number;
|
|
32
|
+
};
|
|
33
|
+
/** React Flow's style object, or Svelte Flow's CSS string. */
|
|
34
|
+
style?: string | {
|
|
35
|
+
width?: number | string;
|
|
36
|
+
height?: number | string;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export interface FlowEdge {
|
|
40
|
+
id: string;
|
|
41
|
+
source: string;
|
|
42
|
+
target: string;
|
|
43
|
+
label?: unknown;
|
|
44
|
+
sourceHandle?: string | null;
|
|
45
|
+
targetHandle?: string | null;
|
|
46
|
+
animated?: boolean;
|
|
47
|
+
type?: string;
|
|
48
|
+
data?: Record<string, unknown>;
|
|
49
|
+
}
|
|
50
|
+
export interface FlowGraph<N extends FlowNode = FlowNode, E extends FlowEdge = FlowEdge> {
|
|
51
|
+
nodes: N[];
|
|
52
|
+
edges: E[];
|
|
53
|
+
}
|
|
54
|
+
export interface FlowOptions {
|
|
55
|
+
/** A draftably shape for a node, such as `n => n.type === 'decision' ? 'diamond' : undefined`. */
|
|
56
|
+
shape?: (node: FlowNode) => Shape | undefined;
|
|
57
|
+
}
|
|
58
|
+
/** What `layout` and `route` add to each edge, under `data.draftably`. */
|
|
59
|
+
export interface DraftablyEdgeData {
|
|
60
|
+
path: string;
|
|
61
|
+
points: EdgeOut['points'];
|
|
62
|
+
label: EdgeOut['label'];
|
|
63
|
+
sourceSide: Side;
|
|
64
|
+
targetSide: Side;
|
|
65
|
+
blocked: boolean;
|
|
66
|
+
}
|
|
67
|
+
/** A Svelte Flow node as `layout` returns it: placed relative to its parent, with its size. */
|
|
68
|
+
export type SvelteFlowNodeOut<N extends FlowNode> = N & {
|
|
69
|
+
position: {
|
|
70
|
+
x: number;
|
|
71
|
+
y: number;
|
|
72
|
+
};
|
|
73
|
+
width: number;
|
|
74
|
+
height: number;
|
|
75
|
+
};
|
|
76
|
+
/** A React Flow node as `layout` returns it: the size is also in its `style`. */
|
|
77
|
+
export type FlowNodeOut<N extends FlowNode> = SvelteFlowNodeOut<N> & {
|
|
78
|
+
style: Exclude<NonNullable<N['style']>, string> & {
|
|
79
|
+
width: number;
|
|
80
|
+
height: number;
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
export type FlowEdgeOut<E extends FlowEdge> = E & {
|
|
84
|
+
type: string;
|
|
85
|
+
data: E['data'] & {
|
|
86
|
+
draftably: DraftablyEdgeData;
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
export declare function fromFlow({ nodes, edges }: FlowGraph, options?: FlowOptions): GraphIn;
|
|
90
|
+
/**
|
|
91
|
+
* Svelte Flow keeps `style` as a CSS string and sizes a node from `width` and `height`, so its
|
|
92
|
+
* nodes keep their own style; React Flow nodes also get the size in `style`.
|
|
93
|
+
*/
|
|
94
|
+
export declare function toFlow<N extends FlowNode, E extends FlowEdge>({ nodes, edges }: FlowGraph<N, E>, out: LayoutResult, svelte?: boolean): FlowGraph<FlowNodeOut<N>, FlowEdgeOut<E>>;
|
|
95
|
+
/**
|
|
96
|
+
* The boxes React Flow shows now, for `route`: each position made absolute through its parents.
|
|
97
|
+
* A node without a size is skipped, with its edges, until React Flow has measured it.
|
|
98
|
+
*/
|
|
99
|
+
export declare function placedFlow({ nodes, edges }: FlowGraph, options?: FlowOptions): RouteIn;
|
|
100
|
+
export declare function routedFlow<E extends FlowEdge>(edges: E[], routed: Routed): FlowEdgeOut<E>[];
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Whole-drawing moves for adapters whose library draws in another frame. */
|
|
2
|
+
import type { LayoutResult } from './core.js';
|
|
3
|
+
/** The drawing moved so that its bounds start at (0, 0). */
|
|
4
|
+
export declare function shifted(out: LayoutResult): LayoutResult;
|
|
5
|
+
/** The drawing flipped across its bounds, so a `right` layout reads leftward (or `down` upward). */
|
|
6
|
+
export declare function mirrored(out: LayoutResult, axis: 'x' | 'y'): LayoutResult;
|
|
@@ -93,6 +93,15 @@ export interface EdgeLayout {
|
|
|
93
93
|
toOffset?: number;
|
|
94
94
|
/** A sequence message: drawn straight between the two lifelines at this height, not routed. */
|
|
95
95
|
row?: number;
|
|
96
|
+
/**
|
|
97
|
+
* Set by the compiler for a forward line in a `flow` scope: its route planned from the ranks.
|
|
98
|
+
* The quick router takes it as it is when it clears every box.
|
|
99
|
+
*/
|
|
100
|
+
plan?: {
|
|
101
|
+
points: Point[];
|
|
102
|
+
fromOffset: number;
|
|
103
|
+
toOffset: number;
|
|
104
|
+
};
|
|
96
105
|
}
|
|
97
106
|
/**
|
|
98
107
|
* A channel between two bands of a fold: a level line at `y`, or an upright one at `x`. With
|