@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
@@ -1,12 +1,12 @@
1
- import * as _weasel_js_geom from '@weasel-js/geom';
2
1
  import { Path, Vec2, PoseDescriptor } from '@weasel-js/core/math';
2
+ import * as _weasel_js_geom from '@weasel-js/geom';
3
3
 
4
4
  /**
5
5
  * The shapes a built body can wear, as paths in the node's bounds.
6
6
  *
7
7
  * These are the flowchart vocabulary — a decision is a diamond, an I/O step a
8
- * parallelogram, a terminator a stadium, a demultiplexer a trapezoid, a preparation step a hexagon —
9
- * plus `'rect'` for everything else and
8
+ * parallelogram, a terminator a stadium, a demultiplexer a trapezoid, a preparation step a hexagon,
9
+ * a connector an ellipse — plus `'rect'` for everything else and
10
10
  * a `Path` escape hatch for a shape the vocabulary does not have. The path is
11
11
  * built in world coordinates from the bounds it is given, the same way the
12
12
  * kit's own `clipFromPose` factories are; a custom `Path` is drawn in a unit
@@ -26,7 +26,7 @@ interface Bounds {
26
26
  /** A named flowchart shape, or a path a consumer built themselves in a unit
27
27
  * square — `(0, 0)` the box's top-left, `(1, 1)` its bottom-right — so it
28
28
  * follows its node wherever layout or a drag puts it. */
29
- type Outline = 'rect' | 'diamond' | 'stadium' | 'parallelogram' | 'trapezoid' | 'hexagon' | Path;
29
+ type Outline = 'rect' | 'diamond' | 'stadium' | 'ellipse' | 'parallelogram' | 'trapezoid' | 'hexagon' | Path;
30
30
  /** The path `outline` describes inside `bounds`. A zero-area box gives a
31
31
  * zero-area rect rather than a degenerate polygon. */
32
32
  declare function outlinePath(outline: Outline, bounds: Bounds): Path;
@@ -58,94 +58,45 @@ declare function boxForContent(outline: Outline, content: {
58
58
  };
59
59
 
60
60
  /**
61
- * Where a port sits on its node, in **normalized bounds coordinates**:
62
- * `(0, 0)` is the top-left corner of the node's AABB and `(1, 1)` the
63
- * bottom-right. `COMPASS` names the eight positions almost everything wants.
64
- *
65
- * Normalized rather than absolute because a node's size is authored data that
66
- * resize, align and distribute all write — a port fixed at an offset would
67
- * drift off the shape the first time one of them ran.
61
+ * The label trait: where along its edge a label sits. Data only — placing the
62
+ * label on the route is `label`'s job, so layout can read one without
63
+ * reaching the scene.
68
64
  */
69
- interface PortAnchor {
70
- u: number;
71
- v: number;
72
- }
73
- /** One more place a port may sit, and optionally the direction it faces there. */
74
- interface PortSite extends PortAnchor {
75
- normal?: Vec2 | null;
76
- }
77
- /** One attachment point declared on a node. */
78
- interface PortSpec {
79
- /** Unique within the node. Edges name this, so it outlives a re-layout. */
80
- id: string;
81
- at: PortAnchor;
82
- /** Other places the port may sit. An edge meeting the port takes whichever
83
- * of `at` and these faces the edge's next point most directly, so a
84
- * diamond's second exit can leave by its top or its bottom vertex, toward
85
- * wherever its wire goes. Everything else that shows a port where it is —
86
- * the connect affordance, `portsOf` — reads `at`. A site faces away from
87
- * the node's center unless it gives a `normal` of its own. */
88
- sites?: readonly PortSite[];
89
- /** Consulted by a connect gesture's validity predicate. Uninterpreted here. */
90
- type?: string;
91
- /** What the port is for, drawn beside it outside the node: beside the
92
- * wire rather than across it. A built body draws it and keeps it in its
93
- * `margin`; any other participant gets it on its resolved `Port`. */
94
- label?: string;
95
- /** The direction an edge leaves along, overriding the one the anchor
96
- * implies. `null` means "no preferred direction" — a router goes straight
97
- * at it. Applies at `at`; each of `sites` says its own. */
98
- normal?: Vec2 | null;
99
- }
100
- /**
101
- * The trait that makes an existing scene node a diagram participant.
102
- *
103
- * Attached to a node's `data`, not a node kind the plugin mints: a text block,
104
- * an image, a path, a group or a plain rect all take part by carrying this,
105
- * and nothing has to be authored through this package to be connectable.
106
- */
107
- interface DiagramNode {
108
- /** Defaults to {@link DEFAULT_PORTS} — the four edge midpoints of the
109
- * node's own bounds, which every node has. */
110
- ports?: readonly PortSpec[];
111
- /** Layout must not move this node. */
112
- pinned?: boolean;
113
- /** What the node is *drawn* as. Present on a built body; absent on a
114
- * participant that already had a look of its own — a text block, an image,
115
- * a path — which keeps whatever painter it already matched. */
116
- outline?: Outline;
117
- /** Present on a group's box: a node drawn around the participants it
118
- * depends on, which layout keeps together and leaves room for. The box
119
- * itself is never laid out — it derives its pose from its members — but an
120
- * edge can attach to it like any participant. */
121
- group?: DiagramGroup;
122
- /** How far past its bounds something drawn with it reaches, on each side —
123
- * a built body's port labels. Layout keeps neighbors that far off too. */
124
- margin?: GroupInset;
125
- }
126
- /** The group half of a {@link DiagramNode}. */
127
- interface DiagramGroup {
128
- /** Room the box keeps around its members, in world units: one number for
129
- * every side, or per side. Default 12 on each. */
130
- inset?: number | Partial<GroupInset>;
131
- /** The narrowest the box may be, in world units, as room for its label.
132
- * A box its members leave narrower grows evenly on both sides. */
133
- minWidth?: number;
134
- }
135
- /** A port resolved against a node's current pose: where it is in world
136
- * coordinates, and which way an edge leaves it. */
137
- interface Port {
138
- id: string;
139
- /** The node this port belongs to. */
140
- nodeId: string;
141
- /** World point an edge attaches to. */
142
- point: Vec2;
143
- /** Unit vector pointing away from the node, or `null` when the port
144
- * declared no direction. Rotated with the node. */
145
- normal: Vec2 | null;
146
- type?: string;
147
- label?: string;
148
- }
65
+
66
+ /** Where along an edge a label sits. */
67
+ interface DiagramLabel {
68
+ /** `'start'`, `'mid'` and `'end'` are 0, 0.5 and 1; a number is that
69
+ * fraction of the route's length. `{ near }` is the point on the route
70
+ * nearest `near`, in world coordinates — where `layered` leaves a label
71
+ * room — so a bend added or removed elsewhere leaves the label on the
72
+ * stretch it was on. */
73
+ at: 'start' | 'mid' | 'end' | number | {
74
+ near: Vec2;
75
+ };
76
+ /** World units between the route and the label's near side, to the **left
77
+ * of the direction of travel** — above a left-to-right edge. Default 0,
78
+ * which centers the label on the line. */
79
+ offset?: number;
80
+ /** Where label placement moved it, off a station something covered:
81
+ * `at` a fraction of the route's length, `offset` as above. Read in place
82
+ * of `at` and `offset`, which stay the author's preference. Written only
83
+ * by placement (`installLabelPlacement`). */
84
+ placed?: LabelSpot;
85
+ /** `false` keeps placement from ever moving this label. */
86
+ dodge?: false;
87
+ }
88
+ /** A station placement chose: a fraction of the route's length, and the
89
+ * offset from the line. */
90
+ interface LabelSpot {
91
+ at: number;
92
+ offset: number;
93
+ }
94
+ /** Where an edge label sits when neither the edge nor the scene says. */
95
+ declare const LABEL_PLACEMENT: DiagramLabel;
96
+ /** The label trait on a node's data, or `null`. */
97
+ declare function diagramLabelOf(node: {
98
+ data: unknown;
99
+ }): DiagramLabel | null;
149
100
 
150
101
  /**
151
102
  * Reading the `DiagramNode` trait off a scene node.
@@ -190,7 +141,7 @@ interface DiagramNodeEntry {
190
141
  * the two apart. Without that test an edge reads as a participant declaring
191
142
  * no ports, and collects the four defaults on the degenerate pose an edge
192
143
  * carries. An edge label's `label` trait and an anchored node's `anchor` are
193
- * excluded the same way. */
144
+ * excluded the same way, and so is a pool's lane, which takes no connectors. */
194
145
  declare const dataKeyReader: DiagramNodeReader;
195
146
  /**
196
147
  * A reader over declared kinds. A trait on the node's own data still wins, so
@@ -257,6 +208,9 @@ interface GraphGroup {
257
208
  minWidth?: number;
258
209
  /** The group this one is directly inside. */
259
210
  parent?: string;
211
+ /** Its direct members, nodes and groups, in the order a layered layout
212
+ * keeps them across every rank: set for a group that reorders. */
213
+ ordered?: readonly string[];
260
214
  }
261
215
  /** One connection. `id` is the edge node's own id, so a caller can go back to
262
216
  * the scene for its trait. */
@@ -520,7 +474,7 @@ declare const DEFAULT_GROUP_INSET = 12;
520
474
  * across it. A group's inset there includes that of any group nested in it
521
475
  * that ends, or starts, at the same rank. `rows` is the nodes of each rank.
522
476
  */
523
- declare function rankGaps(graph: Graph, rows: readonly (readonly GraphNode[])[], axes: LayoutAxes, rankGap: number): number[];
477
+ declare function rankGaps(graph: Pick<Graph, 'groups'>, rows: readonly (readonly Pick<GraphNode, 'id'>[])[], axes: LayoutAxes, rankGap: number): number[];
524
478
  /**
525
479
  * Cross positions for every node, with each group's members kept in a column
526
480
  * of their own, and a nested group in a column inside its parent's.
@@ -540,53 +494,165 @@ declare function packClusters(graph: Graph, rows: readonly (readonly GraphNode[]
540
494
  declare function expandGroupEdges(edges: readonly GraphEdge[], groups: readonly GraphGroup[]): GraphEdge[];
541
495
 
542
496
  /**
543
- * Perimeter port labels: where the text naming a port is drawn, and how far
544
- * past its node that reaches.
497
+ * The container trait: what makes a core `ContainerNode` a diagram container,
498
+ * a pool, or one of a pool's lanes, and where its header is.
545
499
  *
546
- * A label sits outside the node, on the port's own face, and to one side of
547
- * the line the port's wire leaves along, so the wire does not run through it.
548
- * A port inside a row draws its label inside the box instead; that is a
549
- * `ports` row's job, not this module's.
500
+ * A container's title is a text child in its header, named
501
+ * `<container id>/title`. The layouts find it by that name, because a layout
502
+ * strategy sees only ids and poses.
550
503
  */
551
504
 
552
- /** Between a port and the near sides of its label, in world units. */
553
- declare const PORT_LABEL_GAP = 4;
505
+ /** Which kind of region a container is. */
506
+ type ContainerRole = 'container' | 'pool' | 'lane';
507
+ /** The strip a container's title sits in, along one side. */
508
+ interface ContainerHeader {
509
+ side: 'top' | 'left';
510
+ /** Its depth into the container, in world units. */
511
+ size: number;
512
+ }
513
+ /** The container half of a diagram node's trait, under `data.diagram.container`. */
514
+ interface DiagramContainer {
515
+ role: ContainerRole;
516
+ header?: ContainerHeader;
517
+ /** Its box is fitted to its members each time the diagram is built from data
518
+ * (`DataContainer` with no `box`), so a move that carries it along is no edit of its own. */
519
+ fitted?: true;
520
+ }
521
+ type Box = {
522
+ x: number;
523
+ y: number;
524
+ width: number;
525
+ height: number;
526
+ };
527
+ /** The container trait on a node's data, or `null`. */
528
+ declare function diagramContainerOf(node: {
529
+ data: unknown;
530
+ }): DiagramContainer | null;
531
+ /** The id of a container's title node. */
532
+ declare const titleIdOf: (containerId: string) => string;
533
+ /** The header strip of a container at `bounds`; null with no header. */
534
+ declare function headerBox(bounds: Box, header: ContainerHeader | undefined): Box | null;
535
+ /** What a container at `bounds` holds members in: everything past its header. */
536
+ declare function bodyBox(bounds: Box, header: ContainerHeader | undefined): Box;
537
+
538
+ /** A color on a shape or connector that the author can set by hand, and a theme then leaves alone.
539
+ * On a connector, `text` is its label's color. */
540
+ type StyleField = 'fill' | 'stroke' | 'text';
541
+ /** A part of a shape's or connector's text face the author can set by hand, which a theme then
542
+ * leaves alone. Kept apart from {@link StyleField}, so choosing a role, which hands back the
543
+ * colors, keeps it. */
544
+ type FontField = 'size';
545
+
554
546
  /**
555
- * Where a label `size` big goes for a port at `point` facing `normal`.
547
+ * Where a port sits on its node, in **normalized bounds coordinates**:
548
+ * `(0, 0)` is the top-left corner of the node's AABB and `(1, 1)` the
549
+ * bottom-right. `COMPASS` names the eight positions almost everything wants.
556
550
  *
557
- * A port on a left or right face gets its label outside that face, above its
558
- * wire; one on a top or bottom face, outside that face, right of its wire; a
559
- * corner port, off the corner. A port with no direction gets it centered
560
- * above.
551
+ * Normalized rather than absolute because a node's size is authored data that
552
+ * resize, align and distribute all write — a port fixed at an offset would
553
+ * drift off the shape the first time one of them ran.
561
554
  */
562
- declare function portLabelBox(port: {
555
+ interface PortAnchor {
556
+ u: number;
557
+ v: number;
558
+ }
559
+ /** One more place a port may sit, and optionally the direction it faces there. */
560
+ interface PortSite extends PortAnchor {
561
+ normal?: Vec2 | null;
562
+ }
563
+ /** One attachment point declared on a node. */
564
+ interface PortSpec {
565
+ /** Unique within the node. Edges name this, so it outlives a re-layout. */
566
+ id: string;
567
+ at: PortAnchor;
568
+ /** Other places the port may sit. An edge meeting the port takes whichever
569
+ * of `at` and these faces the edge's next point most directly, so a
570
+ * diamond's second exit can leave by its top or its bottom vertex, toward
571
+ * wherever its wire goes. Everything else that shows a port where it is —
572
+ * the connect affordance, `portsOf` — reads `at`. A site faces away from
573
+ * the node's center unless it gives a `normal` of its own. */
574
+ sites?: readonly PortSite[];
575
+ /** Consulted by a connect gesture's validity predicate. Uninterpreted here. */
576
+ type?: string;
577
+ /** What the port is for, drawn beside it outside the node: beside the
578
+ * wire rather than across it. A built body draws it and keeps it in its
579
+ * `margin`; any other participant gets it on its resolved `Port`. */
580
+ label?: string;
581
+ /** The direction an edge leaves along, overriding the one the anchor
582
+ * implies. `null` means "no preferred direction" — a router goes straight
583
+ * at it. Applies at `at`; each of `sites` says its own. */
584
+ normal?: Vec2 | null;
585
+ }
586
+ /**
587
+ * The trait that makes an existing scene node a diagram participant.
588
+ *
589
+ * Attached to a node's `data`, not a node kind the plugin mints: a text block,
590
+ * an image, a path, a group or a plain rect all take part by carrying this,
591
+ * and nothing has to be authored through this package to be connectable.
592
+ */
593
+ interface DiagramNode {
594
+ /** Defaults to {@link DEFAULT_PORTS} — the four edge midpoints of the
595
+ * node's own bounds, which every node has. */
596
+ ports?: readonly PortSpec[];
597
+ /** Layout must not move this node. */
598
+ pinned?: boolean;
599
+ /** What the node is *drawn* as. Present on a built body; absent on a
600
+ * participant that already had a look of its own — a text block, an image,
601
+ * a path — which keeps whatever painter it already matched. */
602
+ outline?: Outline;
603
+ /** Present on a group's box: a node drawn around the participants it
604
+ * depends on, which layout keeps together and leaves room for. The box
605
+ * itself is never laid out — it derives its pose from its members — but an
606
+ * edge can attach to it like any participant. */
607
+ group?: DiagramGroup;
608
+ /** Present on a container, a pool, or a lane: a `ContainerNode` holding
609
+ * members (`containers/trait.ts`). */
610
+ container?: DiagramContainer;
611
+ /** How far past its bounds something drawn with it reaches, on each side —
612
+ * a built body's port labels. Layout keeps neighbors that far off too. */
613
+ margin?: GroupInset;
614
+ /** The theme role it is drawn in. Unset, the theme's default role. */
615
+ style?: string;
616
+ /** The colors the author set by hand, which a theme leaves as they are. */
617
+ ownStyle?: readonly StyleField[];
618
+ /** The parts of its text face the author set by hand, which a theme leaves as they are. */
619
+ ownFont?: readonly FontField[];
620
+ /** On a built body whose rows are all text: how it stacks them, so it can be laid out again when
621
+ * their text changes size. Each row's text node carries its place as `bodyRow`. */
622
+ body?: BodyLayout;
623
+ }
624
+ /** How a built body stacks its text rows: the `BodySpec` fields its layout reads, and how many rows. */
625
+ interface BodyLayout {
626
+ padding: number;
627
+ gap: number;
628
+ verticalAlign: 'top' | 'center' | 'bottom';
629
+ rows: number;
630
+ }
631
+ /** The group half of a {@link DiagramNode}. */
632
+ interface DiagramGroup {
633
+ /** Room the box keeps around its members, in world units: one number for
634
+ * every side, or per side. Default 12 on each. */
635
+ inset?: number | Partial<GroupInset>;
636
+ /** The narrowest the box may be, in world units, as room for its label.
637
+ * A box its members leave narrower grows evenly on both sides. */
638
+ minWidth?: number;
639
+ /** The axis its members can be dragged along to change their order. */
640
+ reorder?: 'x' | 'y';
641
+ }
642
+ /** A port resolved against a node's current pose: where it is in world
643
+ * coordinates, and which way an edge leaves it. */
644
+ interface Port {
645
+ id: string;
646
+ /** The node this port belongs to. */
647
+ nodeId: string;
648
+ /** World point an edge attaches to. */
563
649
  point: Vec2;
650
+ /** Unit vector pointing away from the node, or `null` when the port
651
+ * declared no direction. Rotated with the node. */
564
652
  normal: Vec2 | null;
565
- }, size: {
566
- width: number;
567
- height: number;
568
- }, gap?: number): Bounds;
569
- /** Where a built body's perimeter port label sits, as `buildBody`'s
570
- * `portLabel` is handed it. */
571
- interface PerimeterPortLabelBox extends Bounds {
572
- port: PortSpec;
573
- side: 'outside';
574
- }
575
- /** A labeled port, resolved, and the box its label is drawn in. */
576
- interface PortLabelPlacement {
577
- port: Port & {
578
- label: string;
579
- };
580
- box: Bounds;
653
+ type?: string;
654
+ label?: string;
581
655
  }
582
- /** Every labeled port of `trait` resolved against `bounds`, with its label's
583
- * box. `size` measures one label. */
584
- declare function portLabelsOf(trait: DiagramNode, bounds: Bounds, size: (text: string) => {
585
- width: number;
586
- height: number;
587
- }): PortLabelPlacement[];
588
- /** How far `boxes` reach past `bounds` on each side; `undefined` for none. */
589
- declare function marginOf(bounds: Bounds, boxes: readonly Bounds[]): GroupInset | undefined;
590
656
 
591
657
  /** One line of body content. */
592
658
  type Row =
@@ -659,20 +725,6 @@ interface BodySpec {
659
725
  /** Perimeter port labels by id, drawn outside the box; over a port's own `label`. */
660
726
  portLabels?: Readonly<Record<string, string>>;
661
727
  }
662
- /** What {@link buildBody} emits: the `AddNodeSpec` fields it fills in. Named
663
- * structurally rather than imported so a consumer whose scene is typed
664
- * differently can still spread one. */
665
- interface BodyNodeSpec<TData, TLayer extends string, TPose> {
666
- kind: 'container' | 'leaf';
667
- layer: TLayer;
668
- pose: TPose;
669
- data: TData;
670
- id?: string;
671
- parent?: string;
672
- /** Set `false` on every leaf the builder emits: the innermost hit wins, so a
673
- * row that answers a press is a body that cannot be dragged. */
674
- pickable?: boolean;
675
- }
676
728
  /** The floor a body's content puts under its node's size. */
677
729
  interface BodyFloor {
678
730
  minWidth: number;
@@ -744,43 +796,30 @@ declare function bodyTrait(spec: BodySpec, bounds: Bounds, measure?: MeasureRowT
744
796
  /** The outline path for a built body at `bounds` — what paints it, and what a
745
797
  * perimeter-hugging port will eventually be placed on. */
746
798
  declare function bodyOutline(spec: BodySpec, bounds: Bounds): _weasel_js_geom.Path;
747
- /** What a built body's rows are handed to, one call per row.
748
- *
749
- * `text` is the row's content already formatted — a `label`'s own text, or a
750
- * `field`'s `"label: value"` — so the common case needs no discrimination.
751
- * Return `null` for a row the consumer paints itself; `ports` and `slot` rows
752
- * arrive with `text` empty and are the usual ones to decline. */
753
- type RowNodeData<TData> = (text: string, box: RowBox) => TData | null;
754
- /** Options for {@link buildBody}: the layer and data of each node it emits.
755
- * Without `measure`, rows are sized from a fallback line height rather than
756
- * their text. */
757
- interface BuildBodyOptions<TData, TLayer extends string, TPose extends Bounds> {
758
- layer: TLayer;
759
- /** The container's id. Edges name it, so pass one for anything an edge or a
760
- * layout `pin` will refer to. */
761
- id?: string;
762
- measure?: MeasureRowText;
763
- /** The container's own data, given the trait the builder computed and the
764
- * pose it was computed against. */
765
- body: (trait: DiagramNode, pose: TPose) => TData;
766
- /** One row's data, or `null` to leave that row undrawn. */
767
- row: RowNodeData<TData>;
768
- /** One port's label — a row port's or a perimeter port's — or `null` to
769
- * leave it undrawn. Ports with no label are never offered. Omit to draw none. */
770
- portLabel?: (text: string, box: RowPortBox | PerimeterPortLabelBox) => TData | null;
771
- }
799
+
772
800
  /**
773
- * The scene nodes a built body is: one container carrying the trait, and one
774
- * leaf per row that wants drawing.
775
- *
776
- * Rows are ordinary scene nodes rather than something this package paints, so
777
- * the kit's own text painter draws them and text editing, styling, and
778
- * selection work on them unchanged. The returned pose is `at` grown to fit the
779
- * body, never shrunk.
801
+ * Line jumps as data: the document value that turns them on, and the hops a
802
+ * connector carries. Plain data, so layout and any reader can use it.
780
803
  */
781
- declare function buildBody<TData, TLayer extends string, TPose extends Bounds>(spec: BodySpec, at: TPose, opts: BuildBodyOptions<TData, TLayer, TPose>): {
782
- pose: TPose;
783
- specs: BodyNodeSpec<TData, TLayer, TPose>[];
784
- };
785
804
 
786
- export { buildGraph as $, type GraphNode as A, type BodySpec as B, type GroupInset as C, type DiagramGroup as D, type EdgeLabelRoom as E, type LayoutAxes as F, type Graph as G, PORT_LABEL_GAP as H, type PerimeterPortLabelBox as I, type PortLabelPlacement as J, type PortSite as K, type LayoutPorts as L, type MeasureRowText as M, type RowBox as N, type Outline as O, type PortAnchor as P, type RowNodeData as Q, type RowTextStyle as R, type RowPort as S, type RowPortBox as T, type Slot as U, anchorOffset as V, axesFor as W, bodyOutline as X, bodyTrait as Y, boxForContent as Z, buildBody as _, type Row as a, canvasMeasure as a0, contentBox as a1, createDiagramNodes as a2, dataKeyReader as a3, diagramNodeOf as a4, expandGroupEdges as a5, graphOrder as a6, insetOf as a7, isPinned as a8, layoutBody as a9, layoutRowPorts as aa, marginOf as ab, measureBody as ac, outlinePath as ad, packAcross as ae, packClusters as af, pinnedSet as ag, planOf as ah, plannerPlan as ai, portLabelBox as aj, portLabelsOf as ak, rankGaps as al, seededOrder as am, settle as an, sizeToBody as ao, translated as ap, untilSettled as aq, extent as ar, type PortSpec as b, type LayoutFn as c, type LayoutOptions as d, type DiagramNode as e, type Port as f, type DiagramNodeLike as g, type DiagramNodeReader as h, type LayoutResult as i, type GraphSource as j, type LayoutPlanner as k, type LayoutDirection as l, type LayoutPlan as m, type GraphNodeLike as n, type BodyFloor as o, type BodyNodeSpec as p, type Bounds as q, type BuildBodyOptions as r, type BuildGraphOptions as s, DEFAULT_GROUP_INSET as t, DEFAULT_NODE_GAP as u, DEFAULT_RANK_GAP as v, DIAGRAM_TRAIT_KEY as w, type DiagramNodeEntry as x, type GraphEdge as y, type GraphGroup as z };
805
+ /** The document value (`scene.doc`) holding the line-jump setting: present
806
+ * while hops are on, absent while off. */
807
+ declare const HOPS_DOC_KEY = "diagram:hops";
808
+ /** The line-jump setting while it is on. */
809
+ interface HopsDocValue {
810
+ /** A hop's radius, in world units. */
811
+ size: number;
812
+ }
813
+ /** The radius a hop takes when nothing sets one. */
814
+ declare const DEFAULT_HOP_SIZE = 5;
815
+ /** Where a connector bows over others: a half circle of radius `r` centered
816
+ * on `at`, which lies on the connector's route. `over` names the connectors
817
+ * it passes over; hops closer than `2r` merge into one, which passes over all
818
+ * of theirs. */
819
+ interface EdgeHop {
820
+ at: Vec2;
821
+ over: readonly string[];
822
+ r: number;
823
+ }
824
+
825
+ export { anchorOffset as $, type DiagramNodeEntry as A, type BodySpec as B, type ContainerRole as C, type DiagramGroup as D, type EdgeHop as E, type FontField as F, type Graph as G, type EdgeLabelRoom as H, type GraphEdge as I, type GraphGroup as J, type GraphNode as K, type LayoutPorts as L, type MeasureRowText as M, type GroupInset as N, type Outline as O, type PortAnchor as P, HOPS_DOC_KEY as Q, type RowTextStyle as R, type StyleField as S, type HopsDocValue as T, LABEL_PLACEMENT as U, type LayoutAxes as V, type PortSite as W, type RowBox as X, type RowPort as Y, type RowPortBox as Z, type Slot as _, type Row as a, axesFor as a0, bodyBox as a1, bodyOutline as a2, bodyTrait as a3, boxForContent as a4, buildGraph as a5, canvasMeasure as a6, contentBox as a7, createDiagramNodes as a8, dataKeyReader as a9, diagramContainerOf as aa, diagramLabelOf as ab, diagramNodeOf as ac, expandGroupEdges as ad, graphOrder as ae, headerBox as af, insetOf as ag, isPinned as ah, layoutBody as ai, layoutRowPorts as aj, measureBody as ak, outlinePath as al, packAcross as am, packClusters as an, pinnedSet as ao, planOf as ap, plannerPlan as aq, rankGaps as ar, seededOrder as as, settle as at, sizeToBody as au, titleIdOf as av, translated as aw, untilSettled as ax, extent as ay, type PortSpec as b, type DiagramLabel as c, type LayoutFn as d, type LayoutOptions as e, type DiagramNode as f, type Port as g, type DiagramNodeLike as h, type DiagramNodeReader as i, type DiagramContainer as j, type ContainerHeader as k, type LabelSpot as l, type Bounds as m, type LayoutResult as n, type GraphSource as o, type LayoutPlanner as p, type LayoutDirection as q, type LayoutPlan as r, type GraphNodeLike as s, type BodyFloor as t, type BuildGraphOptions as u, DEFAULT_GROUP_INSET as v, DEFAULT_HOP_SIZE as w, DEFAULT_NODE_GAP as x, DEFAULT_RANK_GAP as y, DIAGRAM_TRAIT_KEY as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weasel-js/diagram",
3
- "version": "1.11.0",
3
+ "version": "1.12.0",
4
4
  "description": "Node-link diagramming for weasel: any scene node becomes a diagram participant, with ports on its perimeter and an optional body builder for flowchart-shaped boxes.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -21,15 +21,36 @@
21
21
  "import": "./dist/effect.js",
22
22
  "types": "./dist/effect.d.ts"
23
23
  },
24
+ "./effect-audio": {
25
+ "import": "./dist/effect-audio.js",
26
+ "types": "./dist/effect-audio.d.ts"
27
+ },
28
+ "./icons": {
29
+ "import": "./dist/icons.table.js",
30
+ "types": "./dist/icons.table.d.ts"
31
+ },
24
32
  "./package.json": "./package.json"
25
33
  },
26
34
  "peerDependencies": {
27
35
  "react": ">=18",
28
- "@weasel-js/animator": "1.11.0",
29
- "@weasel-js/core": "1.11.0",
30
- "@weasel-js/font": "1.11.0",
31
- "@weasel-js/geom": "1.11.0",
32
- "@weasel-js/simulation": "1.11.0"
36
+ "@weasel-js/animator": "1.12.0",
37
+ "@weasel-js/audio": "1.12.0",
38
+ "@weasel-js/core": "1.12.0",
39
+ "@weasel-js/font": "1.12.0",
40
+ "@weasel-js/geom": "1.12.0",
41
+ "@weasel-js/react": "1.12.0",
42
+ "@weasel-js/simulation": "1.12.0"
43
+ },
44
+ "peerDependenciesMeta": {
45
+ "@weasel-js/audio": {
46
+ "optional": true
47
+ }
48
+ },
49
+ "weaselIcons": {
50
+ "table": "./dist/icons.table.json"
51
+ },
52
+ "dependencies": {
53
+ "@weasel-js/icons": "1.12.0"
33
54
  },
34
55
  "author": "orochi235",
35
56
  "homepage": "https://orochi235.github.io/weasel/",
@@ -50,7 +71,7 @@
50
71
  "LICENSE"
51
72
  ],
52
73
  "scripts": {
53
- "build": "tsup"
74
+ "build": "tsup && cp src/icons.table.json dist/"
54
75
  },
55
76
  "publishConfig": {
56
77
  "access": "public",