@zukhruf/diagram 0.3.32 → 0.3.34
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 +98 -52
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/compiler/diagram-compile.d.ts +3 -4
- package/dist/lib/compiler/diagram-compile.d.ts.map +1 -1
- package/dist/lib/compiler/diagram-compile.js +85 -370
- package/dist/lib/compiler/diagram-compile.js.map +1 -1
- package/dist/lib/layouts/graph/attach.d.ts +25 -0
- package/dist/lib/layouts/graph/attach.d.ts.map +1 -0
- package/dist/lib/layouts/graph/attach.js +272 -0
- package/dist/lib/layouts/graph/attach.js.map +1 -0
- package/dist/lib/layouts/graph/connections.d.ts +45 -0
- package/dist/lib/layouts/graph/connections.d.ts.map +1 -0
- package/dist/lib/layouts/graph/connections.js +138 -0
- package/dist/lib/layouts/graph/connections.js.map +1 -0
- package/dist/lib/layouts/graph/graph-layout-result.d.ts +5 -3
- package/dist/lib/layouts/graph/graph-layout-result.d.ts.map +1 -1
- package/dist/lib/layouts/graph/graph-layout-result.js.map +1 -1
- package/dist/lib/layouts/graph/gutters.js +41 -22
- package/dist/lib/layouts/graph/gutters.js.map +1 -1
- package/dist/lib/layouts/graph/labels.d.ts +23 -0
- package/dist/lib/layouts/graph/labels.d.ts.map +1 -0
- package/dist/lib/layouts/graph/labels.js +120 -0
- package/dist/lib/layouts/graph/labels.js.map +1 -0
- package/dist/lib/layouts/graph/layout.d.ts +1 -1
- package/dist/lib/layouts/graph/layout.d.ts.map +1 -1
- package/dist/lib/layouts/graph/layout.js +37 -12
- package/dist/lib/layouts/graph/layout.js.map +1 -1
- package/dist/lib/layouts/graph/measure.d.ts +15 -11
- package/dist/lib/layouts/graph/measure.d.ts.map +1 -1
- package/dist/lib/layouts/graph/measure.js +82 -38
- package/dist/lib/layouts/graph/measure.js.map +1 -1
- package/dist/lib/layouts/graph/min-heap.d.ts +8 -0
- package/dist/lib/layouts/graph/min-heap.d.ts.map +1 -0
- package/dist/lib/layouts/graph/min-heap.js +56 -0
- package/dist/lib/layouts/graph/min-heap.js.map +1 -0
- package/dist/lib/layouts/graph/node-content.d.ts +2 -3
- package/dist/lib/layouts/graph/node-content.d.ts.map +1 -1
- package/dist/lib/layouts/graph/node-content.js +67 -47
- package/dist/lib/layouts/graph/node-content.js.map +1 -1
- package/dist/lib/layouts/graph/path.d.ts +6 -0
- package/dist/lib/layouts/graph/path.d.ts.map +1 -0
- package/dist/lib/layouts/graph/path.js +53 -0
- package/dist/lib/layouts/graph/path.js.map +1 -0
- package/dist/lib/layouts/graph/round.d.ts +11 -0
- package/dist/lib/layouts/graph/round.d.ts.map +1 -0
- package/dist/lib/layouts/graph/round.js +181 -0
- package/dist/lib/layouts/graph/round.js.map +1 -0
- package/dist/lib/layouts/graph/route-search.d.ts +34 -0
- package/dist/lib/layouts/graph/route-search.d.ts.map +1 -0
- package/dist/lib/layouts/graph/route-search.js +208 -0
- package/dist/lib/layouts/graph/route-search.js.map +1 -0
- package/dist/lib/layouts/graph/route.d.ts +20 -0
- package/dist/lib/layouts/graph/route.d.ts.map +1 -0
- package/dist/lib/layouts/graph/route.js +276 -0
- package/dist/lib/layouts/graph/route.js.map +1 -0
- package/dist/lib/layouts/graph/sides.d.ts +28 -0
- package/dist/lib/layouts/graph/sides.d.ts.map +1 -0
- package/dist/lib/layouts/graph/sides.js +98 -0
- package/dist/lib/layouts/graph/sides.js.map +1 -0
- package/dist/lib/layouts/timeline/timeline-layout.d.ts +2 -1
- package/dist/lib/layouts/timeline/timeline-layout.d.ts.map +1 -1
- package/dist/lib/layouts/timeline/timeline-layout.js +9 -4
- package/dist/lib/layouts/timeline/timeline-layout.js.map +1 -1
- package/dist/lib/model/diagram-ir.d.ts +19 -156
- package/dist/lib/model/diagram-ir.d.ts.map +1 -1
- package/dist/lib/model/diagram-ir.js.map +1 -1
- package/dist/lib/model/validate-graph.d.ts +7 -0
- package/dist/lib/model/validate-graph.d.ts.map +1 -0
- package/dist/lib/model/validate-graph.js +54 -0
- package/dist/lib/model/validate-graph.js.map +1 -0
- package/dist/lib/react/Diagram.d.ts +3 -9
- package/dist/lib/react/Diagram.d.ts.map +1 -1
- package/dist/lib/react/Diagram.js +1 -13
- package/dist/lib/react/Diagram.js.map +1 -1
- package/dist/lib/react/diagram-types.d.ts +17 -46
- package/dist/lib/react/diagram-types.d.ts.map +1 -1
- package/dist/lib/react/diagram-types.js.map +1 -1
- package/dist/lib/renderers/canvas/graph-canvas.d.ts +2 -5
- package/dist/lib/renderers/canvas/graph-canvas.d.ts.map +1 -1
- package/dist/lib/renderers/canvas/graph-canvas.js +68 -43
- package/dist/lib/renderers/canvas/graph-canvas.js.map +1 -1
- package/dist/lib/renderers/html/graph-html.d.ts +2 -3
- package/dist/lib/renderers/html/graph-html.d.ts.map +1 -1
- package/dist/lib/renderers/html/graph-html.js +298 -289
- package/dist/lib/renderers/html/graph-html.js.map +1 -1
- package/dist/lib/renderers/shared/graph-parts.d.ts +3 -1
- package/dist/lib/renderers/shared/graph-parts.d.ts.map +1 -1
- package/dist/lib/renderers/shared/graph-parts.js +350 -418
- package/dist/lib/renderers/shared/graph-parts.js.map +1 -1
- package/dist/lib/renderers/shared/node-parts.d.ts +5 -6
- package/dist/lib/renderers/shared/node-parts.d.ts.map +1 -1
- package/dist/lib/renderers/shared/node-parts.js +112 -190
- package/dist/lib/renderers/shared/node-parts.js.map +1 -1
- package/dist/lib/renderers/shared/run-spans.js +2 -2
- package/dist/lib/renderers/shared/run-spans.js.map +1 -1
- package/dist/lib/renderers/shared/text-runs.d.ts +0 -6
- package/dist/lib/renderers/shared/text-runs.d.ts.map +1 -1
- package/dist/lib/renderers/shared/text-runs.js +0 -12
- package/dist/lib/renderers/shared/text-runs.js.map +1 -1
- package/dist/lib/renderers/svg/graph-svg.d.ts +1 -3
- package/dist/lib/renderers/svg/graph-svg.d.ts.map +1 -1
- package/dist/lib/renderers/svg/graph-svg.js +66 -80
- package/dist/lib/renderers/svg/graph-svg.js.map +1 -1
- package/dist/lib/renderers/svg/timeline-svg.d.ts.map +1 -1
- package/dist/lib/renderers/svg/timeline-svg.js +7 -5
- package/dist/lib/renderers/svg/timeline-svg.js.map +1 -1
- package/package.json +1 -1
- package/dist/lib/layouts/graph/graph-layout.d.ts +0 -154
- package/dist/lib/layouts/graph/graph-layout.d.ts.map +0 -1
- package/dist/lib/layouts/graph/graph-layout.js +0 -2340
- package/dist/lib/layouts/graph/graph-layout.js.map +0 -1
- package/dist/lib/layouts/graph/legacy-graph-layout.d.ts +0 -6
- package/dist/lib/layouts/graph/legacy-graph-layout.d.ts.map +0 -1
- package/dist/lib/layouts/graph/legacy-graph-layout.js +0 -542
- package/dist/lib/layouts/graph/legacy-graph-layout.js.map +0 -1
- package/dist/lib/layouts/text-metrics.d.ts +0 -7
- package/dist/lib/layouts/text-metrics.d.ts.map +0 -1
- package/dist/lib/layouts/text-metrics.js +0 -40
- package/dist/lib/layouts/text-metrics.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connections.d.ts","sourceRoot":"","sources":["../../../../src/lib/layouts/graph/connections.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,GAAG,EACH,cAAc,EACd,WAAW,EACZ,MAAM,2BAA2B,CAAC;AAEnC,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACtD,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,UAAU,EACX,MAAM,0BAA0B,CAAC;AAIlC,2DAA2D;AAC3D,MAAM,MAAM,KAAK,GAAG;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC;IACpC,GAAG,EAAE,GAAG,CAAC;IACT,oDAAoD;IACpD,MAAM,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,MAAM,EAAE,GAAG,EAAE,CAAC;IACd,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,sEAAsE;IACtE,KAAK,EAAE,GAAG,EAAE,CAAC;IACb,IAAI,EAAE,QAAQ,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,KAAK,CAAC;IACb,IAAI,EAAE,WAAW,CAAC;IAClB,IAAI,EAAE,UAAU,GAAG,SAAS,CAAC;IAC7B,0GAA0G;IAC1G,IAAI,EAAE,GAAG,CAAC;CACX,CAAC;AAEF,sGAAsG;AACtG,MAAM,MAAM,UAAU,GAAG;IACvB,gEAAgE;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,qEAAqE;IACrE,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,IAAI,EAAE,aAAa,CAAC;IACpB,EAAE,EAAE,aAAa,CAAC;IAClB,kEAAkE;IAClE,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAC9B,EAAE,EAAE,cAAc,EAClB,KAAK,EAAE,UAAU,EAAE,EACnB,MAAM,EAAE,WAAW,EAAE,EACrB,KAAK,EAAE,SAAS,GACf,UAAU,EAAE,EAAE,CAiJhB"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { parseEndpointRef } from "../../model/endpoint-ref.js";
|
|
2
|
+
import { sideLine, sidePairs } from "./sides.js";
|
|
3
|
+
import { LAYOUT_TOKENS } from "./tokens.js";
|
|
4
|
+
|
|
5
|
+
/** A node or group that a connection starts or ends at. */
|
|
6
|
+
|
|
7
|
+
/** An edge, or the leader from a note to its target: anything the router draws between two shapes. */
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Resolves every edge and every note leader to the shapes and sides it may
|
|
11
|
+
* join, in order of preference. A side hint wins over the cells; a port
|
|
12
|
+
* fixes the side; a side that declares ports takes no edge without one. A
|
|
13
|
+
* connection between two shapes with no hint and no port on either end may
|
|
14
|
+
* also take the other side pairs the cells allow, whose sides declare no
|
|
15
|
+
* ports; any other connection has one choice.
|
|
16
|
+
*/
|
|
17
|
+
export function graphConnections(ir, nodes, groups, areas) {
|
|
18
|
+
const shapes = new Map();
|
|
19
|
+
for (const {
|
|
20
|
+
node,
|
|
21
|
+
box,
|
|
22
|
+
frames,
|
|
23
|
+
radius,
|
|
24
|
+
ports,
|
|
25
|
+
caption
|
|
26
|
+
} of nodes) {
|
|
27
|
+
shapes.set(node.id, {
|
|
28
|
+
id: node.id,
|
|
29
|
+
kind: node.kind === 'junction' ? 'junction' : 'node',
|
|
30
|
+
box,
|
|
31
|
+
radius,
|
|
32
|
+
frames,
|
|
33
|
+
ports,
|
|
34
|
+
clear: caption ? [caption.box] : [],
|
|
35
|
+
area: areas.nodes.get(node.id)
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
for (const [index, {
|
|
39
|
+
group,
|
|
40
|
+
rect,
|
|
41
|
+
ports
|
|
42
|
+
}] of groups.entries()) {
|
|
43
|
+
shapes.set(group.id, {
|
|
44
|
+
id: group.id,
|
|
45
|
+
kind: 'group',
|
|
46
|
+
box: rect,
|
|
47
|
+
radius: LAYOUT_TOKENS.RADIUS,
|
|
48
|
+
frames: [],
|
|
49
|
+
ports,
|
|
50
|
+
clear: [],
|
|
51
|
+
area: areas.groups[index].area
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
const connect = (name, edge, fromRef, toRef, hints) => {
|
|
55
|
+
const resolve = ref => {
|
|
56
|
+
const {
|
|
57
|
+
nodeId,
|
|
58
|
+
portId
|
|
59
|
+
} = parseEndpointRef(ref);
|
|
60
|
+
const shape = shapes.get(nodeId);
|
|
61
|
+
if (!shape) {
|
|
62
|
+
throw new Error(`Diagram ${name}: "${nodeId}" is not a node or a group.`);
|
|
63
|
+
}
|
|
64
|
+
if (portId === undefined) return {
|
|
65
|
+
shape,
|
|
66
|
+
port: undefined
|
|
67
|
+
};
|
|
68
|
+
const port = shape.ports.find(candidate => candidate.id === portId);
|
|
69
|
+
if (!port) {
|
|
70
|
+
throw new Error(`Diagram ${name}: "${nodeId}" has no port "${portId}".`);
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
shape,
|
|
74
|
+
port
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
const from = resolve(fromRef);
|
|
78
|
+
const to = resolve(toRef);
|
|
79
|
+
const a = from.shape.area;
|
|
80
|
+
const b = to.shape.area;
|
|
81
|
+
const [[exitByCells, entryByCells], ...others] = from.shape === to.shape ?
|
|
82
|
+
// A loop has no cell delta to read; it leaves and re-enters the right side.
|
|
83
|
+
[['right', 'right']] : sidePairs(a, b);
|
|
84
|
+
const declaresPorts = (shape, side) => shape.ports.some(port => port.side === side);
|
|
85
|
+
const sideEnd = (shape, side) => ({
|
|
86
|
+
shape,
|
|
87
|
+
side,
|
|
88
|
+
port: undefined,
|
|
89
|
+
face: outermostFace(shape, side)
|
|
90
|
+
});
|
|
91
|
+
const end = ({
|
|
92
|
+
shape,
|
|
93
|
+
port
|
|
94
|
+
}, hint, byCells, role, ref) => {
|
|
95
|
+
if (port) {
|
|
96
|
+
if (hint !== undefined && hint !== port.side) {
|
|
97
|
+
throw new Error(`Diagram ${name}: ${role} ${hint} contradicts port "${ref}" on side ${port.side}.`);
|
|
98
|
+
}
|
|
99
|
+
return {
|
|
100
|
+
shape,
|
|
101
|
+
side: port.side,
|
|
102
|
+
port,
|
|
103
|
+
face: shape.box
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
const side = hint ?? byCells;
|
|
107
|
+
if (declaresPorts(shape, side)) {
|
|
108
|
+
throw new Error(`Diagram ${shape.kind === 'group' ? 'group' : 'node'} "${shape.id}" side ${side} declares ports; ${name} must use "${shape.id}:<port>".`);
|
|
109
|
+
}
|
|
110
|
+
return sideEnd(shape, side);
|
|
111
|
+
};
|
|
112
|
+
const cellDistance = Math.abs(b.row + b.rowSpan / 2 - (a.row + a.rowSpan / 2)) + Math.abs(b.col + b.colSpan / 2 - (a.col + a.colSpan / 2));
|
|
113
|
+
const chosen = {
|
|
114
|
+
name,
|
|
115
|
+
edge,
|
|
116
|
+
from: end(from, hints.exitSide, exitByCells, 'exitSide', fromRef),
|
|
117
|
+
to: end(to, hints.entrySide, entryByCells, 'entrySide', toRef),
|
|
118
|
+
cellDistance
|
|
119
|
+
};
|
|
120
|
+
const free = hints.exitSide === undefined && hints.entrySide === undefined && !from.port && !to.port;
|
|
121
|
+
if (!free) return [chosen];
|
|
122
|
+
return [chosen, ...others.filter(([exit, entry]) => !declaresPorts(from.shape, exit) && !declaresPorts(to.shape, entry)).map(([exit, entry]) => ({
|
|
123
|
+
name,
|
|
124
|
+
edge,
|
|
125
|
+
from: sideEnd(from.shape, exit),
|
|
126
|
+
to: sideEnd(to.shape, entry),
|
|
127
|
+
cellDistance
|
|
128
|
+
}))];
|
|
129
|
+
};
|
|
130
|
+
return [...ir.edges.map((edge, index) => connect(`edge ${edge.from}→${edge.to}`, index, edge.from, edge.to, edge)), ...ir.nodes.flatMap(node => node.kind === 'note' && node.target !== undefined ? [connect(`note leader "${node.id}"→"${node.target}"`, undefined, node.id, node.target, {})] : [])];
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** The frame of `shape` whose `side` lies farthest out: the front frame, or a stacked back frame. */
|
|
134
|
+
function outermostFace(shape, side) {
|
|
135
|
+
const outward = side === 'bottom' || side === 'right' ? 1 : -1;
|
|
136
|
+
return shape.frames.reduce((best, frame) => sideLine(frame, side) * outward > sideLine(best, side) * outward ? frame : best, shape.box);
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=connections.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connections.js","names":["parseEndpointRef","sideLine","sidePairs","LAYOUT_TOKENS","graphConnections","ir","nodes","groups","areas","shapes","Map","node","box","frames","radius","ports","caption","set","id","kind","clear","area","get","index","group","rect","entries","RADIUS","connect","name","edge","fromRef","toRef","hints","resolve","ref","nodeId","portId","shape","Error","undefined","port","find","candidate","from","to","a","b","exitByCells","entryByCells","others","declaresPorts","side","some","sideEnd","face","outermostFace","end","hint","byCells","role","cellDistance","Math","abs","row","rowSpan","col","colSpan","chosen","exitSide","entrySide","free","filter","exit","entry","map","edges","flatMap","target","outward","reduce","best","frame"],"sources":["../../../../src/lib/layouts/graph/connections.ts"],"sourcesContent":["import type {\n Box,\n DiagramGraphIR,\n DiagramSide,\n} from '../../model/diagram-ir.ts';\nimport { parseEndpointRef } from '../../model/endpoint-ref.ts';\nimport type { CellArea, GridAreas } from './areas.ts';\nimport type {\n GroupLayout,\n NodeLayout,\n PortLayout,\n} from './graph-layout-result.ts';\nimport { type SidePair, sideLine, sidePairs } from './sides.ts';\nimport { LAYOUT_TOKENS } from './tokens.ts';\n\n/** A node or group that a connection starts or ends at. */\nexport type Shape = {\n id: string;\n kind: 'node' | 'junction' | 'group';\n box: Box;\n /** The corner radius, which slots keep clear of. */\n radius: number;\n /** A stack's back frames, which draw as one unit with `box`. */\n frames: Box[];\n ports: PortLayout[];\n /** What a connection may not touch the shape through: its caption. */\n clear: Box[];\n area: CellArea;\n};\n\nexport type ConnectionEnd = {\n shape: Shape;\n side: DiagramSide;\n port: PortLayout | undefined;\n /** The box whose `side` the end touches: of a stack, the frame that reaches farthest out on that side. */\n face: Box;\n};\n\n/** An edge, or the leader from a note to its target: anything the router draws between two shapes. */\nexport type Connection = {\n /** How errors name it: `edge a→b`, or `note leader \"n\"→\"t\"`. */\n name: string;\n /** The index of the edge in the graph, or undefined for a leader. */\n edge: number | undefined;\n from: ConnectionEnd;\n to: ConnectionEnd;\n /** The Manhattan distance between the two cell areas' centres. */\n cellDistance: number;\n};\n\n/**\n * Resolves every edge and every note leader to the shapes and sides it may\n * join, in order of preference. A side hint wins over the cells; a port\n * fixes the side; a side that declares ports takes no edge without one. A\n * connection between two shapes with no hint and no port on either end may\n * also take the other side pairs the cells allow, whose sides declare no\n * ports; any other connection has one choice.\n */\nexport function graphConnections(\n ir: DiagramGraphIR,\n nodes: NodeLayout[],\n groups: GroupLayout[],\n areas: GridAreas,\n): Connection[][] {\n const shapes = new Map<string, Shape>();\n for (const { node, box, frames, radius, ports, caption } of nodes) {\n shapes.set(node.id, {\n id: node.id,\n kind: node.kind === 'junction' ? 'junction' : 'node',\n box,\n radius,\n frames,\n ports,\n clear: caption ? [caption.box] : [],\n area: areas.nodes.get(node.id)!,\n });\n }\n for (const [index, { group, rect, ports }] of groups.entries()) {\n shapes.set(group.id, {\n id: group.id,\n kind: 'group',\n box: rect,\n radius: LAYOUT_TOKENS.RADIUS,\n frames: [],\n ports,\n clear: [],\n area: areas.groups[index]!.area,\n });\n }\n\n const connect = (\n name: string,\n edge: number | undefined,\n fromRef: string,\n toRef: string,\n hints: {\n exitSide?: DiagramSide | undefined;\n entrySide?: DiagramSide | undefined;\n },\n ): Connection[] => {\n const resolve = (ref: string) => {\n const { nodeId, portId } = parseEndpointRef(ref);\n const shape = shapes.get(nodeId);\n if (!shape) {\n throw new Error(\n `Diagram ${name}: \"${nodeId}\" is not a node or a group.`,\n );\n }\n if (portId === undefined) return { shape, port: undefined };\n const port = shape.ports.find((candidate) => candidate.id === portId);\n if (!port) {\n throw new Error(\n `Diagram ${name}: \"${nodeId}\" has no port \"${portId}\".`,\n );\n }\n return { shape, port };\n };\n const from = resolve(fromRef);\n const to = resolve(toRef);\n const a = from.shape.area;\n const b = to.shape.area;\n const [[exitByCells, entryByCells], ...others]: [SidePair, ...SidePair[]] =\n from.shape === to.shape\n ? // A loop has no cell delta to read; it leaves and re-enters the right side.\n [['right', 'right']]\n : sidePairs(a, b);\n const declaresPorts = (shape: Shape, side: DiagramSide) =>\n shape.ports.some((port) => port.side === side);\n const sideEnd = (shape: Shape, side: DiagramSide): ConnectionEnd => ({\n shape,\n side,\n port: undefined,\n face: outermostFace(shape, side),\n });\n const end = (\n { shape, port }: { shape: Shape; port: PortLayout | undefined },\n hint: DiagramSide | undefined,\n byCells: DiagramSide,\n role: 'exitSide' | 'entrySide',\n ref: string,\n ): ConnectionEnd => {\n if (port) {\n if (hint !== undefined && hint !== port.side) {\n throw new Error(\n `Diagram ${name}: ${role} ${hint} contradicts port \"${ref}\" on side ${port.side}.`,\n );\n }\n return { shape, side: port.side, port, face: shape.box };\n }\n const side = hint ?? byCells;\n if (declaresPorts(shape, side)) {\n throw new Error(\n `Diagram ${shape.kind === 'group' ? 'group' : 'node'} \"${shape.id}\" side ${side} declares ports; ${name} must use \"${shape.id}:<port>\".`,\n );\n }\n return sideEnd(shape, side);\n };\n const cellDistance =\n Math.abs(b.row + b.rowSpan / 2 - (a.row + a.rowSpan / 2)) +\n Math.abs(b.col + b.colSpan / 2 - (a.col + a.colSpan / 2));\n const chosen = {\n name,\n edge,\n from: end(from, hints.exitSide, exitByCells, 'exitSide', fromRef),\n to: end(to, hints.entrySide, entryByCells, 'entrySide', toRef),\n cellDistance,\n };\n const free =\n hints.exitSide === undefined &&\n hints.entrySide === undefined &&\n !from.port &&\n !to.port;\n if (!free) return [chosen];\n return [\n chosen,\n ...others\n .filter(\n ([exit, entry]) =>\n !declaresPorts(from.shape, exit) && !declaresPorts(to.shape, entry),\n )\n .map(([exit, entry]) => ({\n name,\n edge,\n from: sideEnd(from.shape, exit),\n to: sideEnd(to.shape, entry),\n cellDistance,\n })),\n ];\n };\n\n return [\n ...ir.edges.map((edge, index) =>\n connect(`edge ${edge.from}→${edge.to}`, index, edge.from, edge.to, edge),\n ),\n ...ir.nodes.flatMap((node) =>\n node.kind === 'note' && node.target !== undefined\n ? [\n connect(\n `note leader \"${node.id}\"→\"${node.target}\"`,\n undefined,\n node.id,\n node.target,\n {},\n ),\n ]\n : [],\n ),\n ];\n}\n\n/** The frame of `shape` whose `side` lies farthest out: the front frame, or a stacked back frame. */\nfunction outermostFace(shape: Shape, side: DiagramSide): Box {\n const outward = side === 'bottom' || side === 'right' ? 1 : -1;\n return shape.frames.reduce(\n (best, frame) =>\n sideLine(frame, side) * outward > sideLine(best, side) * outward\n ? frame\n : best,\n shape.box,\n );\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -34,6 +34,8 @@ export type NodeLayout = {
|
|
|
34
34
|
};
|
|
35
35
|
text: TextRun[];
|
|
36
36
|
bullets: Point[];
|
|
37
|
+
/** The box reserved for the node's React content, under its text. */
|
|
38
|
+
contentBox?: Box;
|
|
37
39
|
caption?: {
|
|
38
40
|
box: Box;
|
|
39
41
|
framed: boolean;
|
|
@@ -54,15 +56,15 @@ export type GroupLayout = {
|
|
|
54
56
|
rect: Box;
|
|
55
57
|
/** The title band, inside `rect`. */
|
|
56
58
|
band?: Box;
|
|
59
|
+
/** The line on the band edge that faces the content; present exactly when `band` is. */
|
|
60
|
+
separator?: [Point, Point];
|
|
57
61
|
label: TextRun[];
|
|
58
62
|
dividers: [Point, Point][];
|
|
59
|
-
ports
|
|
63
|
+
ports: PortLayout[];
|
|
60
64
|
};
|
|
61
65
|
export type EdgeLabelLayout = {
|
|
62
66
|
box: Box;
|
|
63
67
|
text: TextRun[];
|
|
64
|
-
/** The index of the route segment that the label sits beside. */
|
|
65
|
-
segment?: number;
|
|
66
68
|
};
|
|
67
69
|
export type EdgeLayout = {
|
|
68
70
|
edge: DiagramEdge;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph-layout-result.d.ts","sourceRoot":"","sources":["../../../../src/lib/layouts/graph/graph-layout-result.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,GAAG,EACH,WAAW,EACX,YAAY,EACZ,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,KAAK,EACN,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAE5C,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEpD,MAAM,MAAM,OAAO,GAAG;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,EAAE,MAAM,CAAC;IACV,oBAAoB;IACpB,CAAC,EAAE,MAAM,CAAC;IACV,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,IAAI,CAAC;IACX,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,uCAAuC;IACvC,MAAM,EAAE,GAAG,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,KAAK,CAAC;IACb,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,WAAW,CAAC;IAClB,iBAAiB;IACjB,GAAG,EAAE,GAAG,CAAC;IACT,mEAAmE;IACnE,MAAM,EAAE,GAAG,CAAC;IACZ,+BAA+B;IAC/B,MAAM,EAAE,GAAG,EAAE,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,OAAO,EAAE,KAAK,EAAE,CAAC;IACjB,OAAO,CAAC,EAAE;QAAE,GAAG,EAAE,GAAG,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,OAAO,EAAE,CAAA;KAAE,CAAC;IACzD,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,SAAS,CAAC,EAAE;QACV,IAAI,EAAE,KAAK,EAAE,CAAC;QACd,iDAAiD;QACjD,IAAI,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACrB,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC;QAC1B,KAAK,EAAE,GAAG,EAAE,CAAC;KACd,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,YAAY,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,GAAG,CAAC;IACV,qCAAqC;IACrC,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC;IAC3B,KAAK,
|
|
1
|
+
{"version":3,"file":"graph-layout-result.d.ts","sourceRoot":"","sources":["../../../../src/lib/layouts/graph/graph-layout-result.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"graph-layout-result.js","names":[],"sources":["../../../../src/lib/layouts/graph/graph-layout-result.ts"],"sourcesContent":["import type {\n Box,\n DiagramEdge,\n DiagramGroup,\n DiagramNode,\n DiagramSide,\n DiagramTextColor,\n Point,\n} from '../../model/diagram-ir.ts';\nimport type { Font } from '../text/font.ts';\n\nexport type TextAnchor = 'start' | 'middle' | 'end';\n\nexport type TextRun = {\n text: string;\n x: number;\n /** The baseline. */\n y: number;\n anchor: TextAnchor;\n font: Font;\n color?: DiagramTextColor;\n /** The ink box the engine measured. */\n bounds: Box;\n};\n\nexport type PortLayout = {\n id: string;\n side: DiagramSide;\n point: Point;\n label?: TextRun;\n};\n\nexport type NodeLayout = {\n node: DiagramNode;\n /** The frame. */\n box: Box;\n /** The frame, the stacked back frames and the caption together. */\n visual: Box;\n /** The stacked back frames. */\n frames: Box[];\n radius: number;\n icon?: { x: number; y: number; size: number };\n text: TextRun[];\n bullets: Point[];\n caption?: { box: Box; framed: boolean; text: TextRun[] };\n ports: PortLayout[];\n appliance?: {\n body: Point[];\n /** The line under the front edge of the body. */\n face: [Point, Point];\n antenna: [Point, Point][];\n jacks: Box[];\n };\n};\n\nexport type GroupLayout = {\n group: DiagramGroup;\n depth: number;\n rect: Box;\n /** The title band, inside `rect`. */\n band?: Box;\n label: TextRun[];\n dividers: [Point, Point][];\n ports
|
|
1
|
+
{"version":3,"file":"graph-layout-result.js","names":[],"sources":["../../../../src/lib/layouts/graph/graph-layout-result.ts"],"sourcesContent":["import type {\n Box,\n DiagramEdge,\n DiagramGroup,\n DiagramNode,\n DiagramSide,\n DiagramTextColor,\n Point,\n} from '../../model/diagram-ir.ts';\nimport type { Font } from '../text/font.ts';\n\nexport type TextAnchor = 'start' | 'middle' | 'end';\n\nexport type TextRun = {\n text: string;\n x: number;\n /** The baseline. */\n y: number;\n anchor: TextAnchor;\n font: Font;\n color?: DiagramTextColor;\n /** The ink box the engine measured. */\n bounds: Box;\n};\n\nexport type PortLayout = {\n id: string;\n side: DiagramSide;\n point: Point;\n label?: TextRun;\n};\n\nexport type NodeLayout = {\n node: DiagramNode;\n /** The frame. */\n box: Box;\n /** The frame, the stacked back frames and the caption together. */\n visual: Box;\n /** The stacked back frames. */\n frames: Box[];\n radius: number;\n icon?: { x: number; y: number; size: number };\n text: TextRun[];\n bullets: Point[];\n /** The box reserved for the node's React content, under its text. */\n contentBox?: Box;\n caption?: { box: Box; framed: boolean; text: TextRun[] };\n ports: PortLayout[];\n appliance?: {\n body: Point[];\n /** The line under the front edge of the body. */\n face: [Point, Point];\n antenna: [Point, Point][];\n jacks: Box[];\n };\n};\n\nexport type GroupLayout = {\n group: DiagramGroup;\n depth: number;\n rect: Box;\n /** The title band, inside `rect`. */\n band?: Box;\n /** The line on the band edge that faces the content; present exactly when `band` is. */\n separator?: [Point, Point];\n label: TextRun[];\n dividers: [Point, Point][];\n ports: PortLayout[];\n};\n\nexport type EdgeLabelLayout = {\n box: Box;\n text: TextRun[];\n};\n\nexport type EdgeLayout = {\n edge: DiagramEdge;\n exitSide: DiagramSide;\n entrySide: DiagramSide;\n points: Point[];\n d: string;\n label?: EdgeLabelLayout;\n badge?: { box: Box; icon?: Box; text: TextRun[] };\n};\n\nexport type LeaderLayout = {\n /** The id of the note node. */\n note: string;\n /** The id of the node or group that the note explains. */\n target: string;\n points: Point[];\n d: string;\n};\n\nexport type GraphLayout = {\n nodes: NodeLayout[];\n groups: GroupLayout[];\n edges: EdgeLayout[];\n leaders: LeaderLayout[];\n viewBox: Box;\n};\n"],"mappings":"","ignoreList":[]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { parseEndpointRef } from "../../model/endpoint-ref.js";
|
|
2
|
-
import {
|
|
2
|
+
import { measureEdgeTags } from "./measure.js";
|
|
3
3
|
import { LAYOUT_TOKENS } from "./tokens.js";
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -18,7 +18,7 @@ const STROKE = 1;
|
|
|
18
18
|
* boundary, so every group border stays a straight line.
|
|
19
19
|
*/
|
|
20
20
|
export function gridGutters(areas, titleHeights, edges) {
|
|
21
|
-
const minimums =
|
|
21
|
+
const minimums = tagMinimums(edges, areas.nodes);
|
|
22
22
|
const chrome = LAYOUT_TOKENS.GROUP_PAD + STROKE;
|
|
23
23
|
const spans = axis => areas.groups.map(({
|
|
24
24
|
group,
|
|
@@ -47,9 +47,8 @@ function axisGutters(count, spans, minimums) {
|
|
|
47
47
|
}, (_, boundary) => {
|
|
48
48
|
const closing = slotWidths(spans.filter(span => span.end === boundary), span => span.closingChrome);
|
|
49
49
|
const opening = slotWidths(spans.filter(span => span.start === boundary), span => span.openingChrome);
|
|
50
|
-
const slots = [...closing.values(), ...opening.values()].reduce((total, width) => total + width, 0);
|
|
51
50
|
const outer = boundary === 0 || boundary === count;
|
|
52
|
-
const middle = Math.max(outer ? 0 : LAYOUT_TOKENS.GAP,
|
|
51
|
+
const middle = Math.max(outer ? 0 : LAYOUT_TOKENS.GAP, minimums.get(boundary) ?? 0);
|
|
53
52
|
const closingEdges = new Map();
|
|
54
53
|
let offset = 0;
|
|
55
54
|
for (const [depth, width] of [...closing].sort(([a], [b]) => b - a)) {
|
|
@@ -81,37 +80,57 @@ function slotWidths(spans, chromeOf) {
|
|
|
81
80
|
}
|
|
82
81
|
|
|
83
82
|
/**
|
|
84
|
-
* A
|
|
85
|
-
*
|
|
86
|
-
*
|
|
83
|
+
* A tagged edge between two facing cells, with no node between them, runs
|
|
84
|
+
* straight across the gutters between them, and the tracks between them may
|
|
85
|
+
* be empty. Its label and its badge sit in a row along it, LABEL_GAP apart.
|
|
86
|
+
* The tags must not straddle the border of a group that opens or closes
|
|
87
|
+
* there, so the middles of those gutters, outside all their chrome, share
|
|
88
|
+
* the row and a stub on each side of it.
|
|
87
89
|
*/
|
|
88
|
-
function
|
|
90
|
+
function tagMinimums(edges, nodes) {
|
|
89
91
|
const minimums = {
|
|
90
92
|
row: new Map(),
|
|
91
93
|
col: new Map()
|
|
92
94
|
};
|
|
93
|
-
const raise = (axis,
|
|
95
|
+
const raise = (axis, boundaries, need) => {
|
|
96
|
+
for (const boundary of boundaries) {
|
|
97
|
+
minimums[axis].set(boundary, Math.max(minimums[axis].get(boundary) ?? 0, need / boundaries.length));
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
const areas = [...nodes.values()];
|
|
94
101
|
for (const edge of edges) {
|
|
95
|
-
|
|
102
|
+
const {
|
|
103
|
+
label,
|
|
104
|
+
badge
|
|
105
|
+
} = measureEdgeTags(edge);
|
|
106
|
+
const tags = [label, badge].filter(tag => tag !== undefined);
|
|
107
|
+
if (tags.length === 0) continue;
|
|
96
108
|
const from = nodes.get(parseEndpointRef(edge.from).nodeId);
|
|
97
109
|
const to = nodes.get(parseEndpointRef(edge.to).nodeId);
|
|
98
110
|
if (!from || !to) continue;
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
const stacked = sideBySide(transpose(from), transpose(to));
|
|
103
|
-
if (stacked) raise('row', stacked, label.h + 2 * LAYOUT_TOKENS.STUB);
|
|
111
|
+
const rowLength = along => tags.reduce((sum, tag) => sum + tag[along], 0) + (tags.length - 1) * LAYOUT_TOKENS.LABEL_GAP + 2 * LAYOUT_TOKENS.STUB;
|
|
112
|
+
raise('col', facingBoundaries(from, to, areas), rowLength('w'));
|
|
113
|
+
raise('row', facingBoundaries(transpose(from), transpose(to), areas.map(transpose)), rowLength('h'));
|
|
104
114
|
}
|
|
105
115
|
return minimums;
|
|
106
116
|
}
|
|
107
117
|
|
|
108
|
-
/**
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
118
|
+
/**
|
|
119
|
+
* The column boundaries between two areas that share rows and face each
|
|
120
|
+
* other across them, with no other area between them in the rows they share.
|
|
121
|
+
*/
|
|
122
|
+
function facingBoundaries(a, b, areas) {
|
|
123
|
+
const top = Math.max(a.row, b.row);
|
|
124
|
+
const bottom = Math.min(a.row + a.rowSpan, b.row + b.rowSpan);
|
|
125
|
+
const [left, right] = a.col < b.col ? [a, b] : [b, a];
|
|
126
|
+
const start = left.col + left.colSpan;
|
|
127
|
+
const end = right.col;
|
|
128
|
+
if (top >= bottom || start > end) return [];
|
|
129
|
+
const blocked = areas.some(area => area.col < end && area.col + area.colSpan > start && area.row < bottom && area.row + area.rowSpan > top);
|
|
130
|
+
if (blocked) return [];
|
|
131
|
+
return Array.from({
|
|
132
|
+
length: end - start + 1
|
|
133
|
+
}, (_, index) => start + index);
|
|
115
134
|
}
|
|
116
135
|
function transpose(area) {
|
|
117
136
|
return {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gutters.js","names":["parseEndpointRef","measureEdgeLabel","LAYOUT_TOKENS","STROKE","gridGutters","areas","titleHeights","edges","minimums","labelMinimums","nodes","chrome","GROUP_PAD","spans","axis","groups","map","group","depth","area","start","span","row","rowSpan","col","colSpan","title","get","id","titleAtEnd","labelSide","end","openingChrome","closingChrome","axisGutters","rows","cols","count","Array","from","length","_","boundary","closing","slotWidths","filter","opening","slots","values","reduce","total","width","outer","middle","Math","max","GAP","closingEdges","Map","offset","sort","a","b","set","openingEdges","size","chromeOf","widths","CHANNEL","raise","need","edge","label","nodeId","to","side","sideBySide","w","STUB","stacked","transpose","h","shareRows","min","undefined"],"sources":["../../../../src/lib/layouts/graph/gutters.ts"],"sourcesContent":["import type { DiagramEdge } from '../../model/diagram-ir.ts';\nimport { parseEndpointRef } from '../../model/endpoint-ref.ts';\nimport type { CellArea, GridAreas } from './areas.ts';\nimport { measureEdgeLabel } from './measure.ts';\nimport { LAYOUT_TOKENS } from './tokens.ts';\n\nexport type Axis = 'row' | 'col';\n\n/**\n * The space at one track boundary. Boundary b lies before track b, so\n * boundaries 0 and N are the outer edges of the grid.\n */\nexport type Gutter = {\n size: number;\n /** For each depth, how far from the gutter's start the border of a group closing here lies. */\n closing: Map<number, number>;\n /** For each depth, how far from the gutter's start the border of a group opening here lies. */\n opening: Map<number, number>;\n};\n\nexport type GridGutters = Record<Axis, Gutter[]>;\n\n/** The border stroke a group draws, which its chrome must hold. */\nconst STROKE = 1;\n\ntype GroupSpan = {\n depth: number;\n start: number;\n end: number;\n openingChrome: number;\n closingChrome: number;\n};\n\n/**\n * Sizes every gutter before the tracks, because no gutter depends on a\n * track's size. A gutter holds, in order: the chrome of the groups closing\n * there (deepest first, next to the track before), a middle gap, and the\n * chrome of the groups opening there (deepest last, next to the track after).\n * Each depth's slot is as wide as its widest group anywhere along the\n * boundary, so every group border stays a straight line.\n */\nexport function gridGutters(\n areas: GridAreas,\n titleHeights: Map<string, number>,\n edges: DiagramEdge[],\n): GridGutters {\n const minimums = labelMinimums(edges, areas.nodes);\n const chrome = LAYOUT_TOKENS.GROUP_PAD + STROKE;\n const spans = (axis: Axis): GroupSpan[] =>\n areas.groups.map(({ group, depth, area }) => {\n const [start, span] =\n axis === 'row' ? [area.row, area.rowSpan] : [area.col, area.colSpan];\n const title = axis === 'row' ? titleHeights.get(group.id)! : 0;\n const titleAtEnd = group.labelSide === 'bottom';\n return {\n depth,\n start,\n end: start + span,\n openingChrome: chrome + (titleAtEnd ? 0 : title),\n closingChrome: chrome + (titleAtEnd ? title : 0),\n };\n });\n return {\n row: axisGutters(areas.rows, spans('row'), minimums.row),\n col: axisGutters(areas.cols, spans('col'), minimums.col),\n };\n}\n\nfunction axisGutters(\n count: number,\n spans: GroupSpan[],\n minimums: Map<number, number>,\n): Gutter[] {\n return Array.from({ length: count + 1 }, (_, boundary) => {\n const closing = slotWidths(\n spans.filter((span) => span.end === boundary),\n (span) => span.closingChrome,\n );\n const opening = slotWidths(\n spans.filter((span) => span.start === boundary),\n (span) => span.openingChrome,\n );\n const slots = [...closing.values(), ...opening.values()].reduce(\n (total, width) => total + width,\n 0,\n );\n const outer = boundary === 0 || boundary === count;\n const middle = Math.max(\n outer ? 0 : LAYOUT_TOKENS.GAP,\n (minimums.get(boundary) ?? 0) - slots,\n );\n\n const closingEdges = new Map<number, number>();\n let offset = 0;\n for (const [depth, width] of [...closing].sort(([a], [b]) => b - a)) {\n offset += width;\n closingEdges.set(depth, offset);\n }\n offset += middle;\n const openingEdges = new Map<number, number>();\n for (const [depth, width] of [...opening].sort(([a], [b]) => a - b)) {\n openingEdges.set(depth, offset);\n offset += width;\n }\n return { size: offset, closing: closingEdges, opening: openingEdges };\n });\n}\n\n/** The width of each depth's slot: its widest chrome plus a channel for edges. */\nfunction slotWidths(\n spans: GroupSpan[],\n chromeOf: (span: GroupSpan) => number,\n): Map<number, number> {\n const widths = new Map<number, number>();\n for (const span of spans) {\n const width = chromeOf(span) + LAYOUT_TOKENS.CHANNEL;\n widths.set(span.depth, Math.max(widths.get(span.depth) ?? 0, width));\n }\n return widths;\n}\n\n/**\n * A labelled edge between two neighbouring cells has only the gutter between\n * them for its label, so that gutter must hold the label and a stub on each\n * side of it.\n */\nfunction labelMinimums(\n edges: DiagramEdge[],\n nodes: Map<string, CellArea>,\n): Record<Axis, Map<number, number>> {\n const minimums: Record<Axis, Map<number, number>> = {\n row: new Map(),\n col: new Map(),\n };\n const raise = (axis: Axis, boundary: number, need: number) =>\n minimums[axis].set(\n boundary,\n Math.max(minimums[axis].get(boundary) ?? 0, need),\n );\n for (const edge of edges) {\n if (!edge.label?.length) continue;\n const from = nodes.get(parseEndpointRef(edge.from).nodeId);\n const to = nodes.get(parseEndpointRef(edge.to).nodeId);\n if (!from || !to) continue;\n const label = measureEdgeLabel(edge, LAYOUT_TOKENS);\n const side = sideBySide(from, to);\n if (side) raise('col', side, label.w + 2 * LAYOUT_TOKENS.STUB);\n const stacked = sideBySide(transpose(from), transpose(to));\n if (stacked) raise('row', stacked, label.h + 2 * LAYOUT_TOKENS.STUB);\n }\n return minimums;\n}\n\n/** The column boundary between two areas that share rows and touch across it. */\nfunction sideBySide(a: CellArea, b: CellArea): number | undefined {\n const shareRows =\n Math.max(a.row, b.row) < Math.min(a.row + a.rowSpan, b.row + b.rowSpan);\n if (!shareRows) return undefined;\n if (a.col + a.colSpan === b.col) return b.col;\n if (b.col + b.colSpan === a.col) return a.col;\n return undefined;\n}\n\nfunction transpose(area: CellArea): CellArea {\n return {\n row: area.col,\n col: area.row,\n rowSpan: area.colSpan,\n colSpan: area.rowSpan,\n };\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"gutters.js","names":["parseEndpointRef","measureEdgeTags","LAYOUT_TOKENS","STROKE","gridGutters","areas","titleHeights","edges","minimums","tagMinimums","nodes","chrome","GROUP_PAD","spans","axis","groups","map","group","depth","area","start","span","row","rowSpan","col","colSpan","title","get","id","titleAtEnd","labelSide","end","openingChrome","closingChrome","axisGutters","rows","cols","count","Array","from","length","_","boundary","closing","slotWidths","filter","opening","outer","middle","Math","max","GAP","closingEdges","Map","offset","width","sort","a","b","set","openingEdges","size","chromeOf","widths","CHANNEL","raise","boundaries","need","values","edge","label","badge","tags","tag","undefined","nodeId","to","rowLength","along","reduce","sum","LABEL_GAP","STUB","facingBoundaries","transpose","top","bottom","min","left","right","blocked","some","index"],"sources":["../../../../src/lib/layouts/graph/gutters.ts"],"sourcesContent":["import type { DiagramEdge } from '../../model/diagram-ir.ts';\nimport { parseEndpointRef } from '../../model/endpoint-ref.ts';\nimport type { CellArea, GridAreas } from './areas.ts';\nimport { measureEdgeTags } from './measure.ts';\nimport { LAYOUT_TOKENS } from './tokens.ts';\n\nexport type Axis = 'row' | 'col';\n\n/**\n * The space at one track boundary. Boundary b lies before track b, so\n * boundaries 0 and N are the outer edges of the grid.\n */\nexport type Gutter = {\n size: number;\n /** For each depth, how far from the gutter's start the border of a group closing here lies. */\n closing: Map<number, number>;\n /** For each depth, how far from the gutter's start the border of a group opening here lies. */\n opening: Map<number, number>;\n};\n\nexport type GridGutters = Record<Axis, Gutter[]>;\n\n/** The border stroke a group draws, which its chrome must hold. */\nconst STROKE = 1;\n\ntype GroupSpan = {\n depth: number;\n start: number;\n end: number;\n openingChrome: number;\n closingChrome: number;\n};\n\n/**\n * Sizes every gutter before the tracks, because no gutter depends on a\n * track's size. A gutter holds, in order: the chrome of the groups closing\n * there (deepest first, next to the track before), a middle gap, and the\n * chrome of the groups opening there (deepest last, next to the track after).\n * Each depth's slot is as wide as its widest group anywhere along the\n * boundary, so every group border stays a straight line.\n */\nexport function gridGutters(\n areas: GridAreas,\n titleHeights: Map<string, number>,\n edges: DiagramEdge[],\n): GridGutters {\n const minimums = tagMinimums(edges, areas.nodes);\n const chrome = LAYOUT_TOKENS.GROUP_PAD + STROKE;\n const spans = (axis: Axis): GroupSpan[] =>\n areas.groups.map(({ group, depth, area }) => {\n const [start, span] =\n axis === 'row' ? [area.row, area.rowSpan] : [area.col, area.colSpan];\n const title = axis === 'row' ? titleHeights.get(group.id)! : 0;\n const titleAtEnd = group.labelSide === 'bottom';\n return {\n depth,\n start,\n end: start + span,\n openingChrome: chrome + (titleAtEnd ? 0 : title),\n closingChrome: chrome + (titleAtEnd ? title : 0),\n };\n });\n return {\n row: axisGutters(areas.rows, spans('row'), minimums.row),\n col: axisGutters(areas.cols, spans('col'), minimums.col),\n };\n}\n\nfunction axisGutters(\n count: number,\n spans: GroupSpan[],\n minimums: Map<number, number>,\n): Gutter[] {\n return Array.from({ length: count + 1 }, (_, boundary) => {\n const closing = slotWidths(\n spans.filter((span) => span.end === boundary),\n (span) => span.closingChrome,\n );\n const opening = slotWidths(\n spans.filter((span) => span.start === boundary),\n (span) => span.openingChrome,\n );\n const outer = boundary === 0 || boundary === count;\n const middle = Math.max(\n outer ? 0 : LAYOUT_TOKENS.GAP,\n minimums.get(boundary) ?? 0,\n );\n\n const closingEdges = new Map<number, number>();\n let offset = 0;\n for (const [depth, width] of [...closing].sort(([a], [b]) => b - a)) {\n offset += width;\n closingEdges.set(depth, offset);\n }\n offset += middle;\n const openingEdges = new Map<number, number>();\n for (const [depth, width] of [...opening].sort(([a], [b]) => a - b)) {\n openingEdges.set(depth, offset);\n offset += width;\n }\n return { size: offset, closing: closingEdges, opening: openingEdges };\n });\n}\n\n/** The width of each depth's slot: its widest chrome plus a channel for edges. */\nfunction slotWidths(\n spans: GroupSpan[],\n chromeOf: (span: GroupSpan) => number,\n): Map<number, number> {\n const widths = new Map<number, number>();\n for (const span of spans) {\n const width = chromeOf(span) + LAYOUT_TOKENS.CHANNEL;\n widths.set(span.depth, Math.max(widths.get(span.depth) ?? 0, width));\n }\n return widths;\n}\n\n/**\n * A tagged edge between two facing cells, with no node between them, runs\n * straight across the gutters between them, and the tracks between them may\n * be empty. Its label and its badge sit in a row along it, LABEL_GAP apart.\n * The tags must not straddle the border of a group that opens or closes\n * there, so the middles of those gutters, outside all their chrome, share\n * the row and a stub on each side of it.\n */\nfunction tagMinimums(\n edges: DiagramEdge[],\n nodes: Map<string, CellArea>,\n): Record<Axis, Map<number, number>> {\n const minimums: Record<Axis, Map<number, number>> = {\n row: new Map(),\n col: new Map(),\n };\n const raise = (axis: Axis, boundaries: number[], need: number) => {\n for (const boundary of boundaries) {\n minimums[axis].set(\n boundary,\n Math.max(minimums[axis].get(boundary) ?? 0, need / boundaries.length),\n );\n }\n };\n const areas = [...nodes.values()];\n for (const edge of edges) {\n const { label, badge } = measureEdgeTags(edge);\n const tags = [label, badge].filter((tag) => tag !== undefined);\n if (tags.length === 0) continue;\n const from = nodes.get(parseEndpointRef(edge.from).nodeId);\n const to = nodes.get(parseEndpointRef(edge.to).nodeId);\n if (!from || !to) continue;\n const rowLength = (along: 'w' | 'h') =>\n tags.reduce((sum, tag) => sum + tag[along], 0) +\n (tags.length - 1) * LAYOUT_TOKENS.LABEL_GAP +\n 2 * LAYOUT_TOKENS.STUB;\n raise('col', facingBoundaries(from, to, areas), rowLength('w'));\n raise(\n 'row',\n facingBoundaries(transpose(from), transpose(to), areas.map(transpose)),\n rowLength('h'),\n );\n }\n return minimums;\n}\n\n/**\n * The column boundaries between two areas that share rows and face each\n * other across them, with no other area between them in the rows they share.\n */\nfunction facingBoundaries(\n a: CellArea,\n b: CellArea,\n areas: CellArea[],\n): number[] {\n const top = Math.max(a.row, b.row);\n const bottom = Math.min(a.row + a.rowSpan, b.row + b.rowSpan);\n const [left, right] = a.col < b.col ? [a, b] : [b, a];\n const start = left.col + left.colSpan;\n const end = right.col;\n if (top >= bottom || start > end) return [];\n const blocked = areas.some(\n (area) =>\n area.col < end &&\n area.col + area.colSpan > start &&\n area.row < bottom &&\n area.row + area.rowSpan > top,\n );\n if (blocked) return [];\n return Array.from({ length: end - start + 1 }, (_, index) => start + index);\n}\n\nfunction transpose(area: CellArea): CellArea {\n return {\n row: area.col,\n col: area.row,\n rowSpan: area.colSpan,\n colSpan: area.rowSpan,\n };\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Box, Point } from '../../model/diagram-ir.ts';
|
|
2
|
+
type Size = {
|
|
3
|
+
w: number;
|
|
4
|
+
h: number;
|
|
5
|
+
};
|
|
6
|
+
export type TagKind = 'label' | 'badge';
|
|
7
|
+
/**
|
|
8
|
+
* The first free position for an edge's tags on its route: the longest
|
|
9
|
+
* segment first, and on each segment the fractions in FRACTIONS order. A
|
|
10
|
+
* label sits LABEL_GAP beside the segment (above, then below a horizontal
|
|
11
|
+
* one; right, then left of a vertical one). A badge sits centred on it. An
|
|
12
|
+
* edge with both puts them in a row along the segment, LABEL_GAP apart and
|
|
13
|
+
* centred on the fraction: the label first, then the badge first.
|
|
14
|
+
*/
|
|
15
|
+
export declare function tagPosition(tags: {
|
|
16
|
+
label?: Size;
|
|
17
|
+
badge?: Size;
|
|
18
|
+
}, points: Point[], isFree: (box: Box, kind: TagKind) => boolean): {
|
|
19
|
+
label?: Box;
|
|
20
|
+
badge?: Box;
|
|
21
|
+
} | undefined;
|
|
22
|
+
export {};
|
|
23
|
+
//# sourceMappingURL=labels.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"labels.d.ts","sourceRoot":"","sources":["../../../../src/lib/layouts/graph/labels.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAM5D,KAAK,IAAI,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAErC,MAAM,MAAM,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;AAExC;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE;IAAE,KAAK,CAAC,EAAE,IAAI,CAAC;IAAC,KAAK,CAAC,EAAE,IAAI,CAAA;CAAE,EACpC,MAAM,EAAE,KAAK,EAAE,EACf,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,KAAK,OAAO,GAC3C;IAAE,KAAK,CAAC,EAAE,GAAG,CAAC;IAAC,KAAK,CAAC,EAAE,GAAG,CAAA;CAAE,GAAG,SAAS,CAgD1C"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { LAYOUT_TOKENS } from "./tokens.js";
|
|
2
|
+
|
|
3
|
+
/** Where along a segment the tags are tried, in order. */
|
|
4
|
+
const FRACTIONS = [0.5, 0.3, 0.7, 0.15, 0.85];
|
|
5
|
+
/**
|
|
6
|
+
* The first free position for an edge's tags on its route: the longest
|
|
7
|
+
* segment first, and on each segment the fractions in FRACTIONS order. A
|
|
8
|
+
* label sits LABEL_GAP beside the segment (above, then below a horizontal
|
|
9
|
+
* one; right, then left of a vertical one). A badge sits centred on it. An
|
|
10
|
+
* edge with both puts them in a row along the segment, LABEL_GAP apart and
|
|
11
|
+
* centred on the fraction: the label first, then the badge first.
|
|
12
|
+
*/
|
|
13
|
+
export function tagPosition(tags, points, isFree) {
|
|
14
|
+
const {
|
|
15
|
+
label,
|
|
16
|
+
badge
|
|
17
|
+
} = tags;
|
|
18
|
+
const freeLabel = (size, at, horizontal) => beside(size, at, horizontal).find(box => isFree(box, 'label'));
|
|
19
|
+
const freeBadge = (size, at) => {
|
|
20
|
+
const box = on(size, at);
|
|
21
|
+
return isFree(box, 'badge') ? box : undefined;
|
|
22
|
+
};
|
|
23
|
+
const segments = points.slice(1).map((to, segment) => ({
|
|
24
|
+
from: points[segment],
|
|
25
|
+
to,
|
|
26
|
+
segment
|
|
27
|
+
})).sort((a, b) => length(b.from, b.to) - length(a.from, a.to) || a.segment - b.segment);
|
|
28
|
+
for (const {
|
|
29
|
+
from,
|
|
30
|
+
to
|
|
31
|
+
} of segments) {
|
|
32
|
+
const horizontal = from.y === to.y;
|
|
33
|
+
for (const t of FRACTIONS) {
|
|
34
|
+
const at = {
|
|
35
|
+
x: from.x + (to.x - from.x) * t,
|
|
36
|
+
y: from.y + (to.y - from.y) * t
|
|
37
|
+
};
|
|
38
|
+
if (label && badge) {
|
|
39
|
+
const along = ({
|
|
40
|
+
w,
|
|
41
|
+
h
|
|
42
|
+
}) => horizontal ? w : h;
|
|
43
|
+
const half = (along(label) + LAYOUT_TOKENS.LABEL_GAP + along(badge)) / 2;
|
|
44
|
+
for (const first of [-1, 1]) {
|
|
45
|
+
const labelBox = freeLabel(label, shift(at, horizontal, first * (half - along(label) / 2)), horizontal);
|
|
46
|
+
const badgeBox = freeBadge(badge, shift(at, horizontal, -first * (half - along(badge) / 2)));
|
|
47
|
+
if (labelBox && badgeBox) return {
|
|
48
|
+
label: labelBox,
|
|
49
|
+
badge: badgeBox
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
} else if (label) {
|
|
53
|
+
const labelBox = freeLabel(label, at, horizontal);
|
|
54
|
+
if (labelBox) return {
|
|
55
|
+
label: labelBox
|
|
56
|
+
};
|
|
57
|
+
} else if (badge) {
|
|
58
|
+
const badgeBox = freeBadge(badge, at);
|
|
59
|
+
if (badgeBox) return {
|
|
60
|
+
badge: badgeBox
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
function beside({
|
|
68
|
+
w,
|
|
69
|
+
h
|
|
70
|
+
}, at, horizontal) {
|
|
71
|
+
const gap = LAYOUT_TOKENS.LABEL_GAP;
|
|
72
|
+
if (horizontal) {
|
|
73
|
+
return [{
|
|
74
|
+
x: at.x - w / 2,
|
|
75
|
+
y: at.y - gap - h,
|
|
76
|
+
w,
|
|
77
|
+
h
|
|
78
|
+
}, {
|
|
79
|
+
x: at.x - w / 2,
|
|
80
|
+
y: at.y + gap,
|
|
81
|
+
w,
|
|
82
|
+
h
|
|
83
|
+
}];
|
|
84
|
+
}
|
|
85
|
+
return [{
|
|
86
|
+
x: at.x + gap,
|
|
87
|
+
y: at.y - h / 2,
|
|
88
|
+
w,
|
|
89
|
+
h
|
|
90
|
+
}, {
|
|
91
|
+
x: at.x - gap - w,
|
|
92
|
+
y: at.y - h / 2,
|
|
93
|
+
w,
|
|
94
|
+
h
|
|
95
|
+
}];
|
|
96
|
+
}
|
|
97
|
+
function on({
|
|
98
|
+
w,
|
|
99
|
+
h
|
|
100
|
+
}, at) {
|
|
101
|
+
return {
|
|
102
|
+
x: at.x - w / 2,
|
|
103
|
+
y: at.y - h / 2,
|
|
104
|
+
w,
|
|
105
|
+
h
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function shift(at, horizontal, by) {
|
|
109
|
+
return horizontal ? {
|
|
110
|
+
x: at.x + by,
|
|
111
|
+
y: at.y
|
|
112
|
+
} : {
|
|
113
|
+
x: at.x,
|
|
114
|
+
y: at.y + by
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
function length(a, b) {
|
|
118
|
+
return Math.abs(a.x - b.x) + Math.abs(a.y - b.y);
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=labels.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"labels.js","names":["LAYOUT_TOKENS","FRACTIONS","tagPosition","tags","points","isFree","label","badge","freeLabel","size","at","horizontal","beside","find","box","freeBadge","on","undefined","segments","slice","map","to","segment","from","sort","a","b","length","y","t","x","along","w","h","half","LABEL_GAP","first","labelBox","shift","badgeBox","gap","by","Math","abs"],"sources":["../../../../src/lib/layouts/graph/labels.ts"],"sourcesContent":["import type { Box, Point } from '../../model/diagram-ir.ts';\nimport { LAYOUT_TOKENS } from './tokens.ts';\n\n/** Where along a segment the tags are tried, in order. */\nconst FRACTIONS = [0.5, 0.3, 0.7, 0.15, 0.85];\n\ntype Size = { w: number; h: number };\n\nexport type TagKind = 'label' | 'badge';\n\n/**\n * The first free position for an edge's tags on its route: the longest\n * segment first, and on each segment the fractions in FRACTIONS order. A\n * label sits LABEL_GAP beside the segment (above, then below a horizontal\n * one; right, then left of a vertical one). A badge sits centred on it. An\n * edge with both puts them in a row along the segment, LABEL_GAP apart and\n * centred on the fraction: the label first, then the badge first.\n */\nexport function tagPosition(\n tags: { label?: Size; badge?: Size },\n points: Point[],\n isFree: (box: Box, kind: TagKind) => boolean,\n): { label?: Box; badge?: Box } | undefined {\n const { label, badge } = tags;\n const freeLabel = (size: Size, at: Point, horizontal: boolean) =>\n beside(size, at, horizontal).find((box) => isFree(box, 'label'));\n const freeBadge = (size: Size, at: Point) => {\n const box = on(size, at);\n return isFree(box, 'badge') ? box : undefined;\n };\n const segments = points\n .slice(1)\n .map((to, segment) => ({ from: points[segment]!, to, segment }))\n .sort(\n (a, b) =>\n length(b.from, b.to) - length(a.from, a.to) || a.segment - b.segment,\n );\n for (const { from, to } of segments) {\n const horizontal = from.y === to.y;\n for (const t of FRACTIONS) {\n const at = {\n x: from.x + (to.x - from.x) * t,\n y: from.y + (to.y - from.y) * t,\n };\n if (label && badge) {\n const along = ({ w, h }: Size) => (horizontal ? w : h);\n const half =\n (along(label) + LAYOUT_TOKENS.LABEL_GAP + along(badge)) / 2;\n for (const first of [-1, 1]) {\n const labelBox = freeLabel(\n label,\n shift(at, horizontal, first * (half - along(label) / 2)),\n horizontal,\n );\n const badgeBox = freeBadge(\n badge,\n shift(at, horizontal, -first * (half - along(badge) / 2)),\n );\n if (labelBox && badgeBox) return { label: labelBox, badge: badgeBox };\n }\n } else if (label) {\n const labelBox = freeLabel(label, at, horizontal);\n if (labelBox) return { label: labelBox };\n } else if (badge) {\n const badgeBox = freeBadge(badge, at);\n if (badgeBox) return { badge: badgeBox };\n }\n }\n }\n return undefined;\n}\n\nfunction beside({ w, h }: Size, at: Point, horizontal: boolean): Box[] {\n const gap = LAYOUT_TOKENS.LABEL_GAP;\n if (horizontal) {\n return [\n { x: at.x - w / 2, y: at.y - gap - h, w, h },\n { x: at.x - w / 2, y: at.y + gap, w, h },\n ];\n }\n return [\n { x: at.x + gap, y: at.y - h / 2, w, h },\n { x: at.x - gap - w, y: at.y - h / 2, w, h },\n ];\n}\n\nfunction on({ w, h }: Size, at: Point): Box {\n return { x: at.x - w / 2, y: at.y - h / 2, w, h };\n}\n\nfunction shift(at: Point, horizontal: boolean, by: number): Point {\n return horizontal ? { x: at.x + by, y: at.y } : { x: at.x, y: at.y + by };\n}\n\nfunction length(a: Point, b: Point): number {\n return Math.abs(a.x - b.x) + Math.abs(a.y - b.y);\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -4,7 +4,7 @@ import type { GraphLayout } from './graph-layout-result.ts';
|
|
|
4
4
|
* Lays out a graph on a content-sized grid: it measures every node, sizes
|
|
5
5
|
* each row and column to the content in it, and reserves the chrome of the
|
|
6
6
|
* groups in the gutters between them. It throws when the grid cannot be
|
|
7
|
-
* drawn without overlap.
|
|
7
|
+
* drawn without overlap, or when an id or an edge end is wrong.
|
|
8
8
|
*/
|
|
9
9
|
export declare function layoutGraph(ir: DiagramGraphIR): GraphLayout;
|
|
10
10
|
//# sourceMappingURL=layout.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../../src/lib/layouts/graph/layout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAO,cAAc,EAAS,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../../../src/lib/layouts/graph/layout.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAO,cAAc,EAAS,MAAM,2BAA2B,CAAC;AAG5E,OAAO,KAAK,EACV,WAAW,EAGZ,MAAM,0BAA0B,CAAC;AAclC;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,EAAE,EAAE,cAAc,GAAG,WAAW,CAqE3D"}
|