@weasel-js/diagram 1.4.3 → 1.5.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.
package/README.md CHANGED
@@ -6,8 +6,10 @@ simple visual programming.
6
6
  Any scene node becomes a diagram participant by carrying the `DiagramNode`
7
7
  trait; nothing has to be authored through this package to take part. Ports
8
8
  default to anchors on the node's own bounds, so a node needs to say nothing to
9
- be connectable. An optional body builder composes ordinary scene nodes for
10
- nodes that should *look* like a flowchart box.
9
+ be connectable. Edges are ordinary scene nodes whose geometry derives from the
10
+ two they join, so they re-route whenever either end moves. An optional body
11
+ builder composes ordinary scene nodes for nodes that should *look* like a
12
+ flowchart box.
11
13
 
12
14
  Part of [weasel](https://github.com/orochi235/weasel), a domain-agnostic 2D
13
15
  scene-graph canvas kit for React. See the
@@ -25,6 +27,71 @@ npm install @weasel-js/diagram
25
27
  import { portsOf, COMPASS } from '@weasel-js/diagram';
26
28
  ```
27
29
 
30
+ ### Building a body
31
+
32
+ A participant that should read as a flowchart box gets one from `buildBody`:
33
+ the container carrying the trait, plus an ordinary text node per row, so the
34
+ kit's own text painter draws them and editing and styling work unchanged.
35
+
36
+ ```ts
37
+ const { specs } = buildBody<Data, 'main', Pose>(
38
+ { outline: 'diamond', rows: [{ kind: 'label', text: 'ready?' }] },
39
+ { x: 40, y: 40, width: 150, height: 56 },
40
+ {
41
+ id: 'check',
42
+ layer: 'main',
43
+ body: (trait) => ({ diagram: trait, stroke }),
44
+ row: (text) => (text === '' ? null : { text }),
45
+ },
46
+ );
47
+ ```
48
+
49
+ The rows measure a floor and the authored pose is grown to clear it, never
50
+ shrunk — so resize, align, distribute, snapping and undo need no special case.
51
+
52
+ ### Making ports grabbable
53
+
54
+ `diagramPorts` returns the two halves of the connect gesture. Attach the layer
55
+ with `registerLayer` — the only route the kit hit-tests — and pass the
56
+ contribution as `ambient`:
57
+
58
+ ```tsx
59
+ const { layer, contribution } = useMemo(() => diagramPorts({
60
+ participants: sceneParticipants(scene),
61
+ }), [scene]);
62
+
63
+ const canvasRef = useRef<SceneCanvasApi | null>(null);
64
+ useEffect(() => canvasRef.current?.registerLayer(layer), [layer]);
65
+
66
+ return <SceneCanvas ref={canvasRef} scene={scene} ambient={[contribution]} />;
67
+ ```
68
+
69
+ Dragging one port onto another authors an edge. Which pairs may be joined is
70
+ `canConnect`, which defaults to "a port may not join itself, and two ports that
71
+ both declare a `type` must declare the same one".
72
+
73
+ ### Laying it out
74
+
75
+ `layered`, `tree` and `force` are plain functions of the graph. Each hands back
76
+ the new top-left for every node that **moves** — a node already standing where
77
+ the layout wants it is absent, so re-running a layout on an unchanged diagram
78
+ writes nothing at all.
79
+
80
+ ```tsx
81
+ useAction(useMemo(() => createLayoutAction<Pose>({
82
+ source: sceneParticipants(scene),
83
+ algorithm: 'layered',
84
+ }), [scene]));
85
+ ```
86
+
87
+ The action rebuilds the graph from the scene on each press and writes the whole
88
+ move as one undo entry. Three rules keep a re-layout from scrambling a diagram
89
+ someone has arranged: no RNG anywhere, within-rank order seeded from where the
90
+ nodes already sit, and a node carrying `pinned: true` that nothing moves.
91
+
92
+ `force` is the exception to the second half of that: it is an iterative
93
+ relaxation seeded from the current positions, so re-running it keeps relaxing.
94
+
28
95
  ## License
29
96
 
30
97
  MIT