@weasel-js/diagram 1.11.0 → 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/dist/index.d.ts CHANGED
@@ -1,43 +1,144 @@
1
- import { f as Port, g as DiagramNodeLike, h as DiagramNodeReader, d as LayoutOptions, i as LayoutResult, G as Graph, c as LayoutFn, j as GraphSource, k as LayoutPlanner, l as LayoutDirection, L as LayoutPorts, m as LayoutPlan, n as GraphNodeLike } from './body-2lC7IiIA.js';
2
- export { o as BodyFloor, p as BodyNodeSpec, B as BodySpec, q as Bounds, r as BuildBodyOptions, s as BuildGraphOptions, t as DEFAULT_GROUP_INSET, u as DEFAULT_NODE_GAP, v as DEFAULT_RANK_GAP, w as DIAGRAM_TRAIT_KEY, D as DiagramGroup, e as DiagramNode, x as DiagramNodeEntry, E as EdgeLabelRoom, y as GraphEdge, z as GraphGroup, A as GraphNode, C as GroupInset, F as LayoutAxes, M as MeasureRowText, O as Outline, H as PORT_LABEL_GAP, I as PerimeterPortLabelBox, P as PortAnchor, J as PortLabelPlacement, K as PortSite, b as PortSpec, a as Row, N as RowBox, Q as RowNodeData, S as RowPort, T as RowPortBox, R as RowTextStyle, U as Slot, V as anchorOffset, W as axesFor, X as bodyOutline, Y as bodyTrait, Z as boxForContent, _ as buildBody, $ as buildGraph, a0 as canvasMeasure, a1 as contentBox, a2 as createDiagramNodes, a3 as dataKeyReader, a4 as diagramNodeOf, a5 as expandGroupEdges, a6 as graphOrder, a7 as insetOf, a8 as isPinned, a9 as layoutBody, aa as layoutRowPorts, ab as marginOf, ac as measureBody, ad as outlinePath, ae as packAcross, af as packClusters, ag as pinnedSet, ah as planOf, ai as plannerPlan, aj as portLabelBox, ak as portLabelsOf, al as rankGaps, am as seededOrder, an as settle, ao as sizeToBody, ap as translated, aq as untilSettled } from './body-2lC7IiIA.js';
3
- import { P as PortsOptions, F as ForceOptions } from './layout.entry-BoWFcR4G.js';
4
- export { C as COMPASS, D as DEFAULT_PORTS, a as ForceBody, b as ForceRelaxation, c as Forest, L as LayeredPlan, d as backEdges, e as chain, f as footprintNode, g as force, h as forceRelaxation, i as forestOf, l as layered, j as layeredPlan, o as outlinePolyline, p as portOf, k as portSitesOf, m as portsOf, n as portsOnOutline, r as ranksByLength, q as ranksOf, s as rayHit, t as tree } from './layout.entry-BoWFcR4G.js';
5
- import { Vec2, DerivedDep, Path, SceneRegistry, PoseDescriptor, ChromeState, CommandFill, CommandStroke, CursorSpec, Affordance, InvocationCtx, Stroke, GestureBinding, Action, Contribution, RenderLayer, NodeId, Scene, GatedLayer, Fill, NodeShapeEntry, RectPose, Paint, View, SelectionApi } from '@weasel-js/core';
6
- import { f as EdgeEnd, e as DiagramSpec, b as DataEdge } from './fromData-GKqRgPFs.js';
7
- export { A as ANCHOR_DERIVE_POSE, g as DIAGRAM_ANCHOR, h as DIAGRAM_GROUP, i as DataGroup, j as DataMark, c as DataNode, k as DiagramAnchor, D as DiagramData, l as DiagramDerivePose, m as DiagramEdge, n as DiagramLabel, o as DiagramMark, d as DiagramRouter, p as DiagramSceneData, a as DiagramSceneOptions, q as DiagramTextStyle, E as EdgeStyle, G as GROUP_DERIVE_POSE, r as GroupPoseOptions, N as NodeStyle, s as anchorDerivePose, t as boxAround, u as diagramAnchorOf, v as diagramEdgeOf, w as diagramGroupOf, x as diagramLabelOf, y as diagramMarkOf, z as diagramScene, B as edgeIdOf, C as groupDerivePose, F as layoutOwnsPort, H as layoutOwnsRoute, I as markShape, J as registerMarkShape } from './fromData-GKqRgPFs.js';
1
+ import { g as Port, h as DiagramNodeLike, i as DiagramNodeReader, O as Outline, a as Row, M as MeasureRowText, C as ContainerRole, j as DiagramContainer, k as ContainerHeader, c as DiagramLabel, l as LabelSpot, E as EdgeHop, R as RowTextStyle, m as Bounds$2, e as LayoutOptions, n as LayoutResult, G as Graph, d as LayoutFn, o as GraphSource, p as LayoutPlanner, q as LayoutDirection, L as LayoutPorts, r as LayoutPlan, s as GraphNodeLike, S as StyleField, F as FontField } from './types-BbHunLXm.js';
2
+ export { t as BodyFloor, u as BodyNodeSpec, B as BodySpec, v as BuildBodyOptions, w as BuildGraphOptions, x as DEFAULT_GROUP_INSET, y as DEFAULT_HOP_SIZE, z as DEFAULT_NODE_GAP, A as DEFAULT_RANK_GAP, H as DIAGRAM_TRAIT_KEY, D as DiagramGroup, f as DiagramNode, I as DiagramNodeEntry, J as EdgeLabelRoom, K as GraphEdge, N as GraphGroup, Q as GraphNode, T as GroupInset, U as HOPS_DOC_KEY, V as HopsDocValue, W as LABEL_PLACEMENT, X as LayoutAxes, Y as PORT_LABEL_GAP, Z as PerimeterPortLabelBox, P as PortAnchor, _ as PortLabelPlacement, $ as PortSite, b as PortSpec, a0 as RowBox, a1 as RowNodeData, a2 as RowPort, a3 as RowPortBox, a4 as Slot, a5 as anchorOffset, a6 as axesFor, a7 as bodyBox, a8 as bodyOutline, a9 as bodyTrait, aa as boxForContent, ab as buildBody, ac as buildGraph, ad as canvasMeasure, ae as contentBox, af as createDiagramNodes, ag as dataKeyReader, ah as diagramContainerOf, ai as diagramLabelOf, aj as diagramNodeOf, ak as expandGroupEdges, al as graphOrder, am as headerBox, an as insetOf, ao as isPinned, ap as layoutBody, aq as layoutRowPorts, ar as marginOf, as as measureBody, at as outlinePath, au as packAcross, av as packClusters, aw as pinnedSet, ax as planOf, ay as plannerPlan, az as portLabelBox, aA as portLabelsOf, aB as rankGaps, aC as seededOrder, aD as settle, aE as sizeToBody, aF as titleIdOf, aG as translated, aH as untilSettled } from './types-BbHunLXm.js';
3
+ import { P as PortsOptions, A as AvoidInput, a as AvoidRouter, b as AvoidOptions, c as AvoidRoutes, d as PlaceLabelsOptions, F as ForceOptions } from './layout.entry-CH9gc0CY.js';
4
+ export { e as AVOID_DEFAULTS, f as AvoidEdge, g as AvoidEnd, h as AvoidLabel, i as AvoidObstacle, j as AvoidPort, k as AvoidUpdateOptions, C as COMPASS, D as DEFAULT_PORTS, l as ForceBody, m as ForceRelaxation, n as Forest, L as LabelPlacements, o as LayeredPlan, p as PlaceLabel, q as PlaceLabelsInput, r as PlaceRoute, s as backEdges, t as chain, u as createAvoidRouter, v as edgeHops, w as footprintNode, x as force, y as forceRelaxation, z as forestOf, B as labelCenter, E as layered, G as layeredPlan, H as outlinePolyline, I as placeLabels, J as portOf, K as portSitesOf, M as portsOf, N as portsOnOutline, O as ranksByLength, Q as ranksOf, R as rayHit, S as routeHolds, T as tree } from './layout.entry-CH9gc0CY.js';
5
+ import { Vec2, ActionDeps, Action, InvocationCtx, TargetPredicate, GestureBinding, Contribution, DerivedDep, Path, SceneRegistry, paintsLayer, PoseDescriptor, ChromeState, CommandFill, CommandStroke, CursorSpec, Affordance, Stroke, Tool, Op, AddNodeSpec, RectPose, NodeId, Scene, LayoutStrategy, ContainerBounds, RenderLayer, TransformFollower, PlacedPage, Bounds as Bounds$3, GatedLayer, Fill, NodeShapeEntry, Paint, View, SelectionApi } from '@weasel-js/core';
6
+ import { Vec2 as Vec2$1, Path as Path$2 } from '@weasel-js/core/math';
7
+ import { c as DataEdge, a as DiagramData, b as DiagramSceneOptions, f as DiagramSpec, g as EdgeEnd, N as NodeStyle, h as DiagramSceneData, i as DiagramEdge, O as OffPageSplit, D as DiagramTheme, j as DataContainer, E as EdgeStyle, d as DataNode } from './dataTypes-B-iEwKZp.js';
8
+ export { A as ANCHOR_DERIVE_POSE, k as DEFAULT_LANE_SIZE, l as DEFAULT_POOL_ACROSS, m as DIAGRAM_ANCHOR, n as DIAGRAM_GROUP, o as DIAGRAM_ROLES, p as DIAGRAM_THEME_KEY, q as DataGroup, r as DataLane, s as DataMark, t as DiagramAnchor, u as DiagramDerivePose, v as DiagramFont, w as DiagramMark, x as DiagramRole, e as DiagramRouter, y as DiagramTextStyle, z as EDGE_STROKE_WIDTH, G as GROUP_DERIVE_POSE, B as GroupPoseOptions, L as LANE_STROKE_WIDTH, C as NODE_STROKE_WIDTH, F as OffPageTag, H as anchorDerivePose, I as boxAround, J as diagramAnchorOf, K as diagramEdgeOf, M as diagramGroupOf, P as diagramMarkOf, Q as groupDerivePose, R as layoutOwnsPort, S as layoutOwnsRoute, T as layoutWritesRoute, U as markShape, V as offPageTagId, W as offPageTagOf, X as registerMarkShape, Y as rowTextStyle } from './dataTypes-B-iEwKZp.js';
9
+ import { IconRef } from '@weasel-js/icons';
10
+ import { Path as Path$1, Placement } from '@weasel-js/geom';
8
11
  import { EasingFn } from '@weasel-js/animator';
9
- import { Vec2 as Vec2$1 } from '@weasel-js/core/math';
10
12
  import * as react from 'react';
11
- import '@weasel-js/geom';
13
+ import { ReactNode } from 'react';
12
14
  import '@weasel-js/simulation';
13
15
 
16
+ /** The scene node id `diagramScene` gives an edge: its `id` when set, else one
17
+ * built from its ends, ports, and label. Two edges differing in any of those
18
+ * get different ids, an empty port or label included: a `.`, `>`, `:`, `/` or
19
+ * `\` in one of them is escaped with a backslash. */
20
+ declare const edgeIdOf: (e: DataEdge) => string;
21
+
22
+ /** Every spec carries an id — a node's own, `<id>/<k>` for its text,
23
+ * `<id>/mark:<i>` for its marks, `<edge id>/label`, a group's own and
24
+ * `<group id>/label`, a region's own and `<region id>/title` — so a later call's
25
+ * specs can be reconciled against this one's. Throws on a repeated id among
26
+ * nodes, groups, containers and lanes, which names two things as one. An edge whose
27
+ * end is not a node is dropped, and so is a repeat of an earlier edge with
28
+ * the same ends, ports and label: it would draw exactly on top of the first. */
29
+ declare function diagramScene<TLayer extends string>(data: DiagramData, opts: DiagramSceneOptions<TLayer> & {
30
+ layer: TLayer;
31
+ }): DiagramSpec<TLayer>[];
32
+ declare function diagramScene(data: DiagramData, opts?: DiagramSceneOptions): DiagramSpec[];
33
+
14
34
  /**
15
- * `DiagramEdge` — a connection between two participants.
16
- *
17
- * An edge is an ordinary leaf scene node with `dependsOn: [from, to]` and a
18
- * `derivePath` that runs a **router**. Being a scene node rather than a
19
- * plugin-owned render layer buys selection, hit-testing, hover, styling,
20
- * z-order, SVG export, undo, and copy/paste. The cost is that an edge costs
21
- * what a node costs — right for tens to hundreds of edges, wrong for a
22
- * 10k-edge force graph.
23
- *
24
- * **Author-dragged waypoints are data on the edge and the router routes
25
- * through them**, so a moved endpoint still re-routes.
26
- *
27
- * Arrowheads are not here. They are stroke markers, the same
28
- * `markerStart` / `markerEnd` any other stroke carries.
35
+ * The `'slide'` look of a reorder: the carried item under the pointer and the
36
+ * others in the places they would take, published as pose overrides so
37
+ * everything that derives its pose from them follows.
38
+ */
39
+
40
+ type Box$3 = {
41
+ x: number;
42
+ y: number;
43
+ width: number;
44
+ height: number;
45
+ };
46
+
47
+ /**
48
+ * Reorder: dragging one item of a drawn sequence — boxes in a row, rows in a
49
+ * column, the members of a group — to another place in it. The item follows
50
+ * the pointer along the sequence's axis and lands in the gap nearest its
51
+ * middle. A `'bar'` drag marks that gap with an insertion bar; a `'slide'`
52
+ * drag slides the other items into the places they would take. Either way
53
+ * the release hands the move to a commit, and nothing is written to the scene.
54
+ */
55
+
56
+ /** The action that drags an item of a sequence to another place in it. */
57
+ declare const REORDER_ACTION_ID = "diagram.reorder";
58
+ /** One item of a sequence, in world units. */
59
+ interface ReorderItem {
60
+ /** The scene node drawn for it. */
61
+ id: string;
62
+ bounds: Box$3;
63
+ /** Where a press picks it up. Default `bounds`; `null` never picks it up, though it keeps its gaps. */
64
+ grip?: Box$3 | null;
65
+ /** The scene nodes that move with it, in either `show` mode. Default `[id]`. */
66
+ carries?: readonly string[];
67
+ }
68
+ /** A place an item can land: before `items[index]`, or after the last at `items.length`. */
69
+ interface ReorderGap {
70
+ index: number;
71
+ /** The insertion bar's two ends. */
72
+ a: Vec2;
73
+ b: Vec2;
74
+ }
75
+ /** A drawn sequence: its items in order along `axis`, and the gaps between them. */
76
+ interface ReorderSlots {
77
+ axis: 'x' | 'y';
78
+ items: readonly ReorderItem[];
79
+ gaps: readonly ReorderGap[];
80
+ }
81
+ /** The item at index `from` dropped in gap `to`, and every item's id in the order that leaves. */
82
+ interface ReorderMove {
83
+ id: string;
84
+ from: number;
85
+ to: number;
86
+ order: readonly string[];
87
+ }
88
+ /** Options for {@link createReorderAction}. */
89
+ interface ReorderOptions {
90
+ /** Default {@link REORDER_ACTION_ID}. */
91
+ id?: string;
92
+ /** Default 'Reorder'. */
93
+ label?: string;
94
+ /** The sequence a press at `at` picks from, as drawn now, or `null` when there is none. */
95
+ slots: (deps: ActionDeps, at: Vec2) => ReorderSlots | null;
96
+ /** Deps `slots` reads beyond `scene`. */
97
+ requires?: Action['requires'];
98
+ /**
99
+ * `'bar'` (default) carries the item and draws an insertion bar at its
100
+ * gap. `'slide'` carries everything each item `carries` as pose overrides,
101
+ * so what derives from them follows, and slides the others into place; the
102
+ * overrides stay after a commit until the scene next changes.
103
+ */
104
+ show?: 'bar' | 'slide';
105
+ /** Whether a drop may land. The bar draws refused, or nothing slides, where not. Default: every drop. */
106
+ canDrop?: (move: ReorderMove) => boolean;
107
+ /** Called once, on release over a gap that is not the item's own and that `canDrop` allows. */
108
+ commit: (move: ReorderMove, ctx: InvocationCtx) => void;
109
+ }
110
+ /**
111
+ * The slots of items laid out in order along `axis`: a gap halfway between
112
+ * each pair, its bar spanning both across the axis, and one beyond each end,
113
+ * as far out as the nearest interior gap's half, or `END_GAP / 2` with none.
29
114
  */
115
+ declare function sequenceSlots(axis: 'x' | 'y', items: readonly ReorderItem[]): ReorderSlots;
116
+ /** The `diagram.reorder` action: an ongoing drag carrying one item of a sequence. */
117
+ declare function createReorderAction(opts: ReorderOptions): Action;
118
+ /** The binding that starts a reorder: a drag pressed on `on`, by default anywhere; the action declines off an item's grip. */
119
+ declare function reorderBinding(actionId?: string, on?: TargetPredicate): GestureBinding;
120
+ /** The reorder action and its binding, to pass as `ambient`. */
121
+ declare function reorderContribution(opts: ReorderOptions & {
122
+ on?: TargetPredicate;
123
+ }): Contribution;
30
124
 
31
- /** What a router is given: the two resolved ends, and the author's waypoints
32
- * between them. */
125
+ /**
126
+ * The routers an edge is drawn with: functions from two resolved ends and the
127
+ * waypoints between them to the points the edge runs through. `edge` resolves
128
+ * the ends and calls one by the key the edge names.
129
+ */
130
+
131
+ /** What a router is given: the two resolved ends, the author's waypoints
132
+ * between them, and the route stored on the edge, when it holds one. */
33
133
  interface RouteRequest {
34
134
  from: Port;
35
135
  to: Port;
36
- waypoints: readonly Vec2[];
136
+ waypoints: readonly Vec2$1[];
137
+ route?: readonly Vec2$1[] | undefined;
37
138
  }
38
139
  /** A router returns the points the edge runs through, `from.point` first and
39
140
  * `to.point` last. */
40
- type Router = (req: RouteRequest) => readonly Vec2[];
141
+ type Router = (req: RouteRequest) => readonly Vec2$1[];
41
142
  /** The straight run between the two ends, through any waypoints. */
42
143
  declare const straight: Router;
43
144
  /**
@@ -59,8 +160,33 @@ declare const orthogonal: Router;
59
160
  * same thing.
60
161
  */
61
162
  declare const bezier: Router;
163
+ /**
164
+ * The route the obstacle-avoiding router stored on the edge, while it still
165
+ * fits the ends and passes every waypoint; else `orthogonal` through the stops,
166
+ * so an end moved by something that did not reroute still draws sensibly.
167
+ * The route itself is computed at edit time (`useAvoidRouting`).
168
+ */
169
+ declare const avoid: Router;
62
170
  /** The routers this package ships. A consumer's own go in the same shape. */
63
171
  declare const ROUTERS: Readonly<Record<string, Router>>;
172
+
173
+ /**
174
+ * `DiagramEdge` — a connection between two participants.
175
+ *
176
+ * An edge is an ordinary leaf scene node with `dependsOn: [from, to]` and a
177
+ * `derivePath` that runs a **router**. Being a scene node rather than a
178
+ * plugin-owned render layer buys selection, hit-testing, hover, styling,
179
+ * z-order, SVG export, undo, and copy/paste. The cost is that an edge costs
180
+ * what a node costs — right for tens to hundreds of edges, wrong for a
181
+ * 10k-edge force graph.
182
+ *
183
+ * **Author-dragged waypoints are data on the edge and the router routes
184
+ * through them**, so a moved endpoint still re-routes.
185
+ *
186
+ * Arrowheads are not here. They are stroke markers, the same
187
+ * `markerStart` / `markerEnd` any other stroke carries.
188
+ */
189
+
64
190
  /**
65
191
  * The port an end resolves to: the one it named, at whichever of its places
66
192
  * faces `toward` most directly, else the port facing `toward` most directly.
@@ -84,12 +210,36 @@ interface EdgeRouteOptions<TPose> extends PortsOptions<TPose> {
84
210
  * sides {@link selfLoop} picks, and where the author set no waypoints the
85
211
  * router is handed that rule's point outside the node as one.
86
212
  *
213
+ * An edge carrying `hops` bows over each one that still lies on its route.
214
+ *
87
215
  * Returns `null` — nothing to draw — when the node is not an edge, when either
88
216
  * dependency is gone, or when an endpoint offers no ports at all.
89
217
  */
90
218
  declare function edgeDerivePath<TPose>(opts?: EdgeRouteOptions<TPose>): (node: {
91
219
  data: unknown;
92
220
  }, deps: readonly (DerivedDep<TPose> | undefined)[]) => Path | null;
221
+ /** An edge's route as {@link edgeDerivePath} draws it, before it becomes a path. */
222
+ interface ResolvedRoute {
223
+ /** The two ends, resolved. */
224
+ from: Port;
225
+ to: Port;
226
+ /** What the router was handed between them: the author's waypoints, or a
227
+ * self-loop's turning point. */
228
+ waypoints: readonly Vec2[];
229
+ /** The router's answer, `from.point` first and `to.point` last. */
230
+ points: readonly Vec2[];
231
+ /** Set while the edge is split across pages (`DiagramEdge.offPage`): the
232
+ * two runs drawn in place of `points`, one out of `from` to its tag's
233
+ * side and one from the other tag's side into `to`. */
234
+ stubs?: readonly [readonly Vec2[], readonly Vec2[]];
235
+ }
236
+ /** How far a split edge's stub runs out of its shape, in world units. */
237
+ declare const OFF_PAGE_STUB = 24;
238
+ /** Routes an edge between its two dependencies the way {@link edgeDerivePath}
239
+ * does, answering the route itself; null where that draws nothing. */
240
+ declare function edgeRouter<TPose>(opts?: EdgeRouteOptions<TPose>): (node: {
241
+ data: unknown;
242
+ }, deps: readonly (DerivedDep<TPose> | undefined)[]) => ResolvedRoute | null;
93
243
  /** Registry key for {@link EDGE_DERIVE_PATH}. */
94
244
  declare const DIAGRAM_EDGE = "diagram:edge";
95
245
  /** The default edge router, as one stable function reference so `toJSON` can
@@ -144,6 +294,14 @@ interface ParticipantPose<TPose> {
144
294
  * paint (`ChromeState.layerIsPainted`, `ViewApi.layerIsPainted`). */
145
295
  layer?: string;
146
296
  }
297
+ /** Whether a participant's ports are drawn, grabbed and landed on. A hidden
298
+ * or locked node gets none, as it gets no selection or hover chrome either,
299
+ * and nor does one on a layer the asking view does not paint. */
300
+ declare function offersPorts(p: {
301
+ hidden?: boolean;
302
+ locked?: boolean;
303
+ layer?: string;
304
+ }, view?: Parameters<typeof paintsLayer>[0]): boolean;
147
305
  /** Where the affordance gets its participants. A thunk rather than a scene so
148
306
  * the geometry is testable without one, and so a consumer whose participants
149
307
  * come from somewhere else needs no adapter. */
@@ -199,6 +357,36 @@ declare function portScratchOf(hit: {
199
357
  */
200
358
  declare function createPortAffordance<TPose>(participants: ParticipantSource<TPose>, opts?: PortAffordanceOptions<TPose>): Affordance;
201
359
 
360
+ /** An end on a participant's body rather than on one of its ports. `point` is
361
+ * where the pointer was, in world coordinates. */
362
+ interface BodyEnd {
363
+ kind: 'body';
364
+ nodeId: string;
365
+ point: Vec2$1;
366
+ }
367
+ /** Either end of a connect. */
368
+ type ConnectEnd = Port | BodyEnd;
369
+ /** Whether a connect end lands on a node's body rather than a port. */
370
+ declare function isBodyEnd(end: ConnectEnd): end is BodyEnd;
371
+ /** A body under the pointer, and the participant it belongs to. */
372
+ interface BodyHit<TPose> {
373
+ end: BodyEnd;
374
+ participant: ParticipantPose<TPose>;
375
+ }
376
+ /** The view a connect started in, which decides what layers it may reach. */
377
+ type ConnectView = Parameters<typeof offersPorts>[1];
378
+ /**
379
+ * The topmost participant whose body contains `at`, or `null`.
380
+ *
381
+ * Its outline when it declares one, else its bounds, both taken in the pose's
382
+ * unrotated frame. Edges, edge labels and group boxes are not bodies, and nor
383
+ * is anything the reader does not take as a participant or that `offersPorts`
384
+ * turns away.
385
+ */
386
+ declare function bodyAt<TPose>(participants: ParticipantSource<TPose>, at: Vec2$1, opts?: PortsOptions<TPose> & {
387
+ view?: ConnectView;
388
+ }): BodyHit<TPose> | null;
389
+
202
390
  /**
203
391
  * The connect gesture — dragging one port onto another to author an edge.
204
392
  *
@@ -215,17 +403,26 @@ declare function createPortAffordance<TPose>(participants: ParticipantSource<TPo
215
403
  *
216
404
  * One resolver answers both the live preview and the commit, so the preview
217
405
  * cannot lie about what releasing will do.
406
+ *
407
+ * With `bodies`, a release over a participant's body away from any port lands
408
+ * on the body (`connectTargets`); with `startFrom: 'body'`, so can the press.
218
409
  */
219
410
 
220
411
  /** The default action id, and what {@link connectBinding} points at. */
221
412
  declare const CONNECT_ACTION_ID = "diagram.connect";
222
- /** Whether an edge may run from `from` to `to`. */
223
- type CanConnect = (from: Port, to: Port) => boolean;
224
- /** The edge a finished connect describes. Both ends are resolved ports, so a
225
- * consumer minting the node has nothing left to look up. */
413
+ /** The edge end a reconnect is carrying: the scene id of the edge, and which end. */
414
+ interface MovingEnd {
415
+ edge: string;
416
+ end: 'from' | 'to';
417
+ }
418
+ /** Whether an edge may run from `from` to `to`. `moving` is the end being
419
+ * dragged when the edge already exists, and absent for a new connect. */
420
+ type CanConnect = (from: ConnectEnd, to: ConnectEnd, moving?: MovingEnd) => boolean;
421
+ /** The edge a finished connect describes. Each end is a resolved port, or a
422
+ * body whose port the edge picks each time it is routed. */
226
423
  interface PendingEdge {
227
- from: Port;
228
- to: Port;
424
+ from: ConnectEnd;
425
+ to: ConnectEnd;
229
426
  /** Registry key for the router the new edge should name. */
230
427
  router: string;
231
428
  }
@@ -234,7 +431,8 @@ interface PendingEdge {
234
431
  * declare a `type` must declare the same one.
235
432
  *
236
433
  * A port with no type joins anything. Two different ports on the *same node*
237
- * may be joined: a self-edge is meaningful in a state machine.
434
+ * may be joined: a self-edge is meaningful in a state machine. A body is
435
+ * untyped, and never joins its own node.
238
436
  */
239
437
  declare const defaultCanConnect: CanConnect;
240
438
  /** Options for {@link createConnectAction}. Only `participants` is required. */
@@ -259,13 +457,22 @@ interface ConnectActionOptions<TPose> {
259
457
  * Default `'straight'`. */
260
458
  router?: string;
261
459
  routers?: Readonly<Record<string, Router>>;
460
+ /** A release over a participant's body, with no port in reach, lands on the
461
+ * body. Default false. */
462
+ bodies?: boolean;
463
+ /** `'body'`: a press that is not on a port starts from the participant
464
+ * under it. Default `'port'`, where such a press falls through. */
465
+ startFrom?: 'port' | 'body';
262
466
  /**
263
- * Mints and commits the edge. Called once, on release over a valid port.
467
+ * Mints and commits the edge. Called once, on release over a valid target.
264
468
  *
265
469
  * Defaults to {@link commitEdgeToScene} against `deps.scene`. Override it to
266
470
  * choose the edge node's data, its layer, or its stroke.
267
471
  */
268
472
  commit?: (edge: PendingEdge, ctx: InvocationCtx) => void;
473
+ /** What the default commit draws the edge with. Default {@link DEFAULT_EDGE_STROKE}.
474
+ * Ignored when `commit` is given. */
475
+ edgeStroke?: Stroke;
269
476
  }
270
477
  /** What a connect-authored edge is drawn with, when the consumer overrides
271
478
  * nothing. */
@@ -277,67 +484,1109 @@ declare const DEFAULT_EDGE_STROKE: Stroke;
277
484
  * The string form of `target` rather than a predicate, because it ranks higher
278
485
  * in specificity: a bare `{ kind: 'drag' }` on the select tool cannot outrank it.
279
486
  */
280
- declare function connectBinding(actionId?: string): GestureBinding;
281
- /** The action id that absorbs a press on a port. */
282
- declare const GRAB_PORT_ACTION_ID = "diagram.grabPort";
487
+ declare function connectBinding(actionId?: string): GestureBinding;
488
+ /** The action id that absorbs a press on a port. */
489
+ declare const GRAB_PORT_ACTION_ID = "diagram.grabPort";
490
+ /**
491
+ * Absorbs a press on a port, and does nothing else.
492
+ *
493
+ * A port claims the press **protocol**, not one gesture in it: `pointerDown`,
494
+ * `click` and `drag` are a single claimable `'pointer'` token, and an exclusive
495
+ * claim bars every binding whose target does not consult the affordance. So a
496
+ * bundle that binds only `drag` leaves the pointerdown with nowhere to go, and
497
+ * the dispatcher drops the press — the drag it would have grown into never
498
+ * happens.
499
+ */
500
+ declare function grabPortAction(id?: string): Action;
501
+ /** The two bindings that keep a port's claim from dropping the press. `kind`
502
+ * names another affordance that claims the press protocol the same way. */
503
+ declare function grabPortBindings(actionId?: string, kind?: string): GestureBinding[];
504
+ /**
505
+ * The default commit: one leaf node carrying the edge trait, added to
506
+ * `deps.scene`. One `add` is one history entry, so the edge undoes in one.
507
+ *
508
+ * The edge lands on the **source node's** layer rather than the bottom one.
509
+ */
510
+ declare function commitEdgeToScene(edge: PendingEdge, ctx: InvocationCtx, opts?: {
511
+ stroke?: Stroke;
512
+ }): void;
513
+ /**
514
+ * The `diagram.connect` action: an ongoing drag whose preview is an ephemeral
515
+ * edge and whose commit is one op batch.
516
+ */
517
+ declare function createConnectAction<TPose>(opts: ConnectActionOptions<TPose>): Action;
518
+
519
+ /** The connector tool's id. */
520
+ declare const CONNECTOR_TOOL_ID = "diagram.connector";
521
+ /** The action the connector tool binds a drag to. */
522
+ declare const CONNECTOR_ACTION_ID = "diagram.connectorDraw";
523
+ /** The connector tool's definition, outside React. `id`, `startFrom` and
524
+ * `bodies` are the tool's own. */
525
+ declare function connectorTool<TPose>(opts: ConnectActionOptions<TPose>): Tool;
526
+ /** {@link connectorTool}, rebuilt when one of its options changes rather than
527
+ * when the bag holding them does. */
528
+ declare function useConnectorTool<TPose>(opts: ConnectActionOptions<TPose>): Tool;
529
+
530
+ /**
531
+ * Stencils: the shapes a palette offers, as data, and what one becomes when it
532
+ * is drawn — a `buildBody` body whose rows are ordinary text nodes.
533
+ */
534
+
535
+ /** One shape a palette offers. `size` is what a click places; `rows` default
536
+ * to one empty label, so the body has a text node to type into. `icon` is its
537
+ * tool's glyph in a palette. */
538
+ interface DiagramStencil {
539
+ id: string;
540
+ label: string;
541
+ outline: Outline;
542
+ size: {
543
+ width: number;
544
+ height: number;
545
+ };
546
+ rows?: readonly Row[];
547
+ icon?: IconRef;
548
+ }
549
+ /** The basic flowchart symbols. */
550
+ declare const FLOWCHART_STENCILS: readonly DiagramStencil[];
551
+ /** The insert kind a stencil's tool passes to the `insert` dep. */
552
+ declare const stencilKind: (id: string) => string;
553
+ /** The stencil id an insert kind names, or `null` for a kind that is no stencil's. */
554
+ declare function stencilIdOf(kind: string): string | null;
555
+ type Bounds$1 = {
556
+ x: number;
557
+ y: number;
558
+ width: number;
559
+ height: number;
560
+ };
561
+ /**
562
+ * The ops that insert `stencil` at `bounds`: its container first, then one
563
+ * text node per text row. Applied as one batch, they are one undo entry.
564
+ * `style` colors the body and its text; default `diagramScene`'s node style.
565
+ * `font` is the face its text rows fall back on; default 12px sans-serif.
566
+ * `parent` is the container the body goes in; default the top level.
567
+ */
568
+ declare function stencilBuild<TLayer extends string>(stencil: DiagramStencil, bounds: Bounds$1, opts: {
569
+ layer: TLayer;
570
+ newId: () => string;
571
+ measure?: MeasureRowText;
572
+ style?: NodeStyle;
573
+ font?: {
574
+ fontFamily: string;
575
+ fontSize: number;
576
+ };
577
+ parent?: string | null;
578
+ }): {
579
+ id: string;
580
+ ops: Op[];
581
+ };
582
+
583
+ /**
584
+ * The node specs of a region — a container, a pool, or a lane — and its title,
585
+ * which a stencil drawn on the canvas and a `DiagramData` container both build
586
+ * from.
587
+ */
588
+
589
+ /** A region's node spec, always with an id. */
590
+ type RegionSpec<TLayer extends string> = AddNodeSpec<DiagramSceneData, TLayer, RectPose> & {
591
+ id: NodeId;
592
+ };
593
+ /** Options for `containerBuild`. */
594
+ interface ContainerBuildOptions<TLayer extends string> {
595
+ layer: TLayer;
596
+ newId: () => string;
597
+ /** The box's fill, stroke and title colors. Default `diagramScene`'s node style. */
598
+ style?: NodeStyle;
599
+ /** The container the new one goes in. Default the top level. */
600
+ parent?: string | null;
601
+ /** A pool's header colors and its lanes' bodies in turn. Default `style` for both. */
602
+ laneStyles?: {
603
+ header: NodeStyle;
604
+ bodies: readonly NodeStyle[];
605
+ };
606
+ }
607
+ /** Options for {@link regionSpecs}. */
608
+ interface RegionOptions<TLayer extends string> {
609
+ id: string;
610
+ layer: TLayer;
611
+ /** Default the top level. */
612
+ parent?: string | null;
613
+ /** Default `diagramScene`'s node style. */
614
+ style?: NodeStyle;
615
+ /** Marks a region whose box is fitted to its members each time it is built from data. */
616
+ fitted?: boolean;
617
+ /** The title's family. Default sans-serif. */
618
+ fontFamily?: string;
619
+ }
620
+ /** The node specs of one region, and its title unless `title` is null. */
621
+ declare function regionSpecs<TLayer extends string>(role: ContainerRole, axis: 'x' | 'y', pose: RectPose, title: string | null, opts: RegionOptions<TLayer>): RegionSpec<TLayer>[];
622
+ /** The lane specs a new pool at `at` starts with. */
623
+ declare function firstLanes<TLayer extends string>(poolId: string, axis: 'x' | 'y', at: RectPose, opts: ContainerBuildOptions<TLayer>): RegionSpec<TLayer>[];
624
+
625
+ /**
626
+ * The container stencils a palette offers, what one becomes when it is drawn,
627
+ * and the edits on one: adding a lane to a pool, and releasing a container's
628
+ * members.
629
+ */
630
+
631
+ /** One container a palette offers. A pool stacks its lanes along `axis`. */
632
+ interface ContainerStencil {
633
+ id: string;
634
+ label: string;
635
+ role: 'container' | 'pool';
636
+ axis?: 'x' | 'y';
637
+ size: {
638
+ width: number;
639
+ height: number;
640
+ };
641
+ /** The glyph a palette draws on its button. */
642
+ icon?: IconRef;
643
+ }
644
+ /** A titled box, and pools of rows and of columns. */
645
+ declare const CONTAINER_STENCILS: readonly ContainerStencil[];
646
+ type Bounds = {
647
+ x: number;
648
+ y: number;
649
+ width: number;
650
+ height: number;
651
+ };
652
+ type AnyScene$3 = Scene<unknown, string, unknown>;
653
+ /** The ops that insert `stencil` at `bounds`: the region and its title, and a
654
+ * pool's first lanes. Applied as one batch, they are one undo entry. */
655
+ declare function containerBuild<TLayer extends string>(stencil: ContainerStencil, bounds: Bounds, opts: ContainerBuildOptions<TLayer>): {
656
+ id: string;
657
+ ops: Op[];
658
+ };
659
+ /** The axis a pool stacks its lanes along, read off its header. */
660
+ declare const poolAxisOf: (pool: DiagramContainer) => "x" | "y";
661
+ /** The lanes of `poolId`, in the order they stack. */
662
+ declare function lanesOf(scene: AnyScene$3, poolId: string): NodeId[];
663
+ /**
664
+ * Add a lane to `poolId` before the lane at `index`, or at the end of the
665
+ * stack, as one history entry. The pool grows to hold it. Returns the new
666
+ * lane's id, or null when `poolId` is not a pool.
667
+ */
668
+ declare function addLane(scene: AnyScene$3, poolId: string, index?: number, style?: NodeStyle): string | null;
669
+ /**
670
+ * Remove container `id` and keep its members, which take its place in its
671
+ * parent, as one history entry. A pool's members are its lanes' members, and
672
+ * a lane's go past its pool. Connectors on what is removed go with it.
673
+ */
674
+ declare function releaseMembers(scene: AnyScene$3, id: string): void;
675
+
676
+ /** The tool that draws `stencil`, a shape's or a container's: its id is the stencil's insert kind. */
677
+ declare function stencilTool(stencil: Pick<DiagramStencil, 'id' | 'label' | 'icon'>): Tool;
678
+ /** {@link stencilTool}, rebuilt only when the stencil changes. */
679
+ declare function useStencilTool(stencil: Pick<DiagramStencil, 'id' | 'label' | 'icon'>): Tool;
680
+ /** Options for {@link useStencilInsert}. */
681
+ interface StencilInsertOptions {
682
+ /** The layer bodies are inserted on. Default: the scene's first layer. */
683
+ layer?: string;
684
+ measure?: MeasureRowText;
685
+ /** The body's fill, stroke and text colors. Default `diagramScene`'s node style. */
686
+ style?: NodeStyle;
687
+ /** The face the body's text rows fall back on. Default 12px sans-serif. */
688
+ font?: {
689
+ fontFamily: string;
690
+ fontSize: number;
691
+ };
692
+ /** Container stencils to draw beside the shapes (`CONTAINER_STENCILS`). */
693
+ containers?: readonly ContainerStencil[];
694
+ /** Container stencils' box and title colors. Default `style`. */
695
+ containerStyle?: NodeStyle;
696
+ /** A new pool's header colors and its lanes' bodies in turn. Default `containerStyle`. */
697
+ laneStyles?: {
698
+ header: NodeStyle;
699
+ bodies: readonly NodeStyle[];
700
+ };
701
+ }
702
+ /**
703
+ * Registers the `insert` dep for stencil kinds. Any other kind goes to the
704
+ * `insert` dep this one displaced, so core's rect, ellipse and text tools
705
+ * keep working beside the stencils. A stencil drawn inside a container or a
706
+ * lane becomes its member (`diagramDropParentAt`).
707
+ */
708
+ declare function useStencilInsert(stencils: readonly DiagramStencil[], opts?: StencilInsertOptions): void;
709
+
710
+ type Box$2 = {
711
+ x: number;
712
+ y: number;
713
+ width: number;
714
+ height: number;
715
+ };
716
+ /** Where a container's title sits: its header strip, turned a quarter to run
717
+ * up a left header. */
718
+ declare function titlePose(bounds: Box$2, header: ContainerHeader | undefined): RectPose;
719
+
720
+ /**
721
+ * `diagramContainerLayout` — free placement under a header. A member stays
722
+ * wherever it is dropped or the container is resized to; only the title is
723
+ * placed, in the header.
724
+ *
725
+ * A strategy sees ids and poses, never data, so it cannot tell a lane from a
726
+ * shape. Which nodes a container admits is `diagramCanDropInto`'s call.
727
+ */
728
+
729
+ /** Options for {@link diagramContainerLayout}. */
730
+ interface ContainerLayoutOptions {
731
+ /** Where the title sits; matches the container trait's own `header`. */
732
+ header?: ContainerHeader;
733
+ }
734
+ /** A free-placement layout whose drops land in the body below or beside `header`. */
735
+ declare function diagramContainerLayout(opts?: ContainerLayoutOptions): LayoutStrategy<RectPose>;
736
+
737
+ /**
738
+ * `laneStackLayout` — a pool's lanes, stacked along one axis in the order they
739
+ * sit and stretched across the body past the header. The pool's size along
740
+ * the stack is the sum of its lanes; its size across is the author's.
741
+ *
742
+ * Like every strategy it sees ids and poses only: the title is told apart by
743
+ * its name, and which nodes a pool admits (lanes) is `diagramCanDropInto`'s call.
744
+ */
745
+
746
+ /** Options for {@link laneStackLayout}. */
747
+ interface LaneStackOptions {
748
+ /** The axis lanes stack along: `'y'` for a pool of rows, `'x'` for columns. */
749
+ axis: 'x' | 'y';
750
+ /** The header's depth, across the stack. Default {@link POOL_HEADER_SIZE}. */
751
+ headerSize?: number;
752
+ }
753
+ /** A pool header's default depth. */
754
+ declare const POOL_HEADER_SIZE = 32;
755
+ /** The least a lane is along the stack. */
756
+ declare const MIN_LANE_SIZE = 40;
757
+ /** The header a pool stacking along `axis` has: across the stack, at its start. */
758
+ declare const poolHeader: (axis: "x" | "y", size?: number) => ContainerHeader;
759
+ /** Where lanes of the given sizes sit, in order, in a pool at `bounds`. */
760
+ declare function stackedLanes(axis: 'x' | 'y', bounds: ContainerBounds, header: ContainerHeader, lanes: readonly {
761
+ id: string;
762
+ size: number;
763
+ }[]): Map<string, RectPose>;
764
+ /** A pool stacking its lanes along `axis`. */
765
+ declare function laneStackLayout(opts: LaneStackOptions): LayoutStrategy<RectPose>;
766
+
767
+ /**
768
+ * The container layouts by registry key, as stable references so a saved
769
+ * scene finds them again (`withDiagramRegistry`).
770
+ */
771
+
772
+ /** A plain container's header. */
773
+ declare const CONTAINER_HEADER: ContainerHeader;
774
+ /** A lane's header depth, across its pool's stack. */
775
+ declare const LANE_HEADER_SIZE = 28;
776
+ /** The header a lane of a pool stacking along `axis` has. */
777
+ declare const laneHeader: (axis: "x" | "y") => ContainerHeader;
778
+ /** A titled container's layout key: free placement in the body below its header. */
779
+ declare const DIAGRAM_CONTAINER_LAYOUT = "diagram:container";
780
+ /** A pool's layout key when its lanes stack as rows, top to bottom. */
781
+ declare const DIAGRAM_POOL_ROWS_LAYOUT = "diagram:pool-rows";
782
+ /** A pool's layout key when its lanes stack as columns, left to right. */
783
+ declare const DIAGRAM_POOL_COLUMNS_LAYOUT = "diagram:pool-columns";
784
+ /** The layout key of a lane in a pool of rows: free placement beside its left header. */
785
+ declare const DIAGRAM_LANE_ROWS_LAYOUT = "diagram:lane-rows";
786
+ /** The layout key of a lane in a pool of columns: free placement below its top header. */
787
+ declare const DIAGRAM_LANE_COLUMNS_LAYOUT = "diagram:lane-columns";
788
+ /** Every container layout this package registers, by key. */
789
+ declare const CONTAINER_LAYOUTS: Readonly<Record<string, LayoutStrategy<RectPose>>>;
790
+ /** The layout key and header for a container of `role`; a pool or lane's
791
+ * follow the axis its pool stacks along. */
792
+ declare function containerShape(role: ContainerRole, axis?: 'x' | 'y'): {
793
+ layout: string;
794
+ header: ContainerHeader;
795
+ };
796
+
797
+ type SceneLike = {
798
+ get(id: never): {
799
+ id: string;
800
+ kind: 'leaf' | 'container';
801
+ data: unknown;
802
+ } | undefined;
803
+ };
804
+ /**
805
+ * The `canDropInto` dep for a diagram scene. A container or a lane takes
806
+ * shapes and other containers, a pool takes only lanes, and a lane goes
807
+ * nowhere but a pool. A stencil body, an edge, or a label takes nothing, and
808
+ * edges and labels are never dropped in: they stay where they are, drawn from
809
+ * what they are attached to. Any other container — a plain group — takes
810
+ * anything but a lane.
811
+ */
812
+ declare function diagramCanDropInto(scene: SceneLike): (parent: string, ids: readonly string[]) => boolean;
813
+ /** What {@link diagramDropParentAt} walks. */
814
+ interface DropParentScene {
815
+ readonly roots: readonly string[];
816
+ childrenOf(id: never): readonly string[];
817
+ get(id: never): {
818
+ id: string;
819
+ kind: 'leaf' | 'container';
820
+ data: unknown;
821
+ pose: unknown;
822
+ } | undefined;
823
+ }
824
+ /**
825
+ * The innermost container or lane whose body holds `point`, that would admit
826
+ * a new node of `role` (`null` for a shape): where an insert at `point` goes.
827
+ * Null for the top level — always so for a pool.
828
+ */
829
+ declare function diagramDropParentAt(scene: DropParentScene, point: {
830
+ x: number;
831
+ y: number;
832
+ }, role: ContainerRole | null): string | null;
833
+
834
+ /**
835
+ * The lane affordances on every pool: the boundary after each lane, which a
836
+ * drag moves to resize that lane, and the add-lane button past the end of the
837
+ * stack. Built the way the edge-end handles are: regions with a `null`
838
+ * `targetId`, composed into a layer whose id is the kind a press reports.
839
+ */
840
+
841
+ /** The layer id the lane affordances are composed into. */
842
+ declare const LANE_LAYER_ID = "diagram-lanes";
843
+ /** The affordance kind a press on a lane affordance reports. */
844
+ declare const LANE_AFFORDANCE_KIND: "layer:diagram-lanes";
845
+ /** What a press on a lane affordance hands the action: the boundary after
846
+ * `laneId`, or, with no lane, the add-lane button. */
847
+ interface LaneScratch {
848
+ targetId: string;
849
+ poolId: string;
850
+ laneId?: string;
851
+ }
852
+ /** Read a lane press's scratch back off the hit an action was handed. */
853
+ declare function laneScratchOf(hit: {
854
+ payload?: unknown;
855
+ } | null | undefined): LaneScratch | null;
856
+ type AnyScene$2 = Scene<unknown, string, unknown>;
857
+ /** A pool as the affordances see it: its box, the axis it stacks along, and its lanes in order. */
858
+ interface PoolLanes {
859
+ id: string;
860
+ axis: 'x' | 'y';
861
+ pose: RectPose;
862
+ lanes: {
863
+ id: string;
864
+ pose: RectPose;
865
+ }[];
866
+ }
867
+ /** Every pool in `scene` that is drawn and not locked. */
868
+ declare function poolsOf(scene: AnyScene$2): PoolLanes[];
869
+ /** Options for {@link laneLayer}. */
870
+ interface LaneLayerOptions {
871
+ /** Screen-pixel reach of a boundary either side of it. Default 4. */
872
+ hitRadiusPx?: number;
873
+ /** Screen-pixel diameter of the add-lane button. Default 14; 0 hides it. */
874
+ addSizePx?: number;
875
+ fill?: CommandFill;
876
+ stroke?: CommandStroke;
877
+ }
878
+ /** The affordance: a boundary region after each lane of each pool, and an add-lane button per pool. */
879
+ declare function createLaneAffordance(scene: AnyScene$2, opts?: LaneLayerOptions): Affordance;
880
+ /** The composed layer, for `CanvasExtensionApi.registerLayer`. */
881
+ declare function laneLayer(scene: AnyScene$2, opts?: LaneLayerOptions): RenderLayer<unknown>;
882
+
883
+ /**
884
+ * The container actions: dragging the boundary after a lane resizes it, the
885
+ * add-lane button adds one at the end of the stack, and Release members
886
+ * removes a container and keeps what it holds. The two lane gestures take a
887
+ * swappable commit; the default writes the scene.
888
+ */
889
+
890
+ /** The action that drags a lane's boundary. */
891
+ declare const LANE_RESIZE_ACTION_ID = "diagram.resizeLane";
892
+ /** The action the add-lane button runs. */
893
+ declare const ADD_LANE_ACTION_ID = "diagram.addLane";
894
+ /** The command that removes the selected containers and keeps their members. */
895
+ declare const RELEASE_MEMBERS_ACTION_ID = "diagram.releaseMembers";
896
+ type AnyScene$1 = Scene<unknown, string, unknown>;
897
+ /** A lane resized: its new size along its pool's stack. */
898
+ interface LaneResize {
899
+ poolId: string;
900
+ laneId: string;
901
+ size: number;
902
+ }
903
+ /** The default commit: the lane's and the pool's new size, as one history
904
+ * entry labeled "Resize lane". The pool's layout restacks the lanes after it. */
905
+ declare function commitLaneResizeToScene(resize: LaneResize, ctx: InvocationCtx): void;
906
+ /** Where everything stands with the lane at `index` of `pool` resized to `size`: the
907
+ * lane, its title, the pool and its title, and every later lane with what it holds. */
908
+ declare function laneResizeFrame(scene: AnyScene$1, pool: PoolLanes, index: number, size: number): Map<string, RectPose>;
909
+ /** Options for the container actions. */
910
+ interface LaneActionOptions extends LaneLayerOptions {
911
+ scene: AnyScene$1;
912
+ /** The selected ids, which Release members reads. */
913
+ selected?: () => readonly string[];
914
+ /** Defaults to {@link commitLaneResizeToScene}. */
915
+ commitResize?: (resize: LaneResize, ctx: InvocationCtx) => void;
916
+ /** Defaults to `addLane` on `deps.scene`, at the end of the stack. */
917
+ commitAddLane?: (poolId: string, ctx: InvocationCtx) => void;
918
+ /** Runs for each selected region in place of `releaseMembers`. */
919
+ commitRelease?: (id: string) => void;
920
+ }
921
+ /** The `diagram.resizeLane` action: an ongoing drag moving one lane's far boundary. */
922
+ declare function createLaneResizeAction(opts: LaneActionOptions): Action;
923
+ /** The `diagram.addLane` action: the add-lane button's click. */
924
+ declare function createAddLaneAction(opts: LaneActionOptions): Action;
925
+ /** The `diagram.releaseMembers` command: removes each selected container and
926
+ * keeps what it holds, in one history entry. */
927
+ declare function createReleaseMembersAction(opts: LaneActionOptions): Action;
928
+ /**
929
+ * Both halves of container editing: the lane layer to `registerLayer`, and
930
+ * the contribution to pass as `ambient`, which carries the lane boundary
931
+ * drag, the add-lane click, and the `diagram.releaseMembers` command. Like
932
+ * `diagramPorts`, one without the other fails quietly.
933
+ */
934
+ declare function diagramContainers(opts: LaneActionOptions): {
935
+ layer: RenderLayer<unknown>;
936
+ contribution: Contribution;
937
+ };
938
+
939
+ /**
940
+ * A double-click on a region's header: the action that reports which region's
941
+ * title to edit, and its binding.
942
+ */
943
+
944
+ /** The action a double-click on a region's header runs. */
945
+ declare const EDIT_CONTAINER_TITLE_ACTION_ID = "diagram.editContainerTitle";
946
+ /** The container, pool, or lane whose header holds `at`: the node under it, or a region around that. */
947
+ declare function regionHeaderAt(deps: ActionDeps | undefined, at: {
948
+ x: number;
949
+ y: number;
950
+ } | undefined): string | null;
951
+ /** The action that hands `commit` the region whose header a double-click landed on. It declines anywhere else. */
952
+ declare function editContainerTitleAction(commit: (id: string) => void): Action;
953
+ /** A double-click on a node's body; the action declines unless it lands in a region's header. */
954
+ declare function editContainerTitleBinding(): GestureBinding;
955
+
956
+ /**
957
+ * Moving an edge label along and beside its edge.
958
+ *
959
+ * The label layer (`labelDragLayer`) claims the press; this action moves the
960
+ * label. The drag previews the label's own data at the station the pointer
961
+ * proposes, and the pose that data derives, so the preview stands where the
962
+ * commit will.
963
+ */
964
+
965
+ /** The action that drags an edge label. */
966
+ declare const MOVE_LABEL_ACTION_ID = "diagram.moveLabel";
967
+ /** A label placed: where it now sits on its edge, or `null` to reset it to {@link LABEL_PLACEMENT}. */
968
+ interface LabelEdit {
969
+ labelId: string;
970
+ edgeId: string;
971
+ placement: DiagramLabel | null;
972
+ }
973
+ /** Options for {@link createLabelDragAction}. */
974
+ interface LabelDragOptions {
975
+ /** Defaults to {@link commitLabelToScene} against `deps.scene`. */
976
+ commit?: (edit: LabelEdit, ctx: InvocationCtx) => void;
977
+ id?: string;
978
+ }
979
+ /** `data` with its label trait at `spot`, owned by the author from now on:
980
+ * placement's `placed` is dropped, and placement won't move it again. */
981
+ declare function movedLabelData(data: unknown, spot: LabelSpot): Record<string, unknown>;
982
+ /** The default commit: the label's placement in `data.diagram.label`, as one
983
+ * history entry labeled "Move label", or "Reset label" for a `null` placement. */
984
+ declare function commitLabelToScene(edit: LabelEdit, ctx: InvocationCtx): void;
985
+ /** The `diagram.moveLabel` action: an ongoing drag moving one edge label along and beside its edge. */
986
+ declare function createLabelDragAction(opts?: LabelDragOptions): Action;
987
+
988
+ /**
989
+ * Handles on the ends of a selected edge — what makes an edge's end grabbable,
990
+ * so a drag can carry it onto another shape (`reconnect`).
991
+ *
992
+ * Built the way the port affordance is: point regions with a `null`
993
+ * `targetId` and no `hitKind`, composed into a layer whose id is the kind a
994
+ * press reports. See `portAffordance` for why both matter.
995
+ */
996
+
997
+ /** The layer id the edge-end handles are composed into. */
998
+ declare const EDGE_END_LAYER_ID = "diagram-edge-ends";
999
+ /** The affordance kind a press on an edge-end handle reports. */
1000
+ declare const EDGE_END_AFFORDANCE_KIND: "layer:diagram-edge-ends";
1001
+ /** What a press on an edge-end handle hands the reconnect action, as
1002
+ * `InvocationCtx.drag.affordance.payload`. */
1003
+ interface EdgeEndScratch {
1004
+ targetId: string;
1005
+ edgeId: string;
1006
+ end: 'from' | 'to';
1007
+ }
1008
+ /** Read an edge-end press's scratch back off the hit an action was handed. */
1009
+ declare function edgeEndScratchOf(hit: {
1010
+ payload?: unknown;
1011
+ } | null | undefined): EdgeEndScratch | null;
1012
+ /** An edge as it stands: its trait, the participants at its two ends, and
1013
+ * where its routed path starts and ends. */
1014
+ interface EdgeEnds<TPose> {
1015
+ edge: ParticipantPose<TPose>;
1016
+ trait: DiagramEdge;
1017
+ from: ParticipantPose<TPose>;
1018
+ to: ParticipantPose<TPose>;
1019
+ points: {
1020
+ from: Vec2$1;
1021
+ to: Vec2$1;
1022
+ };
1023
+ /** The route as the edge's own `derivePath` draws it. */
1024
+ route: ResolvedRoute;
1025
+ }
1026
+ /** Options shared by the edge-end affordance and the reconnect action. */
1027
+ interface EdgeEndOptions<TPose> extends PortsOptions<TPose> {
1028
+ routers?: Readonly<Record<string, Router>>;
1029
+ }
1030
+ /** Options for {@link createEdgeEndAffordance}. */
1031
+ interface EdgeEndAffordanceOptions<TPose> extends EdgeEndOptions<TPose> {
1032
+ /** Also the chrome-caps visibility id. Default {@link EDGE_END_LAYER_ID}. */
1033
+ id?: string;
1034
+ /** Screen-pixel hit radius. Default 8. */
1035
+ hitRadiusPx?: number;
1036
+ /** Screen-pixel side of the painted square. Default 8; 0 paints nothing. */
1037
+ sizePx?: number;
1038
+ fill?: CommandFill;
1039
+ stroke?: CommandStroke;
1040
+ cursor?: CursorSpec;
1041
+ }
1042
+ /** The affordance: one point region on each end of each selected edge. */
1043
+ declare function createEdgeEndAffordance<TPose>(participants: ParticipantSource<TPose>, selected: () => readonly string[], opts?: EdgeEndAffordanceOptions<TPose>): Affordance;
1044
+ /** The composed layer, for `CanvasExtensionApi.registerLayer`. Register it
1045
+ * after the port layer: the last-registered layer is hit first, and an edge's
1046
+ * end sits on a port. */
1047
+ declare function edgeEndLayer<TPose>(participants: ParticipantSource<TPose>, selected: () => readonly string[], opts?: EdgeEndAffordanceOptions<TPose>): RenderLayer<unknown>;
1048
+
1049
+ /**
1050
+ * Route editing — dragging a selected edge's waypoints and segments.
1051
+ *
1052
+ * The route handles (`waypointLayer`) claim the press; this action reshapes
1053
+ * the route. The drag previews the edge's own data with the new waypoints,
1054
+ * so its `derivePath` draws the preview exactly as the commit will.
1055
+ */
1056
+
1057
+ /** The action that drags a route handle. */
1058
+ declare const ROUTE_EDIT_ACTION_ID = "diagram.editRoute";
1059
+ /** An edge's route edited: its waypoints as they now stand. */
1060
+ interface RouteEdit {
1061
+ edgeId: string;
1062
+ waypoints: readonly Vec2$1[];
1063
+ }
1064
+ /** Options for the route-editing actions: the drag, the double-click that removes, and Reset route. */
1065
+ interface RouteEditOptions<TPose> extends EdgeEndOptions<TPose> {
1066
+ participants: ParticipantSource<TPose>;
1067
+ /** The selected edge ids, whose routes show handles. */
1068
+ selected: () => readonly string[];
1069
+ /** Screen pixels within which a dragged handle lines up with a neighbor
1070
+ * or a port's axis. Default 6. */
1071
+ snapPx?: number;
1072
+ /** Screen-pixel reach of a handle, as the handle layer's `hitRadiusPx`. Default 7. */
1073
+ hitRadiusPx?: number;
1074
+ /** Defaults to {@link commitRouteToScene} against `deps.scene`. */
1075
+ commit?: (edit: RouteEdit, ctx: InvocationCtx) => void;
1076
+ id?: string;
1077
+ }
1078
+ /** `data` with its edge trait routed through `waypoints`: owned by the author
1079
+ * from now on, so layout's mark is dropped, and no waypoints at all when there are none. */
1080
+ declare function routedData(data: unknown, trait: DiagramEdge, waypoints: readonly Vec2$1[]): Record<string, unknown>;
1081
+ /** The default commit: the edge's new waypoints in `data.diagram`, as one history entry labeled "Edit route". */
1082
+ declare function commitRouteToScene(edit: RouteEdit, ctx: InvocationCtx): void;
1083
+ /** The `diagram.editRoute` action: an ongoing drag reshaping one edge's route. */
1084
+ declare function createRouteEditAction<TPose>(opts: RouteEditOptions<TPose>): Action;
1085
+
1086
+ /** Polyline arithmetic shared by the routers and route editing. */
1087
+
1088
+ /** `points` without repeats, and without any interior point lying straight
1089
+ * between its neighbors. The first and last always stay. */
1090
+ declare function simplifyStops(points: readonly Vec2$1[]): Vec2$1[];
1091
+
1092
+ /**
1093
+ * Waypoint editing as pure math on an edge's route.
1094
+ *
1095
+ * The **stops** are the points a route must pass through: its `from` end, the
1096
+ * author's waypoints, and its `to` end. The **drawn** route is what the router
1097
+ * made of them. Every shipped router passes through each stop exactly, so the
1098
+ * drawn polyline splits at the stops and a leg's middle is found on it.
1099
+ *
1100
+ * Each edit answers the edge's new waypoints, never the whole route.
1101
+ */
1102
+
1103
+ /** A handle a selected edge shows along its route. `at` is where it sits, in world units. */
1104
+ type RouteHandle =
1105
+ /** Waypoint `index`: dragging moves it. */
1106
+ {
1107
+ kind: 'vertex';
1108
+ index: number;
1109
+ at: Vec2$1;
1110
+ }
1111
+ /** The middle of leg `leg`, between stops `leg` and `leg + 1`: dragging inserts a waypoint there. */
1112
+ | {
1113
+ kind: 'insert';
1114
+ leg: number;
1115
+ at: Vec2$1;
1116
+ }
1117
+ /** Segment `index` of an orthogonal route, which runs along `axis`: dragging slides it across. */
1118
+ | {
1119
+ kind: 'segment';
1120
+ index: number;
1121
+ axis: 'x' | 'y';
1122
+ at: Vec2$1;
1123
+ };
1124
+ /** The axis a segment runs along, or null when it is a point or slanted. */
1125
+ declare function segmentAxis(a: Vec2$1, b: Vec2$1): 'x' | 'y' | null;
1126
+ /** The handles an edge shows: a bar per segment under `orthogonal` and
1127
+ * `avoid`, else a dot per waypoint and a hollow dot per leg. */
1128
+ declare function routeHandles(drawn: readonly Vec2$1[], stops: readonly Vec2$1[], router: Router): RouteHandle[];
1129
+ /** The waypoints with waypoint `index` moved to `to`. */
1130
+ declare function dragVertex(stops: readonly Vec2$1[], index: number, to: Vec2$1): Vec2$1[];
1131
+ /** The waypoints with one at `at` inserted on leg `leg`: it becomes waypoint `leg`. */
1132
+ declare function insertWaypoint(stops: readonly Vec2$1[], leg: number, at: Vec2$1): Vec2$1[];
1133
+ /** The waypoints without waypoint `index`. */
1134
+ declare function removeWaypoint(stops: readonly Vec2$1[], index: number): Vec2$1[];
1135
+ /**
1136
+ * The waypoints of `drawn`, an orthogonal route, with segment `index` slid
1137
+ * `offset` across its axis: every interior bend of the new route, since the
1138
+ * orthogonal router recomputes elbows between stops. A segment touching a
1139
+ * port keeps a short stub there and jogs over, so the port end stays square.
1140
+ */
1141
+ declare function dragSegment(drawn: readonly Vec2$1[], index: number, offset: number): Vec2$1[];
1142
+ /**
1143
+ * The waypoints of an `avoid` route with segment `index` of `drawn` slid
1144
+ * `offset` across its axis and pinned there: its two ends join the author's
1145
+ * waypoints, in route order, and the router keeps the rest. A waypoint at one
1146
+ * of its ends moves with it, and a segment meeting a port jogs off it so the
1147
+ * port end stays square.
1148
+ */
1149
+ declare function pinSegment(drawn: readonly Vec2$1[], stops: readonly Vec2$1[], index: number, offset: number): Vec2$1[];
1150
+ /** The waypoints of an `avoid` route without those at either end of segment
1151
+ * `index`, which hands the segment back to the router; null when neither end is one. */
1152
+ declare function unpinSegment(drawn: readonly Vec2$1[], stops: readonly Vec2$1[], index: number): Vec2$1[] | null;
1153
+ /**
1154
+ * The waypoints with segment `index` straightened away: its neighbors run in
1155
+ * parallel, and the one touching no port slides onto the other's line. Null
1156
+ * when it is the first or last segment, or both neighbors touch a port.
1157
+ */
1158
+ declare function removeSegment(drawn: readonly Vec2$1[], index: number): Vec2$1[] | null;
1159
+
1160
+ /**
1161
+ * Handles along a selected edge's route — what makes its waypoints and
1162
+ * segments grabbable, so a drag can reshape the route (`waypointAction`).
1163
+ *
1164
+ * Built the way the edge-end handles are: point regions with a `null`
1165
+ * `targetId` and no `hitKind`, composed into a layer whose id is the kind a
1166
+ * press reports.
1167
+ */
1168
+
1169
+ /** The layer id the route handles are composed into. */
1170
+ declare const WAYPOINT_LAYER_ID = "diagram-waypoints";
1171
+ /** The affordance kind a press on a route handle reports. */
1172
+ declare const WAYPOINT_AFFORDANCE_KIND: "layer:diagram-waypoints";
1173
+ /** What a press on a route handle hands the route-edit actions, as the hit's `payload`. */
1174
+ interface WaypointScratch {
1175
+ targetId: string;
1176
+ edgeId: string;
1177
+ handle: RouteHandle;
1178
+ }
1179
+ /** Read a route-handle press's scratch back off the hit an action was handed. */
1180
+ declare function waypointScratchOf(hit: {
1181
+ payload?: unknown;
1182
+ } | null | undefined): WaypointScratch | null;
1183
+ /** An edge's route as the handles read it: its resolved ends, its stops, the
1184
+ * route drawn through them, the router that drew it, and the handles it shows. */
1185
+ interface EdgeRouteState {
1186
+ from: Port;
1187
+ to: Port;
1188
+ stops: readonly Vec2$1[];
1189
+ drawn: readonly Vec2$1[];
1190
+ router: Router;
1191
+ handles: readonly RouteHandle[];
1192
+ }
1193
+ /** The route state of an edge whose ends `ends` resolved. */
1194
+ declare function routeStateOf(ends: EdgeEnds<unknown>, routers?: Readonly<Record<string, Router>>): EdgeRouteState;
1195
+ /** Options for {@link createWaypointAffordance}. */
1196
+ interface WaypointAffordanceOptions<TPose> extends EdgeEndOptions<TPose> {
1197
+ /** Also the chrome-caps visibility id. Default {@link WAYPOINT_LAYER_ID}. */
1198
+ id?: string;
1199
+ /** Screen-pixel hit radius. Default 7. */
1200
+ hitRadiusPx?: number;
1201
+ /** Screen-pixel diameter of a waypoint's dot; an insert dot is three
1202
+ * quarters of it, and a segment bar twice as long. Default 8; 0 paints nothing. */
1203
+ sizePx?: number;
1204
+ fill?: CommandFill;
1205
+ stroke?: CommandStroke;
1206
+ cursor?: CursorSpec;
1207
+ }
1208
+ /** A route handle's default screen-pixel hit radius. */
1209
+ declare const WAYPOINT_HIT_PX = 7;
1210
+ /** The affordance: a region on each route handle of each selected edge. */
1211
+ declare function createWaypointAffordance<TPose>(participants: ParticipantSource<TPose>, selected: () => readonly string[], opts?: WaypointAffordanceOptions<TPose>): Affordance;
1212
+ /** The composed layer, for `CanvasExtensionApi.registerLayer`. Register it
1213
+ * after the port layer and before the edge-end layer: the last registered is
1214
+ * hit first, and an edge's end handle must win over a handle beside it. */
1215
+ declare function waypointLayer<TPose>(participants: ParticipantSource<TPose>, selected: () => readonly string[], opts?: WaypointAffordanceOptions<TPose>): RenderLayer<unknown>;
1216
+
1217
+ /**
1218
+ * The plugin as a `Contribution` bundle — one object a consumer hands to
1219
+ * `<SceneCanvas ambient={…}>`.
1220
+ *
1221
+ * **Ambient, not a tool.** A port is grabbable whatever tool is active:
1222
+ * `claimed` makes the bundle live for a press the port layer's affordance
1223
+ * claimed, and dormant otherwise.
1224
+ *
1225
+ * **The layer is not in here, on purpose.** `Contribution.overlay` is painted
1226
+ * and never hit-tested — only `CanvasExtensionApi.registerLayer` gets a
1227
+ * `hitTest` call — so the port layer as an overlay would paint every port and
1228
+ * make none of them grabbable. {@link diagramPorts} hands back both.
1229
+ */
1230
+
1231
+ /** The connect action's options and the port affordance's, in one bag. */
1232
+ interface DiagramContributionOptions<TPose> extends ConnectActionOptions<TPose>, PortAffordanceOptions<TPose> {
1233
+ }
1234
+ /** The bundle: the connect action and the one binding that reaches it. */
1235
+ declare function createDiagramContribution<TPose>(opts: DiagramContributionOptions<TPose>): Contribution;
1236
+ /**
1237
+ * Both halves of the port affordance: the layer to `registerLayer`, and the
1238
+ * contribution to pass as `ambient`.
1239
+ *
1240
+ * They are returned together because attaching one without the other fails
1241
+ * quietly — the layer alone paints ports that start no gesture, and the
1242
+ * contribution alone binds an affordance kind nothing ever reports.
1243
+ */
1244
+ declare function diagramPorts<TPose>(opts: DiagramContributionOptions<TPose>): {
1245
+ layer: RenderLayer<unknown>;
1246
+ contribution: Contribution;
1247
+ };
1248
+ /** The action id that absorbs the rest of a press on a route handle. */
1249
+ declare const GRAB_WAYPOINT_ACTION_ID = "diagram.grabWaypoint";
1250
+ /**
1251
+ * Both halves of route editing: the handle layer to `registerLayer` — after
1252
+ * the port layer and before the edge-end layer, so an end handle wins over a
1253
+ * route handle beside it — and the contribution to pass as `ambient`, which
1254
+ * carries the drag, the double-click that removes, the
1255
+ * `diagram.resetRoute` command, the commands that set the selected
1256
+ * connectors' router (`SET_ROUTER_ACTION_IDS`), and the line jumps toggle
1257
+ * (`SET_HOPS_ACTION_ID`). Like `diagramPorts`, one without the other
1258
+ * fails quietly.
1259
+ */
1260
+ declare function diagramWaypoints<TPose>(opts: RouteEditOptions<TPose> & Omit<WaypointAffordanceOptions<TPose>, 'id'>): {
1261
+ layer: RenderLayer<unknown>;
1262
+ contribution: Contribution;
1263
+ };
1264
+ /** The action id that absorbs a press on an edge label, so it reaches neither marquee nor pan. */
1265
+ declare const GRAB_LABEL_ACTION_ID = "diagram.grabLabel";
1266
+ /** The action id that selects a clicked label's edge. */
1267
+ declare const SELECT_LABEL_EDGE_ACTION_ID = "diagram.selectLabelEdge";
1268
+ /**
1269
+ * Both halves of label dragging: the label layer to `registerLayer` — before
1270
+ * the port layer, so a port or a route handle wins over a label beside it —
1271
+ * and the contribution to pass as `ambient`, which carries the drag
1272
+ * (`diagram.moveLabel`), a click that selects the label's edge, and a
1273
+ * double-click that edits the label's text through
1274
+ * `EDIT_EDGE_LABEL_ACTION_ID`, which the host registers. Like `diagramPorts`,
1275
+ * one without the other fails quietly.
1276
+ */
1277
+ declare function diagramLabelDrag(opts: LabelDragOptions & {
1278
+ scene: Scene<unknown, string, unknown>;
1279
+ selected: () => readonly string[];
1280
+ cursor?: CursorSpec;
1281
+ }): {
1282
+ layer: RenderLayer<unknown>;
1283
+ contribution: Contribution;
1284
+ };
1285
+
1286
+ /**
1287
+ * The route edits that are not drags: a double-click on a route handle, and
1288
+ * the Reset route command.
1289
+ */
1290
+
1291
+ /** The action that removes a waypoint, straightens a segment, or unpins an
1292
+ * `avoid` connector's segment, on a double-click of its handle. */
1293
+ declare const REMOVE_WAYPOINT_ACTION_ID = "diagram.removeWaypoint";
1294
+ /** The command that clears the selected edges' waypoints. */
1295
+ declare const RESET_ROUTE_ACTION_ID = "diagram.resetRoute";
1296
+ /** The `diagram.removeWaypoint` action: a double-click on a waypoint's dot
1297
+ * removes it, and on a segment's bar straightens that jog away. Where it
1298
+ * would remove nothing it declines, so the double-click reaches whatever is
1299
+ * under the handle, an edge's label editing among them. */
1300
+ declare function createRemoveWaypointAction<TPose>(opts: RouteEditOptions<TPose>): Action;
1301
+ /** The `diagram.resetRoute` command: clears the selected edges' waypoints,
1302
+ * in one history entry when they commit to the scene. */
1303
+ declare function createResetRouteAction<TPose>(opts: RouteEditOptions<TPose>): Action;
1304
+
1305
+ /**
1306
+ * The commands that set the selected connectors' router: Around shapes,
1307
+ * Orthogonal, Straight, and Curved. Leaving `avoid` drops the stored route;
1308
+ * joining it leaves the route to the edit pass `useAvoidRouting` installs,
1309
+ * which routes the connectors in the same history entry.
1310
+ */
1311
+
1312
+ /** The router commands' ids, by router key. */
1313
+ declare const SET_ROUTER_ACTION_IDS: {
1314
+ readonly avoid: "diagram.router.avoid";
1315
+ readonly orthogonal: "diagram.router.orthogonal";
1316
+ readonly straight: "diagram.router.straight";
1317
+ readonly bezier: "diagram.router.bezier";
1318
+ };
1319
+ /** Each shipped router's name in a menu. */
1320
+ declare const ROUTER_LABELS: Readonly<Record<keyof typeof SET_ROUTER_ACTION_IDS, string>>;
1321
+ /** One connector's router changed. */
1322
+ interface RouterEdit {
1323
+ edgeId: string;
1324
+ router: string;
1325
+ }
1326
+ /** Options for {@link createSetRouterAction}. */
1327
+ interface SetRouterOptions<TPose> {
1328
+ participants: ParticipantSource<TPose>;
1329
+ /** The selected ids; the connectors among them are set. */
1330
+ selected: () => readonly string[];
1331
+ /** Defaults to {@link commitRouterToScene} against `deps.scene`. */
1332
+ commit?: (edit: RouterEdit, ctx: InvocationCtx) => void;
1333
+ }
1334
+ /** `data` with its edge trait on `router`, its stored route dropped. */
1335
+ declare function withRouter(data: unknown, trait: DiagramEdge, router: string): Record<string, unknown>;
1336
+ /** The default commit: the connector's `data.diagram.router`, written to the scene. */
1337
+ declare function commitRouterToScene(edit: RouterEdit, ctx: InvocationCtx): void;
1338
+ /** The command that puts the selected connectors on `router`, in one history
1339
+ * entry. Active while every selected connector is on it already. */
1340
+ declare function createSetRouterAction<TPose>(router: keyof typeof SET_ROUTER_ACTION_IDS, opts: SetRouterOptions<TPose>): Action;
1341
+ /** One command per shipped router, in menu order. */
1342
+ declare function routerActions<TPose>(opts: SetRouterOptions<TPose>): Action[];
1343
+
1344
+ /**
1345
+ * Waypoints ride along with a move: when a whole-node transform carries both
1346
+ * ends of an edge by the same offset, the edge's waypoints go with them.
1347
+ * Otherwise they stay put — a route the author placed is not bent by moving
1348
+ * one end.
1349
+ */
1350
+
1351
+ /**
1352
+ * The transform follower that carries waypoints along with a move, for the
1353
+ * `transformFollowers` dep (`useTransformFollower`). `geometry` reads a pose's
1354
+ * bounds; default `AUTO_POSE_DESCRIPTOR`.
1355
+ */
1356
+ declare function waypointFollower<TPose>(scene: Scene<unknown, string, TPose>, geometry?: PoseDescriptor<TPose>): TransformFollower;
1357
+
1358
+ /**
1359
+ * A diagram scene as the avoid router reads it: every participant, container,
1360
+ * pool, group box, and header as an obstacle, and every `avoid` connector not
1361
+ * split across pages, with the ports each end may use and its label. A split
1362
+ * connector's label, on its first stub, is an obstacle of its own.
1363
+ */
1364
+
1365
+ /** How a scene is read for routing. */
1366
+ interface AvoidSceneOptions<TPose> extends PortsOptions<TPose> {
1367
+ /** The router key whose connectors are routed. Default `'avoid'`. */
1368
+ routerKey?: string;
1369
+ }
1370
+ /** The id of a container's header obstacle. */
1371
+ declare const headerIdOf: (id: string) => string;
1372
+ /**
1373
+ * What the router reads off `scene`: its obstacles and its `avoid` connectors,
1374
+ * each node at the pose `poseOf` gives it, else the one the document holds.
1375
+ */
1376
+ declare function avoidSceneInput<TPose>(scene: Scene<unknown, string, TPose>, opts?: AvoidSceneOptions<TPose>, poseOf?: (id: string) => TPose | undefined): AvoidInput;
1377
+
1378
+ /**
1379
+ * Obstacle-avoiding routing on a live scene: a scene edit pass that reroutes
1380
+ * whatever an edit disturbed, in that edit's own history entry, and a
1381
+ * transform follower that reroutes the connectors near a dragged shape each
1382
+ * frame.
1383
+ */
1384
+
1385
+ /** Options for {@link installAvoidRouting} and `useAvoidRouting`. */
1386
+ interface AvoidRoutingOptions<TPose> extends AvoidSceneOptions<TPose>, AvoidOptions {
1387
+ /** World units one screen pixel covers now. A drag frame that moves
1388
+ * nothing further than this does no work. Default 1. */
1389
+ pixelSize?: () => number;
1390
+ /** Milliseconds one drag frame may spend rerouting. Default 4. */
1391
+ frameBudgetMs?: number;
1392
+ }
1393
+ /** Routing installed on a scene. */
1394
+ interface AvoidRouting {
1395
+ router: AvoidRouter;
1396
+ /** The drag half, for the `transformFollowers` dep (`useTransformFollower`). */
1397
+ follower: TransformFollower;
1398
+ /** Remove the edit pass. */
1399
+ dispose(): void;
1400
+ }
1401
+ /** The data writes that store `routes` on their edges, skipping any unchanged. */
1402
+ declare function routeDataOps(scene: Scene<unknown, string, unknown>, routes: AvoidRoutes): Op[];
1403
+ /**
1404
+ * Route `scene`'s `avoid` connectors around its shapes from now on. Every
1405
+ * live edit reroutes what it disturbed, in its own history entry; on install
1406
+ * nothing reroutes, and the routes the scene holds stand. A host without
1407
+ * React calls this; a component calls `useAvoidRouting`.
1408
+ */
1409
+ declare function installAvoidRouting<TPose>(scene: Scene<unknown, string, TPose>, opts?: AvoidRoutingOptions<TPose>): AvoidRouting;
1410
+
1411
+ /**
1412
+ * Where each of the diagram's scene edit passes runs among the others
1413
+ * (`scene.addEditPass`'s `order`). Each pass hears what the ones before it
1414
+ * wrote: markers are placed before routing sees them, routes before labels
1415
+ * dodge them, and line jumps last, on the routes as they end up.
1416
+ */
1417
+ declare const DIAGRAM_PASS_ORDER: {
1418
+ readonly offPage: 100;
1419
+ readonly avoid: 200;
1420
+ readonly labels: 300;
1421
+ readonly hops: 400;
1422
+ };
1423
+
1424
+ /**
1425
+ * Route `scene`'s `avoid` connectors around its shapes for the life of the
1426
+ * calling component: each edit reroutes what it disturbed in its own history
1427
+ * entry, and a drag reroutes the connectors near what it moves each frame.
1428
+ * Mount it as a child of `<SceneCanvas>`, where the drag's follower is heard,
1429
+ * after any `waypointFollower`, whose carried waypoints the drag routes through.
1430
+ * Options are read when the scene changes; `pixelSize` defaults to the
1431
+ * canvas's own view.
1432
+ */
1433
+ declare function useAvoidRouting<TPose>(scene: Scene<unknown, string, TPose>, opts?: AvoidRoutingOptions<TPose>): void;
1434
+
1435
+ /**
1436
+ * A function from specs to the same specs with each edge on `avoid` and
1437
+ * holding its route. It holds one router across calls, so each call reroutes
1438
+ * only the edges the change since the last one disturbed.
1439
+ */
1440
+ declare function createSpecRouter(options?: AvoidOptions): (specs: readonly DiagramSpec[]) => DiagramSpec[];
1441
+
1442
+ /**
1443
+ * A connector's route drawn with its hops: each one a half circle in place of
1444
+ * the stretch of route it spans.
1445
+ */
1446
+
1447
+ /**
1448
+ * The open path through `points`, bowing over each of `hops` in a half circle
1449
+ * of its radius. A hop more than half a unit off the route, or too near a bend
1450
+ * or an end for its half circle to fit on one segment, is stale and does not
1451
+ * draw; nor does one overlapping the hop before it.
1452
+ */
1453
+ declare function withHops(points: readonly Vec2$1[], hops: readonly EdgeHop[]): Path$1;
1454
+
1455
+ /**
1456
+ * Line jumps on a live scene: an edit pass that recomputes the hops an edit
1457
+ * disturbed, in that edit's own history entry, while the document's
1458
+ * line-jump setting is on.
1459
+ */
1460
+
1461
+ /** Options for {@link installHops} and `useHops`: how a connector routes, as
1462
+ * its own `derivePath` does. */
1463
+ type HopsOptions<TPose> = EdgeRouteOptions<TPose>;
1464
+ /** Line jumps installed on a scene. */
1465
+ interface Hops {
1466
+ /** The drag half, for the `transformFollowers` dep (`useTransformFollower`). */
1467
+ follower: TransformFollower;
1468
+ /** Remove the edit pass. */
1469
+ dispose(): void;
1470
+ }
283
1471
  /**
284
- * Absorbs a press on a port, and does nothing else.
285
- *
286
- * A port claims the press **protocol**, not one gesture in it: `pointerDown`,
287
- * `click` and `drag` are a single claimable `'pointer'` token, and an exclusive
288
- * claim bars every binding whose target does not consult the affordance. So a
289
- * bundle that binds only `drag` leaves the pointerdown with nowhere to go, and
290
- * the dispatcher drops the press — the drag it would have grown into never
291
- * happens.
1472
+ * Hop `scene`'s crossing connectors while its `HOPS_DOC_KEY` value is set.
1473
+ * Turning the value on or off, or changing its size, recomputes or clears
1474
+ * every connector in that same entry; any other edit recomputes the
1475
+ * connectors it rerouted and those whose routes meet theirs. Installing
1476
+ * writes nothing. A host without React calls this; a component calls `useHops`.
292
1477
  */
293
- declare function grabPortAction(id?: string): Action;
294
- /** The two bindings that keep a port's claim from dropping the press. */
295
- declare function grabPortBindings(actionId?: string): GestureBinding[];
1478
+ declare function installHops<TPose>(scene: Scene<unknown, string, TPose>, opts?: HopsOptions<TPose>): Hops;
1479
+
296
1480
  /**
297
- * The default commit: one leaf node carrying the edge trait, added to
298
- * `deps.scene`. One `add` is one history entry, so the edge undoes in one.
299
- *
300
- * The edge lands on the **source node's** layer rather than the bottom one.
1481
+ * The transform follower that hides hops while a drag is in progress: each
1482
+ * frame previews the connectors it moves, and every connector hopping over
1483
+ * one, without their hops. A hop stays where the edit pass put it, so it
1484
+ * would sit off a moving route; on release the pass recomputes them in the
1485
+ * drag's entry. Register it after any follower that reroutes connectors, whose
1486
+ * previewed data it keeps.
301
1487
  */
302
- declare function commitEdgeToScene(edge: PendingEdge, ctx: InvocationCtx): void;
1488
+ declare function hopFollower<TPose>(scene: Scene<unknown, string, TPose>): TransformFollower;
1489
+
303
1490
  /**
304
- * The `diagram.connect` action: an ongoing drag whose preview is an ephemeral
305
- * edge and whose commit is one op batch.
1491
+ * Hop `scene`'s crossing connectors for the life of the calling component,
1492
+ * while its line-jump setting is on: each edit recomputes the hops it
1493
+ * disturbed in its own history entry, and a drag hides the hops on what it
1494
+ * moves. Mount it as a child of `<SceneCanvas>`, after any routing hook, so its
1495
+ * follower hears the routes that one previews. Options are read when the scene
1496
+ * changes.
306
1497
  */
307
- declare function createConnectAction<TPose>(opts: ConnectActionOptions<TPose>): Action;
1498
+ declare function useHops<TPose>(scene: Scene<unknown, string, TPose>, opts?: HopsOptions<TPose>): void;
308
1499
 
1500
+ /** The line jumps command's id. */
1501
+ declare const SET_HOPS_ACTION_ID = "diagram.hops";
1502
+ /** Options for {@link createSetHopsAction}. */
1503
+ interface SetHopsOptions {
1504
+ /** The radius hops take when the command turns them on. Default
1505
+ * {@link DEFAULT_HOP_SIZE}. */
1506
+ size?: number;
1507
+ }
309
1508
  /**
310
- * The plugin as a `Contribution` bundle — one object a consumer hands to
311
- * `<SceneCanvas ambient={…}>`.
312
- *
313
- * **Ambient, not a tool.** A port is grabbable whatever tool is active:
314
- * `claimed` makes the bundle live for a press the port layer's affordance
315
- * claimed, and dormant otherwise.
1509
+ * The command that turns line jumps on for the whole document, or off, by
1510
+ * writing its `HOPS_DOC_KEY` value: one history entry, which the hop pass
1511
+ * (`useHops`) joins with every connector's hops. Active while they are on.
1512
+ */
1513
+ declare function createSetHopsAction(opts?: SetHopsOptions): Action;
1514
+
1515
+ /** A function from specs to the same specs with every edge's hops of radius
1516
+ * `r`, edges hopping those earlier in the list. An edge split across pages
1517
+ * takes no part. */
1518
+ declare function createSpecHops(r: number): (specs: readonly DiagramSpec[]) => DiagramSpec[];
1519
+
1520
+ /**
1521
+ * Reconnect — dragging a selected edge's end onto another port or shape.
316
1522
  *
317
- * **The layer is not in here, on purpose.** `Contribution.overlay` is painted
318
- * and never hit-tested — only `CanvasExtensionApi.registerLayer` gets a
319
- * `hitTest` call — so the port layer as an overlay would paint every port and
320
- * make none of them grabbable. {@link diagramPorts} hands back both.
1523
+ * The edge-end handles (`edgeEndLayer`) claim the press; this action carries
1524
+ * the end. It lands where a connect from the edge's other end would land, by
1525
+ * the same resolver and the same `canConnect`, asked with the edge's from/to
1526
+ * order kept, so a reconnect can never make an edge a connect could not.
321
1527
  */
322
1528
 
323
- /** The connect action's options and the port affordance's, in one bag. */
324
- interface DiagramContributionOptions<TPose> extends ConnectActionOptions<TPose>, PortAffordanceOptions<TPose> {
1529
+ /** The action that drags an edge end onto a new port or body. */
1530
+ declare const RECONNECT_ACTION_ID = "diagram.reconnect";
1531
+ /** The action id that absorbs a press on an edge-end handle. */
1532
+ declare const GRAB_EDGE_END_ACTION_ID = "diagram.grabEdgeEnd";
1533
+ /** One end of one edge, moved onto `target`. */
1534
+ interface EndChange {
1535
+ edgeId: string;
1536
+ end: 'from' | 'to';
1537
+ target: ConnectEnd;
1538
+ }
1539
+ /** Options for {@link createReconnectAction}. `bodies` defaults to true: an end
1540
+ * may be dropped on a shape's body. */
1541
+ interface ReconnectOptions<TPose> extends Omit<ConnectActionOptions<TPose>, 'commit' | 'startFrom'> {
1542
+ /** The selected edge ids whose ends show handles. */
1543
+ selected: () => readonly string[];
1544
+ /** Defaults to {@link commitReconnectToScene} against `deps.scene`. */
1545
+ commit?: (change: EndChange, ctx: InvocationCtx) => void;
325
1546
  }
326
- /** The bundle: the connect action and the one binding that reaches it. */
327
- declare function createDiagramContribution<TPose>(opts: DiagramContributionOptions<TPose>): Contribution;
328
1547
  /**
329
- * Both halves of the port affordance: the layer to `registerLayer`, and the
330
- * contribution to pass as `ambient`.
331
- *
332
- * They are returned together because attaching one without the other fails
333
- * quietly — the layer alone paints ports that start no gesture, and the
334
- * contribution alone binds an affordance kind nothing ever reports.
1548
+ * The default commit: rewrites the moved end in `data.diagram` — `{ port }`,
1549
+ * or `{}` for a body — and points the edge's `dependsOn` at the new node, as
1550
+ * one history entry.
335
1551
  */
336
- declare function diagramPorts<TPose>(opts: DiagramContributionOptions<TPose>): {
1552
+ declare function commitReconnectToScene(change: EndChange, ctx: InvocationCtx): void;
1553
+ /** The `diagram.reconnect` action: an ongoing drag carrying one edge end. */
1554
+ declare function createReconnectAction<TPose>(opts: ReconnectOptions<TPose>): Action;
1555
+ /** The binding that starts a reconnect: a drag pressed on an edge-end handle. */
1556
+ declare function reconnectBinding(actionId?: string): GestureBinding;
1557
+ /**
1558
+ * Both halves of reconnect: the handle layer to `registerLayer` — after the
1559
+ * port layer, since an edge's end sits on a port — and the contribution to
1560
+ * pass as `ambient`. Like `diagramPorts`, one without the other fails quietly.
1561
+ */
1562
+ declare function diagramEdgeEnds<TPose>(opts: ReconnectOptions<TPose> & Omit<EdgeEndAffordanceOptions<TPose>, 'id'>): {
337
1563
  layer: RenderLayer<unknown>;
338
1564
  contribution: Contribution;
339
1565
  };
340
1566
 
1567
+ /**
1568
+ * Reordering a group marked `reorder`: a member dragged along that axis among
1569
+ * its siblings, which slide into the places they would take, or the selected
1570
+ * one stepped with Alt and an arrow key. Nothing is written: the host hears
1571
+ * the new order, writes it to its data, and layout keeps it.
1572
+ */
1573
+
1574
+ /** Alt and an arrow key: the selected member one place along. */
1575
+ declare const STEP_REORDER_ACTION_ID = "diagram.stepReorder";
1576
+ /** A reorderable group's members in their new order. */
1577
+ interface ReorderChange {
1578
+ group: string;
1579
+ order: readonly string[];
1580
+ }
1581
+ /** The members of the reorderable group a press at `at` carries one of, each
1582
+ * with everything drawn with it, or `null` off any such group. */
1583
+ declare function groupReorderSlots(deps: ActionDeps, at: Vec2): ReorderSlots | null;
1584
+ /** Steps the selected node's member one place toward the start (`-1`) or the end (`1`). */
1585
+ declare function createStepReorderAction(report: (change: ReorderChange) => void): Action;
1586
+ /** Everything `DiagramView` installs for `onReorder`: the reorder drag,
1587
+ * sliding, pressed on a node's body, and the step action. */
1588
+ declare function groupReorderContribution(report: (change: ReorderChange) => void): Contribution;
1589
+
341
1590
  /** How a self-edge with no ports named leaves its node and comes back. */
342
1591
  interface SelfLoop {
343
1592
  from: Port;
@@ -357,6 +1606,111 @@ interface SelfLoop {
357
1606
  */
358
1607
  declare function selfLoop(ports: readonly Port[], standoff: number): SelfLoop | null;
359
1608
 
1609
+ /**
1610
+ * Edge labels: the one place a label node's spec is made, and the action that
1611
+ * adds or edits an edge's label on a double-click.
1612
+ */
1613
+
1614
+ /** The box a label's text takes: measured width, and a height of the font size
1615
+ * whatever the measure reports. */
1616
+ declare function labelSize(text: string, style: RowTextStyle, measure?: MeasureRowText): {
1617
+ width: number;
1618
+ height: number;
1619
+ };
1620
+ /** Options for {@link edgeLabelSpec}. */
1621
+ interface EdgeLabelOptions<TLayer extends string> {
1622
+ layer: TLayer;
1623
+ /** Where along the edge it sits. Default {@link LABEL_PLACEMENT}. */
1624
+ label?: DiagramLabel;
1625
+ style?: RowTextStyle;
1626
+ /** Text color. */
1627
+ fill?: string;
1628
+ /** Sizes the box. Default: a per-character estimate. */
1629
+ measure?: MeasureRowText;
1630
+ }
1631
+ /** The label node for edge `edgeId`: a leaf that derives its pose from the edge's route. */
1632
+ declare function edgeLabelSpec<TLayer extends string>(edgeId: string, text: string, opts: EdgeLabelOptions<TLayer>): AddNodeSpec<unknown, TLayer, RectPose>;
1633
+ /**
1634
+ * Removes node `id` if it is an edge label left with no text, and says whether
1635
+ * it did. The default edit adds a label before its text is typed, so a host
1636
+ * passes this as its text edit's `onEnd` to drop one that ends empty.
1637
+ */
1638
+ declare function dropEmptyEdgeLabel(scene: Scene<unknown, string, unknown>, id: string): boolean;
1639
+ /** The action that adds or edits an edge's label. */
1640
+ declare const EDIT_EDGE_LABEL_ACTION_ID = "diagram.editEdgeLabel";
1641
+ /** Options for {@link editEdgeLabelAction}. */
1642
+ interface EditEdgeLabelOptions {
1643
+ /** Runs in place of the default add-then-edit. */
1644
+ commit?: (edgeId: string, ctx: InvocationCtx) => void;
1645
+ /** The face a new label is set in. Default the diagram's, two sizes down. Ignored when `commit` is given. */
1646
+ style?: RowTextStyle;
1647
+ /** A new label's text color. Ignored when `commit` is given. */
1648
+ fill?: string;
1649
+ }
1650
+ /**
1651
+ * Creates an edge's label, or edits the one it has, where a double-click
1652
+ * lands on the edge. It declines a double-click on anything else.
1653
+ *
1654
+ * An immediate invoker is handed no `InvocationCtx`, so `commit` gets one
1655
+ * built from the deps and the click point.
1656
+ */
1657
+ declare function editEdgeLabelAction(opts?: EditEdgeLabelOptions): Action;
1658
+ /** A double-click on a node's body; the action itself declines unless that node is an edge. */
1659
+ declare function editEdgeLabelBinding(actionId?: string): GestureBinding;
1660
+
1661
+ /**
1662
+ * What makes an edge label grabbable, so a drag can move it along and beside
1663
+ * its edge (`labelDragAction`).
1664
+ *
1665
+ * Built the way the route handles are: rect regions with a `null` `targetId`
1666
+ * and no paint, composed into a layer whose id is the kind a press reports.
1667
+ */
1668
+
1669
+ /** The layer id the label regions are composed into. */
1670
+ declare const LABEL_DRAG_LAYER_ID = "diagram-edge-labels";
1671
+ /** The affordance kind a press on an edge label reports. */
1672
+ declare const LABEL_DRAG_AFFORDANCE_KIND: "layer:diagram-edge-labels";
1673
+ /** What a press on an edge label hands the label actions, as the hit's `payload`. */
1674
+ interface LabelScratch {
1675
+ targetId: string;
1676
+ labelId: string;
1677
+ edgeId: string;
1678
+ }
1679
+ /** Read a label press's scratch back off the hit an action was handed. */
1680
+ declare function labelScratchOf(hit: {
1681
+ payload?: unknown;
1682
+ } | null | undefined): LabelScratch | null;
1683
+ /** A label a press can pick up: its box as the document places it, and its edge's route. */
1684
+ interface DraggableLabel {
1685
+ labelId: string;
1686
+ edgeId: string;
1687
+ box: Bounds$2;
1688
+ path: Path$2;
1689
+ }
1690
+ /** Every editable label in `scene` whose edge derives a path, in render order. */
1691
+ declare function draggableLabels(scene: Scene<unknown, string, unknown>): Iterable<DraggableLabel>;
1692
+ /** The topmost draggable label whose box holds `at`, as its press scratch. */
1693
+ declare function labelUnder(scene: Scene<unknown, string, unknown>, at: Vec2$1): LabelScratch | null;
1694
+ /** The composed layer, for `CanvasExtensionApi.registerLayer`. Register it
1695
+ * before the port layer: the last registered is hit first, and a port or a
1696
+ * route handle must win over a label beside it. */
1697
+ declare function labelDragLayer(scene: Scene<unknown, string, unknown>, opts?: {
1698
+ cursor?: CursorSpec;
1699
+ }): RenderLayer<unknown>;
1700
+
1701
+ /**
1702
+ * The label edit that is not a drag: the Reset label command.
1703
+ */
1704
+
1705
+ /** The command that puts the selected edges' dragged labels back where placement puts them. */
1706
+ declare const RESET_LABEL_ACTION_ID = "diagram.resetLabel";
1707
+ /** The `diagram.resetLabel` command: sets each selected edge's dragged label
1708
+ * back to `LABEL_PLACEMENT`, in one history entry when they commit to the scene. */
1709
+ declare function createResetLabelAction(opts: {
1710
+ selected: () => readonly string[];
1711
+ commit?: (edit: LabelEdit, ctx: InvocationCtx) => void;
1712
+ }): Action;
1713
+
360
1714
  /**
361
1715
  * A label on an edge: an ordinary leaf node that derives its *pose* from the
362
1716
  * route it sits on.
@@ -393,6 +1747,298 @@ declare const LABEL_DERIVE_POSE: (node: {
393
1747
  data: unknown;
394
1748
  }, deps: readonly (DerivedDep<unknown, unknown, string> | undefined)[]) => unknown;
395
1749
 
1750
+ /**
1751
+ * Label placement on a live scene: a scene edit pass that moves the labels
1752
+ * an edit covered to the nearest clear station, in that edit's own history
1753
+ * entry. It runs after routing, so labels dodge the routes the edit made.
1754
+ */
1755
+
1756
+ /** Options for {@link installLabelPlacement} and `useLabelPlacement`. */
1757
+ interface LabelPlacementOptions<TPose> extends PlaceLabelsOptions {
1758
+ geometry?: PoseDescriptor<TPose>;
1759
+ /** How a node's diagram trait is read. Default its own `data.diagram`. */
1760
+ read?: DiagramNodeReader;
1761
+ /** Sizes a label to the text an edit gives it. Default a per-character estimate. */
1762
+ measure?: MeasureRowText;
1763
+ }
1764
+ /** Placement installed on a scene. */
1765
+ interface LabelPlacement {
1766
+ /** Remove the edit pass. */
1767
+ dispose(): void;
1768
+ }
1769
+ /**
1770
+ * Move `scene`'s edge labels off whatever an edit leaves covering them, from
1771
+ * now on: each live edit places the labels it may have covered, in its own
1772
+ * history entry. Labels hold still during a drag and settle on release. A
1773
+ * host without React calls this; a component calls `useLabelPlacement`.
1774
+ */
1775
+ declare function installLabelPlacement<TPose>(scene: Scene<unknown, string, TPose>, opts?: LabelPlacementOptions<TPose>): LabelPlacement;
1776
+
1777
+ /**
1778
+ * Move `scene`'s edge labels off whatever an edit leaves covering them, for
1779
+ * the life of the calling component, each edit's moves in its own history
1780
+ * entry. Options are read when the scene changes.
1781
+ */
1782
+ declare function useLabelPlacement<TPose>(scene: Scene<unknown, string, TPose>, opts?: LabelPlacementOptions<TPose>): void;
1783
+
1784
+ /**
1785
+ * A function from specs to the same specs with each edge label placed off
1786
+ * whatever covers it. Every label is placed afresh, in id order, whenever
1787
+ * the shapes, routes, or labels change, and the last answer is reused while
1788
+ * they do not. Run it after any router, so labels dodge the routes drawn.
1789
+ */
1790
+ declare function createSpecLabelPlacer(opts?: PlaceLabelsOptions): (specs: readonly DiagramSpec[]) => DiagramSpec[];
1791
+
1792
+ /**
1793
+ * An off-page tag: a text leaf with a background that names the far page and
1794
+ * the reference, and stations itself past the tip of its connector's stub.
1795
+ */
1796
+
1797
+ /** How a tag is drawn: its face, its text color, and the box behind the text. */
1798
+ interface OffPageTagLook {
1799
+ style: RowTextStyle;
1800
+ fill: string;
1801
+ background: string;
1802
+ /** World units between the box and the text. Default {@link OFF_PAGE_TAG_PADDING}. */
1803
+ padding?: number;
1804
+ /** Sizes the text. Default: a per-character estimate. */
1805
+ measure?: MeasureRowText;
1806
+ }
1807
+ /** A tag's default padding, in world units. */
1808
+ declare const OFF_PAGE_TAG_PADDING = 3;
1809
+ /** A tag's look under `theme`: the theme's connector-label face and color, on its page color. */
1810
+ declare const offPageTagLook: (theme: DiagramTheme) => OffPageTagLook;
1811
+ /** What a tag reads: the far page's name and the connector's reference. */
1812
+ declare const offPageTagText: (pageName: string, ref: string) => string;
1813
+ /** What the tag at `end` of a split reads: the page at the other end, by name or place, else its raw id, and the reference. */
1814
+ declare function offPageFarText(pages: readonly PlacedPage[], split: OffPageSplit, end: 'from' | 'to'): string;
1815
+ /** The box a tag of `text` takes in `look`. */
1816
+ declare function offPageTagSize(text: string, look: OffPageTagLook): {
1817
+ width: number;
1818
+ height: number;
1819
+ };
1820
+ /** The tag `data` for end `end` of `edgeId`, reading `text` in `look`. */
1821
+ declare function offPageTagData(edgeId: string, end: 'from' | 'to', text: string, look: OffPageTagLook): {
1822
+ diagram: {
1823
+ offPageTag: {
1824
+ edge: string;
1825
+ end: "from" | "to";
1826
+ };
1827
+ };
1828
+ text: string;
1829
+ style: RowTextStyle;
1830
+ fill: {
1831
+ paint: {
1832
+ color: string;
1833
+ };
1834
+ };
1835
+ background: {
1836
+ paint: {
1837
+ color: string;
1838
+ };
1839
+ };
1840
+ padding: number;
1841
+ };
1842
+ /** The tag node at end `end` of connector `edgeId`, on `layer`: it derives its pose from the connector's stub. */
1843
+ declare function offPageTagSpec<TLayer extends string>(edgeId: string, end: 'from' | 'to', text: string, look: OffPageTagLook & {
1844
+ layer: TLayer;
1845
+ }): AddNodeSpec<unknown, TLayer, RectPose>;
1846
+ /** A split connector's two tag specs, `from` then `to`. */
1847
+ declare function offPageTagSpecs<TLayer extends string>(edgeId: string, split: OffPageSplit, pages: readonly PlacedPage[], look: OffPageTagLook & {
1848
+ layer: TLayer;
1849
+ }): AddNodeSpec<unknown, TLayer, RectPose>[];
1850
+ /**
1851
+ * A `derivePose` that stations a tag just past its stub's tip, on the far
1852
+ * side from the shape. `null`, so the tag keeps its authored pose, while its
1853
+ * connector draws no stub at that end.
1854
+ */
1855
+ declare function offPageTagDerivePose<TPose>(opts?: {
1856
+ geometry?: PoseDescriptor<TPose>;
1857
+ }): (node: {
1858
+ pose: TPose;
1859
+ data: unknown;
1860
+ }, deps: readonly (DerivedDep<TPose> | undefined)[]) => TPose | null;
1861
+ /** Registry key for {@link OFF_PAGE_TAG_DERIVE_POSE}. */
1862
+ declare const DIAGRAM_OFF_PAGE_TAG = "diagram:offPageTag";
1863
+ /** The default tag derivation, as one stable function reference so `toJSON` can find its key. */
1864
+ declare const OFF_PAGE_TAG_DERIVE_POSE: (node: {
1865
+ pose: unknown;
1866
+ data: unknown;
1867
+ }, deps: readonly (DerivedDep<unknown, unknown, string> | undefined)[]) => unknown;
1868
+
1869
+ /** The pages a {@link DiagramData} is drawn on, and the connectors that cross between them. */
1870
+
1871
+ /** `data`'s pages, placed in world space. */
1872
+ declare function diagramPages(data: DiagramData): PlacedPage[];
1873
+ /**
1874
+ * Which of `edges` cross between `pages`, lettered in their order, and the two
1875
+ * off-page tags of each that does. An edge with an end `boxOf` has no box for
1876
+ * is left whole.
1877
+ */
1878
+ declare function dataOffPage(edges: readonly {
1879
+ id: string;
1880
+ from: string;
1881
+ to: string;
1882
+ }[], pages: readonly PlacedPage[], boxOf: (id: string) => Bounds$3 | undefined, look: OffPageTagLook): {
1883
+ splits: ReadonlyMap<string, OffPageSplit>;
1884
+ tags: DiagramSpec[];
1885
+ };
1886
+
1887
+ /**
1888
+ * Which connectors cross from one page to another, as arithmetic: page
1889
+ * rects and end boxes in, splits out. Nothing here reads a scene.
1890
+ */
1891
+
1892
+ type Box$1 = {
1893
+ x: number;
1894
+ y: number;
1895
+ width: number;
1896
+ height: number;
1897
+ };
1898
+ /** One connector as {@link offPageSplits} reads it: its two ends' world boxes,
1899
+ * and the split it holds now, if any. */
1900
+ interface OffPageEdgeInput {
1901
+ id: string;
1902
+ from: Box$1;
1903
+ to: Box$1;
1904
+ offPage?: OffPageSplit | undefined;
1905
+ }
1906
+ /** What {@link offPageSplits} reads. */
1907
+ interface OffPageSplitInput {
1908
+ pages: readonly PlacedPage[];
1909
+ edges: readonly OffPageEdgeInput[];
1910
+ /** Refs held by split connectors not in `edges`, which no edge here may take. */
1911
+ used?: Iterable<string>;
1912
+ }
1913
+ /** The first ref, in A…Z, AA… order, that `used` does not hold. */
1914
+ declare function nextOffPageRef(used: ReadonlySet<string>): string;
1915
+ /**
1916
+ * Each connector's split, or `null` where it stays whole. A connector splits
1917
+ * when its two ends belong to different pages (`pageOfBounds`); an end in a
1918
+ * gap belongs to none, and never splits. A split keeps the ref it holds while
1919
+ * no earlier connector here or `used` holds it too; a new one takes the next
1920
+ * free ref.
1921
+ */
1922
+ declare function offPageSplits(input: OffPageSplitInput): Map<string, OffPageSplit | null>;
1923
+
1924
+ /** The box `node` has in document space, which is where pages are: its pose through every ancestor's transform. */
1925
+ declare function documentBoundsOf<TPose>(scene: Scene<unknown, string, TPose>, node: {
1926
+ id: string;
1927
+ }, geometry?: PoseDescriptor<unknown>): Bounds$3;
1928
+
1929
+ /**
1930
+ * Off-page markers on a live scene: an edit pass that splits a connector
1931
+ * whose ends land on different pages, joins one whose ends share a page
1932
+ * again, and keeps each split connector's two tags, all in the entry of the
1933
+ * edit that caused it.
1934
+ */
1935
+
1936
+ /** Options for {@link installOffPageMarkers} and `useOffPageMarkers`. */
1937
+ interface OffPageMarkerOptions<TPose> {
1938
+ /** How node poses are measured. Default `AUTO_POSE_DESCRIPTOR`. */
1939
+ geometry?: PoseDescriptor<TPose>;
1940
+ /** The look a tag is given as it is made or retexted. Default the scene's
1941
+ * theme (`diagram:theme`), else `theme`. */
1942
+ look?: () => OffPageTagLook;
1943
+ /** The theme a scene naming none is drawn in. */
1944
+ theme?: DiagramTheme;
1945
+ }
1946
+ /**
1947
+ * The ops that split, join, and tag the connectors `edges` names (every one,
1948
+ * for `'all'`), so each is split exactly when its ends sit on different
1949
+ * pages. Empty when nothing changes. The edit pass runs this; a host can run
1950
+ * it once over a document saved before it had off-page markers.
1951
+ */
1952
+ declare function offPageOps<TPose>(scene: Scene<unknown, string, TPose>, edges: Iterable<string> | 'all', opts?: OffPageMarkerOptions<TPose>): Op[];
1953
+ /**
1954
+ * Split `scene`'s connectors across pages from now on: every live edit that
1955
+ * moves a connector's end, adds or rewrites a connector, or changes the pages
1956
+ * splits, joins, and retags what it reached, in its own history entry. On
1957
+ * install nothing is recomputed. Returns the remover. A host without React
1958
+ * calls this; a component calls `useOffPageMarkers`.
1959
+ */
1960
+ declare function installOffPageMarkers<TPose>(scene: Scene<unknown, string, TPose>, opts?: OffPageMarkerOptions<TPose>): () => void;
1961
+
1962
+ /**
1963
+ * Split `scene`'s connectors across pages for the life of the calling
1964
+ * component: each edit that moves a connector's end or changes the pages
1965
+ * splits, joins, and retags what it reached, in its own history entry.
1966
+ * Options are read when the scene changes.
1967
+ */
1968
+ declare function useOffPageMarkers<TPose>(scene: Scene<unknown, string, TPose>, opts?: OffPageMarkerOptions<TPose>): void;
1969
+
1970
+ /**
1971
+ * Following a connector off the page: a double-click on an off-page tag goes
1972
+ * to the page at the connector's far end and selects the shape there.
1973
+ */
1974
+
1975
+ /** The action that follows an off-page tag to its far page. */
1976
+ declare const FOLLOW_OFF_PAGE_ACTION_ID = "diagram.followOffPage";
1977
+ /** Where a tag leads: the shape at its connector's far end, and that shape's page. */
1978
+ interface OffPageTarget {
1979
+ tag: string;
1980
+ edge: string;
1981
+ node: string;
1982
+ page: string;
1983
+ }
1984
+ type SceneReads = NonNullable<ActionDeps['scene']>;
1985
+ /** Where tag `tagId` leads, or `null` when it is no tag of a split connector. */
1986
+ declare function offPageTargetOf(scene: SceneReads, tagId: string): OffPageTarget | null;
1987
+ /** Options for {@link createFollowOffPageAction}. */
1988
+ interface FollowOffPageOptions {
1989
+ /** Runs in place of the default, which selects `target.node` and fits the view to `target.page`. */
1990
+ follow?: (target: OffPageTarget, ctx: InvocationCtx) => void;
1991
+ /** Screen pixels the default leaves around the page it fits. Default 24. */
1992
+ padding?: number;
1993
+ }
1994
+ /**
1995
+ * Goes to the far page of the off-page tag a double-click lands on, and
1996
+ * selects the shape at the connector's far end there. It declines a
1997
+ * double-click on anything else.
1998
+ */
1999
+ declare function createFollowOffPageAction(opts?: FollowOffPageOptions): Action;
2000
+ /** A double-click on a node's body; the action itself declines unless that node is an off-page tag. */
2001
+ declare function followOffPageBinding(actionId?: string): GestureBinding;
2002
+ /** Following off-page tags, as a contribution to pass as `ambient`. */
2003
+ declare function diagramOffPage(opts?: FollowOffPageOptions): {
2004
+ contribution: Contribution;
2005
+ };
2006
+
2007
+ /** Subpath `index` of `path` as a path of its own: the whole path for index 0
2008
+ * of one with a single subpath, or of a shape with no commands; null past the last. */
2009
+ declare function subpathOf(path: Path$1, index: number): Path$1 | null;
2010
+
2011
+ /**
2012
+ * `<SceneCanvas selectTool={{ resize: { resizable } }}>` for a diagram scene:
2013
+ * edges and edge labels take their geometry from what they are attached to,
2014
+ * so their own pose is a placeholder, and a resize handle on it sits at the
2015
+ * origin and resizes nothing. A group's box is its members' union, and a
2016
+ * pool's lane is sized by its pool's stack and resized by dragging its
2017
+ * boundary.
2018
+ */
2019
+ declare function diagramResizable(scene: {
2020
+ get(id: never): {
2021
+ data: unknown;
2022
+ } | undefined;
2023
+ }): (id: string) => boolean;
2024
+
2025
+ /** A node's style: its colors over its role's under `theme`, else over {@link NODE}. */
2026
+ declare function dataNodeStyle(node: Pick<DataNode, 'style' | 'colors'>, theme?: DiagramTheme): NodeStyle;
2027
+ /** An edge's style: its colors over its role's stroke under `theme`, else over the theme's connector, else over {@link EDGE}. */
2028
+ declare function dataEdgeStyle(edge: Pick<DataEdge, 'style' | 'colors'>, theme?: DiagramTheme): EdgeStyle;
2029
+ /** A region as {@link dataRegionStyle} reads it: a container, a pool, or a lane. */
2030
+ interface StyledRegion {
2031
+ role: DataContainer['role'] | 'lane';
2032
+ style?: string;
2033
+ colors?: Partial<NodeStyle>;
2034
+ }
2035
+ /**
2036
+ * A region's style: its colors over its theme role's, else over the theme's
2037
+ * container, its pool header, or the lane body at `laneIndex` in turn; with no
2038
+ * theme, over {@link NODE}.
2039
+ */
2040
+ declare function dataRegionStyle(region: StyledRegion, theme?: DiagramTheme, laneIndex?: number): NodeStyle;
2041
+
396
2042
  /**
397
2043
  * A live layout's producers: what each frame of a run says about where the
398
2044
  * participants are. `forceProducer` relaxes; `easedProducer` walks to a
@@ -565,7 +2211,8 @@ declare function layeredRoutes(input: LayeredRouteInput): Map<string, LayeredRou
565
2211
  * where its label sits among them.
566
2212
  *
567
2213
  * Layout writes only what it owns. An edge's route is its own while the edge
568
- * has no waypoints or still has the ones layout last wrote (`laidOut`); a
2214
+ * has no waypoints or still has the ones layout last wrote (`laidOut`), and
2215
+ * is not an `avoid` connector, which only gets its ports named; a
569
2216
  * label's place is its own while the label sits at the default middle or at a
570
2217
  * `{ near }`, and its edge's route is layout's.
571
2218
  */
@@ -749,6 +2396,67 @@ declare function diagramShape<TPose>(opts?: DiagramShapeOptions<TPose>): NodeSha
749
2396
  */
750
2397
  declare function registerDiagramShape<TPose>(opts?: DiagramShapeOptions<TPose>): () => void;
751
2398
 
2399
+ /**
2400
+ * DOM pinned to a diagram's nodes and edges: a settings card beside the picked
2401
+ * node, a button on an edge's midpoint. Each overlay is placed after every
2402
+ * paint, so it follows a pan, a zoom, a resize and a layout run's every frame.
2403
+ */
2404
+
2405
+ /** One piece of DOM held against a node, a group or an edge. */
2406
+ interface DiagramOverlay {
2407
+ /** The node, group or edge it is held against. While no such id is in the
2408
+ * diagram it is not shown. */
2409
+ target: string;
2410
+ /** Beside the target's box, kept inside the view and flipped to the far
2411
+ * side when the near one has no room; or `'center'`, centered on it.
2412
+ * Default `'center'`. */
2413
+ placement?: Placement | 'center';
2414
+ /** Gap between the target's box and the overlay, in CSS pixels. Default 0. */
2415
+ offset?: number;
2416
+ /** Tells two overlays on one target apart. Default `target`. */
2417
+ key?: string;
2418
+ content: ReactNode;
2419
+ }
2420
+
2421
+ /**
2422
+ * The regions half of `DiagramView`'s sync: where each container, pool, and
2423
+ * lane stands, and the region edits a change to that is reported as.
2424
+ */
2425
+
2426
+ type Box = {
2427
+ x: number;
2428
+ y: number;
2429
+ width: number;
2430
+ height: number;
2431
+ };
2432
+ /**
2433
+ * A region edit, which `DiagramView` reports and does not keep: `box`, a
2434
+ * container or pool moved or resized (`parent` present when a drop changed
2435
+ * the region it is in, `null` for the top level); `lanes`, a pool's lanes
2436
+ * resized, reordered, or added to, every lane in stacking order with its size
2437
+ * (a new lane's id is minted by the view); `release`, Release members run on
2438
+ * a region; `title`, a double-click on a region's header.
2439
+ */
2440
+ type ContainerEdit = {
2441
+ kind: 'box';
2442
+ id: string;
2443
+ box: Box;
2444
+ parent?: string | null;
2445
+ } | {
2446
+ kind: 'lanes';
2447
+ pool: string;
2448
+ lanes: readonly {
2449
+ id: string;
2450
+ size: number;
2451
+ }[];
2452
+ } | {
2453
+ kind: 'release';
2454
+ id: string;
2455
+ } | {
2456
+ kind: 'title';
2457
+ id: string;
2458
+ };
2459
+
752
2460
  /**
753
2461
  * `DiagramView`'s two-way sync with the data it was built from: new specs are
754
2462
  * reconciled into the scene, and what a drag or a layout run changed is
@@ -756,11 +2464,14 @@ declare function registerDiagramShape<TPose>(opts?: DiagramShapeOptions<TPose>):
756
2464
  * `diagramLayoutOf` reads the same report off a `diagramScene` build.
757
2465
  */
758
2466
 
759
- /** Where a moved node now stands. */
2467
+ /** Where a moved node now stands. `parent` is present when a drop changed
2468
+ * the region it is in: that container's or lane's id, or `null` for the top
2469
+ * level. The host moves the id from one `members` list to the other. */
760
2470
  interface NodeMove {
761
2471
  id: string;
762
2472
  x: number;
763
2473
  y: number;
2474
+ parent?: string | null;
764
2475
  }
765
2476
  /** An edge whose route or ports a layout run rewrote. `id` is the edge's
766
2477
  * scene id, `edgeIdOf` of its data edge; `waypoints` is empty when the run
@@ -773,15 +2484,52 @@ interface EdgeRoute {
773
2484
  waypoints: readonly Vec2$1[];
774
2485
  ports: LayoutPorts;
775
2486
  }
776
- /** What layout placed in a `diagramScene` build, in the shape `DiagramView`'s
777
- * `onMove` reports: every node not pinned, where it stands, and every edge
778
- * whose route or ports layout wrote. Store them the way `onMove` says and
779
- * the next build leaves those nodes where they are. */
2487
+ /** What layout placed in a `diagramScene` build, in the shapes `DiagramView`
2488
+ * reports: every node not pinned, where it stands, every edge whose route
2489
+ * or ports layout wrote, and the box of every container and pool not pinned
2490
+ * whose box is its own rather than fitted. Store them the way `onMove` and
2491
+ * `onEditContainer` say and the next build leaves them where they are. */
780
2492
  declare function diagramLayoutOf(specs: readonly DiagramSpec[]): {
781
2493
  moves: NodeMove[];
782
2494
  routes: EdgeRoute[];
2495
+ containers: ContainerEdit[];
783
2496
  };
784
2497
 
2498
+ /** One end of a data edge moved onto node `node`, at `port` or on its body. */
2499
+ interface ReconnectChange {
2500
+ /** The data edge's id, `edgeIdOf` of it. */
2501
+ edge: string;
2502
+ end: 'from' | 'to';
2503
+ node: string;
2504
+ port?: string;
2505
+ }
2506
+ /** A data edge's route as a drag or a double-click left it. */
2507
+ interface RouteChange {
2508
+ /** The data edge's id, `edgeIdOf` of it. */
2509
+ edge: string;
2510
+ /** Empty when the edge no longer has any. */
2511
+ waypoints: readonly Vec2$1[];
2512
+ }
2513
+ /** Where a drag left a data edge's label, or `null` for Reset label. */
2514
+ interface LabelMove {
2515
+ /** The data edge's id, `edgeIdOf` of it. */
2516
+ edge: string;
2517
+ placement: DiagramLabel | null;
2518
+ }
2519
+ /** A node's box as a resize handle's drag left it: its place too, since a
2520
+ * handle on its top or left edge moves it. */
2521
+ interface NodeResize {
2522
+ id: string;
2523
+ x: number;
2524
+ y: number;
2525
+ width: number;
2526
+ height: number;
2527
+ }
2528
+ /** What a delete would take: the data nodes, and every data edge that goes with them. */
2529
+ interface DeleteReport {
2530
+ nodes: readonly string[];
2531
+ edges: readonly string[];
2532
+ }
785
2533
  /** Props for `DiagramView`. */
786
2534
  interface DiagramViewProps {
787
2535
  /** Every spec needs an id, which `diagramScene` gives them. A new array is
@@ -789,6 +2537,18 @@ interface DiagramViewProps {
789
2537
  * selection and anything moved since stay put unless the new specs change
790
2538
  * them. Pass a new `key` to start over instead. */
791
2539
  specs: readonly DiagramSpec[];
2540
+ /** `'avoid'` routes every edge around the shapes, holding one router across
2541
+ * new `specs` so each reroutes only what it disturbed. The routes derive
2542
+ * from the specs and are never reported. */
2543
+ router?: 'avoid';
2544
+ /** `'dodge'` moves each edge label off whatever covers it, along its
2545
+ * route or across it, after any `router` has run. Placement derives from
2546
+ * the specs and is never reported. */
2547
+ labels?: 'dodge';
2548
+ /** Line jumps of this radius: where two edges cross, the later one bows
2549
+ * over the earlier in a half circle. Applied after `router` and `labels`; derived from
2550
+ * the specs and never reported. */
2551
+ hops?: number;
792
2552
  /** The view opens fitted to the diagram, and fits again when the size or a
793
2553
  * fit option changes or a layout run settles, until the user pans or zooms;
794
2554
  * from then on the view is theirs. Omit both to fill the parent, which
@@ -801,22 +2561,80 @@ interface DiagramViewProps {
801
2561
  * picked node reports it again. The canvas keeps the pick even if
802
2562
  * `selected` does not follow it; only a change to `selected` is pushed in. */
803
2563
  onSelect?: (id: string | null) => void;
2564
+ /** Reports the node, group or edge the pointer comes to be over, and `null`
2565
+ * once it is over none or leaves the canvas. An edge answers only while
2566
+ * edges are picked (`pickEdges`). */
2567
+ onHover?: (id: string | null) => void;
2568
+ /** Whether a click or a hover can land on an edge, which is then picked
2569
+ * like a node. Default: on when `onReconnect`, `onEditRoute`, `onDelete`,
2570
+ * `onEditLabel` or `onMoveLabel` is set. */
2571
+ pickEdges?: boolean;
2572
+ /** DOM held against nodes, groups and edges, kept in place through pans,
2573
+ * zooms, resizes and layout runs. The view's box is their containing
2574
+ * block; their content takes the pointer, and the canvas beneath does not
2575
+ * see it. */
2576
+ overlays?: readonly DiagramOverlay[];
804
2577
  /** Set to let nodes be dragged. Reports every node a drag or a layout run
805
2578
  * moved, and every edge whose route or ports a layout run rewrote. Store
806
2579
  * each move as the data node's `at` with `pinned: true`, and each route as
807
2580
  * the data edge's `routed` and `routedPorts`, or the next `diagramScene`
808
2581
  * lays them out again. */
809
2582
  onMove?: (moves: readonly NodeMove[], routes: readonly EdgeRoute[]) => void;
2583
+ /** Set to give a selected node resize handles. The box resizes live while
2584
+ * a handle is dragged; on release the new box is reported and the view
2585
+ * draws it only once the specs do. Store it as the data node's `width`,
2586
+ * `height`, and `at` with `pinned: true`; the size is a minimum, so a box
2587
+ * dragged smaller than its rows grows back to them. */
2588
+ onResize?: (resizes: readonly NodeResize[]) => void;
810
2589
  /** Ports are grabbable when this is set, unless `ports` says otherwise. Dragging one port onto another reports the
811
- * edge it describes and draws nothing; add it to the data to keep it. */
2590
+ * edge it describes and draws nothing; add it to the data to keep it. An
2591
+ * end on a shape's body (`connectBodies`) has no port field. */
812
2592
  onConnect?: (edge: DataEdge) => void;
2593
+ /** Set to let a selected edge's ends be dragged onto another port, or with
2594
+ * `connectBodies` onto a shape's body. Reports the move and draws nothing; change the data edge to keep it. */
2595
+ onReconnect?: (change: ReconnectChange) => void;
2596
+ /** Set to give a selected edge handles along its route: drag one to move or
2597
+ * insert a waypoint, or slide an orthogonal segment; double-click one to
2598
+ * remove it. Reports the edge's new waypoints and draws nothing; store them
2599
+ * as the data edge's `waypoints` and clear its `routed`. */
2600
+ onEditRoute?: (change: RouteChange) => void;
2601
+ /** Set to let Delete and Backspace remove the selection. Reports the
2602
+ * selected data nodes (a selected group, not its members; a selected
2603
+ * container, pool, or lane with everything inside it) and every edge
2604
+ * selected or ending on one of them, and removes nothing. */
2605
+ onDelete?: (removed: DeleteReport) => void;
2606
+ /** Set to let a member of a group marked `reorder` be dragged along that
2607
+ * axis among its siblings, or the selected one stepped with Alt and an
2608
+ * arrow key. Reports the members' new order and moves nothing: write it to
2609
+ * the group's `members`, which layered layout keeps. */
2610
+ onReorder?: (change: ReorderChange) => void;
2611
+ /** Set to report a double-click on an edge, for its label to be edited. */
2612
+ onEditLabel?: (edge: string) => void;
2613
+ /** Set to let an edge's label be dragged along and beside it, and to enable
2614
+ * Reset label for the selected edge. Reports the placement and draws
2615
+ * nothing; store it as the data edge's `labelPlacement`, and delete that
2616
+ * field for `null`. */
2617
+ onMoveLabel?: (change: LabelMove) => void;
2618
+ /** Set to edit `DiagramData` containers and pools: drag a lane's boundary,
2619
+ * click a pool's add-lane button, drag a lane by its header to reorder,
2620
+ * move or resize a region, double-click a header, or run Release members.
2621
+ * Each is reported and nothing is kept until the specs follow. A region's
2622
+ * move also reports what it carried to `onMove`, and a lane resize the
2623
+ * members of the lanes it shifts. Store a `box` edit as the container's
2624
+ * `box` with `pinned: true`. */
2625
+ onEditContainer?: (edit: ContainerEdit) => void;
2626
+ /** Whether a connect or a reconnect may end on a shape's body, away from
2627
+ * its ports. Default false. */
2628
+ connectBodies?: boolean;
2629
+ /** Contributions to install after the view's own: a tool's bindings, a key. */
2630
+ ambient?: readonly Contribution[];
813
2631
  /** Whether ports are drawn. `'connect'` draws them and lets one be dragged
814
2632
  * onto another; `'show'` only draws them. Default: `'connect'` when
815
2633
  * `onConnect` is set, else `'none'`. */
816
2634
  ports?: 'connect' | 'show' | 'none';
817
2635
  /** Whether the canvas's keyboard shortcuts — held Space to pan among them —
818
2636
  * run. They listen page-wide, so a view-only diagram beside other UI would
819
- * claim keys meant for the page. Default: on when `onMove` or `onConnect`
2637
+ * claim keys meant for the page. Default: on when any callback that edits
820
2638
  * is set. */
821
2639
  enableKeybindings?: boolean;
822
2640
  /** Which ports may be joined. Default: a port may not join itself, and two
@@ -843,6 +2661,12 @@ interface DiagramViewProps {
843
2661
  fitPadding?: number;
844
2662
  /** What the canvas paints behind the diagram. Unset, it is transparent. */
845
2663
  background?: Paint;
2664
+ /** Sheets painted under the diagram, one filled rect per page; `diagramPages(data)`
2665
+ * places them. The default fit takes in every page. */
2666
+ pages?: {
2667
+ placed: readonly PlacedPage[];
2668
+ fill: string;
2669
+ };
846
2670
  /** The view, controlled. Set it and the fit is skipped; pair it
847
2671
  * with `onViewChange` or panning does nothing. */
848
2672
  view?: View;
@@ -860,11 +2684,36 @@ interface DiagramViewApi {
860
2684
  layout(algorithm?: DiagramLayout): void;
861
2685
  /** The run `layout` started: stop it where it stands, or cancel it. */
862
2686
  live: LiveLayout;
2687
+ /** The world point under a client point: where a drop from outside the canvas lands. */
2688
+ worldAt(clientX: number, clientY: number): Vec2$1;
2689
+ /** The world rect the canvas shows, or `null` before it has a size. */
2690
+ visible(): {
2691
+ x: number;
2692
+ y: number;
2693
+ width: number;
2694
+ height: number;
2695
+ } | null;
2696
+ /** Where a node, group or edge is drawn, in client coordinates — for an
2697
+ * edge, an empty rect at the midpoint along its route. `null` for an id the
2698
+ * diagram does not hold, or before the canvas mounts. Read it again from
2699
+ * {@link subscribeFrame}, after every paint. */
2700
+ rectOf(id: string): {
2701
+ x: number;
2702
+ y: number;
2703
+ width: number;
2704
+ height: number;
2705
+ } | null;
2706
+ /** Run `fn` after every paint: a pan, a zoom, a layout frame, a change of
2707
+ * specs. Returns an unsubscribe; a call before the canvas mounts returns one
2708
+ * and never runs `fn`. */
2709
+ subscribeFrame(fn: () => void): () => void;
863
2710
  }
864
2711
  /** What {@link DiagramViewApi.layout} runs. */
865
2712
  type DiagramLayout = 'layered' | 'tree' | 'force' | 'chain' | LayoutFn | LayoutPlanner;
2713
+
866
2714
  /** A diagram: drag or wheel to pan, zoom, and pick a node; drag nodes with
867
- * `onMove`, join ports with `onConnect`. Labels paint only in a registered
2715
+ * `onMove`, join ports with `onConnect`. Every edit is reported, never
2716
+ * written: change the specs to keep it. Labels paint only in a registered
868
2717
  * font family; `diagramScene` defaults to sans-serif, so call
869
2718
  * `registerCanvasFont('sans-serif')` or text renders blank. */
870
2719
  declare const DiagramView: react.ForwardRefExoticComponent<DiagramViewProps & react.RefAttributes<DiagramViewApi>>;
@@ -875,4 +2724,216 @@ declare const DiagramView: react.ForwardRefExoticComponent<DiagramViewProps & re
875
2724
  * `<SceneCanvas onClick>`. */
876
2725
  declare function useMirroredSelection(selection: Pick<SelectionApi, 'get' | 'set'>, selected: string | null | undefined, onSelect: ((id: string | null) => void) | undefined): () => void;
877
2726
 
878
- export { type ApplyLayoutOptions, CONNECT_ACTION_ID, type CanConnect, type ConnectActionOptions, DEFAULT_EDGE_STROKE, DIAGRAM_EDGE, DIAGRAM_LABEL, DataEdge, type DiagramContributionOptions, type DiagramLayout, DiagramNodeLike, DiagramNodeReader, type DiagramShapeOptions, DiagramSpec, DiagramView, type DiagramViewApi, type DiagramViewProps, EASED_LAYOUTS, EDGE_DERIVE_PATH, type EasedProducerOptions, EdgeEnd, type EdgeRoute, type EdgeRouteOptions, ForceOptions, type ForceProducerOptions, GRAB_PORT_ACTION_ID, Graph, GraphNodeLike, GraphSource, LABEL_DERIVE_POSE, LAYOUTS, LAYOUT_ACTION_ID, type LabelPoseOptions, type LayeredRoute, type LayeredRouteInput, type LayoutActionOptions, LayoutDirection, LayoutFn, LayoutOptions, LayoutPlan, LayoutPlanner, LayoutPorts, LayoutResult, type LayoutRoutes, type LiveLayout, type LiveLayoutCtx, type LiveLayoutFrame, type LiveLayoutProducer, type NodeMove, PORT_AFFORDANCE_KIND, PORT_LAYER_ID, type ParticipantPose, type ParticipantScene, type ParticipantSource, type PendingEdge, Port, type PortAffordanceOptions, type PortScratch, PortsOptions, ROUTERS, type RouteEdge, type RouteRequest, type RoutedScene, type Router, type SelfLoop, type UseLiveLayoutOptions, applyLayout, bezier, commitEdgeToScene, connectBinding, createConnectAction, createDiagramContribution, createLayoutAction, createPortAffordance, defaultCanConnect, diagramLayoutOf, diagramPorts, diagramShape, easedProducer, edgeDerivePath, forceProducer, grabPortAction, grabPortBindings, labelDerivePose, layeredRoutes, layoutPoses, orthogonal, portLayer, portScratchOf, registerDiagramShape, resolveEnd, routeWrites, routesOf, sceneParticipants, selfLoop, straight, useLiveLayout, useMirroredSelection, withDiagramRegistry };
2727
+ /** The themes that ship, by id, in the order a picker lists them. `paper` is ink on white;
2728
+ * `night` is the effect looks' own dark colors. */
2729
+ declare const DIAGRAM_THEMES: Readonly<Record<string, DiagramTheme>>;
2730
+
2731
+ /**
2732
+ * A theme matching its host's chrome, built from resolved `--wzl-*` values:
2733
+ * `read` answers a custom property's value, as `getComputedStyle(el)
2734
+ * .getPropertyValue` does. A token that reads empty takes `paper`'s color.
2735
+ */
2736
+ declare function diagramThemeFromTokens(read: (token: string) => string, opts?: {
2737
+ id?: string;
2738
+ name?: string;
2739
+ }): DiagramTheme;
2740
+
2741
+ /** The style a shape naming `role` is drawn in: that role's, or the theme's default role's. */
2742
+ declare function roleStyle(theme: DiagramTheme, role?: string): NodeStyle;
2743
+ /** The style a connector naming `role` is drawn in: the role's stroke, its label in that stroke too;
2744
+ * with no role, the theme's own connector and label colors. */
2745
+ declare function roleEdgeStyle(theme: DiagramTheme, role?: string): EdgeStyle;
2746
+ /** The stroke a connector drawn under `theme` starts with, for a connect action's `edgeStroke`. */
2747
+ declare function themeEdgeStroke(theme: DiagramTheme): Stroke;
2748
+ /** The theme's face as `diagramScene` and the stencils take one. */
2749
+ declare const themeFont: (theme: DiagramTheme) => {
2750
+ fontFamily: string;
2751
+ fontSize: number;
2752
+ };
2753
+ /** The face edge labels are sized from, before `labelStyleOf` takes two sizes off: the theme's label
2754
+ * face where it names one, else `font`. */
2755
+ declare const themeLabelFont: (theme: DiagramTheme, font?: {
2756
+ fontFamily: string;
2757
+ fontSize: number;
2758
+ }) => {
2759
+ fontFamily: string;
2760
+ fontSize: number;
2761
+ };
2762
+ /** The face a new connector label is set in under `theme`. */
2763
+ declare const themeLabelStyle: (theme: DiagramTheme) => {
2764
+ fontSize: number;
2765
+ fontFamily: string;
2766
+ };
2767
+ /** The theme a document value names: a shipped theme by id, or a whole theme. `fallback` for none,
2768
+ * or for an id no shipped theme has. */
2769
+ declare function diagramThemeFrom(value: unknown, fallback?: DiagramTheme): DiagramTheme;
2770
+ /** The theme a scene's `diagram:theme` value names. */
2771
+ declare function diagramThemeOf(scene: {
2772
+ doc: {
2773
+ get(key: string): unknown;
2774
+ };
2775
+ }, fallback?: DiagramTheme): DiagramTheme;
2776
+ /** What `diagram:theme` holds for `theme`: a shipped theme's id, or the whole theme. */
2777
+ declare const themeDocValue: (theme: DiagramTheme) => string | DiagramTheme;
2778
+
2779
+ /** A scene node as {@link themeWrites} reads it. */
2780
+ interface ThemedNode {
2781
+ id: string;
2782
+ parent: string | null;
2783
+ data: unknown;
2784
+ dependsOn?: readonly string[] | 'children';
2785
+ }
2786
+ /** A scene as {@link themeWrites} reads it. */
2787
+ interface ThemedScene {
2788
+ get(id: never): ThemedNode | undefined;
2789
+ renderOrderNodes(): readonly ThemedNode[];
2790
+ childrenOf(id: never): readonly string[];
2791
+ }
2792
+ /**
2793
+ * The new `data` for every node `theme` recolors: shapes, their text rows,
2794
+ * groups and containers and their titles, connectors and their labels. Given
2795
+ * `ids`, only those boxes and connectors, and the text that belongs to them.
2796
+ * Given `from`, the theme the scene was in, text moves by the step between the
2797
+ * two themes' sizes, except where its owner's author set the size. A node
2798
+ * already as the theme draws it is left out.
2799
+ */
2800
+ declare function themeWrites(scene: ThemedScene, theme: DiagramTheme, ids?: ReadonlySet<string>, from?: DiagramTheme): Map<string, unknown>;
2801
+
2802
+ /**
2803
+ * Measures a row's text as the kit's text renderer lays it out, from the
2804
+ * registered font's metrics, so a body sized by it holds the text it draws.
2805
+ * The line height is 1.2 sizes, as `canvasMeasure`'s is. Needs the family
2806
+ * registered; an unregistered one measures as the fallback glyph.
2807
+ */
2808
+ declare const rendererMeasure: MeasureRowText;
2809
+
2810
+ /**
2811
+ * Laying a built body out again once its text changes size. A body whose
2812
+ * rows are all text records how it stacks them (`DiagramNode.body`), and each
2813
+ * text row records its place (`bodyRow`), so the rows can be read back from
2814
+ * the scene and handed to the same layout `buildBody` used.
2815
+ */
2816
+
2817
+ /** A scene as {@link relayoutBodies} reads and writes it. */
2818
+ interface RelayoutScene {
2819
+ get(id: never): {
2820
+ pose: unknown;
2821
+ data: unknown;
2822
+ } | undefined;
2823
+ childrenOf(id: never): readonly string[];
2824
+ setPose(id: never, pose: never): void;
2825
+ }
2826
+ /**
2827
+ * Lays each body among `ids` out again from its text rows as they are now:
2828
+ * the body grows to what its rows need, never shrinks, and its rows are
2829
+ * stacked again inside it. Anything that is not a body carrying a `body`
2830
+ * record is left alone. Call inside the batch that changed the text, so it is
2831
+ * the same undo entry.
2832
+ */
2833
+ declare function relayoutBodies(scene: RelayoutScene, ids: Iterable<string>, measure?: MeasureRowText): void;
2834
+
2835
+ /**
2836
+ * The edits a theme makes to a scene, each one undo entry: applying a theme,
2837
+ * naming a shape's or connector's role, and setting a color by hand.
2838
+ */
2839
+
2840
+ type AnyScene = Scene<unknown, string, unknown>;
2841
+ /** What a styleable node says about its style: a shape or a connector, the role it names, and the
2842
+ * colors its author set by hand. */
2843
+ interface DiagramStyleState {
2844
+ kind: 'shape' | 'connector';
2845
+ role?: string;
2846
+ own: readonly StyleField[];
2847
+ /** The parts of its text face the author set: a theme's size change leaves those. */
2848
+ ownFont: readonly FontField[];
2849
+ }
2850
+ /** The style state of a shape (a body) or a connector, or `null` for anything else — a text row,
2851
+ * a label, a group, a container. */
2852
+ declare function diagramStyleOf(node: {
2853
+ data: unknown;
2854
+ }): DiagramStyleState | null;
2855
+ /** Options for {@link applyDiagramTheme}. */
2856
+ interface ApplyDiagramThemeOptions {
2857
+ /** Fold this apply into the undo entry before it when that one was made under the same key, so a
2858
+ * run of applies, such as a theme color dragged, undoes as one. See `scene.batch`. */
2859
+ coalesceKey?: string;
2860
+ /** The theme the scene is in now, whose font size text moves from. Default the scene's own
2861
+ * `diagram:theme`; a host that draws a scene naming none in another theme passes that. */
2862
+ from?: DiagramTheme;
2863
+ /** Measures text, for laying out again a body whose text changed size. Default an estimate. */
2864
+ measure?: MeasureRowText;
2865
+ }
2866
+ /** Recolors the whole scene in `theme` and saves it as the `diagram:theme` document value, as one
2867
+ * undo entry. Colors the author set by hand stay. */
2868
+ declare function applyDiagramTheme(scene: AnyScene, theme: DiagramTheme, label?: string, opts?: ApplyDiagramThemeOptions): void;
2869
+ /** Options for {@link setDiagramStyle} and {@link setDiagramColor}. */
2870
+ interface DiagramStyleEditOptions {
2871
+ /** The theme to color by. Default the scene's own `diagram:theme`. */
2872
+ theme?: DiagramTheme;
2873
+ label?: string;
2874
+ }
2875
+ /**
2876
+ * Names `role` on every shape and connector among `ids` and recolors them in
2877
+ * it, as one undo entry. Choosing a role hands back any color the author had
2878
+ * set, so the role shows.
2879
+ */
2880
+ declare function setDiagramStyle(scene: AnyScene, ids: readonly string[], role: string, opts?: DiagramStyleEditOptions): void;
2881
+ /**
2882
+ * Sets `field` to `color` on every shape and connector among `ids` — `text`
2883
+ * reaching a shape's rows and a connector's label — and records it in their
2884
+ * `ownStyle`, so a theme change leaves it. One undo entry. A connector has no
2885
+ * fill, and ignores one.
2886
+ */
2887
+ declare function setDiagramColor(scene: AnyScene, ids: readonly string[], field: StyleField, color: string, opts?: Pick<DiagramStyleEditOptions, 'label'>): void;
2888
+ /**
2889
+ * Sets the text of every shape and connector among `ids` — a shape's rows, a
2890
+ * connector's label — to `size`, and records it in their `ownFont`, so a
2891
+ * theme's size change leaves it. One undo entry.
2892
+ */
2893
+ declare function setDiagramFontSize(scene: AnyScene, ids: readonly string[], size: number, opts?: Pick<DiagramStyleEditOptions, 'label'> & {
2894
+ measure?: MeasureRowText;
2895
+ }): void;
2896
+
2897
+ type BoxField = 'fill' | 'stroke' | 'text';
2898
+ /** Where one value sits in a {@link DiagramTheme}. */
2899
+ type ThemePath = readonly ['roles', string, BoxField] | readonly ['edge', 'stroke'] | readonly ['label', 'fill'] | readonly ['container', BoxField] | readonly ['lane', 'header', BoxField] | readonly ['lane', 'bodies', number, BoxField] | readonly ['page'] | readonly ['font', 'family'] | readonly ['font', 'size'] | readonly ['series', number];
2900
+ /** Whether `theme` is one of {@link DIAGRAM_THEMES} itself, which no edit may change. */
2901
+ declare const isShippedTheme: (theme: DiagramTheme) => boolean;
2902
+ /** A custom copy of `theme`, named "<name> (edited)", for a document to keep and change. */
2903
+ declare function forkTheme(theme: DiagramTheme): DiagramTheme;
2904
+ /** `theme` when it is already a custom theme, else a fork of it: what the first edit to a shipped
2905
+ * theme starts from. */
2906
+ declare const editableTheme: (theme: DiagramTheme) => DiagramTheme;
2907
+ /** The value at `path` in `theme`. */
2908
+ declare function themeValue(theme: DiagramTheme, path: ThemePath): unknown;
2909
+ /** `theme` with `value` at `path`; everything else shared with it. */
2910
+ declare const setThemeValue: (theme: DiagramTheme, path: ThemePath, value: string | number) => DiagramTheme;
2911
+ /** Every role `theme` styles with the name a picker shows: the shipped roles first, in their order,
2912
+ * then the theme's own. */
2913
+ declare function themeRoles(theme: DiagramTheme): {
2914
+ id: string;
2915
+ label: string;
2916
+ }[];
2917
+ /** `theme` with a role named `label`, in the default role's colors, and the id it was given. */
2918
+ declare function addThemeRole(theme: DiagramTheme, label: string): {
2919
+ theme: DiagramTheme;
2920
+ id: string;
2921
+ };
2922
+ /** `theme` with role `id` shown as `label`. The id, which shapes name the role by, stays. */
2923
+ declare const renameThemeRole: (theme: DiagramTheme, id: string, label: string) => DiagramTheme;
2924
+ /** `theme` without role `id`; its shapes fall to the default role when the theme is next applied.
2925
+ * The default role stays: `theme` comes back unchanged. */
2926
+ declare function removeThemeRole(theme: DiagramTheme, id: string): DiagramTheme;
2927
+
2928
+ /** The extension a theme file is saved with. */
2929
+ declare const DIAGRAM_THEME_EXTENSION = ".weasel-theme.json";
2930
+ /** `theme` as the text of a theme file. */
2931
+ declare const themeToJson: (theme: DiagramTheme) => string;
2932
+ /** The theme a theme file holds, or what is wrong with it, each error naming where. */
2933
+ declare function parseDiagramTheme(json: string): {
2934
+ theme: DiagramTheme;
2935
+ } | {
2936
+ errors: string[];
2937
+ };
2938
+
2939
+ export { ADD_LANE_ACTION_ID, type ApplyDiagramThemeOptions, type ApplyLayoutOptions, AvoidInput, AvoidOptions, AvoidRouter, AvoidRoutes, type AvoidRouting, type AvoidRoutingOptions, type AvoidSceneOptions, type BodyEnd, type BodyHit, Bounds$2 as Bounds, CONNECTOR_ACTION_ID, CONNECTOR_TOOL_ID, CONNECT_ACTION_ID, CONTAINER_HEADER, CONTAINER_LAYOUTS, CONTAINER_STENCILS, type CanConnect, type ConnectActionOptions, type ConnectEnd, type ConnectView, type ContainerBuildOptions, type ContainerEdit, ContainerHeader, type ContainerLayoutOptions, ContainerRole, type ContainerStencil, DEFAULT_EDGE_STROKE, DIAGRAM_CONTAINER_LAYOUT, DIAGRAM_EDGE, DIAGRAM_LABEL, DIAGRAM_LANE_COLUMNS_LAYOUT, DIAGRAM_LANE_ROWS_LAYOUT, DIAGRAM_OFF_PAGE_TAG, DIAGRAM_PASS_ORDER, DIAGRAM_POOL_COLUMNS_LAYOUT, DIAGRAM_POOL_ROWS_LAYOUT, DIAGRAM_THEMES, DIAGRAM_THEME_EXTENSION, DataContainer, DataEdge, DataNode, type DeleteReport, DiagramContainer, type DiagramContributionOptions, DiagramData, DiagramEdge, DiagramLabel, type DiagramLayout, DiagramNodeLike, DiagramNodeReader, type DiagramOverlay, DiagramSceneData, DiagramSceneOptions, type DiagramShapeOptions, DiagramSpec, type DiagramStencil, type DiagramStyleEditOptions, type DiagramStyleState, DiagramTheme, DiagramView, type DiagramViewApi, type DiagramViewProps, type DraggableLabel, type DropParentScene, EASED_LAYOUTS, EDGE_DERIVE_PATH, EDGE_END_AFFORDANCE_KIND, EDGE_END_LAYER_ID, EDIT_CONTAINER_TITLE_ACTION_ID, EDIT_EDGE_LABEL_ACTION_ID, type EasedProducerOptions, EdgeEnd, type EdgeEndAffordanceOptions, type EdgeEndScratch, EdgeHop, type EdgeLabelOptions, type EdgeRoute, type EdgeRouteOptions, type EdgeRouteState, EdgeStyle, type EditEdgeLabelOptions, type EndChange, FLOWCHART_STENCILS, FOLLOW_OFF_PAGE_ACTION_ID, type FollowOffPageOptions, FontField, ForceOptions, type ForceProducerOptions, GRAB_EDGE_END_ACTION_ID, GRAB_LABEL_ACTION_ID, GRAB_PORT_ACTION_ID, GRAB_WAYPOINT_ACTION_ID, Graph, GraphNodeLike, GraphSource, type Hops, type HopsOptions, LABEL_DERIVE_POSE, LABEL_DRAG_AFFORDANCE_KIND, LABEL_DRAG_LAYER_ID, LANE_AFFORDANCE_KIND, LANE_HEADER_SIZE, LANE_LAYER_ID, LANE_RESIZE_ACTION_ID, LAYOUTS, LAYOUT_ACTION_ID, type LabelDragOptions, type LabelEdit, type LabelMove, type LabelPlacement, type LabelPlacementOptions, type LabelPoseOptions, type LabelScratch, LabelSpot, type LaneActionOptions, type LaneLayerOptions, type LaneResize, type LaneScratch, type LaneStackOptions, type LayeredRoute, type LayeredRouteInput, type LayoutActionOptions, LayoutDirection, LayoutFn, LayoutOptions, LayoutPlan, LayoutPlanner, LayoutPorts, LayoutResult, type LayoutRoutes, type LiveLayout, type LiveLayoutCtx, type LiveLayoutFrame, type LiveLayoutProducer, MIN_LANE_SIZE, MOVE_LABEL_ACTION_ID, MeasureRowText, type MovingEnd, type NodeMove, type NodeResize, NodeStyle, OFF_PAGE_STUB, OFF_PAGE_TAG_DERIVE_POSE, OFF_PAGE_TAG_PADDING, type OffPageEdgeInput, type OffPageMarkerOptions, OffPageSplit, type OffPageSplitInput, type OffPageTagLook, type OffPageTarget, Outline, POOL_HEADER_SIZE, PORT_AFFORDANCE_KIND, PORT_LAYER_ID, type ParticipantPose, type ParticipantScene, type ParticipantSource, type PendingEdge, PlaceLabelsOptions, type PoolLanes, Port, type PortAffordanceOptions, type PortScratch, PortsOptions, RECONNECT_ACTION_ID, RELEASE_MEMBERS_ACTION_ID, REMOVE_WAYPOINT_ACTION_ID, REORDER_ACTION_ID, RESET_LABEL_ACTION_ID, RESET_ROUTE_ACTION_ID, ROUTERS, ROUTER_LABELS, ROUTE_EDIT_ACTION_ID, type ReconnectChange, type ReconnectOptions, type RegionOptions, type RegionSpec, type RelayoutScene, type ReorderChange, type ReorderGap, type ReorderItem, type ReorderMove, type ReorderOptions, type ReorderSlots, type ResolvedRoute, type RouteChange, type RouteEdge, type RouteEdit, type RouteEditOptions, type RouteHandle, type RouteRequest, type RoutedScene, type Router, type RouterEdit, Row, RowTextStyle, SELECT_LABEL_EDGE_ACTION_ID, SET_HOPS_ACTION_ID, SET_ROUTER_ACTION_IDS, STEP_REORDER_ACTION_ID, type SelfLoop, type SetHopsOptions, type SetRouterOptions, type StencilInsertOptions, StyleField, type StyledRegion, type ThemePath, type ThemedNode, type ThemedScene, type UseLiveLayoutOptions, WAYPOINT_AFFORDANCE_KIND, WAYPOINT_HIT_PX, WAYPOINT_LAYER_ID, type WaypointAffordanceOptions, type WaypointScratch, addLane, addThemeRole, applyDiagramTheme, applyLayout, avoid, avoidSceneInput, bezier, bodyAt, commitEdgeToScene, commitLabelToScene, commitLaneResizeToScene, commitReconnectToScene, commitRouteToScene, commitRouterToScene, connectBinding, connectorTool, containerBuild, containerShape, createAddLaneAction, createConnectAction, createDiagramContribution, createEdgeEndAffordance, createFollowOffPageAction, createLabelDragAction, createLaneAffordance, createLaneResizeAction, createLayoutAction, createPortAffordance, createReconnectAction, createReleaseMembersAction, createRemoveWaypointAction, createReorderAction, createResetLabelAction, createResetRouteAction, createRouteEditAction, createSetHopsAction, createSetRouterAction, createSpecHops, createSpecLabelPlacer, createSpecRouter, createStepReorderAction, createWaypointAffordance, dataEdgeStyle, dataNodeStyle, dataOffPage, dataRegionStyle, defaultCanConnect, diagramCanDropInto, diagramContainerLayout, diagramContainers, diagramDropParentAt, diagramEdgeEnds, diagramLabelDrag, diagramLayoutOf, diagramOffPage, diagramPages, diagramPorts, diagramResizable, diagramScene, diagramShape, diagramStyleOf, diagramThemeFrom, diagramThemeFromTokens, diagramThemeOf, diagramWaypoints, documentBoundsOf, dragSegment, dragVertex, draggableLabels, dropEmptyEdgeLabel, easedProducer, edgeDerivePath, edgeEndLayer, edgeEndScratchOf, edgeIdOf, edgeLabelSpec, edgeRouter, editContainerTitleAction, editContainerTitleBinding, editEdgeLabelAction, editEdgeLabelBinding, editableTheme, firstLanes, followOffPageBinding, forceProducer, forkTheme, grabPortAction, grabPortBindings, groupReorderContribution, groupReorderSlots, headerIdOf, hopFollower, insertWaypoint, installAvoidRouting, installHops, installLabelPlacement, installOffPageMarkers, isBodyEnd, isShippedTheme, labelDerivePose, labelDragLayer, labelScratchOf, labelSize, labelUnder, laneHeader, laneLayer, laneResizeFrame, laneScratchOf, laneStackLayout, lanesOf, layeredRoutes, layoutPoses, movedLabelData, nextOffPageRef, offPageFarText, offPageOps, offPageSplits, offPageTagData, offPageTagDerivePose, offPageTagLook, offPageTagSize, offPageTagSpec, offPageTagSpecs, offPageTagText, offPageTargetOf, orthogonal, parseDiagramTheme, pinSegment, poolAxisOf, poolHeader, poolsOf, portLayer, portScratchOf, reconnectBinding, regionHeaderAt, regionSpecs, registerDiagramShape, relayoutBodies, releaseMembers, removeSegment, removeThemeRole, removeWaypoint, renameThemeRole, rendererMeasure, reorderBinding, reorderContribution, resolveEnd, roleEdgeStyle, roleStyle, routeDataOps, routeHandles, routeStateOf, routeWrites, routedData, routerActions, routesOf, sceneParticipants, segmentAxis, selfLoop, sequenceSlots, setDiagramColor, setDiagramFontSize, setDiagramStyle, setThemeValue, simplifyStops, stackedLanes, stencilBuild, stencilIdOf, stencilKind, stencilTool, straight, subpathOf, themeDocValue, themeEdgeStroke, themeFont, themeLabelFont, themeLabelStyle, themeRoles, themeToJson, themeValue, themeWrites, titlePose, unpinSegment, useAvoidRouting, useConnectorTool, useHops, useLabelPlacement, useLiveLayout, useMirroredSelection, useOffPageMarkers, useStencilInsert, useStencilTool, waypointFollower, waypointLayer, waypointScratchOf, withDiagramRegistry, withHops, withRouter };