@weasel-js/diagram 1.10.1 → 1.11.1
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 +1160 -26
- package/dist/chunk-43LDZ6L4.js +2053 -0
- package/dist/chunk-43LDZ6L4.js.map +1 -0
- package/dist/chunk-CI3I3I6T.js +3600 -0
- package/dist/chunk-CI3I3I6T.js.map +1 -0
- package/dist/chunk-IM6DHWZO.js +3220 -0
- package/dist/chunk-IM6DHWZO.js.map +1 -0
- package/dist/chunk-QKSWZEJH.js +312 -0
- package/dist/chunk-QKSWZEJH.js.map +1 -0
- package/dist/chunk-T6DQT553.js +1431 -0
- package/dist/chunk-T6DQT553.js.map +1 -0
- package/dist/chunk-WDIE35AK.js +3 -0
- package/dist/chunk-WDIE35AK.js.map +1 -0
- package/dist/dataTypes-B-iEwKZp.d.ts +553 -0
- package/dist/effect-audio.d.ts +138 -0
- package/dist/effect-audio.js +527 -0
- package/dist/effect-audio.js.map +1 -0
- package/dist/effect.d.ts +782 -0
- package/dist/effect.js +2542 -0
- package/dist/effect.js.map +1 -0
- package/dist/icons.table.d.ts +6 -0
- package/dist/icons.table.js +32 -0
- package/dist/icons.table.js.map +1 -0
- package/dist/icons.table.json +24 -0
- package/dist/index.d.ts +2270 -355
- package/dist/index.js +953 -1331
- package/dist/index.js.map +1 -1
- package/dist/layout.d.ts +3 -2
- package/dist/layout.entry-CH9gc0CY.d.ts +512 -0
- package/dist/layout.js +3 -1
- package/dist/stageTypes-DvnR8cKQ.d.ts +189 -0
- package/dist/{layout.entry-BUkiRKuX.d.ts → types-BbHunLXm.d.ts} +382 -261
- package/package.json +32 -7
- package/dist/chunk-JZ4CVLAB.js +0 -1247
- package/dist/chunk-JZ4CVLAB.js.map +0 -1
|
@@ -1,15 +1,16 @@
|
|
|
1
|
+
import { Path, Vec2, PoseDescriptor } from '@weasel-js/core/math';
|
|
1
2
|
import * as _weasel_js_geom from '@weasel-js/geom';
|
|
2
|
-
import { Path, PoseDescriptor, Vec2 } from '@weasel-js/core/math';
|
|
3
|
-
import { SimulationNode, createSimulation } from '@weasel-js/simulation';
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* The shapes a built body can wear, as paths in the node's bounds.
|
|
7
6
|
*
|
|
8
7
|
* These are the flowchart vocabulary — a decision is a diamond, an I/O step a
|
|
9
|
-
* parallelogram, a terminator a stadium
|
|
8
|
+
* parallelogram, a terminator a stadium, a demultiplexer a trapezoid, a preparation step a hexagon,
|
|
9
|
+
* a connector an ellipse — plus `'rect'` for everything else and
|
|
10
10
|
* a `Path` escape hatch for a shape the vocabulary does not have. The path is
|
|
11
11
|
* built in world coordinates from the bounds it is given, the same way the
|
|
12
|
-
* kit's own `clipFromPose` factories are
|
|
12
|
+
* kit's own `clipFromPose` factories are; a custom `Path` is drawn in a unit
|
|
13
|
+
* square and stretched over them, as a mark is.
|
|
13
14
|
*/
|
|
14
15
|
|
|
15
16
|
/** An axis-aligned box. This is `PoseDescriptor.getBounds`'s return shape
|
|
@@ -22,8 +23,10 @@ interface Bounds {
|
|
|
22
23
|
width: number;
|
|
23
24
|
height: number;
|
|
24
25
|
}
|
|
25
|
-
/** A named flowchart shape, or a path a consumer built themselves
|
|
26
|
-
|
|
26
|
+
/** A named flowchart shape, or a path a consumer built themselves in a unit
|
|
27
|
+
* square — `(0, 0)` the box's top-left, `(1, 1)` its bottom-right — so it
|
|
28
|
+
* follows its node wherever layout or a drag puts it. */
|
|
29
|
+
type Outline = 'rect' | 'diamond' | 'stadium' | 'ellipse' | 'parallelogram' | 'trapezoid' | 'hexagon' | Path;
|
|
27
30
|
/** The path `outline` describes inside `bounds`. A zero-area box gives a
|
|
28
31
|
* zero-area rect rather than a degenerate polygon. */
|
|
29
32
|
declare function outlinePath(outline: Outline, bounds: Bounds): Path;
|
|
@@ -54,6 +57,208 @@ declare function boxForContent(outline: Outline, content: {
|
|
|
54
57
|
height: number;
|
|
55
58
|
};
|
|
56
59
|
|
|
60
|
+
/**
|
|
61
|
+
* The label trait: where along its edge a label sits. Data only — placing the
|
|
62
|
+
* label on the route is `label`'s job, so layout can read one without
|
|
63
|
+
* reaching the scene.
|
|
64
|
+
*/
|
|
65
|
+
|
|
66
|
+
/** Where along an edge a label sits. */
|
|
67
|
+
interface DiagramLabel {
|
|
68
|
+
/** `'start'`, `'mid'` and `'end'` are 0, 0.5 and 1; a number is that
|
|
69
|
+
* fraction of the route's length. `{ near }` is the point on the route
|
|
70
|
+
* nearest `near`, in world coordinates — where `layered` leaves a label
|
|
71
|
+
* room — so a bend added or removed elsewhere leaves the label on the
|
|
72
|
+
* stretch it was on. */
|
|
73
|
+
at: 'start' | 'mid' | 'end' | number | {
|
|
74
|
+
near: Vec2;
|
|
75
|
+
};
|
|
76
|
+
/** World units between the route and the label's near side, to the **left
|
|
77
|
+
* of the direction of travel** — above a left-to-right edge. Default 0,
|
|
78
|
+
* which centers the label on the line. */
|
|
79
|
+
offset?: number;
|
|
80
|
+
/** Where label placement moved it, off a station something covered:
|
|
81
|
+
* `at` a fraction of the route's length, `offset` as above. Read in place
|
|
82
|
+
* of `at` and `offset`, which stay the author's preference. Written only
|
|
83
|
+
* by placement (`installLabelPlacement`). */
|
|
84
|
+
placed?: LabelSpot;
|
|
85
|
+
/** `false` keeps placement from ever moving this label. */
|
|
86
|
+
dodge?: false;
|
|
87
|
+
}
|
|
88
|
+
/** A station placement chose: a fraction of the route's length, and the
|
|
89
|
+
* offset from the line. */
|
|
90
|
+
interface LabelSpot {
|
|
91
|
+
at: number;
|
|
92
|
+
offset: number;
|
|
93
|
+
}
|
|
94
|
+
/** Where an edge label sits when neither the edge nor the scene says. */
|
|
95
|
+
declare const LABEL_PLACEMENT: DiagramLabel;
|
|
96
|
+
/** The label trait on a node's data, or `null`. */
|
|
97
|
+
declare function diagramLabelOf(node: {
|
|
98
|
+
data: unknown;
|
|
99
|
+
}): DiagramLabel | null;
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* The container trait: what makes a core `ContainerNode` a diagram container,
|
|
103
|
+
* a pool, or one of a pool's lanes, and where its header is.
|
|
104
|
+
*
|
|
105
|
+
* A container's title is a text child in its header, named
|
|
106
|
+
* `<container id>/title`. The layouts find it by that name, because a layout
|
|
107
|
+
* strategy sees only ids and poses.
|
|
108
|
+
*/
|
|
109
|
+
|
|
110
|
+
/** Which kind of region a container is. */
|
|
111
|
+
type ContainerRole = 'container' | 'pool' | 'lane';
|
|
112
|
+
/** The strip a container's title sits in, along one side. */
|
|
113
|
+
interface ContainerHeader {
|
|
114
|
+
side: 'top' | 'left';
|
|
115
|
+
/** Its depth into the container, in world units. */
|
|
116
|
+
size: number;
|
|
117
|
+
}
|
|
118
|
+
/** The container half of a diagram node's trait, under `data.diagram.container`. */
|
|
119
|
+
interface DiagramContainer {
|
|
120
|
+
role: ContainerRole;
|
|
121
|
+
header?: ContainerHeader;
|
|
122
|
+
/** Its box is fitted to its members each time the diagram is built from data
|
|
123
|
+
* (`DataContainer` with no `box`), so a move that carries it along is no edit of its own. */
|
|
124
|
+
fitted?: true;
|
|
125
|
+
}
|
|
126
|
+
type Box = {
|
|
127
|
+
x: number;
|
|
128
|
+
y: number;
|
|
129
|
+
width: number;
|
|
130
|
+
height: number;
|
|
131
|
+
};
|
|
132
|
+
/** The container trait on a node's data, or `null`. */
|
|
133
|
+
declare function diagramContainerOf(node: {
|
|
134
|
+
data: unknown;
|
|
135
|
+
}): DiagramContainer | null;
|
|
136
|
+
/** The id of a container's title node. */
|
|
137
|
+
declare const titleIdOf: (containerId: string) => string;
|
|
138
|
+
/** The header strip of a container at `bounds`; null with no header. */
|
|
139
|
+
declare function headerBox(bounds: Box, header: ContainerHeader | undefined): Box | null;
|
|
140
|
+
/** What a container at `bounds` holds members in: everything past its header. */
|
|
141
|
+
declare function bodyBox(bounds: Box, header: ContainerHeader | undefined): Box;
|
|
142
|
+
|
|
143
|
+
/** A color on a shape or connector that the author can set by hand, and a theme then leaves alone.
|
|
144
|
+
* On a connector, `text` is its label's color. */
|
|
145
|
+
type StyleField = 'fill' | 'stroke' | 'text';
|
|
146
|
+
/** A part of a shape's or connector's text face the author can set by hand, which a theme then
|
|
147
|
+
* leaves alone. Kept apart from {@link StyleField}, so choosing a role, which hands back the
|
|
148
|
+
* colors, keeps it. */
|
|
149
|
+
type FontField = 'size';
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Where a port sits on its node, in **normalized bounds coordinates**:
|
|
153
|
+
* `(0, 0)` is the top-left corner of the node's AABB and `(1, 1)` the
|
|
154
|
+
* bottom-right. `COMPASS` names the eight positions almost everything wants.
|
|
155
|
+
*
|
|
156
|
+
* Normalized rather than absolute because a node's size is authored data that
|
|
157
|
+
* resize, align and distribute all write — a port fixed at an offset would
|
|
158
|
+
* drift off the shape the first time one of them ran.
|
|
159
|
+
*/
|
|
160
|
+
interface PortAnchor {
|
|
161
|
+
u: number;
|
|
162
|
+
v: number;
|
|
163
|
+
}
|
|
164
|
+
/** One more place a port may sit, and optionally the direction it faces there. */
|
|
165
|
+
interface PortSite extends PortAnchor {
|
|
166
|
+
normal?: Vec2 | null;
|
|
167
|
+
}
|
|
168
|
+
/** One attachment point declared on a node. */
|
|
169
|
+
interface PortSpec {
|
|
170
|
+
/** Unique within the node. Edges name this, so it outlives a re-layout. */
|
|
171
|
+
id: string;
|
|
172
|
+
at: PortAnchor;
|
|
173
|
+
/** Other places the port may sit. An edge meeting the port takes whichever
|
|
174
|
+
* of `at` and these faces the edge's next point most directly, so a
|
|
175
|
+
* diamond's second exit can leave by its top or its bottom vertex, toward
|
|
176
|
+
* wherever its wire goes. Everything else that shows a port where it is —
|
|
177
|
+
* the connect affordance, `portsOf` — reads `at`. A site faces away from
|
|
178
|
+
* the node's center unless it gives a `normal` of its own. */
|
|
179
|
+
sites?: readonly PortSite[];
|
|
180
|
+
/** Consulted by a connect gesture's validity predicate. Uninterpreted here. */
|
|
181
|
+
type?: string;
|
|
182
|
+
/** What the port is for, drawn beside it outside the node: beside the
|
|
183
|
+
* wire rather than across it. A built body draws it and keeps it in its
|
|
184
|
+
* `margin`; any other participant gets it on its resolved `Port`. */
|
|
185
|
+
label?: string;
|
|
186
|
+
/** The direction an edge leaves along, overriding the one the anchor
|
|
187
|
+
* implies. `null` means "no preferred direction" — a router goes straight
|
|
188
|
+
* at it. Applies at `at`; each of `sites` says its own. */
|
|
189
|
+
normal?: Vec2 | null;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* The trait that makes an existing scene node a diagram participant.
|
|
193
|
+
*
|
|
194
|
+
* Attached to a node's `data`, not a node kind the plugin mints: a text block,
|
|
195
|
+
* an image, a path, a group or a plain rect all take part by carrying this,
|
|
196
|
+
* and nothing has to be authored through this package to be connectable.
|
|
197
|
+
*/
|
|
198
|
+
interface DiagramNode {
|
|
199
|
+
/** Defaults to {@link DEFAULT_PORTS} — the four edge midpoints of the
|
|
200
|
+
* node's own bounds, which every node has. */
|
|
201
|
+
ports?: readonly PortSpec[];
|
|
202
|
+
/** Layout must not move this node. */
|
|
203
|
+
pinned?: boolean;
|
|
204
|
+
/** What the node is *drawn* as. Present on a built body; absent on a
|
|
205
|
+
* participant that already had a look of its own — a text block, an image,
|
|
206
|
+
* a path — which keeps whatever painter it already matched. */
|
|
207
|
+
outline?: Outline;
|
|
208
|
+
/** Present on a group's box: a node drawn around the participants it
|
|
209
|
+
* depends on, which layout keeps together and leaves room for. The box
|
|
210
|
+
* itself is never laid out — it derives its pose from its members — but an
|
|
211
|
+
* edge can attach to it like any participant. */
|
|
212
|
+
group?: DiagramGroup;
|
|
213
|
+
/** Present on a container, a pool, or a lane: a `ContainerNode` holding
|
|
214
|
+
* members (`containers/trait.ts`). */
|
|
215
|
+
container?: DiagramContainer;
|
|
216
|
+
/** How far past its bounds something drawn with it reaches, on each side —
|
|
217
|
+
* a built body's port labels. Layout keeps neighbors that far off too. */
|
|
218
|
+
margin?: GroupInset;
|
|
219
|
+
/** The theme role it is drawn in. Unset, the theme's default role. */
|
|
220
|
+
style?: string;
|
|
221
|
+
/** The colors the author set by hand, which a theme leaves as they are. */
|
|
222
|
+
ownStyle?: readonly StyleField[];
|
|
223
|
+
/** The parts of its text face the author set by hand, which a theme leaves as they are. */
|
|
224
|
+
ownFont?: readonly FontField[];
|
|
225
|
+
/** On a built body whose rows are all text: how it stacks them, so it can be laid out again when
|
|
226
|
+
* their text changes size. Each row's text node carries its place as `bodyRow`. */
|
|
227
|
+
body?: BodyLayout;
|
|
228
|
+
}
|
|
229
|
+
/** How a built body stacks its text rows: the `BodySpec` fields its layout reads, and how many rows. */
|
|
230
|
+
interface BodyLayout {
|
|
231
|
+
padding: number;
|
|
232
|
+
gap: number;
|
|
233
|
+
verticalAlign: 'top' | 'center' | 'bottom';
|
|
234
|
+
rows: number;
|
|
235
|
+
}
|
|
236
|
+
/** The group half of a {@link DiagramNode}. */
|
|
237
|
+
interface DiagramGroup {
|
|
238
|
+
/** Room the box keeps around its members, in world units: one number for
|
|
239
|
+
* every side, or per side. Default 12 on each. */
|
|
240
|
+
inset?: number | Partial<GroupInset>;
|
|
241
|
+
/** The narrowest the box may be, in world units, as room for its label.
|
|
242
|
+
* A box its members leave narrower grows evenly on both sides. */
|
|
243
|
+
minWidth?: number;
|
|
244
|
+
/** The axis its members can be dragged along to change their order. */
|
|
245
|
+
reorder?: 'x' | 'y';
|
|
246
|
+
}
|
|
247
|
+
/** A port resolved against a node's current pose: where it is in world
|
|
248
|
+
* coordinates, and which way an edge leaves it. */
|
|
249
|
+
interface Port {
|
|
250
|
+
id: string;
|
|
251
|
+
/** The node this port belongs to. */
|
|
252
|
+
nodeId: string;
|
|
253
|
+
/** World point an edge attaches to. */
|
|
254
|
+
point: Vec2;
|
|
255
|
+
/** Unit vector pointing away from the node, or `null` when the port
|
|
256
|
+
* declared no direction. Rotated with the node. */
|
|
257
|
+
normal: Vec2 | null;
|
|
258
|
+
type?: string;
|
|
259
|
+
label?: string;
|
|
260
|
+
}
|
|
261
|
+
|
|
57
262
|
/**
|
|
58
263
|
* Reading the `DiagramNode` trait off a scene node.
|
|
59
264
|
*
|
|
@@ -97,7 +302,7 @@ interface DiagramNodeEntry {
|
|
|
97
302
|
* the two apart. Without that test an edge reads as a participant declaring
|
|
98
303
|
* no ports, and collects the four defaults on the degenerate pose an edge
|
|
99
304
|
* carries. An edge label's `label` trait and an anchored node's `anchor` are
|
|
100
|
-
* excluded the same way. */
|
|
305
|
+
* excluded the same way, and so is a pool's lane, which takes no connectors. */
|
|
101
306
|
declare const dataKeyReader: DiagramNodeReader;
|
|
102
307
|
/**
|
|
103
308
|
* A reader over declared kinds. A trait on the node's own data still wins, so
|
|
@@ -140,6 +345,15 @@ interface GraphNode {
|
|
|
140
345
|
pinned: boolean;
|
|
141
346
|
/** The innermost group it belongs to, when it belongs to one. */
|
|
142
347
|
group?: string;
|
|
348
|
+
/** Where its ports sit. Absent, the four compass midpoints
|
|
349
|
+
* (`DEFAULT_PORTS`). */
|
|
350
|
+
ports?: readonly PortSpec[];
|
|
351
|
+
/** The shape its ports are cast onto, as `portsOf` casts them. Absent,
|
|
352
|
+
* its bounds. */
|
|
353
|
+
outline?: Outline;
|
|
354
|
+
/** How far past `bounds` it reaches (`DiagramNode.margin`). `planOf` lays
|
|
355
|
+
* it out as that much bigger. */
|
|
356
|
+
margin?: GroupInset;
|
|
143
357
|
}
|
|
144
358
|
/** A box drawn around some participants, which a layout keeps together and
|
|
145
359
|
* leaves room for. */
|
|
@@ -155,6 +369,9 @@ interface GraphGroup {
|
|
|
155
369
|
minWidth?: number;
|
|
156
370
|
/** The group this one is directly inside. */
|
|
157
371
|
parent?: string;
|
|
372
|
+
/** Its direct members, nodes and groups, in the order a layered layout
|
|
373
|
+
* keeps them across every rank: set for a group that reorders. */
|
|
374
|
+
ordered?: readonly string[];
|
|
158
375
|
}
|
|
159
376
|
/** One connection. `id` is the edge node's own id, so a caller can go back to
|
|
160
377
|
* the scene for its trait. */
|
|
@@ -162,6 +379,37 @@ interface GraphEdge {
|
|
|
162
379
|
id: string;
|
|
163
380
|
from: string;
|
|
164
381
|
to: string;
|
|
382
|
+
/** The port it leaves `from` by, when it names one. */
|
|
383
|
+
fromPort?: string;
|
|
384
|
+
/** The port it arrives at `to` by, when it names one. */
|
|
385
|
+
toPort?: string;
|
|
386
|
+
/** Room its label needs: the label's box, and how far its near side sits
|
|
387
|
+
* from the wire (`DiagramLabel.offset`). `layered` sets the label beside
|
|
388
|
+
* its wire in a rank of its own. */
|
|
389
|
+
label?: EdgeLabelRoom;
|
|
390
|
+
/** Where its route runs now, from `from` to `to`. `layered` starts each
|
|
391
|
+
* placeholder where the route already crosses that rank, so a re-run keeps
|
|
392
|
+
* the order the last one settled on. */
|
|
393
|
+
waypoints?: readonly Vec2[];
|
|
394
|
+
/** Its route is someone's own: layout leaves it, and keeps no room for it
|
|
395
|
+
* in the ranks it crosses. */
|
|
396
|
+
authored?: boolean;
|
|
397
|
+
/** The edge as drawn, when this one stands in for an edge to or from a
|
|
398
|
+
* group (see `expandGroupEdges`). */
|
|
399
|
+
origin?: {
|
|
400
|
+
id: string;
|
|
401
|
+
from: string;
|
|
402
|
+
to: string;
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
/** The room a {@link GraphEdge}'s label takes, in world units. */
|
|
406
|
+
interface EdgeLabelRoom {
|
|
407
|
+
width: number;
|
|
408
|
+
height: number;
|
|
409
|
+
/** Between the wire and the label's near side, to the left of the
|
|
410
|
+
* direction of travel; negative for the right. Default 0, which centers
|
|
411
|
+
* the label on the wire. */
|
|
412
|
+
offset?: number;
|
|
165
413
|
}
|
|
166
414
|
/**
|
|
167
415
|
* Nodes, edges, and the two adjacency reads a layout needs.
|
|
@@ -229,7 +477,8 @@ interface LayoutOptions {
|
|
|
229
477
|
/** Between one rank and the next. Default 96. */
|
|
230
478
|
rankGap?: number;
|
|
231
479
|
/** How `layered` orders nodes within a rank. `'seeded'` (default) keeps
|
|
232
|
-
* the order they already sit in
|
|
480
|
+
* the order they already sit in, an edge's place included: where its
|
|
481
|
+
* route crosses the rank now. `'barycenter'` reorders to reduce edge
|
|
233
482
|
* crossings, for a generated diagram with no arranged order to keep.
|
|
234
483
|
* Other layouts ignore it. */
|
|
235
484
|
order?: 'seeded' | 'barycenter';
|
|
@@ -239,12 +488,53 @@ interface LayoutOptions {
|
|
|
239
488
|
* `1e-6` — a float-noise floor, not a snapping quantum. Raise it to let a
|
|
240
489
|
* `force` pass that has stopped doing anything useful commit nothing. */
|
|
241
490
|
tolerance?: number;
|
|
491
|
+
/** `chain` only: the ids that stand on the line, in order. Unset, the
|
|
492
|
+
* longest path through the graph. */
|
|
493
|
+
chain?: readonly string[];
|
|
494
|
+
/** `chain` only: which side of the line everything else hangs on, along
|
|
495
|
+
* the cross axis. Default `'after'`. */
|
|
496
|
+
chainSide?: 'after' | 'before';
|
|
242
497
|
}
|
|
243
498
|
/** The new top-left for each node that moves. A node that is already there is
|
|
244
499
|
* absent, so an empty result means "nothing to do". */
|
|
245
500
|
type LayoutResult = ReadonlyMap<string, Vec2>;
|
|
246
|
-
/**
|
|
247
|
-
|
|
501
|
+
/** A layout's answer with the edge routes it laid out, keyed by edge id. */
|
|
502
|
+
interface LayoutPlan {
|
|
503
|
+
moves: LayoutResult;
|
|
504
|
+
/** For each edge layout routed: the points it runs through, from its
|
|
505
|
+
* `from` end to its `to` end. An edge absent runs straight between its
|
|
506
|
+
* ends. Absent altogether, the layout routes nothing. */
|
|
507
|
+
waypoints?: ReadonlyMap<string, readonly Vec2[]>;
|
|
508
|
+
/** For each edge layout left label room beside: the point on its route
|
|
509
|
+
* the room is beside, as a `DiagramLabel`'s `{ near }`. */
|
|
510
|
+
labels?: ReadonlyMap<string, Vec2>;
|
|
511
|
+
/** For each edge layout named ports for: the port it leaves `from` by and
|
|
512
|
+
* the one it arrives at `to` by, either absent where layout names none.
|
|
513
|
+
* Absent altogether, the layout names no ports. */
|
|
514
|
+
ports?: ReadonlyMap<string, LayoutPorts>;
|
|
515
|
+
}
|
|
516
|
+
/** The ports a layout names for one edge. */
|
|
517
|
+
interface LayoutPorts {
|
|
518
|
+
from?: string;
|
|
519
|
+
to?: string;
|
|
520
|
+
}
|
|
521
|
+
/** Every layout in this package has this shape, and so does a consumer's.
|
|
522
|
+
* One that routes edges as well says so with `plan`. */
|
|
523
|
+
interface LayoutFn {
|
|
524
|
+
(graph: Graph, opts?: LayoutOptions): LayoutResult;
|
|
525
|
+
readonly plan?: (graph: Graph, opts?: LayoutOptions) => LayoutPlan;
|
|
526
|
+
}
|
|
527
|
+
/** A layout that answers with a whole plan, now or later: ELK's, say, or one
|
|
528
|
+
* computed on a server. A live run asks it once, with the graph it will ease
|
|
529
|
+
* from, and eases to the answer the way it eases to `layered`'s. */
|
|
530
|
+
interface LayoutPlanner {
|
|
531
|
+
plan(graph: Graph, opts?: LayoutOptions): LayoutPlan | Promise<LayoutPlan>;
|
|
532
|
+
}
|
|
533
|
+
/** A layout's plan: its own `plan`, or its moves alone. A node with a
|
|
534
|
+
* `margin` is laid out as its footprint, so neighbors keep clear of it. */
|
|
535
|
+
declare function planOf(layout: LayoutFn, graph: Graph, opts?: LayoutOptions): LayoutPlan;
|
|
536
|
+
/** `planner`'s plan for `graph`, laid out by footprint the way {@link planOf}'s is. */
|
|
537
|
+
declare function plannerPlan(planner: LayoutPlanner, graph: Graph, opts?: LayoutOptions): LayoutPlan | Promise<LayoutPlan>;
|
|
248
538
|
/** `LayoutOptions.nodeGap`'s default, in world units. */
|
|
249
539
|
declare const DEFAULT_NODE_GAP = 48;
|
|
250
540
|
/** `LayoutOptions.rankGap`'s default, in world units. */
|
|
@@ -295,6 +585,9 @@ declare function untilSettled(once: LayoutFn, graph: Graph, opts?: LayoutOptions
|
|
|
295
585
|
* coordinates.
|
|
296
586
|
*/
|
|
297
587
|
declare function translated(graph: Graph, placed: ReadonlyMap<string, Vec2>, pinned: ReadonlySet<string>, tolerance?: number): LayoutResult;
|
|
588
|
+
/** How far {@link translated} moves a placement: onto the first pinned node,
|
|
589
|
+
* or else so its low corner lands on the graph's current one. */
|
|
590
|
+
declare function anchorOffset(graph: Graph, placed: ReadonlyMap<string, Vec2>, pinned: ReadonlySet<string>): Vec2;
|
|
298
591
|
/**
|
|
299
592
|
* Lay a list of nodes out along the cross axis, in the order given, and hand
|
|
300
593
|
* back each one's low corner plus the total span.
|
|
@@ -342,7 +635,7 @@ declare const DEFAULT_GROUP_INSET = 12;
|
|
|
342
635
|
* across it. A group's inset there includes that of any group nested in it
|
|
343
636
|
* that ends, or starts, at the same rank. `rows` is the nodes of each rank.
|
|
344
637
|
*/
|
|
345
|
-
declare function rankGaps(graph: Graph, rows: readonly (readonly GraphNode[])[], axes: LayoutAxes, rankGap: number): number[];
|
|
638
|
+
declare function rankGaps(graph: Pick<Graph, 'groups'>, rows: readonly (readonly Pick<GraphNode, 'id'>[])[], axes: LayoutAxes, rankGap: number): number[];
|
|
346
639
|
/**
|
|
347
640
|
* Cross positions for every node, with each group's members kept in a column
|
|
348
641
|
* of their own, and a nested group in a column inside its parent's.
|
|
@@ -362,88 +655,74 @@ declare function packClusters(graph: Graph, rows: readonly (readonly GraphNode[]
|
|
|
362
655
|
declare function expandGroupEdges(edges: readonly GraphEdge[], groups: readonly GraphGroup[]): GraphEdge[];
|
|
363
656
|
|
|
364
657
|
/**
|
|
365
|
-
*
|
|
366
|
-
*
|
|
367
|
-
* bottom-right. `COMPASS` names the eight positions almost everything wants.
|
|
658
|
+
* Perimeter port labels: where the text naming a port is drawn, and how far
|
|
659
|
+
* past its node that reaches.
|
|
368
660
|
*
|
|
369
|
-
*
|
|
370
|
-
*
|
|
371
|
-
*
|
|
661
|
+
* A label sits outside the node, on the port's own face, and to one side of
|
|
662
|
+
* the line the port's wire leaves along, so the wire does not run through it.
|
|
663
|
+
* A port inside a row draws its label inside the box instead; that is a
|
|
664
|
+
* `ports` row's job, not this module's.
|
|
372
665
|
*/
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
}
|
|
377
|
-
/** One attachment point declared on a node. */
|
|
378
|
-
interface PortSpec {
|
|
379
|
-
/** Unique within the node. Edges name this, so it outlives a re-layout. */
|
|
380
|
-
id: string;
|
|
381
|
-
at: PortAnchor;
|
|
382
|
-
/** Consulted by a connect gesture's validity predicate. Uninterpreted here. */
|
|
383
|
-
type?: string;
|
|
384
|
-
/** The direction an edge leaves along, overriding the one the anchor
|
|
385
|
-
* implies. `null` means "no preferred direction" — a router goes straight
|
|
386
|
-
* at it. */
|
|
387
|
-
normal?: Vec2 | null;
|
|
388
|
-
}
|
|
666
|
+
|
|
667
|
+
/** Between a port and the near sides of its label, in world units. */
|
|
668
|
+
declare const PORT_LABEL_GAP = 4;
|
|
389
669
|
/**
|
|
390
|
-
*
|
|
670
|
+
* Where a label `size` big goes for a port at `point` facing `normal`.
|
|
391
671
|
*
|
|
392
|
-
*
|
|
393
|
-
*
|
|
394
|
-
*
|
|
672
|
+
* A port on a left or right face gets its label outside that face, above its
|
|
673
|
+
* wire; one on a top or bottom face, outside that face, right of its wire; a
|
|
674
|
+
* corner port, off the corner. A port with no direction gets it centered
|
|
675
|
+
* above.
|
|
395
676
|
*/
|
|
396
|
-
|
|
397
|
-
/** Defaults to {@link DEFAULT_PORTS} — the four edge midpoints of the
|
|
398
|
-
* node's own bounds, which every node has. */
|
|
399
|
-
ports?: readonly PortSpec[];
|
|
400
|
-
/** Layout must not move this node. */
|
|
401
|
-
pinned?: boolean;
|
|
402
|
-
/** What the node is *drawn* as. Present on a built body; absent on a
|
|
403
|
-
* participant that already had a look of its own — a text block, an image,
|
|
404
|
-
* a path — which keeps whatever painter it already matched. */
|
|
405
|
-
outline?: Outline;
|
|
406
|
-
/** Present on a group's box: a node drawn around the participants it
|
|
407
|
-
* depends on, which layout keeps together and leaves room for. The box
|
|
408
|
-
* itself is never laid out — it derives its pose from its members — but an
|
|
409
|
-
* edge can attach to it like any participant. */
|
|
410
|
-
group?: DiagramGroup;
|
|
411
|
-
}
|
|
412
|
-
/** The group half of a {@link DiagramNode}. */
|
|
413
|
-
interface DiagramGroup {
|
|
414
|
-
/** Room the box keeps around its members, in world units: one number for
|
|
415
|
-
* every side, or per side. Default 12 on each. */
|
|
416
|
-
inset?: number | Partial<GroupInset>;
|
|
417
|
-
/** The narrowest the box may be, in world units, as room for its label.
|
|
418
|
-
* A box its members leave narrower grows evenly on both sides. */
|
|
419
|
-
minWidth?: number;
|
|
420
|
-
}
|
|
421
|
-
/** A port resolved against a node's current pose: where it is in world
|
|
422
|
-
* coordinates, and which way an edge leaves it. */
|
|
423
|
-
interface Port {
|
|
424
|
-
id: string;
|
|
425
|
-
/** The node this port belongs to. */
|
|
426
|
-
nodeId: string;
|
|
427
|
-
/** World point an edge attaches to. */
|
|
677
|
+
declare function portLabelBox(port: {
|
|
428
678
|
point: Vec2;
|
|
429
|
-
/** Unit vector pointing away from the node, or `null` when the port
|
|
430
|
-
* declared no direction. Rotated with the node. */
|
|
431
679
|
normal: Vec2 | null;
|
|
432
|
-
|
|
680
|
+
}, size: {
|
|
681
|
+
width: number;
|
|
682
|
+
height: number;
|
|
683
|
+
}, gap?: number): Bounds;
|
|
684
|
+
/** Where a built body's perimeter port label sits, as `buildBody`'s
|
|
685
|
+
* `portLabel` is handed it. */
|
|
686
|
+
interface PerimeterPortLabelBox extends Bounds {
|
|
687
|
+
port: PortSpec;
|
|
688
|
+
side: 'outside';
|
|
689
|
+
}
|
|
690
|
+
/** A labeled port, resolved, and the box its label is drawn in. */
|
|
691
|
+
interface PortLabelPlacement {
|
|
692
|
+
port: Port & {
|
|
693
|
+
label: string;
|
|
694
|
+
};
|
|
695
|
+
box: Bounds;
|
|
433
696
|
}
|
|
697
|
+
/** Every labeled port of `trait` resolved against `bounds`, with its label's
|
|
698
|
+
* box. `size` measures one label. */
|
|
699
|
+
declare function portLabelsOf(trait: DiagramNode, bounds: Bounds, size: (text: string) => {
|
|
700
|
+
width: number;
|
|
701
|
+
height: number;
|
|
702
|
+
}): PortLabelPlacement[];
|
|
703
|
+
/** How far `boxes` reach past `bounds` on each side; `undefined` for none. */
|
|
704
|
+
declare function marginOf(bounds: Bounds, boxes: readonly Bounds[]): GroupInset | undefined;
|
|
434
705
|
|
|
435
706
|
/** One line of body content. */
|
|
436
707
|
type Row =
|
|
437
|
-
/** Text. `label` is the node's name; `field` is a named value.
|
|
708
|
+
/** Text. `label` is the node's name; `field` is a named value. A row with
|
|
709
|
+
* an `id` gets a scene node of that name under the body's, so it can be
|
|
710
|
+
* found again; one without is named by its place. Not a bare number. */
|
|
438
711
|
{
|
|
439
712
|
kind: 'label';
|
|
440
713
|
text: string;
|
|
441
714
|
style?: RowTextStyle;
|
|
442
|
-
|
|
715
|
+
id?: string;
|
|
716
|
+
}
|
|
717
|
+
/** `room` is a value the row is measured as at least as wide as, so a
|
|
718
|
+
* value written in later fits the box it already has. */
|
|
719
|
+
| {
|
|
443
720
|
kind: 'field';
|
|
444
721
|
label: string;
|
|
445
722
|
value: string;
|
|
446
723
|
style?: RowTextStyle;
|
|
724
|
+
id?: string;
|
|
725
|
+
room?: string;
|
|
447
726
|
}
|
|
448
727
|
/** A row that carries ports on its own left and right edges. */
|
|
449
728
|
| {
|
|
@@ -452,10 +731,12 @@ type Row =
|
|
|
452
731
|
right?: readonly RowPort[];
|
|
453
732
|
height?: number;
|
|
454
733
|
}
|
|
455
|
-
/** Reserved space a consumer paints into.
|
|
734
|
+
/** Reserved space a consumer paints into. With a `width`, the body is at
|
|
735
|
+
* least that wide and the slot's box is that wide, centered in its row. */
|
|
456
736
|
| {
|
|
457
737
|
kind: 'slot';
|
|
458
738
|
height: number;
|
|
739
|
+
width?: number;
|
|
459
740
|
id?: string;
|
|
460
741
|
};
|
|
461
742
|
/** A port declared on a row rather than on the node's perimeter. */
|
|
@@ -490,6 +771,8 @@ interface BodySpec {
|
|
|
490
771
|
/** The perimeter ports, replacing the four compass midpoints. A `ports`
|
|
491
772
|
* row's own ports are added either way. */
|
|
492
773
|
ports?: readonly PortSpec[];
|
|
774
|
+
/** Perimeter port labels by id, drawn outside the box; over a port's own `label`. */
|
|
775
|
+
portLabels?: Readonly<Record<string, string>>;
|
|
493
776
|
}
|
|
494
777
|
/** What {@link buildBody} emits: the `AddNodeSpec` fields it fills in. Named
|
|
495
778
|
* structurally rather than imported so a consumer whose scene is typed
|
|
@@ -597,9 +880,9 @@ interface BuildBodyOptions<TData, TLayer extends string, TPose extends Bounds> {
|
|
|
597
880
|
body: (trait: DiagramNode, pose: TPose) => TData;
|
|
598
881
|
/** One row's data, or `null` to leave that row undrawn. */
|
|
599
882
|
row: RowNodeData<TData>;
|
|
600
|
-
/** One row port's
|
|
601
|
-
*
|
|
602
|
-
portLabel?: (text: string, box: RowPortBox) => TData | null;
|
|
883
|
+
/** One port's label — a row port's or a perimeter port's — or `null` to
|
|
884
|
+
* leave it undrawn. Ports with no label are never offered. Omit to draw none. */
|
|
885
|
+
portLabel?: (text: string, box: RowPortBox | PerimeterPortLabelBox) => TData | null;
|
|
603
886
|
}
|
|
604
887
|
/**
|
|
605
888
|
* The scene nodes a built body is: one container carrying the trait, and one
|
|
@@ -616,190 +899,28 @@ declare function buildBody<TData, TLayer extends string, TPose extends Bounds>(s
|
|
|
616
899
|
};
|
|
617
900
|
|
|
618
901
|
/**
|
|
619
|
-
*
|
|
620
|
-
*
|
|
621
|
-
* A port is placed in the node's **unrotated** bounds, then carried through
|
|
622
|
-
* the pose's rotation — the same pivot every other kit reader uses, the AABB
|
|
623
|
-
* center. Bounds come from the pose descriptor rather than from `pose.width`
|
|
624
|
-
* and friends, so a node whose pose is a path, an ellipse or anything else a
|
|
625
|
-
* consumer wired is connectable on the same terms as a rect.
|
|
902
|
+
* Line jumps as data: the document value that turns them on, and the hops a
|
|
903
|
+
* connector carries. Plain data, so layout and any reader can use it.
|
|
626
904
|
*/
|
|
627
905
|
|
|
628
|
-
/** The
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
readonly se: {
|
|
647
|
-
readonly u: 1;
|
|
648
|
-
readonly v: 1;
|
|
649
|
-
};
|
|
650
|
-
readonly s: {
|
|
651
|
-
readonly u: 0.5;
|
|
652
|
-
readonly v: 1;
|
|
653
|
-
};
|
|
654
|
-
readonly sw: {
|
|
655
|
-
readonly u: 0;
|
|
656
|
-
readonly v: 1;
|
|
657
|
-
};
|
|
658
|
-
readonly w: {
|
|
659
|
-
readonly u: 0;
|
|
660
|
-
readonly v: 0.5;
|
|
661
|
-
};
|
|
662
|
-
};
|
|
663
|
-
/**
|
|
664
|
-
* What a node carrying no `ports` gets: the four edge midpoints of its own
|
|
665
|
-
* bounds. Every node has bounds, so every node is connectable without saying
|
|
666
|
-
* anything.
|
|
667
|
-
*/
|
|
668
|
-
declare const DEFAULT_PORTS: readonly PortSpec[];
|
|
669
|
-
/** How ports are resolved against a node: its bounds, and its trait. */
|
|
670
|
-
interface PortsOptions<TPose> {
|
|
671
|
-
/** Reads the AABB a port is placed in, and the node's rotation. Defaults to
|
|
672
|
-
* the kit's `AUTO_POSE_DESCRIPTOR`, which handles rect and path poses. */
|
|
673
|
-
geometry?: PoseDescriptor<TPose>;
|
|
674
|
-
/** How the `DiagramNode` trait is read off a node. */
|
|
675
|
-
read?: DiagramNodeReader;
|
|
906
|
+
/** The document value (`scene.doc`) holding the line-jump setting: present
|
|
907
|
+
* while hops are on, absent while off. */
|
|
908
|
+
declare const HOPS_DOC_KEY = "diagram:hops";
|
|
909
|
+
/** The line-jump setting while it is on. */
|
|
910
|
+
interface HopsDocValue {
|
|
911
|
+
/** A hop's radius, in world units. */
|
|
912
|
+
size: number;
|
|
913
|
+
}
|
|
914
|
+
/** The radius a hop takes when nothing sets one. */
|
|
915
|
+
declare const DEFAULT_HOP_SIZE = 5;
|
|
916
|
+
/** Where a connector bows over others: a half circle of radius `r` centered
|
|
917
|
+
* on `at`, which lies on the connector's route. `over` names the connectors
|
|
918
|
+
* it passes over; hops closer than `2r` merge into one, which passes over all
|
|
919
|
+
* of theirs. */
|
|
920
|
+
interface EdgeHop {
|
|
921
|
+
at: Vec2;
|
|
922
|
+
over: readonly string[];
|
|
923
|
+
r: number;
|
|
676
924
|
}
|
|
677
|
-
/**
|
|
678
|
-
* Every port on `node`, resolved against `pose`.
|
|
679
|
-
*
|
|
680
|
-
* Pass the pose the node is **painted** at — `effectivePose(scene, node)` —
|
|
681
|
-
* not `node.pose`. A port that answers from the document pose while the node
|
|
682
|
-
* is mid-drag puts an edge somewhere the user can see the node is not.
|
|
683
|
-
*/
|
|
684
|
-
declare function portsOf<TPose>(node: DiagramNodeLike, pose: TPose, opts?: PortsOptions<TPose>): Port[];
|
|
685
|
-
/** One named port, or `undefined` when the node has no such port. */
|
|
686
|
-
declare function portOf<TPose>(node: DiagramNodeLike, pose: TPose, portId: string, opts?: PortsOptions<TPose>): Port | undefined;
|
|
687
|
-
|
|
688
|
-
/**
|
|
689
|
-
* `force` — relaxation, for a graph with no direction to read it in.
|
|
690
|
-
*
|
|
691
|
-
* Seeded from where the nodes already are rather than from a fresh random
|
|
692
|
-
* scatter: an author who has arranged half a diagram gets that arrangement
|
|
693
|
-
* relaxed, not replaced. There is no RNG in it at all — two coincident nodes
|
|
694
|
-
* are separated along a golden-angle spiral keyed to their index.
|
|
695
|
-
*
|
|
696
|
-
* The forces are the naive O(n²) kind — right for tens to hundreds of nodes,
|
|
697
|
-
* wrong for a 10k-node graph.
|
|
698
|
-
*
|
|
699
|
-
* **This is the one layout that is not idempotent.** A relaxation re-run from
|
|
700
|
-
* its own output keeps relaxing; `direction` means nothing to it. Pins and the
|
|
701
|
-
* `tolerance` option are what keep a second pass from scrambling a settled
|
|
702
|
-
* diagram.
|
|
703
|
-
*/
|
|
704
|
-
|
|
705
|
-
/** Options for {@link force} and {@link forceRelaxation}. `direction` is
|
|
706
|
-
* ignored. */
|
|
707
|
-
interface ForceOptions extends LayoutOptions {
|
|
708
|
-
/** Ticks to run. Default 300 — one full cooling schedule. */
|
|
709
|
-
iterations?: number;
|
|
710
|
-
/** Rest length of an edge, in world units. Default 160. */
|
|
711
|
-
linkDistance?: number;
|
|
712
|
-
/** How hard an edge pulls, 0..1. Default 0.35. */
|
|
713
|
-
linkStrength?: number;
|
|
714
|
-
/** Pairwise repulsion. Negative repels; default -3000. */
|
|
715
|
-
charge?: number;
|
|
716
|
-
/** How hard the graph is held around its own centroid. Default 0.02. */
|
|
717
|
-
gravity?: number;
|
|
718
|
-
/** Clear space kept between two boxes, in world units. Default 24. */
|
|
719
|
-
padding?: number;
|
|
720
|
-
/** How hard a group draws its members together, 0..1. Default 0.2. */
|
|
721
|
-
groupStrength?: number;
|
|
722
|
-
}
|
|
723
|
-
/** One node as the relaxation sees it: a simulation point centered on the
|
|
724
|
-
* node's box. */
|
|
725
|
-
interface ForceBody extends SimulationNode {
|
|
726
|
-
id: string;
|
|
727
|
-
/** Half the node's box, so separation can work on the shape the author sees
|
|
728
|
-
* rather than on a point. */
|
|
729
|
-
hw: number;
|
|
730
|
-
hh: number;
|
|
731
|
-
}
|
|
732
|
-
/**
|
|
733
|
-
* The bodies and the force list, wound up and ready to tick.
|
|
734
|
-
*/
|
|
735
|
-
interface ForceRelaxation {
|
|
736
|
-
bodies: ForceBody[];
|
|
737
|
-
byId: Map<string, ForceBody>;
|
|
738
|
-
/** Ids the caller must not move: declared pins, held as `fx`/`fy`. */
|
|
739
|
-
pinned: ReadonlySet<string>;
|
|
740
|
-
sim: ReturnType<typeof createSimulation<ForceBody>>;
|
|
741
|
-
/** Where a body's node's top-left sits, given the body's center. */
|
|
742
|
-
placed(): Map<string, {
|
|
743
|
-
x: number;
|
|
744
|
-
y: number;
|
|
745
|
-
}>;
|
|
746
|
-
}
|
|
747
|
-
/** Wind up a relaxation of `graph` without ticking it: bodies seeded from
|
|
748
|
-
* where the nodes are, pins held fixed. Tick `sim` yourself and read the
|
|
749
|
-
* top-lefts from `placed()`. */
|
|
750
|
-
declare function forceRelaxation(graph: Graph, opts?: ForceOptions): ForceRelaxation;
|
|
751
|
-
/** The force-directed layout. Unlike the others it is not idempotent: a
|
|
752
|
-
* re-run keeps relaxing, so pins and `tolerance` are what hold a settled
|
|
753
|
-
* diagram still. */
|
|
754
|
-
declare const force: (graph: Graph, opts?: ForceOptions) => LayoutResult;
|
|
755
|
-
|
|
756
|
-
/** Edge ids that close a cycle, found by a depth-first walk in graph order. */
|
|
757
|
-
declare function backEdges(graph: Graph): Set<string>;
|
|
758
|
-
/** Longest-path rank per node: one past its deepest predecessor. */
|
|
759
|
-
declare function ranksOf(graph: Graph, back: ReadonlySet<string>): Map<string, number>;
|
|
760
|
-
/** The ranked layout: each edge points one rank further along `direction`.
|
|
761
|
-
* Within a rank, nodes keep their current cross-axis order, so a re-run
|
|
762
|
-
* moves nothing — except under `order: 'barycenter'`, which reorders them. */
|
|
763
|
-
declare const layered: LayoutFn;
|
|
764
|
-
|
|
765
|
-
/** A graph read as trees: its roots, each node's children in order, and each node's depth. */
|
|
766
|
-
interface Forest {
|
|
767
|
-
roots: GraphNode[];
|
|
768
|
-
children: Map<string, GraphNode[]>;
|
|
769
|
-
depth: Map<string, number>;
|
|
770
|
-
}
|
|
771
|
-
/** The forest a depth-first walk in graph order finds. Exported because "which
|
|
772
|
-
* node ended up whose child" is the question anyone debugging a tree layout
|
|
773
|
-
* asks first. */
|
|
774
|
-
declare function forestOf(graph: Graph, crossAxis: 'x' | 'y'): Forest;
|
|
775
|
-
/** The hierarchy layout: each parent centered over its children's block, one
|
|
776
|
-
* rank per depth. A graph that is not a tree lays out as the forest
|
|
777
|
-
* {@link forestOf} reads from it. */
|
|
778
|
-
declare const tree: LayoutFn;
|
|
779
|
-
|
|
780
|
-
/** The outline as a closed polyline: `[x0, y0, x1, y1, …]`. */
|
|
781
|
-
declare function outlinePolyline(outline: Outline, bounds: Bounds): number[];
|
|
782
|
-
/**
|
|
783
|
-
* Where the ray from `center` through `point` last crosses `poly`, or `null`
|
|
784
|
-
* when it never does.
|
|
785
|
-
*
|
|
786
|
-
* The *last* crossing rather than the first: a concave outline can be crossed
|
|
787
|
-
* more than once, and the far side is the boundary an edge should attach to.
|
|
788
|
-
*/
|
|
789
|
-
declare function rayHit(poly: readonly number[], center: {
|
|
790
|
-
x: number;
|
|
791
|
-
y: number;
|
|
792
|
-
}, point: {
|
|
793
|
-
x: number;
|
|
794
|
-
y: number;
|
|
795
|
-
}): {
|
|
796
|
-
x: number;
|
|
797
|
-
y: number;
|
|
798
|
-
} | null;
|
|
799
|
-
/**
|
|
800
|
-
* Every port moved onto `outline`. A port the ray misses — one at the node's
|
|
801
|
-
* dead center, with no direction to cast along — is left where it was.
|
|
802
|
-
*/
|
|
803
|
-
declare function portsOnOutline(ports: readonly Port[], outline: Outline, bounds: Bounds): Port[];
|
|
804
925
|
|
|
805
|
-
export {
|
|
926
|
+
export { type PortSite as $, DEFAULT_RANK_GAP as A, type BodySpec as B, type ContainerRole as C, type DiagramGroup as D, type EdgeHop as E, type FontField as F, type Graph as G, DIAGRAM_TRAIT_KEY as H, type DiagramNodeEntry as I, type EdgeLabelRoom as J, type GraphEdge as K, type LayoutPorts as L, type MeasureRowText as M, type GraphGroup as N, type Outline as O, type PortAnchor as P, type GraphNode as Q, type RowTextStyle as R, type StyleField as S, type GroupInset as T, HOPS_DOC_KEY as U, type HopsDocValue as V, LABEL_PLACEMENT as W, type LayoutAxes as X, PORT_LABEL_GAP as Y, type PerimeterPortLabelBox as Z, type PortLabelPlacement as _, type Row as a, type RowBox as a0, type RowNodeData as a1, type RowPort as a2, type RowPortBox as a3, type Slot as a4, anchorOffset as a5, axesFor as a6, bodyBox as a7, bodyOutline as a8, bodyTrait as a9, portLabelsOf as aA, rankGaps as aB, seededOrder as aC, settle as aD, sizeToBody as aE, titleIdOf as aF, translated as aG, untilSettled as aH, extent as aI, boxForContent as aa, buildBody as ab, buildGraph as ac, canvasMeasure as ad, contentBox as ae, createDiagramNodes as af, dataKeyReader as ag, diagramContainerOf as ah, diagramLabelOf as ai, diagramNodeOf as aj, expandGroupEdges as ak, graphOrder as al, headerBox as am, insetOf as an, isPinned as ao, layoutBody as ap, layoutRowPorts as aq, marginOf as ar, measureBody as as, outlinePath as at, packAcross as au, packClusters as av, pinnedSet as aw, planOf as ax, plannerPlan as ay, portLabelBox as az, type PortSpec as b, type DiagramLabel as c, type LayoutFn as d, type LayoutOptions as e, type DiagramNode as f, type Port as g, type DiagramNodeLike as h, type DiagramNodeReader as i, type DiagramContainer as j, type ContainerHeader as k, type LabelSpot as l, type Bounds as m, type LayoutResult as n, type GraphSource as o, type LayoutPlanner as p, type LayoutDirection as q, type LayoutPlan as r, type GraphNodeLike as s, type BodyFloor as t, type BodyNodeSpec as u, type BuildBodyOptions as v, type BuildGraphOptions as w, DEFAULT_GROUP_INSET as x, DEFAULT_HOP_SIZE as y, DEFAULT_NODE_GAP as z };
|