@weasel-js/diagram 1.8.1 → 1.9.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 +17 -0
- package/dist/{chunk-4KXQABRM.js → chunk-6VYT4WCM.js} +109 -82
- package/dist/chunk-6VYT4WCM.js.map +1 -0
- package/dist/index.d.ts +101 -7
- package/dist/index.js +198 -5
- package/dist/index.js.map +1 -1
- package/dist/layout.d.ts +1 -1
- package/dist/{layout.entry-BvR06k9j.d.ts → layout.entry-ClWUwH16.d.ts} +7 -21
- package/dist/layout.js +1 -1
- package/package.json +3 -3
- package/dist/chunk-4KXQABRM.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { portOf, portsOf, diagramNodeOf, force, tree,
|
|
2
|
-
export { COMPASS, DEFAULT_NODE_GAP, DEFAULT_PORTS, DEFAULT_RANK_GAP, DIAGRAM_TRAIT_KEY, axesFor, backEdges, bodyOutline, bodyTrait, boxForContent, buildBody, canvasMeasure, contentBox, createDiagramNodes, dataKeyReader, diagramNodeOf, force, forceRelaxation, forestOf, graphOrder, isPinned, layered, layoutBody, layoutRowPorts, measureBody, outlinePath, outlinePolyline, packAcross, pinnedSet, portOf, portsOf, portsOnOutline, ranksOf, rayHit, seededOrder, settle, sizeToBody, translated, tree } from './chunk-
|
|
3
|
-
import { AUTO_POSE_DESCRIPTOR, pointAlongPath, translatePoseViaDescriptor, polylineFromPoints, effectivePose, composeAffordanceLayer, useLatest, usePoseRun, RECT_POSE_DESCRIPTOR, registerNodeShape } from '@weasel-js/core';
|
|
1
|
+
import { portOf, portsOf, diagramNodeOf, layered, force, tree, forceRelaxation, center, outlinePath } from './chunk-6VYT4WCM.js';
|
|
2
|
+
export { COMPASS, DEFAULT_NODE_GAP, DEFAULT_PORTS, DEFAULT_RANK_GAP, DIAGRAM_TRAIT_KEY, axesFor, backEdges, bodyOutline, bodyTrait, boxForContent, buildBody, canvasMeasure, contentBox, createDiagramNodes, dataKeyReader, diagramNodeOf, force, forceRelaxation, forestOf, graphOrder, isPinned, layered, layoutBody, layoutRowPorts, measureBody, outlinePath, outlinePolyline, packAcross, pinnedSet, portOf, portsOf, portsOnOutline, ranksOf, rayHit, seededOrder, settle, sizeToBody, translated, tree } from './chunk-6VYT4WCM.js';
|
|
3
|
+
import { dragPanContribution, AUTO_POSE_DESCRIPTOR, pointAlongPath, translatePoseViaDescriptor, polylineFromPoints, effectivePose, composeAffordanceLayer, useLatest, usePoseRun, RECT_POSE_DESCRIPTOR, registerNodeShape, WeaselProvider, useScene, useSelection, SceneCanvas, fitViewToBounds } from '@weasel-js/core';
|
|
4
4
|
import { portCurvePoints } from '@weasel-js/geom';
|
|
5
5
|
import { AUTO_POSE_DESCRIPTOR as AUTO_POSE_DESCRIPTOR$1 } from '@weasel-js/core/math';
|
|
6
6
|
import { useRef, useCallback, useEffect, useMemo } from 'react';
|
|
7
|
+
import { jsx } from 'react/jsx-runtime';
|
|
7
8
|
|
|
8
9
|
var NAMED = { start: 0, mid: 0.5, end: 1 };
|
|
9
10
|
function diagramLabelOf(node) {
|
|
@@ -260,7 +261,7 @@ function grabPortBindings(actionId = GRAB_PORT_ACTION_ID) {
|
|
|
260
261
|
];
|
|
261
262
|
}
|
|
262
263
|
function commitEdgeToScene(edge, ctx) {
|
|
263
|
-
const scene = ctx.deps
|
|
264
|
+
const scene = ctx.deps.scene;
|
|
264
265
|
if (scene === void 0) return;
|
|
265
266
|
const trait = {
|
|
266
267
|
from: { port: edge.from.id },
|
|
@@ -441,6 +442,128 @@ function push(index, key, edge) {
|
|
|
441
442
|
if (list === void 0) index.set(key, [edge]);
|
|
442
443
|
else list.push(edge);
|
|
443
444
|
}
|
|
445
|
+
|
|
446
|
+
// src/fromData.ts
|
|
447
|
+
var FONT = { fontFamily: "sans-serif", fontSize: 12 };
|
|
448
|
+
var NODE = { fill: "#16222c", stroke: "#7ba7c7", text: "#dbe7f2" };
|
|
449
|
+
var EDGE = { stroke: "#7ba7c7" };
|
|
450
|
+
var PAD = { x: 12, y: 8 };
|
|
451
|
+
var LINE = 1.4;
|
|
452
|
+
var GLYPH = 0.6;
|
|
453
|
+
var MIN_WIDTH = 64;
|
|
454
|
+
var edgeIdOf = (e) => `edge:${e.from}->${e.to}${e.label ? `:${e.label}` : ""}`;
|
|
455
|
+
function sizeOf(node, fontSize) {
|
|
456
|
+
const longest = Math.max(0, ...node.lines.map((l) => l.length));
|
|
457
|
+
return {
|
|
458
|
+
width: Math.max(MIN_WIDTH, Math.ceil(longest * GLYPH * fontSize + 2 * PAD.x)),
|
|
459
|
+
height: Math.ceil(Math.max(1, node.lines.length) * LINE * fontSize + 2 * PAD.y)
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
function graphOf(nodes, edges) {
|
|
463
|
+
const byId = new Map(nodes.map((n) => [n.id, n]));
|
|
464
|
+
const out = /* @__PURE__ */ new Map();
|
|
465
|
+
const inc = /* @__PURE__ */ new Map();
|
|
466
|
+
for (const e of edges) {
|
|
467
|
+
out.set(e.from, [...out.get(e.from) ?? [], e]);
|
|
468
|
+
inc.set(e.to, [...inc.get(e.to) ?? [], e]);
|
|
469
|
+
}
|
|
470
|
+
return {
|
|
471
|
+
nodes,
|
|
472
|
+
edges,
|
|
473
|
+
node: (id) => byId.get(id),
|
|
474
|
+
outgoing: (id) => out.get(id) ?? [],
|
|
475
|
+
incoming: (id) => inc.get(id) ?? []
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
function diagramScene(data, opts = {}) {
|
|
479
|
+
const font = opts.font ?? FONT;
|
|
480
|
+
const ids = /* @__PURE__ */ new Set();
|
|
481
|
+
for (const n of data.nodes) {
|
|
482
|
+
if (ids.has(n.id)) throw new Error(`diagramScene: node id "${n.id}" appears more than once`);
|
|
483
|
+
ids.add(n.id);
|
|
484
|
+
}
|
|
485
|
+
const seen = /* @__PURE__ */ new Set();
|
|
486
|
+
const edges = data.edges.filter((e) => {
|
|
487
|
+
const id = edgeIdOf(e);
|
|
488
|
+
if (seen.has(id) || !ids.has(e.from) || !ids.has(e.to)) return false;
|
|
489
|
+
seen.add(id);
|
|
490
|
+
return true;
|
|
491
|
+
});
|
|
492
|
+
const seeds = data.nodes.map((n, i) => ({
|
|
493
|
+
id: n.id,
|
|
494
|
+
bounds: { x: i, y: i, ...sizeOf(n, font.fontSize) },
|
|
495
|
+
pinned: false
|
|
496
|
+
}));
|
|
497
|
+
const graph = graphOf(seeds, edges.map((e) => ({ id: edgeIdOf(e), from: e.from, to: e.to })));
|
|
498
|
+
const moved = (opts.layout ?? layered)(graph, opts.layoutOptions ?? { order: "barycenter" });
|
|
499
|
+
const specs = [];
|
|
500
|
+
for (const [i, n] of data.nodes.entries()) {
|
|
501
|
+
const seed = seeds[i].bounds;
|
|
502
|
+
const at = moved.get(n.id) ?? seed;
|
|
503
|
+
const pose = { x: at.x, y: at.y, width: seed.width, height: seed.height };
|
|
504
|
+
const style = opts.nodeStyle?.(n) ?? NODE;
|
|
505
|
+
specs.push({
|
|
506
|
+
id: n.id,
|
|
507
|
+
kind: "container",
|
|
508
|
+
layer: "main",
|
|
509
|
+
pose,
|
|
510
|
+
data: {
|
|
511
|
+
diagram: { outline: "rect" },
|
|
512
|
+
fill: { color: style.fill },
|
|
513
|
+
stroke: { paint: { color: style.stroke }, width: style.strokeWidth ?? 2 }
|
|
514
|
+
}
|
|
515
|
+
});
|
|
516
|
+
for (const [k, text] of n.lines.entries()) {
|
|
517
|
+
specs.push({
|
|
518
|
+
kind: "leaf",
|
|
519
|
+
layer: "main",
|
|
520
|
+
parent: n.id,
|
|
521
|
+
pickable: false,
|
|
522
|
+
pose: {
|
|
523
|
+
x: pose.x + PAD.x,
|
|
524
|
+
y: pose.y + PAD.y + k * LINE * font.fontSize,
|
|
525
|
+
width: pose.width - 2 * PAD.x,
|
|
526
|
+
height: LINE * font.fontSize
|
|
527
|
+
},
|
|
528
|
+
data: { text, style: font, fill: { color: style.text } }
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
for (const e of edges) {
|
|
533
|
+
const id = edgeIdOf(e);
|
|
534
|
+
const style = opts.edgeStyle?.(e) ?? EDGE;
|
|
535
|
+
specs.push({
|
|
536
|
+
id,
|
|
537
|
+
kind: "leaf",
|
|
538
|
+
layer: "main",
|
|
539
|
+
pickable: false,
|
|
540
|
+
pose: { x: 0, y: 0, width: 0, height: 0 },
|
|
541
|
+
data: {
|
|
542
|
+
diagram: { from: {}, to: {}, router: opts.router ?? "bezier" },
|
|
543
|
+
stroke: { paint: { color: style.stroke }, width: style.width ?? 1.5, markerEnd: "arrow" }
|
|
544
|
+
},
|
|
545
|
+
dependsOn: [e.from, e.to],
|
|
546
|
+
derivePath: EDGE_DERIVE_PATH
|
|
547
|
+
});
|
|
548
|
+
if (e.label) {
|
|
549
|
+
specs.push({
|
|
550
|
+
kind: "leaf",
|
|
551
|
+
layer: "main",
|
|
552
|
+
pickable: false,
|
|
553
|
+
pose: { x: 0, y: 0, width: e.label.length * GLYPH * (font.fontSize - 2), height: font.fontSize },
|
|
554
|
+
data: {
|
|
555
|
+
diagram: { label: { at: "mid", offset: 9 } },
|
|
556
|
+
text: e.label,
|
|
557
|
+
style: { ...font, fontSize: font.fontSize - 2 },
|
|
558
|
+
fill: { color: style.stroke }
|
|
559
|
+
},
|
|
560
|
+
dependsOn: [id],
|
|
561
|
+
derivePose: LABEL_DERIVE_POSE
|
|
562
|
+
});
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
return specs;
|
|
566
|
+
}
|
|
444
567
|
var LAYOUTS = Object.freeze({
|
|
445
568
|
layered,
|
|
446
569
|
tree,
|
|
@@ -700,7 +823,77 @@ function diagramShape(opts = {}) {
|
|
|
700
823
|
function registerDiagramShape(opts = {}) {
|
|
701
824
|
return registerNodeShape(diagramShape(opts), { priority: "high" });
|
|
702
825
|
}
|
|
826
|
+
function useMirroredSelection(selection, selected, onSelect) {
|
|
827
|
+
const want = selected ?? null;
|
|
828
|
+
const pushed = useRef(void 0);
|
|
829
|
+
useEffect(() => {
|
|
830
|
+
if (pushed.current === want) return;
|
|
831
|
+
pushed.current = want;
|
|
832
|
+
if ((selection.get()[0] ?? null) !== want) selection.set(want === null ? [] : [want]);
|
|
833
|
+
}, [want]);
|
|
834
|
+
const onSelectRef = useLatest(onSelect);
|
|
835
|
+
return useCallback(() => {
|
|
836
|
+
onSelectRef.current?.(selection.get()[0] ?? null);
|
|
837
|
+
}, [selection, onSelectRef]);
|
|
838
|
+
}
|
|
839
|
+
var made = 0;
|
|
840
|
+
var keys = /* @__PURE__ */ new WeakMap();
|
|
841
|
+
var keyOf = (specs) => {
|
|
842
|
+
let k = keys.get(specs);
|
|
843
|
+
if (k === void 0) keys.set(specs, k = ++made);
|
|
844
|
+
return k;
|
|
845
|
+
};
|
|
846
|
+
var AMBIENT = [dragPanContribution()];
|
|
847
|
+
function DiagramView(props) {
|
|
848
|
+
return /* @__PURE__ */ jsx(WeaselProvider, { children: /* @__PURE__ */ jsx(Inner, { ...props }, keyOf(props.specs)) });
|
|
849
|
+
}
|
|
850
|
+
function Inner({ specs, width, height, selected, onSelect, minScale, anchor, className }) {
|
|
851
|
+
useEffect(() => registerDiagramShape(), []);
|
|
852
|
+
const registry = useMemo(() => withDiagramRegistry(), []);
|
|
853
|
+
const scene = useScene({
|
|
854
|
+
systemLayers: [{ id: "main" }],
|
|
855
|
+
initial: specs,
|
|
856
|
+
registry
|
|
857
|
+
});
|
|
858
|
+
const selection = useSelection({ scene, mode: "single" });
|
|
859
|
+
const onClick = useMirroredSelection(selection, selected, onSelect);
|
|
860
|
+
const defaultView = useMemo(
|
|
861
|
+
() => fitDiagram(specs, { width, height }, minScale, anchor),
|
|
862
|
+
[specs, width, height, minScale, anchor]
|
|
863
|
+
);
|
|
864
|
+
return /* @__PURE__ */ jsx(
|
|
865
|
+
SceneCanvas,
|
|
866
|
+
{
|
|
867
|
+
scene,
|
|
868
|
+
selection,
|
|
869
|
+
features: ["view", "pick"],
|
|
870
|
+
ambient: AMBIENT,
|
|
871
|
+
onClick,
|
|
872
|
+
width,
|
|
873
|
+
height,
|
|
874
|
+
className,
|
|
875
|
+
...defaultView ? { defaultView } : {}
|
|
876
|
+
}
|
|
877
|
+
);
|
|
878
|
+
}
|
|
879
|
+
function fitDiagram(specs, size, minScale, anchor) {
|
|
880
|
+
const boxes = specs.filter((s) => s.kind === "container").map((s) => s.pose);
|
|
881
|
+
if (boxes.length === 0) return void 0;
|
|
882
|
+
const x = Math.min(...boxes.map((b) => b.x));
|
|
883
|
+
const y = Math.min(...boxes.map((b) => b.y));
|
|
884
|
+
const bounds = {
|
|
885
|
+
x,
|
|
886
|
+
y,
|
|
887
|
+
width: Math.max(...boxes.map((b) => b.x + b.width)) - x,
|
|
888
|
+
height: Math.max(...boxes.map((b) => b.y + b.height)) - y
|
|
889
|
+
};
|
|
890
|
+
return fitViewToBounds(bounds, size, { x: 0, y: 0, scale: { x: 1, y: 1 } }, {
|
|
891
|
+
maxScale: 1,
|
|
892
|
+
...minScale !== void 0 ? { minScale } : {},
|
|
893
|
+
...anchor !== void 0 ? { anchor } : {}
|
|
894
|
+
});
|
|
895
|
+
}
|
|
703
896
|
|
|
704
|
-
export { CONNECT_ACTION_ID, DEFAULT_EDGE_STROKE, DIAGRAM_EDGE, DIAGRAM_LABEL, EASED_LAYOUTS, EDGE_DERIVE_PATH, GRAB_PORT_ACTION_ID, LABEL_DERIVE_POSE, LAYOUTS, LAYOUT_ACTION_ID, PORT_AFFORDANCE_KIND, PORT_LAYER_ID, ROUTERS, applyLayout, bezier, buildGraph, commitEdgeToScene, connectBinding, createConnectAction, createDiagramContribution, createLayoutAction, createPortAffordance, defaultCanConnect, diagramEdgeOf, diagramLabelOf, diagramPorts, diagramShape, easedProducer, edgeDerivePath, forceProducer, grabPortAction, grabPortBindings, labelDerivePose, layoutPoses, orthogonal, portLayer, portScratchOf, registerDiagramShape, resolveEnd, sceneParticipants, straight, useLiveLayout, withDiagramRegistry };
|
|
897
|
+
export { CONNECT_ACTION_ID, DEFAULT_EDGE_STROKE, DIAGRAM_EDGE, DIAGRAM_LABEL, DiagramView, EASED_LAYOUTS, EDGE_DERIVE_PATH, GRAB_PORT_ACTION_ID, LABEL_DERIVE_POSE, LAYOUTS, LAYOUT_ACTION_ID, PORT_AFFORDANCE_KIND, PORT_LAYER_ID, ROUTERS, applyLayout, bezier, buildGraph, 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 };
|
|
705
898
|
//# sourceMappingURL=index.js.map
|
|
706
899
|
//# sourceMappingURL=index.js.map
|