@weasel-js/diagram 1.9.2 → 1.9.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { P as Port, a as PortsOptions, D as DiagramNodeLike, b as DiagramNodeReader, R as Row, O as Outline, c as PortSpec, B as BodySpec, d as DiagramNode, L as LayoutFn, e as LayoutOptions, M as MeasureRowText, G as GraphSource, F as ForceOptions, f as LayoutResult, g as Graph } from './layout.entry-W-8PYfGM.js';
2
- export { h as BodyFloor, i as BodyNodeSpec, j as Bounds, k as BuildBodyOptions, l as BuildGraphOptions, C as COMPASS, m as DEFAULT_NODE_GAP, n as DEFAULT_PORTS, o as DEFAULT_RANK_GAP, p as DIAGRAM_TRAIT_KEY, q as DiagramNodeEntry, r as ForceBody, s as ForceRelaxation, t as GraphEdge, u as GraphNode, v as GraphNodeLike, w as LayoutAxes, x as LayoutDirection, y as PortAnchor, z as RowBox, A as RowNodeData, E as RowPort, H as RowPortBox, I as RowTextStyle, S as Slot, J as axesFor, K as backEdges, N as bodyOutline, Q as bodyTrait, T as boxForContent, U as buildBody, V as buildGraph, W as canvasMeasure, X as contentBox, Y as createDiagramNodes, Z as dataKeyReader, _ as diagramNodeOf, $ as force, a0 as forceRelaxation, a1 as forestOf, a2 as graphOrder, a3 as isPinned, a4 as layered, a5 as layoutBody, a6 as layoutRowPorts, a7 as measureBody, a8 as outlinePath, a9 as outlinePolyline, aa as packAcross, ab as pinnedSet, ac as portOf, ad as portsOf, ae as portsOnOutline, af as ranksOf, ag as rayHit, ah as seededOrder, ai as settle, aj as sizeToBody, ak as translated, al as tree } from './layout.entry-W-8PYfGM.js';
3
- import { Vec2, DerivedDep, Path, SceneRegistry, PoseDescriptor, ChromeState, FillStyle, Stroke, CursorSpec, Affordance, InvocationCtx, GestureBinding, Action, Contribution, RenderLayer, MarkerRef, AddNodeSpec, RectPose, Scene, EasingFn, NodeId, NodeShapeEntry, View, SelectionApi } from '@weasel-js/core';
1
+ import { P as Port, a as PortsOptions, D as DiagramNodeLike, b as DiagramNodeReader, c as PortAnchor, d as DiagramGroup, R as Row, O as Outline, e as PortSpec, B as BodySpec, f as DiagramNode, L as LayoutFn, g as LayoutOptions, M as MeasureRowText, G as GraphSource, F as ForceOptions, h as LayoutResult, i as Graph } from './layout.entry-DyKFfHG5.js';
2
+ export { j as BodyFloor, k as BodyNodeSpec, l as Bounds, m as BuildBodyOptions, n as BuildGraphOptions, C as COMPASS, o as DEFAULT_GROUP_INSET, p as DEFAULT_NODE_GAP, q as DEFAULT_PORTS, r as DEFAULT_RANK_GAP, s as DIAGRAM_TRAIT_KEY, t as DiagramNodeEntry, u as ForceBody, v as ForceRelaxation, w as GraphEdge, x as GraphGroup, y as GraphNode, z as GraphNodeLike, A as GroupInset, E as LayoutAxes, H as LayoutDirection, I as RowBox, J as RowNodeData, K as RowPort, N as RowPortBox, Q as RowTextStyle, S as Slot, T as axesFor, U as backEdges, V as bodyOutline, W as bodyTrait, X as boxForContent, Y as buildBody, Z as buildGraph, _ as canvasMeasure, $ as contentBox, a0 as createDiagramNodes, a1 as dataKeyReader, a2 as diagramNodeOf, a3 as expandGroupEdges, a4 as force, a5 as forceRelaxation, a6 as forestOf, a7 as graphOrder, a8 as insetOf, a9 as isPinned, aa as layered, ab as layoutBody, ac as layoutRowPorts, ad as measureBody, ae as outlinePath, af as outlinePolyline, ag as packAcross, ah as packClusters, ai as pinnedSet, aj as portOf, ak as portsOf, al as portsOnOutline, am as rankGaps, an as ranksOf, ao as rayHit, ap as seededOrder, aq as settle, ar as sizeToBody, as as translated, at as tree, au as untilSettled } from './layout.entry-DyKFfHG5.js';
3
+ import { Vec2, DerivedDep, Path, SceneRegistry, PoseDescriptor, ChromeState, CommandFill, CommandStroke, CursorSpec, Affordance, InvocationCtx, Stroke, GestureBinding, Action, Contribution, RenderLayer, MarkerRef, AddNodeSpec, RectPose, Scene, EasingFn, NodeId, FillStyle, NodeShapeEntry, View, SelectionApi } from '@weasel-js/core';
4
4
  import { Vec2 as Vec2$1 } from '@weasel-js/core/math';
5
5
  import * as react from 'react';
6
6
  import '@weasel-js/geom';
@@ -99,10 +99,17 @@ declare function resolveEnd<TPose>(end: EdgeEnd, dep: DerivedDep<TPose>, toward:
99
99
  interface EdgeRouteOptions<TPose> extends PortsOptions<TPose> {
100
100
  /** Routers by key. Defaults to {@link ROUTERS}. */
101
101
  routers?: Readonly<Record<string, Router$1>>;
102
+ /** How far outside its node a self-edge with no ports named turns, in
103
+ * world units. Defaults to half the node's shorter side. */
104
+ selfLoopStandoff?: number;
102
105
  }
103
106
  /**
104
107
  * A `derivePath` that routes an edge between its two dependencies.
105
108
  *
109
+ * An edge from a node to itself that names no ports leaves and returns by the
110
+ * sides {@link selfLoop} picks, and where the author set no waypoints the
111
+ * router is handed that rule's point outside the node as one.
112
+ *
106
113
  * Returns `null` — nothing to draw — when the node is not an edge, when either
107
114
  * dependency is gone, or when an endpoint offers no ports at all. A dangling
108
115
  * edge painting a line to the origin is worse than a dangling edge painting
@@ -187,8 +194,8 @@ interface PortAffordanceOptions<TPose> {
187
194
  /** Screen-pixel side of the painted square. Default 7. Omit `paint` entirely
188
195
  * by passing 0 — a port the consumer draws itself is still hittable. */
189
196
  sizePx?: number;
190
- fill?: FillStyle;
191
- stroke?: Stroke;
197
+ fill?: CommandFill;
198
+ stroke?: CommandStroke;
192
199
  cursor?: CursorSpec;
193
200
  /** Default `'exclusive'` on pointer gestures: a drag from a port is a
194
201
  * connect, never a move of the node underneath it. */
@@ -367,6 +374,25 @@ declare function diagramPorts<TPose>(opts: DiagramContributionOptions<TPose>): {
367
374
  contribution: Contribution;
368
375
  };
369
376
 
377
+ /** How a self-edge with no ports named leaves its node and comes back. */
378
+ interface SelfLoop {
379
+ from: Port;
380
+ to: Port;
381
+ /** A point outside the node, off the corner between the two sides. */
382
+ via: Vec2;
383
+ }
384
+ /**
385
+ * The route a self-edge takes when neither end names a port: out by one side
386
+ * and back by the next one round, past a point `standoff` clear of both.
387
+ *
388
+ * Both ends of such an edge aim at their own node's center, so every port
389
+ * faces it equally, both pick the same one, and the edge has no length. The
390
+ * sides are taken by where they face on the page, east and then north, so the
391
+ * loop sits at the same corner of every node however its ports are listed.
392
+ * `null` where the node has no two ports facing different ways.
393
+ */
394
+ declare function selfLoop(ports: readonly Port[], standoff: number): SelfLoop | null;
395
+
370
396
  /**
371
397
  * A label on an edge: an ordinary leaf node that derives its *pose* from the
372
398
  * route it sits on.
@@ -417,6 +443,65 @@ declare const LABEL_DERIVE_POSE: (node: {
417
443
  data: unknown;
418
444
  }, deps: readonly (DerivedDep<unknown, unknown, string> | undefined)[]) => unknown;
419
445
 
446
+ /**
447
+ * A group's box, and anything pinned to a point on another node.
448
+ *
449
+ * The box is an ordinary node that depends on its members and derives its pose
450
+ * from theirs: their union, grown by the inset. Drag a member and the box
451
+ * follows; lay the diagram out and the box lands around wherever the members
452
+ * went. Nothing has to keep it in sync, because nothing stores it.
453
+ *
454
+ * An anchored node — a group's title is the first — derives its pose from one
455
+ * dependency's bounds the same way, so it travels with the box it labels.
456
+ */
457
+
458
+ /** Where an anchored node sits on its dependency. */
459
+ interface DiagramAnchor {
460
+ /** The point on the dependency's bounds, normalized as a port's is. */
461
+ at: PortAnchor;
462
+ /** The point on the node's own bounds that lands there. Default `at`, so
463
+ * `{ u: 0, v: 0 }` puts the node's top-left on the dependency's. */
464
+ self?: PortAnchor;
465
+ /** Then moved by this much, in world units. */
466
+ offset?: Vec2$1;
467
+ }
468
+ /** The group trait on a node's data, or `null`. */
469
+ declare function diagramGroupOf(node: {
470
+ data: unknown;
471
+ }): DiagramGroup | null;
472
+ /** The anchor trait on a node's data, or `null`. */
473
+ declare function diagramAnchorOf(node: {
474
+ data: unknown;
475
+ }): DiagramAnchor | null;
476
+ /** Options for {@link groupDerivePose} and {@link anchorDerivePose}.
477
+ * `geometry` defaults to the kit's `AUTO_POSE_DESCRIPTOR`. */
478
+ interface GroupPoseOptions<TPose> {
479
+ geometry?: PoseDescriptor<TPose>;
480
+ }
481
+ type DerivePose<TPose> = (node: {
482
+ pose: TPose;
483
+ data: unknown;
484
+ }, deps: readonly (DerivedDep<TPose> | undefined)[]) => TPose | null;
485
+ /**
486
+ * A `derivePose` that draws a group's box around its members: their union,
487
+ * grown by the trait's inset. `null` — the authored pose stands — when the node
488
+ * carries no group trait or every member is gone.
489
+ */
490
+ declare function groupDerivePose<TPose>(opts?: GroupPoseOptions<TPose>): DerivePose<TPose>;
491
+ /**
492
+ * A `derivePose` that keeps a node at a point on its dependency's bounds.
493
+ * `null` when the node carries no anchor trait or the dependency is gone.
494
+ */
495
+ declare function anchorDerivePose<TPose>(opts?: GroupPoseOptions<TPose>): DerivePose<TPose>;
496
+ /** Registry key for {@link GROUP_DERIVE_POSE}. */
497
+ declare const DIAGRAM_GROUP = "diagram:group";
498
+ /** Registry key for {@link ANCHOR_DERIVE_POSE}. */
499
+ declare const DIAGRAM_ANCHOR = "diagram:anchor";
500
+ /** The default group derivation, a stable reference so `toJSON` can find its key. */
501
+ declare const GROUP_DERIVE_POSE: DerivePose<unknown>;
502
+ /** The default anchor derivation, a stable reference for the same reason. */
503
+ declare const ANCHOR_DERIVE_POSE: DerivePose<unknown>;
504
+
420
505
  /**
421
506
  * `diagramScene` — a laid-out diagram from plain `{ nodes, edges }`.
422
507
  *
@@ -426,6 +511,7 @@ declare const LABEL_DERIVE_POSE: (node: {
426
511
  * the same answer in node and in a browser.
427
512
  */
428
513
 
514
+ /** One node of a {@link DiagramData}: its rows of text, and optionally its outline, ports, size, and starting place. */
429
515
  interface DataNode {
430
516
  id: string;
431
517
  /** Shorthand for one `label` row per line. Ignored when `rows` is given. */
@@ -451,7 +537,9 @@ interface DataNode {
451
537
  /** Default `DiagramSceneOptions.verticalAlign`. */
452
538
  verticalAlign?: BodySpec['verticalAlign'];
453
539
  }
540
+ /** One edge of a {@link DiagramData}, between two nodes or groups by id. */
454
541
  interface DataEdge {
542
+ /** A node's id, or a group's: an edge naming a group meets its box. */
455
543
  from: string;
456
544
  to: string;
457
545
  /** The port to leave from or arrive at. Unset, the end facing the other
@@ -466,10 +554,30 @@ interface DataEdge {
466
554
  /** World points the route passes through. Layout does not move them. */
467
555
  waypoints?: readonly Vec2$1[];
468
556
  }
557
+ /** A box drawn around some nodes, which layout keeps together. */
558
+ interface DataGroup {
559
+ /** Shares one namespace with node ids. */
560
+ id: string;
561
+ /** Node ids, and the ids of groups nested in this one. A node or group a
562
+ * later group also names stays in this one; an id that is neither is
563
+ * ignored, and so is one that would put a group inside itself. */
564
+ members: readonly string[];
565
+ /** Drawn inside the box, above its members. */
566
+ label?: string;
567
+ /** Between the box and its members, and around the label. Default
568
+ * `DiagramSceneOptions.groupPadding`. */
569
+ padding?: number;
570
+ }
571
+ /** A diagram as plain data, the input to `diagramScene`. */
469
572
  interface DiagramData {
470
573
  nodes: readonly DataNode[];
471
574
  edges: readonly DataEdge[];
575
+ /** A group may be a member of another. `layered`, `tree`, and `force` keep
576
+ * each group's members together; `'none'` ignores groups but still draws
577
+ * them. */
578
+ groups?: readonly DataGroup[];
472
579
  }
580
+ /** The colors and outline a node is drawn with. */
473
581
  interface NodeStyle {
474
582
  fill: string;
475
583
  stroke: string;
@@ -477,6 +585,7 @@ interface NodeStyle {
477
585
  strokeWidth?: number;
478
586
  dash?: number[];
479
587
  }
588
+ /** The stroke, markers, and label color an edge is drawn with. */
480
589
  interface EdgeStyle {
481
590
  stroke: string;
482
591
  width?: number;
@@ -494,9 +603,12 @@ type TextStyle = {
494
603
  fontSize: number;
495
604
  fontWeight?: number;
496
605
  };
606
+ /** The `data` of a scene node `diagramScene` makes: its diagram role, and what it paints. */
497
607
  interface DiagramSceneData {
498
608
  diagram?: DiagramNode | DiagramEdge | {
499
609
  label: DiagramLabel;
610
+ } | {
611
+ anchor: DiagramAnchor;
500
612
  };
501
613
  fill?: {
502
614
  color: string;
@@ -505,7 +617,9 @@ interface DiagramSceneData {
505
617
  text?: string;
506
618
  style?: TextStyle;
507
619
  }
620
+ /** A scene node spec, as `diagramScene` returns them. */
508
621
  type DiagramSpec = AddNodeSpec<DiagramSceneData, 'main', RectPose>;
622
+ /** How `diagramScene` lays out, routes, and styles a {@link DiagramData}. */
509
623
  interface DiagramSceneOptions {
510
624
  /** A layout by name, or any `LayoutFn`. Default `'layered'`. `'none'`
511
625
  * leaves every node at its `at`. */
@@ -535,12 +649,18 @@ interface DiagramSceneOptions {
535
649
  /** Where edge labels sit. Default `{ at: 'mid', offset: 9 }`. */
536
650
  labelPlacement?: DiagramLabel;
537
651
  nodeStyle?: (node: DataNode) => NodeStyle;
652
+ /** Default 12. */
653
+ groupPadding?: number;
654
+ /** A group's box and label. `text` colors the label. */
655
+ groupStyle?: (group: DataGroup) => NodeStyle;
538
656
  edgeStyle?: (edge: DataEdge) => EdgeStyle;
539
657
  }
658
+ /** The scene node id `diagramScene` gives an edge, built from its ends, ports, and label. */
540
659
  declare const edgeIdOf: (e: DataEdge) => string;
541
- /** Every spec carries an id — a node's own, `<id>/<k>` for its text, and
542
- * `<edge id>/label` — so a later call's specs can be reconciled against this
543
- * one's. Throws on a repeated node id, which names two nodes as one. An edge whose
660
+ /** Every spec carries an id — a node's own, `<id>/<k>` for its text,
661
+ * `<edge id>/label`, a group's own and `<group id>/label` — so a later call's
662
+ * specs can be reconciled against this one's. Throws on a repeated id among
663
+ * nodes and groups, which names two things as one. An edge whose
544
664
  * end is not a node is dropped, and so is a repeat of an earlier edge with
545
665
  * the same ends, ports and label: it would draw exactly on top of the first. */
546
666
  declare function diagramScene(data: DiagramData, opts?: DiagramSceneOptions): DiagramSpec[];
@@ -824,6 +944,7 @@ interface NodeMove {
824
944
  x: number;
825
945
  y: number;
826
946
  }
947
+ /** Props for `DiagramView`. */
827
948
  interface DiagramViewProps {
828
949
  /** Every spec needs an id, which `diagramScene` gives them. A new array is
829
950
  * reconciled into the scene the view already holds, so the view, the
@@ -845,6 +966,11 @@ interface DiagramViewProps {
845
966
  /** Set to make ports grabbable. Dragging one port onto another reports the
846
967
  * edge it describes and draws nothing; add it to the data to keep it. */
847
968
  onConnect?: (edge: DataEdge) => void;
969
+ /** Whether the canvas's keyboard shortcuts — held Space to pan among them —
970
+ * run. They listen page-wide, so a view-only diagram beside other UI would
971
+ * claim keys meant for the page. Default: on when `onMove` or `onConnect`
972
+ * is set. */
973
+ enableKeybindings?: boolean;
848
974
  /** Which ports may be joined. Default: a port may not join itself, and two
849
975
  * typed ports must share a type. */
850
976
  canConnect?: CanConnect;
@@ -896,4 +1022,4 @@ declare const DiagramView: react.ForwardRefExoticComponent<DiagramViewProps & re
896
1022
  * `<SceneCanvas onClick>`. */
897
1023
  declare function useMirroredSelection(selection: Pick<SelectionApi, 'get' | 'set'>, selected: string | null | undefined, onSelect: ((id: string | null) => void) | undefined): () => void;
898
1024
 
899
- export { type ApplyLayoutOptions, BodySpec, CONNECT_ACTION_ID, type CanConnect, type ConnectActionOptions, DEFAULT_EDGE_STROKE, DIAGRAM_EDGE, DIAGRAM_LABEL, type DataEdge, type DataNode, type DiagramContributionOptions, type DiagramData, type DiagramEdge, type DiagramLabel, DiagramNode, DiagramNodeLike, DiagramNodeReader, type DiagramSceneData, type DiagramSceneOptions, type DiagramShapeOptions, type DiagramSpec, DiagramView, type DiagramViewApi, type DiagramViewProps, EASED_LAYOUTS, EDGE_DERIVE_PATH, type EasedProducerOptions, type EdgeEnd, type EdgeRouteOptions, type EdgeStyle, ForceOptions, type ForceProducerOptions, GRAB_PORT_ACTION_ID, Graph, GraphSource, LABEL_DERIVE_POSE, LAYOUTS, LAYOUT_ACTION_ID, type LabelPoseOptions, type LayoutActionOptions, LayoutFn, LayoutOptions, LayoutResult, type LiveLayout, type LiveLayoutCtx, type LiveLayoutFrame, type LiveLayoutProducer, MeasureRowText, type NodeMove, type NodeStyle, Outline, PORT_AFFORDANCE_KIND, PORT_LAYER_ID, type ParticipantPose, type ParticipantScene, type ParticipantSource, type PendingEdge, Port, type PortAffordanceOptions, type PortScratch, PortSpec, PortsOptions, ROUTERS, type RouteRequest, type Router$1 as Router, Row, type UseLiveLayoutOptions, applyLayout, bezier, commitEdgeToScene, connectBinding, createConnectAction, createDiagramContribution, createLayoutAction, createPortAffordance, defaultCanConnect, diagramEdgeOf, diagramLabelOf, diagramPorts, diagramScene, diagramShape, easedProducer, edgeDerivePath, edgeIdOf, forceProducer, grabPortAction, grabPortBindings, labelDerivePose, layoutPoses, orthogonal, portLayer, portScratchOf, registerDiagramShape, resolveEnd, sceneParticipants, straight, useLiveLayout, useMirroredSelection, withDiagramRegistry };
1025
+ export { ANCHOR_DERIVE_POSE, type ApplyLayoutOptions, BodySpec, CONNECT_ACTION_ID, type CanConnect, type ConnectActionOptions, DEFAULT_EDGE_STROKE, DIAGRAM_ANCHOR, DIAGRAM_EDGE, DIAGRAM_GROUP, DIAGRAM_LABEL, type DataEdge, type DataGroup, type DataNode, type DiagramAnchor, type DiagramContributionOptions, type DiagramData, type DiagramEdge, DiagramGroup, type DiagramLabel, DiagramNode, DiagramNodeLike, DiagramNodeReader, type DiagramSceneData, type DiagramSceneOptions, type DiagramShapeOptions, type DiagramSpec, DiagramView, type DiagramViewApi, type DiagramViewProps, EASED_LAYOUTS, EDGE_DERIVE_PATH, type EasedProducerOptions, type EdgeEnd, type EdgeRouteOptions, type EdgeStyle, ForceOptions, type ForceProducerOptions, GRAB_PORT_ACTION_ID, GROUP_DERIVE_POSE, Graph, GraphSource, type GroupPoseOptions, LABEL_DERIVE_POSE, LAYOUTS, LAYOUT_ACTION_ID, type LabelPoseOptions, type LayoutActionOptions, LayoutFn, LayoutOptions, LayoutResult, type LiveLayout, type LiveLayoutCtx, type LiveLayoutFrame, type LiveLayoutProducer, MeasureRowText, type NodeMove, type NodeStyle, Outline, PORT_AFFORDANCE_KIND, PORT_LAYER_ID, type ParticipantPose, type ParticipantScene, type ParticipantSource, type PendingEdge, Port, type PortAffordanceOptions, PortAnchor, type PortScratch, PortSpec, PortsOptions, ROUTERS, type RouteRequest, type Router$1 as Router, Row, type SelfLoop, type UseLiveLayoutOptions, anchorDerivePose, applyLayout, bezier, commitEdgeToScene, connectBinding, createConnectAction, createDiagramContribution, createLayoutAction, createPortAffordance, defaultCanConnect, diagramAnchorOf, diagramEdgeOf, diagramGroupOf, diagramLabelOf, diagramPorts, diagramScene, diagramShape, easedProducer, edgeDerivePath, edgeIdOf, forceProducer, grabPortAction, grabPortBindings, groupDerivePose, labelDerivePose, layoutPoses, orthogonal, portLayer, portScratchOf, registerDiagramShape, resolveEnd, sceneParticipants, selfLoop, straight, useLiveLayout, useMirroredSelection, withDiagramRegistry };