@weasel-js/diagram 1.8.0 → 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 -9
- 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.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { P as Port, a as PortsOptions, D as DiagramNodeLike, b as DiagramNodeReader, L as LayoutFn,
|
|
2
|
-
export { B as BodyFloor,
|
|
3
|
-
import { Vec2, DerivedDep, Path, SceneRegistry, PoseDescriptor, ChromeState, FillStyle, Stroke, CursorSpec, Affordance, InvocationCtx, GestureBinding, Action, Contribution, RenderLayer, EasingFn, NodeId, Scene, NodeShapeEntry } from '@weasel-js/core';
|
|
1
|
+
import { P as Port, a as PortsOptions, D as DiagramNodeLike, b as DiagramNodeReader, c as DiagramNode, L as LayoutFn, d as LayoutOptions, F as ForceOptions, e as LayoutResult, G as GraphSource, f as Graph } from './layout.entry-ClWUwH16.js';
|
|
2
|
+
export { B as BodyFloor, g as BodyNodeSpec, h as BodySpec, i as Bounds, j as BuildBodyOptions, k as BuildGraphOptions, C as COMPASS, l as DEFAULT_NODE_GAP, m as DEFAULT_PORTS, n as DEFAULT_RANK_GAP, o as DIAGRAM_TRAIT_KEY, p as DiagramNodeEntry, q as ForceBody, r as ForceRelaxation, s as GraphEdge, t as GraphNode, u as GraphNodeLike, v as LayoutAxes, w as LayoutDirection, M as MeasureRowText, O as Outline, x as PortAnchor, y as PortSpec, R as Row, 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-ClWUwH16.js';
|
|
3
|
+
import { Vec2, DerivedDep, Path, SceneRegistry, PoseDescriptor, ChromeState, FillStyle, Stroke, CursorSpec, Affordance, InvocationCtx, GestureBinding, Action, Contribution, RenderLayer, AddNodeSpec, RectPose, EasingFn, NodeId, Scene, NodeShapeEntry, SelectionApi } from '@weasel-js/core';
|
|
4
|
+
import * as react from 'react';
|
|
4
5
|
import '@weasel-js/geom';
|
|
5
6
|
import '@weasel-js/core/math';
|
|
6
7
|
|
|
@@ -67,8 +68,6 @@ declare const straight: Router;
|
|
|
67
68
|
* across the corner, which reads as aimed at nothing.
|
|
68
69
|
*/
|
|
69
70
|
declare const orthogonal: Router;
|
|
70
|
-
/** How far a bezier reaches along each end's normal, as a fraction of the
|
|
71
|
-
* straight-line distance between the two points it joins. */
|
|
72
71
|
/**
|
|
73
72
|
* A smooth route, sampled into points.
|
|
74
73
|
*
|
|
@@ -119,10 +118,10 @@ declare const DIAGRAM_EDGE = "diagram:edge";
|
|
|
119
118
|
* `edgeDerivePath(...)` under a key of their choosing. */
|
|
120
119
|
declare const EDGE_DERIVE_PATH: (node: {
|
|
121
120
|
data: unknown;
|
|
122
|
-
}, deps: readonly (DerivedDep<unknown> | undefined)[]) => Path | null;
|
|
121
|
+
}, deps: readonly (DerivedDep<unknown, unknown, string> | undefined)[]) => Path | null;
|
|
123
122
|
/** Merge this package's registry entries under a consumer's, so an edge
|
|
124
123
|
* round-trips through `toJSON` without the consumer wiring the key. */
|
|
125
|
-
declare function withDiagramRegistry<TPose>(registry?: SceneRegistry<TPose>): SceneRegistry<TPose>;
|
|
124
|
+
declare function withDiagramRegistry<TPose, TData = unknown, TLayer extends string = string>(registry?: SceneRegistry<TPose, TData, TLayer>): SceneRegistry<TPose, TData, TLayer>;
|
|
126
125
|
|
|
127
126
|
/**
|
|
128
127
|
* Ports as affordances — what makes a painted port a grabbable one.
|
|
@@ -416,7 +415,69 @@ declare const DIAGRAM_LABEL = "diagram:label";
|
|
|
416
415
|
declare const LABEL_DERIVE_POSE: (node: {
|
|
417
416
|
pose: unknown;
|
|
418
417
|
data: unknown;
|
|
419
|
-
}, deps: readonly (DerivedDep<unknown> | undefined)[]) => unknown;
|
|
418
|
+
}, deps: readonly (DerivedDep<unknown, unknown, string> | undefined)[]) => unknown;
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* `diagramScene` — a laid-out diagram from plain `{ nodes, edges }`.
|
|
422
|
+
*
|
|
423
|
+
* Sizes are estimated from character counts, not measured, so layout runs
|
|
424
|
+
* without a canvas and gives the same answer in node and in a browser.
|
|
425
|
+
*/
|
|
426
|
+
|
|
427
|
+
interface DataNode {
|
|
428
|
+
id: string;
|
|
429
|
+
lines: readonly string[];
|
|
430
|
+
}
|
|
431
|
+
interface DataEdge {
|
|
432
|
+
from: string;
|
|
433
|
+
to: string;
|
|
434
|
+
label?: string;
|
|
435
|
+
}
|
|
436
|
+
interface DiagramData {
|
|
437
|
+
nodes: readonly DataNode[];
|
|
438
|
+
edges: readonly DataEdge[];
|
|
439
|
+
}
|
|
440
|
+
interface NodeStyle {
|
|
441
|
+
fill: string;
|
|
442
|
+
stroke: string;
|
|
443
|
+
text: string;
|
|
444
|
+
strokeWidth?: number;
|
|
445
|
+
}
|
|
446
|
+
interface EdgeStyle {
|
|
447
|
+
stroke: string;
|
|
448
|
+
width?: number;
|
|
449
|
+
}
|
|
450
|
+
interface DiagramSceneData {
|
|
451
|
+
diagram?: DiagramNode | DiagramEdge | {
|
|
452
|
+
label: DiagramLabel;
|
|
453
|
+
};
|
|
454
|
+
fill?: {
|
|
455
|
+
color: string;
|
|
456
|
+
};
|
|
457
|
+
stroke?: Stroke;
|
|
458
|
+
text?: string;
|
|
459
|
+
style?: {
|
|
460
|
+
fontFamily: string;
|
|
461
|
+
fontSize: number;
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
type DiagramSpec = AddNodeSpec<DiagramSceneData, 'main', RectPose>;
|
|
465
|
+
interface DiagramSceneOptions {
|
|
466
|
+
layout?: LayoutFn;
|
|
467
|
+
layoutOptions?: LayoutOptions;
|
|
468
|
+
router?: 'straight' | 'bezier' | 'orthogonal';
|
|
469
|
+
font?: {
|
|
470
|
+
fontFamily: string;
|
|
471
|
+
fontSize: number;
|
|
472
|
+
};
|
|
473
|
+
nodeStyle?: (node: DataNode) => NodeStyle;
|
|
474
|
+
edgeStyle?: (edge: DataEdge) => EdgeStyle;
|
|
475
|
+
}
|
|
476
|
+
declare const edgeIdOf: (e: DataEdge) => string;
|
|
477
|
+
/** Throws on a repeated node id, which names two nodes as one. An edge whose
|
|
478
|
+
* end is not a node is dropped, and so is a repeat of an earlier edge with
|
|
479
|
+
* the same ends and label: it would draw exactly on top of the first. */
|
|
480
|
+
declare function diagramScene(data: DiagramData, opts?: DiagramSceneOptions): DiagramSpec[];
|
|
420
481
|
|
|
421
482
|
/** What a live producer is told, and what it answers with. */
|
|
422
483
|
interface LiveLayoutCtx<TPose> {
|
|
@@ -691,4 +752,35 @@ declare function diagramShape<TPose>(opts?: DiagramShapeOptions<TPose>): NodeSha
|
|
|
691
752
|
*/
|
|
692
753
|
declare function registerDiagramShape<TPose>(opts?: DiagramShapeOptions<TPose>): () => void;
|
|
693
754
|
|
|
694
|
-
|
|
755
|
+
interface DiagramViewProps {
|
|
756
|
+
specs: readonly DiagramSpec[];
|
|
757
|
+
width: number;
|
|
758
|
+
height: number;
|
|
759
|
+
/** A participant id, or null for none. */
|
|
760
|
+
selected?: string | null;
|
|
761
|
+
/** Reports what each click leaves picked, `null` for none — a re-click on the
|
|
762
|
+
* picked node reports it again. The canvas keeps the pick even if
|
|
763
|
+
* `selected` does not follow it; only a change to `selected` is pushed in. */
|
|
764
|
+
onSelect?: (id: string | null) => void;
|
|
765
|
+
/** The smallest scale the initial fit may use. Unset, the whole diagram fits
|
|
766
|
+
* however small that makes it; set, it stops here and the rest is a pan away. */
|
|
767
|
+
minScale?: number;
|
|
768
|
+
/** Which part of a diagram too big for the box it opens on: its middle
|
|
769
|
+
* (default) or its top-left, where a layered flow begins. */
|
|
770
|
+
anchor?: 'center' | 'start';
|
|
771
|
+
className?: string;
|
|
772
|
+
}
|
|
773
|
+
/** A read-only diagram: drag or wheel to pan, zoom, and pick a node, nothing else. A new `specs`
|
|
774
|
+
* array is a new scene, fitted to the box, so memoize it: one built inline
|
|
775
|
+
* remounts the scene on every render. Labels paint only in a registered font
|
|
776
|
+
* family; `diagramScene` defaults to sans-serif, so call
|
|
777
|
+
* `registerCanvasFont('sans-serif')` or text renders blank. */
|
|
778
|
+
declare function DiagramView(props: DiagramViewProps): react.JSX.Element;
|
|
779
|
+
|
|
780
|
+
/** Keeps a canvas selection and a controlled `selected` prop in step: a prop
|
|
781
|
+
* change is pushed in, and every click reports what the selection holds after
|
|
782
|
+
* it — a re-click on the picked node included. Wire the returned handler to
|
|
783
|
+
* `<SceneCanvas onClick>`. */
|
|
784
|
+
declare function useMirroredSelection(selection: Pick<SelectionApi, 'get' | 'set'>, selected: string | null | undefined, onSelect: ((id: string | null) => void) | undefined): () => void;
|
|
785
|
+
|
|
786
|
+
export { type ApplyLayoutOptions, 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 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, type NodeStyle, PORT_AFFORDANCE_KIND, PORT_LAYER_ID, type ParticipantPose, type ParticipantScene, type ParticipantSource, type PendingEdge, Port, type PortAffordanceOptions, type PortScratch, PortsOptions, ROUTERS, type RouteRequest, type Router, 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 };
|
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
|