@weasel-js/diagram 1.11.0 → 1.12.0

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