@zukhruf/diagram 0.3.31 → 0.3.33

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.
Files changed (60) hide show
  1. package/dist/lib/layouts/graph/areas.js +17 -8
  2. package/dist/lib/layouts/graph/areas.js.map +1 -1
  3. package/dist/lib/layouts/graph/attach.d.ts +25 -0
  4. package/dist/lib/layouts/graph/attach.d.ts.map +1 -0
  5. package/dist/lib/layouts/graph/attach.js +216 -0
  6. package/dist/lib/layouts/graph/attach.js.map +1 -0
  7. package/dist/lib/layouts/graph/connections.d.ts +38 -0
  8. package/dist/lib/layouts/graph/connections.d.ts.map +1 -0
  9. package/dist/lib/layouts/graph/connections.js +112 -0
  10. package/dist/lib/layouts/graph/connections.js.map +1 -0
  11. package/dist/lib/layouts/graph/graph-layout-result.d.ts +1 -1
  12. package/dist/lib/layouts/graph/graph-layout-result.d.ts.map +1 -1
  13. package/dist/lib/layouts/graph/graph-layout-result.js.map +1 -1
  14. package/dist/lib/layouts/graph/gutters.d.ts +1 -2
  15. package/dist/lib/layouts/graph/gutters.d.ts.map +1 -1
  16. package/dist/lib/layouts/graph/gutters.js +20 -19
  17. package/dist/lib/layouts/graph/gutters.js.map +1 -1
  18. package/dist/lib/layouts/graph/labels.d.ts +16 -0
  19. package/dist/lib/layouts/graph/labels.d.ts.map +1 -0
  20. package/dist/lib/layouts/graph/labels.js +76 -0
  21. package/dist/lib/layouts/graph/labels.js.map +1 -0
  22. package/dist/lib/layouts/graph/layout.d.ts.map +1 -1
  23. package/dist/lib/layouts/graph/layout.js +34 -13
  24. package/dist/lib/layouts/graph/layout.js.map +1 -1
  25. package/dist/lib/layouts/graph/measure.d.ts +7 -6
  26. package/dist/lib/layouts/graph/measure.d.ts.map +1 -1
  27. package/dist/lib/layouts/graph/measure.js +35 -29
  28. package/dist/lib/layouts/graph/measure.js.map +1 -1
  29. package/dist/lib/layouts/graph/min-heap.d.ts +12 -0
  30. package/dist/lib/layouts/graph/min-heap.d.ts.map +1 -0
  31. package/dist/lib/layouts/graph/min-heap.js +60 -0
  32. package/dist/lib/layouts/graph/min-heap.js.map +1 -0
  33. package/dist/lib/layouts/graph/node-content.d.ts +1 -2
  34. package/dist/lib/layouts/graph/node-content.d.ts.map +1 -1
  35. package/dist/lib/layouts/graph/node-content.js +43 -42
  36. package/dist/lib/layouts/graph/node-content.js.map +1 -1
  37. package/dist/lib/layouts/graph/path.d.ts +14 -0
  38. package/dist/lib/layouts/graph/path.d.ts.map +1 -0
  39. package/dist/lib/layouts/graph/path.js +55 -0
  40. package/dist/lib/layouts/graph/path.js.map +1 -0
  41. package/dist/lib/layouts/graph/route-search.d.ts +34 -0
  42. package/dist/lib/layouts/graph/route-search.d.ts.map +1 -0
  43. package/dist/lib/layouts/graph/route-search.js +208 -0
  44. package/dist/lib/layouts/graph/route-search.js.map +1 -0
  45. package/dist/lib/layouts/graph/route.d.ts +16 -0
  46. package/dist/lib/layouts/graph/route.d.ts.map +1 -0
  47. package/dist/lib/layouts/graph/route.js +241 -0
  48. package/dist/lib/layouts/graph/route.js.map +1 -0
  49. package/dist/lib/layouts/graph/sides.d.ts +23 -0
  50. package/dist/lib/layouts/graph/sides.d.ts.map +1 -0
  51. package/dist/lib/layouts/graph/sides.js +91 -0
  52. package/dist/lib/layouts/graph/sides.js.map +1 -0
  53. package/dist/lib/layouts/graph/tokens.d.ts +2 -7
  54. package/dist/lib/layouts/graph/tokens.d.ts.map +1 -1
  55. package/dist/lib/layouts/graph/tokens.js +91 -104
  56. package/dist/lib/layouts/graph/tokens.js.map +1 -1
  57. package/dist/lib/model/diagram-ir.d.ts +0 -3
  58. package/dist/lib/model/diagram-ir.d.ts.map +1 -1
  59. package/dist/lib/model/diagram-ir.js.map +1 -1
  60. package/package.json +1 -1
@@ -0,0 +1,241 @@
1
+ import { attachConnections } from "./attach.js";
2
+ import { graphConnections } from "./connections.js";
3
+ import { tagPosition } from "./labels.js";
4
+ import { measureEdgeBadge, measureEdgeLabel } from "./measure.js";
5
+ import { pathToSvg, simplifyPath } from "./path.js";
6
+ import { searchRoute } from "./route-search.js";
7
+ import { OPPOSITE, OUTWARD } from "./sides.js";
8
+ import { LAYOUT_TOKENS } from "./tokens.js";
9
+
10
+ /** How far around the content a route may detour. */
11
+ const ROUTING_MARGIN = 64;
12
+ /** How far a route keeps from a node that it does not connect. */
13
+ const NODE_CLEARANCE = 8;
14
+ /**
15
+ * Routes every edge and note leader orthogonally, nearest cells first, and
16
+ * places each edge's label and badge before the next edge routes around
17
+ * them. It throws when a route or a label has no room; it never draws a
18
+ * diagonal or straight line through what is in the way.
19
+ */
20
+ export function routeGraph(ir, nodes, groups, areas, /** How far beyond the bounding box of its two shapes a route first searches. */
21
+ searchMargin) {
22
+ const connections = graphConnections(ir, nodes, groups, areas);
23
+ if (connections.length === 0) return {
24
+ edges: [],
25
+ leaders: []
26
+ };
27
+ const groupLabels = groups.flatMap(({
28
+ group,
29
+ label
30
+ }) => label.map(run => ({
31
+ group: group.id,
32
+ box: inflate(run.bounds, LAYOUT_TOKENS.LABEL_GAP)
33
+ })));
34
+ const attachments = attachConnections(connections, groupLabels);
35
+ const content = union([...nodes.map(nodeLayout => nodeLayout.visual), ...groups.map(groupLayout => groupLayout.rect)]);
36
+ const bounds = inflate(content, ROUTING_MARGIN);
37
+ const solid = nodes.filter(({
38
+ box
39
+ }) => box.w > 0 && box.h > 0);
40
+ const routed = [];
41
+ const tags = [];
42
+ const paths = new Map();
43
+ const labels = new Map();
44
+ const order = connections.map((connection, index) => ({
45
+ connection,
46
+ index
47
+ })).sort((a, b) => Number(a.connection.edge === undefined) - Number(b.connection.edge === undefined) || a.connection.cellDistance - b.connection.cellDistance || a.index - b.index);
48
+ for (const {
49
+ connection,
50
+ index
51
+ } of order) {
52
+ const {
53
+ from,
54
+ to
55
+ } = connection;
56
+ const ends = new Set([from.shape.id, to.shape.id]);
57
+ const junctions = new Set([from, to].filter(end => end.shape.kind === 'junction').map(end => end.shape.id));
58
+ const walls = [...solid.flatMap(({
59
+ node,
60
+ box,
61
+ visual,
62
+ frames,
63
+ caption
64
+ }) => {
65
+ if (!ends.has(node.id)) return [inflate(visual, NODE_CLEARANCE)];
66
+ if (node.kind === 'junction') return [];
67
+ // Its own parts, not their bounding box: a caption wider than the frame leaves room beside the frame.
68
+ return [box, ...frames, ...(caption ? [caption.box] : [])];
69
+ }), ...groupLabels.flatMap(({
70
+ group,
71
+ box
72
+ }) => ends.has(group) ? [] : [box]), ...tags.map(tag => inflate(tag, LAYOUT_TOKENS.LABEL_GAP))];
73
+ const runs = routed.filter(route => !overlaps(route.junctions, junctions)).flatMap(route => segments(route.points));
74
+ const {
75
+ start,
76
+ startStub,
77
+ end,
78
+ endStub
79
+ } = attachments[index];
80
+ const stubs = [[start, startStub], [endStub, end]];
81
+ const stubsClear = stubs.every(([a, b]) => walls.every(wall => !crosses(a, b, wall)));
82
+ const search = window => searchRoute({
83
+ window,
84
+ lines: {
85
+ x: [startStub.x, endStub.x],
86
+ y: [startStub.y, endStub.y]
87
+ },
88
+ walls,
89
+ runs,
90
+ borders: groups.flatMap(({
91
+ rect,
92
+ band
93
+ }) => band ? [rect, band] : [rect]),
94
+ start: startStub,
95
+ startHeading: OUTWARD[from.side],
96
+ goal: endStub,
97
+ goalHeading: OUTWARD[OPPOSITE[to.side]]
98
+ });
99
+ const near = intersection(inflate(union([from.shape.box, to.shape.box, spanOf(startStub, endStub)]), searchMargin), bounds);
100
+ const found = stubsClear ? search(near) ?? search(bounds) : undefined;
101
+ if (!found) {
102
+ const advice = connection.edge === undefined ? 'Move the note or its target.' : 'Change exitSide/entrySide or move a node.';
103
+ throw new Error(`Diagram ${connection.name}: no orthogonal route from ${endName(from)} to ${endName(to)} avoids the nodes and labels. ${advice}`);
104
+ }
105
+ const points = simplifyPath([start, ...found, end]);
106
+ paths.set(connection, points);
107
+ if (connection.edge !== undefined) {
108
+ const edge = ir.edges[connection.edge];
109
+ const isFree = (box, ownSegments) => solid.every(({
110
+ visual
111
+ }) => !intersects(box, visual)) && groups.every(({
112
+ rect,
113
+ band,
114
+ label
115
+ }) => !(band && intersects(box, band)) && label.every(run => !intersects(box, run.bounds)) && !(intersects(box, rect) && !contains(rect, box))) && tags.every(tag => !intersects(box, tag)) && [...routed.flatMap(route => segments(route.points)), ...(ownSegments ? segments(points) : [])].every(([a, b]) => !crosses(a, b, box));
116
+ const placed = {};
117
+ if (edge.label?.length) {
118
+ const measured = measureEdgeLabel(edge);
119
+ const position = tagPosition(measured, points, 'beside', box => isFree(box, true));
120
+ if (!position) {
121
+ throw new Error(`Diagram ${connection.name}: label "${edge.label.join(' / ')}" (${Math.ceil(measured.w)}×${Math.ceil(measured.h)}) has no free position beside its route.`);
122
+ }
123
+ placed.label = {
124
+ ...position,
125
+ text: measured.place(position.box)
126
+ };
127
+ tags.push(position.box);
128
+ }
129
+ if (edge.badgeIcon || edge.badgeLabel?.length) {
130
+ const measured = measureEdgeBadge(edge);
131
+ const position = tagPosition(measured, points, 'on', box => isFree(box, false));
132
+ if (!position) {
133
+ throw new Error(`Diagram ${connection.name}: badge "${(edge.badgeLabel ?? []).join(' / ')}" (${Math.ceil(measured.w)}×${Math.ceil(measured.h)}) has no free position on its route.`);
134
+ }
135
+ placed.badge = {
136
+ box: position.box,
137
+ ...measured.place(position.box)
138
+ };
139
+ tags.push(position.box);
140
+ }
141
+ labels.set(connection, placed);
142
+ }
143
+ routed.push({
144
+ points,
145
+ junctions
146
+ });
147
+ }
148
+ const edges = [];
149
+ const leaders = [];
150
+ for (const connection of connections) {
151
+ const points = paths.get(connection);
152
+ if (connection.edge === undefined) {
153
+ leaders.push({
154
+ note: connection.from.shape.id,
155
+ target: connection.to.shape.id,
156
+ points,
157
+ d: pathToSvg(points)
158
+ });
159
+ continue;
160
+ }
161
+ edges.push({
162
+ edge: ir.edges[connection.edge],
163
+ exitSide: connection.from.side,
164
+ entrySide: connection.to.side,
165
+ points,
166
+ d: pathToSvg(points),
167
+ ...labels.get(connection)
168
+ });
169
+ }
170
+ return {
171
+ edges,
172
+ leaders
173
+ };
174
+ }
175
+ function endName({
176
+ shape,
177
+ side,
178
+ port
179
+ }) {
180
+ if (port) return `port "${shape.id}:${port.id}"`;
181
+ if (shape.kind === 'junction') return `the centre of "${shape.id}"`;
182
+ return `${side} of "${shape.id}"`;
183
+ }
184
+ function segments(points) {
185
+ return points.slice(1).map((point, index) => [points[index], point]);
186
+ }
187
+ function overlaps(a, b) {
188
+ for (const id of a) if (b.has(id)) return true;
189
+ return false;
190
+ }
191
+ function spanOf(a, b) {
192
+ return {
193
+ x: Math.min(a.x, b.x),
194
+ y: Math.min(a.y, b.y),
195
+ w: Math.abs(a.x - b.x),
196
+ h: Math.abs(a.y - b.y)
197
+ };
198
+ }
199
+
200
+ /** Whether the segment enters the box's interior, not only its border. */
201
+ function crosses(a, b, box) {
202
+ const span = spanOf(a, b);
203
+ return span.x + span.w > box.x && span.x < box.x + box.w && span.y + span.h > box.y && span.y < box.y + box.h;
204
+ }
205
+ function intersects(a, b) {
206
+ return a.x < b.x + b.w && b.x < a.x + a.w && a.y < b.y + b.h && b.y < a.y + a.h;
207
+ }
208
+ function contains(outer, inner) {
209
+ return inner.x >= outer.x && inner.y >= outer.y && inner.x + inner.w <= outer.x + outer.w && inner.y + inner.h <= outer.y + outer.h;
210
+ }
211
+ function inflate(box, by) {
212
+ return {
213
+ x: box.x - by,
214
+ y: box.y - by,
215
+ w: box.w + 2 * by,
216
+ h: box.h + 2 * by
217
+ };
218
+ }
219
+ function intersection(a, b) {
220
+ const x = Math.max(a.x, b.x);
221
+ const y = Math.max(a.y, b.y);
222
+ return {
223
+ x,
224
+ y,
225
+ w: Math.min(a.x + a.w, b.x + b.w) - x,
226
+ h: Math.min(a.y + a.h, b.y + b.h) - y
227
+ };
228
+ }
229
+ function union(boxes) {
230
+ const left = Math.min(...boxes.map(box => box.x));
231
+ const top = Math.min(...boxes.map(box => box.y));
232
+ const right = Math.max(...boxes.map(box => box.x + box.w));
233
+ const bottom = Math.max(...boxes.map(box => box.y + box.h));
234
+ return {
235
+ x: left,
236
+ y: top,
237
+ w: right - left,
238
+ h: bottom - top
239
+ };
240
+ }
241
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route.js","names":["attachConnections","graphConnections","tagPosition","measureEdgeBadge","measureEdgeLabel","pathToSvg","simplifyPath","searchRoute","OPPOSITE","OUTWARD","LAYOUT_TOKENS","ROUTING_MARGIN","NODE_CLEARANCE","routeGraph","ir","nodes","groups","areas","searchMargin","connections","length","edges","leaders","groupLabels","flatMap","group","label","map","run","id","box","inflate","bounds","LABEL_GAP","attachments","content","union","nodeLayout","visual","groupLayout","rect","solid","filter","w","h","routed","tags","paths","Map","labels","order","connection","index","sort","a","b","Number","edge","undefined","cellDistance","from","to","ends","Set","shape","junctions","end","kind","walls","node","frames","caption","has","tag","runs","route","overlaps","segments","points","start","startStub","endStub","stubs","stubsClear","every","wall","crosses","search","window","lines","x","y","borders","band","startHeading","side","goal","goalHeading","near","intersection","spanOf","found","advice","Error","name","endName","set","isFree","ownSegments","intersects","contains","placed","measured","position","join","Math","ceil","text","place","push","badgeIcon","badgeLabel","badge","get","note","target","d","exitSide","entrySide","port","slice","point","min","abs","span","outer","inner","by","max","boxes","left","top","right","bottom"],"sources":["../../../../src/lib/layouts/graph/route.ts"],"sourcesContent":["import type { Box, DiagramGraphIR, Point } from '../../model/diagram-ir.ts';\nimport type { GridAreas } from './areas.ts';\nimport { attachConnections } from './attach.ts';\nimport {\n type Connection,\n type ConnectionEnd,\n graphConnections,\n} from './connections.ts';\nimport type {\n EdgeLayout,\n GroupLayout,\n LeaderLayout,\n NodeLayout,\n} from './graph-layout-result.ts';\nimport { tagPosition } from './labels.ts';\nimport { measureEdgeBadge, measureEdgeLabel } from './measure.ts';\nimport { pathToSvg, simplifyPath } from './path.ts';\nimport { searchRoute } from './route-search.ts';\nimport { OPPOSITE, OUTWARD } from './sides.ts';\nimport { LAYOUT_TOKENS } from './tokens.ts';\n\n/** How far around the content a route may detour. */\nconst ROUTING_MARGIN = 64;\n/** How far a route keeps from a node that it does not connect. */\nconst NODE_CLEARANCE = 8;\n\ntype Routed = {\n points: Point[];\n /** The junctions the route ends at: routes that share one may run together into it. */\n junctions: Set<string>;\n};\n\n/**\n * Routes every edge and note leader orthogonally, nearest cells first, and\n * places each edge's label and badge before the next edge routes around\n * them. It throws when a route or a label has no room; it never draws a\n * diagonal or straight line through what is in the way.\n */\nexport function routeGraph(\n ir: DiagramGraphIR,\n nodes: NodeLayout[],\n groups: GroupLayout[],\n areas: GridAreas,\n /** How far beyond the bounding box of its two shapes a route first searches. */\n searchMargin: number,\n): { edges: EdgeLayout[]; leaders: LeaderLayout[] } {\n const connections = graphConnections(ir, nodes, groups, areas);\n if (connections.length === 0) return { edges: [], leaders: [] };\n const groupLabels = groups.flatMap(({ group, label }) =>\n label.map((run) => ({\n group: group.id,\n box: inflate(run.bounds, LAYOUT_TOKENS.LABEL_GAP),\n })),\n );\n const attachments = attachConnections(connections, groupLabels);\n const content = union([\n ...nodes.map((nodeLayout) => nodeLayout.visual),\n ...groups.map((groupLayout) => groupLayout.rect),\n ]);\n const bounds = inflate(content, ROUTING_MARGIN);\n const solid = nodes.filter(({ box }) => box.w > 0 && box.h > 0);\n\n const routed: Routed[] = [];\n const tags: Box[] = [];\n const paths = new Map<Connection, Point[]>();\n const labels = new Map<Connection, Pick<EdgeLayout, 'label' | 'badge'>>();\n\n const order = connections\n .map((connection, index) => ({ connection, index }))\n .sort(\n (a, b) =>\n Number(a.connection.edge === undefined) -\n Number(b.connection.edge === undefined) ||\n a.connection.cellDistance - b.connection.cellDistance ||\n a.index - b.index,\n );\n\n for (const { connection, index } of order) {\n const { from, to } = connection;\n const ends = new Set([from.shape.id, to.shape.id]);\n const junctions = new Set(\n [from, to]\n .filter((end) => end.shape.kind === 'junction')\n .map((end) => end.shape.id),\n );\n const walls = [\n ...solid.flatMap(({ node, box, visual, frames, caption }) => {\n if (!ends.has(node.id)) return [inflate(visual, NODE_CLEARANCE)];\n if (node.kind === 'junction') return [];\n // Its own parts, not their bounding box: a caption wider than the frame leaves room beside the frame.\n return [box, ...frames, ...(caption ? [caption.box] : [])];\n }),\n ...groupLabels.flatMap(({ group, box }) =>\n ends.has(group) ? [] : [box],\n ),\n ...tags.map((tag) => inflate(tag, LAYOUT_TOKENS.LABEL_GAP)),\n ];\n const runs = routed\n .filter((route) => !overlaps(route.junctions, junctions))\n .flatMap((route) => segments(route.points));\n const { start, startStub, end, endStub } = attachments[index]!;\n const stubs: [Point, Point][] = [\n [start, startStub],\n [endStub, end],\n ];\n const stubsClear = stubs.every(([a, b]) =>\n walls.every((wall) => !crosses(a, b, wall)),\n );\n\n const search = (window: Box): Point[] | undefined =>\n searchRoute({\n window,\n lines: {\n x: [startStub.x, endStub.x],\n y: [startStub.y, endStub.y],\n },\n walls,\n runs,\n borders: groups.flatMap(({ rect, band }) =>\n band ? [rect, band] : [rect],\n ),\n start: startStub,\n startHeading: OUTWARD[from.side],\n goal: endStub,\n goalHeading: OUTWARD[OPPOSITE[to.side]],\n });\n const near = intersection(\n inflate(\n union([from.shape.box, to.shape.box, spanOf(startStub, endStub)]),\n searchMargin,\n ),\n bounds,\n );\n const found = stubsClear ? (search(near) ?? search(bounds)) : undefined;\n if (!found) {\n const advice =\n connection.edge === undefined\n ? 'Move the note or its target.'\n : 'Change exitSide/entrySide or move a node.';\n throw new Error(\n `Diagram ${connection.name}: no orthogonal route from ${endName(from)} to ${endName(to)} avoids the nodes and labels. ${advice}`,\n );\n }\n const points = simplifyPath([start, ...found, end]);\n paths.set(connection, points);\n\n if (connection.edge !== undefined) {\n const edge = ir.edges[connection.edge]!;\n const isFree = (box: Box, ownSegments: boolean) =>\n solid.every(({ visual }) => !intersects(box, visual)) &&\n groups.every(\n ({ rect, band, label }) =>\n !(band && intersects(box, band)) &&\n label.every((run) => !intersects(box, run.bounds)) &&\n !(intersects(box, rect) && !contains(rect, box)),\n ) &&\n tags.every((tag) => !intersects(box, tag)) &&\n [\n ...routed.flatMap((route) => segments(route.points)),\n ...(ownSegments ? segments(points) : []),\n ].every(([a, b]) => !crosses(a, b, box));\n const placed: Pick<EdgeLayout, 'label' | 'badge'> = {};\n if (edge.label?.length) {\n const measured = measureEdgeLabel(edge);\n const position = tagPosition(measured, points, 'beside', (box) =>\n isFree(box, true),\n );\n if (!position) {\n throw new Error(\n `Diagram ${connection.name}: label \"${edge.label.join(' / ')}\" (${Math.ceil(measured.w)}×${Math.ceil(measured.h)}) has no free position beside its route.`,\n );\n }\n placed.label = { ...position, text: measured.place(position.box) };\n tags.push(position.box);\n }\n if (edge.badgeIcon || edge.badgeLabel?.length) {\n const measured = measureEdgeBadge(edge);\n const position = tagPosition(measured, points, 'on', (box) =>\n isFree(box, false),\n );\n if (!position) {\n throw new Error(\n `Diagram ${connection.name}: badge \"${(edge.badgeLabel ?? []).join(' / ')}\" (${Math.ceil(measured.w)}×${Math.ceil(measured.h)}) has no free position on its route.`,\n );\n }\n placed.badge = { box: position.box, ...measured.place(position.box) };\n tags.push(position.box);\n }\n labels.set(connection, placed);\n }\n routed.push({ points, junctions });\n }\n\n const edges: EdgeLayout[] = [];\n const leaders: LeaderLayout[] = [];\n for (const connection of connections) {\n const points = paths.get(connection)!;\n if (connection.edge === undefined) {\n leaders.push({\n note: connection.from.shape.id,\n target: connection.to.shape.id,\n points,\n d: pathToSvg(points),\n });\n continue;\n }\n edges.push({\n edge: ir.edges[connection.edge]!,\n exitSide: connection.from.side,\n entrySide: connection.to.side,\n points,\n d: pathToSvg(points),\n ...labels.get(connection),\n });\n }\n return { edges, leaders };\n}\n\nfunction endName({ shape, side, port }: ConnectionEnd): string {\n if (port) return `port \"${shape.id}:${port.id}\"`;\n if (shape.kind === 'junction') return `the centre of \"${shape.id}\"`;\n return `${side} of \"${shape.id}\"`;\n}\n\nfunction segments(points: Point[]): [Point, Point][] {\n return points.slice(1).map((point, index) => [points[index]!, point]);\n}\n\nfunction overlaps(a: Set<string>, b: Set<string>): boolean {\n for (const id of a) if (b.has(id)) return true;\n return false;\n}\n\nfunction spanOf(a: Point, b: Point): Box {\n return {\n x: Math.min(a.x, b.x),\n y: Math.min(a.y, b.y),\n w: Math.abs(a.x - b.x),\n h: Math.abs(a.y - b.y),\n };\n}\n\n/** Whether the segment enters the box's interior, not only its border. */\nfunction crosses(a: Point, b: Point, box: Box): boolean {\n const span = spanOf(a, b);\n return (\n span.x + span.w > box.x &&\n span.x < box.x + box.w &&\n span.y + span.h > box.y &&\n span.y < box.y + box.h\n );\n}\n\nfunction intersects(a: Box, b: Box): boolean {\n return (\n a.x < b.x + b.w && b.x < a.x + a.w && a.y < b.y + b.h && b.y < a.y + a.h\n );\n}\n\nfunction contains(outer: Box, inner: Box): boolean {\n return (\n inner.x >= outer.x &&\n inner.y >= outer.y &&\n inner.x + inner.w <= outer.x + outer.w &&\n inner.y + inner.h <= outer.y + outer.h\n );\n}\n\nfunction inflate(box: Box, by: number): Box {\n return { x: box.x - by, y: box.y - by, w: box.w + 2 * by, h: box.h + 2 * by };\n}\n\nfunction intersection(a: Box, b: Box): Box {\n const x = Math.max(a.x, b.x);\n const y = Math.max(a.y, b.y);\n return {\n x,\n y,\n w: Math.min(a.x + a.w, b.x + b.w) - x,\n h: Math.min(a.y + a.h, b.y + b.h) - y,\n };\n}\n\nfunction union(boxes: Box[]): Box {\n const left = Math.min(...boxes.map((box) => box.x));\n const top = Math.min(...boxes.map((box) => box.y));\n const right = Math.max(...boxes.map((box) => box.x + box.w));\n const bottom = Math.max(...boxes.map((box) => box.y + box.h));\n return { x: left, y: top, w: right - left, h: bottom - top };\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,23 @@
1
+ import type { Box, DiagramSide, Point } from '../../model/diagram-ir.ts';
2
+ import type { CellArea } from './areas.ts';
3
+ import type { Heading } from './route-search.ts';
4
+ export declare const OPPOSITE: Record<DiagramSide, DiagramSide>;
5
+ /** The heading of a line that leaves a box through `side`. */
6
+ export declare const OUTWARD: Record<DiagramSide, Heading>;
7
+ export declare function isVertical(side: DiagramSide): boolean;
8
+ /**
9
+ * The sides a connection leaves and enters by, read from the cells: areas
10
+ * that share rows face left and right, areas that share columns face top
11
+ * and bottom, and otherwise the axis with the larger cell delta wins, the
12
+ * vertical one on a tie.
13
+ */
14
+ export declare function facingSides(from: CellArea, to: CellArea): [DiagramSide, DiagramSide];
15
+ /** The coordinate of the side's line: x for left and right, y for top and bottom. */
16
+ export declare function sideLine(box: Box, side: DiagramSide): number;
17
+ /** Where the side runs along its line: [start, end] in x for top and bottom, in y for left and right. */
18
+ export declare function sideSpan(box: Box, side: DiagramSide): [number, number];
19
+ /** The point on `side` of `box` at `along` on the side's span. */
20
+ export declare function pointOnSide(box: Box, side: DiagramSide, along: number): Point;
21
+ /** The point `distance` beyond `point` out of `side`. */
22
+ export declare function beyond(point: Point, side: DiagramSide, distance: number): Point;
23
+ //# sourceMappingURL=sides.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sides.d.ts","sourceRoot":"","sources":["../../../../src/lib/layouts/graph/sides.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AACzE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjD,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,WAAW,EAAE,WAAW,CAKrD,CAAC;AAEF,8DAA8D;AAC9D,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,WAAW,EAAE,OAAO,CAKhD,CAAC;AAEF,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAErD;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CACzB,IAAI,EAAE,QAAQ,EACd,EAAE,EAAE,QAAQ,GACX,CAAC,WAAW,EAAE,WAAW,CAAC,CAa5B;AAED,qFAAqF;AACrF,wBAAgB,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,WAAW,GAAG,MAAM,CAW5D;AAED,yGAAyG;AACzG,wBAAgB,QAAQ,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,WAAW,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAEtE;AAED,kEAAkE;AAClE,wBAAgB,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,KAAK,CAG7E;AAED,yDAAyD;AACzD,wBAAgB,MAAM,CACpB,KAAK,EAAE,KAAK,EACZ,IAAI,EAAE,WAAW,EACjB,QAAQ,EAAE,MAAM,GACf,KAAK,CAWP"}
@@ -0,0 +1,91 @@
1
+ export const OPPOSITE = {
2
+ top: 'bottom',
3
+ bottom: 'top',
4
+ left: 'right',
5
+ right: 'left'
6
+ };
7
+
8
+ /** The heading of a line that leaves a box through `side`. */
9
+ export const OUTWARD = {
10
+ right: 0,
11
+ left: 1,
12
+ bottom: 2,
13
+ top: 3
14
+ };
15
+ export function isVertical(side) {
16
+ return side === 'top' || side === 'bottom';
17
+ }
18
+
19
+ /**
20
+ * The sides a connection leaves and enters by, read from the cells: areas
21
+ * that share rows face left and right, areas that share columns face top
22
+ * and bottom, and otherwise the axis with the larger cell delta wins, the
23
+ * vertical one on a tie.
24
+ */
25
+ export function facingSides(from, to) {
26
+ const shareRows = Math.max(from.row, to.row) < Math.min(from.row + from.rowSpan, to.row + to.rowSpan);
27
+ const shareCols = Math.max(from.col, to.col) < Math.min(from.col + from.colSpan, to.col + to.colSpan);
28
+ const dr = to.row + to.rowSpan / 2 - (from.row + from.rowSpan / 2);
29
+ const dc = to.col + to.colSpan / 2 - (from.col + from.colSpan / 2);
30
+ const horizontal = shareRows !== shareCols ? shareRows : Math.abs(dc) > Math.abs(dr);
31
+ if (horizontal) return dc > 0 ? ['right', 'left'] : ['left', 'right'];
32
+ return dr >= 0 ? ['bottom', 'top'] : ['top', 'bottom'];
33
+ }
34
+
35
+ /** The coordinate of the side's line: x for left and right, y for top and bottom. */
36
+ export function sideLine(box, side) {
37
+ switch (side) {
38
+ case 'top':
39
+ return box.y;
40
+ case 'bottom':
41
+ return box.y + box.h;
42
+ case 'left':
43
+ return box.x;
44
+ case 'right':
45
+ return box.x + box.w;
46
+ }
47
+ }
48
+
49
+ /** Where the side runs along its line: [start, end] in x for top and bottom, in y for left and right. */
50
+ export function sideSpan(box, side) {
51
+ return isVertical(side) ? [box.x, box.x + box.w] : [box.y, box.y + box.h];
52
+ }
53
+
54
+ /** The point on `side` of `box` at `along` on the side's span. */
55
+ export function pointOnSide(box, side, along) {
56
+ const line = sideLine(box, side);
57
+ return isVertical(side) ? {
58
+ x: along,
59
+ y: line
60
+ } : {
61
+ x: line,
62
+ y: along
63
+ };
64
+ }
65
+
66
+ /** The point `distance` beyond `point` out of `side`. */
67
+ export function beyond(point, side, distance) {
68
+ switch (side) {
69
+ case 'top':
70
+ return {
71
+ x: point.x,
72
+ y: point.y - distance
73
+ };
74
+ case 'bottom':
75
+ return {
76
+ x: point.x,
77
+ y: point.y + distance
78
+ };
79
+ case 'left':
80
+ return {
81
+ x: point.x - distance,
82
+ y: point.y
83
+ };
84
+ case 'right':
85
+ return {
86
+ x: point.x + distance,
87
+ y: point.y
88
+ };
89
+ }
90
+ }
91
+ //# sourceMappingURL=sides.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sides.js","names":["OPPOSITE","top","bottom","left","right","OUTWARD","isVertical","side","facingSides","from","to","shareRows","Math","max","row","min","rowSpan","shareCols","col","colSpan","dr","dc","horizontal","abs","sideLine","box","y","h","x","w","sideSpan","pointOnSide","along","line","beyond","point","distance"],"sources":["../../../../src/lib/layouts/graph/sides.ts"],"sourcesContent":["import type { Box, DiagramSide, Point } from '../../model/diagram-ir.ts';\nimport type { CellArea } from './areas.ts';\nimport type { Heading } from './route-search.ts';\n\nexport const OPPOSITE: Record<DiagramSide, DiagramSide> = {\n top: 'bottom',\n bottom: 'top',\n left: 'right',\n right: 'left',\n};\n\n/** The heading of a line that leaves a box through `side`. */\nexport const OUTWARD: Record<DiagramSide, Heading> = {\n right: 0,\n left: 1,\n bottom: 2,\n top: 3,\n};\n\nexport function isVertical(side: DiagramSide): boolean {\n return side === 'top' || side === 'bottom';\n}\n\n/**\n * The sides a connection leaves and enters by, read from the cells: areas\n * that share rows face left and right, areas that share columns face top\n * and bottom, and otherwise the axis with the larger cell delta wins, the\n * vertical one on a tie.\n */\nexport function facingSides(\n from: CellArea,\n to: CellArea,\n): [DiagramSide, DiagramSide] {\n const shareRows =\n Math.max(from.row, to.row) <\n Math.min(from.row + from.rowSpan, to.row + to.rowSpan);\n const shareCols =\n Math.max(from.col, to.col) <\n Math.min(from.col + from.colSpan, to.col + to.colSpan);\n const dr = to.row + to.rowSpan / 2 - (from.row + from.rowSpan / 2);\n const dc = to.col + to.colSpan / 2 - (from.col + from.colSpan / 2);\n const horizontal =\n shareRows !== shareCols ? shareRows : Math.abs(dc) > Math.abs(dr);\n if (horizontal) return dc > 0 ? ['right', 'left'] : ['left', 'right'];\n return dr >= 0 ? ['bottom', 'top'] : ['top', 'bottom'];\n}\n\n/** The coordinate of the side's line: x for left and right, y for top and bottom. */\nexport function sideLine(box: Box, side: DiagramSide): number {\n switch (side) {\n case 'top':\n return box.y;\n case 'bottom':\n return box.y + box.h;\n case 'left':\n return box.x;\n case 'right':\n return box.x + box.w;\n }\n}\n\n/** Where the side runs along its line: [start, end] in x for top and bottom, in y for left and right. */\nexport function sideSpan(box: Box, side: DiagramSide): [number, number] {\n return isVertical(side) ? [box.x, box.x + box.w] : [box.y, box.y + box.h];\n}\n\n/** The point on `side` of `box` at `along` on the side's span. */\nexport function pointOnSide(box: Box, side: DiagramSide, along: number): Point {\n const line = sideLine(box, side);\n return isVertical(side) ? { x: along, y: line } : { x: line, y: along };\n}\n\n/** The point `distance` beyond `point` out of `side`. */\nexport function beyond(\n point: Point,\n side: DiagramSide,\n distance: number,\n): Point {\n switch (side) {\n case 'top':\n return { x: point.x, y: point.y - distance };\n case 'bottom':\n return { x: point.x, y: point.y + distance };\n case 'left':\n return { x: point.x - distance, y: point.y };\n case 'right':\n return { x: point.x + distance, y: point.y };\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -1,4 +1,3 @@
1
- import type { DiagramDensity } from '../../model/diagram-ir.ts';
2
1
  import type { Font } from '../text/font.ts';
3
2
  export type LayoutFonts = {
4
3
  /** The title of a Card, or of a Box with an icon. */
@@ -49,10 +48,6 @@ export type LayoutTokens = {
49
48
  FLAT_RADIUS: number;
50
49
  fonts: LayoutFonts;
51
50
  };
52
- /**
53
- * The sizes the engine lays out with. Density scales only the space between
54
- * elements (gaps, channels, group and diagram padding); node content and
55
- * fonts keep their size, so text never shrinks to fit.
56
- */
57
- export declare function layoutTokens(density?: DiagramDensity): LayoutTokens;
51
+ /** The sizes the engine lays out with. */
52
+ export declare const LAYOUT_TOKENS: LayoutTokens;
58
53
  //# sourceMappingURL=tokens.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../../../src/lib/layouts/graph/tokens.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAE5C,MAAM,MAAM,WAAW,GAAG;IACxB,qDAAqD;IACrD,KAAK,EAAE,IAAI,CAAC;IACZ,sCAAsC;IACtC,IAAI,EAAE,IAAI,CAAC;IACX,OAAO,EAAE,IAAI,CAAC;IACd,2CAA2C;IAC3C,QAAQ,EAAE,IAAI,CAAC;IACf,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,IAAI,CAAC;IACb,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;IAChB,UAAU,EAAE,IAAI,CAAC;IACjB,SAAS,EAAE,IAAI,CAAC;IAChB,KAAK,EAAE,IAAI,CAAC;IACZ,SAAS,EAAE,IAAI,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,WAAW,CAAC;CACpB,CAAC;AAQF;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,OAAO,GAAE,cAA0B,GAClC,YAAY,CAyCd"}
1
+ {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../../../src/lib/layouts/graph/tokens.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAE5C,MAAM,MAAM,WAAW,GAAG;IACxB,qDAAqD;IACrD,KAAK,EAAE,IAAI,CAAC;IACZ,sCAAsC;IACtC,IAAI,EAAE,IAAI,CAAC;IACX,OAAO,EAAE,IAAI,CAAC;IACd,2CAA2C;IAC3C,QAAQ,EAAE,IAAI,CAAC;IACf,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,IAAI,CAAC;IACb,SAAS,EAAE,IAAI,CAAC;IAChB,SAAS,EAAE,IAAI,CAAC;IAChB,UAAU,EAAE,IAAI,CAAC;IACjB,SAAS,EAAE,IAAI,CAAC;IAChB,KAAK,EAAE,IAAI,CAAC;IACZ,SAAS,EAAE,IAAI,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,WAAW,CAAC;CACpB,CAAC;AAEF,0CAA0C;AAC1C,eAAO,MAAM,aAAa,EAAE,YAsC3B,CAAC"}
@@ -1,108 +1,95 @@
1
- const SPACING_SCALE = {
2
- compact: 0.75,
3
- regular: 1,
4
- spacious: 1.5
5
- };
6
-
7
- /**
8
- * The sizes the engine lays out with. Density scales only the space between
9
- * elements (gaps, channels, group and diagram padding); node content and
10
- * fonts keep their size, so text never shrinks to fit.
11
- */
12
- export function layoutTokens(density = 'regular') {
13
- const scale = SPACING_SCALE[density];
14
- return {
15
- PAD_X: 16,
16
- PAD_Y: 12,
17
- ICON: 28,
18
- ICON_GAP: 12,
19
- GAP: 24 * scale,
20
- CHANNEL: 8 * scale,
21
- STUB: 16,
22
- LABEL_GAP: 4,
23
- CONTENT_PAD: 40 * scale,
24
- GROUP_PAD: 12 * scale,
25
- BAND_PAD: 6,
26
- BULLET_INDENT: 12,
27
- BLOCK_GAP: 8,
28
- CAPTION_GAP: 8,
29
- PORT_SPACING: 24,
30
- STACK_STEP: {
31
- x: 12,
32
- y: 8
1
+ /** The sizes the engine lays out with. */
2
+ export const LAYOUT_TOKENS = {
3
+ PAD_X: 16,
4
+ PAD_Y: 12,
5
+ ICON: 28,
6
+ ICON_GAP: 12,
7
+ GAP: 24,
8
+ CHANNEL: 8,
9
+ STUB: 16,
10
+ LABEL_GAP: 4,
11
+ CONTENT_PAD: 40,
12
+ GROUP_PAD: 12,
13
+ BAND_PAD: 6,
14
+ BULLET_INDENT: 12,
15
+ BLOCK_GAP: 8,
16
+ CAPTION_GAP: 8,
17
+ PORT_SPACING: 24,
18
+ STACK_STEP: {
19
+ x: 12,
20
+ y: 8
21
+ },
22
+ MARKER_ICON: 34,
23
+ CONNECTOR_ICON: 16,
24
+ BADGE_ICON: 22,
25
+ JUNCTION: 16,
26
+ APPLIANCE: {
27
+ w: 112,
28
+ h: 72
29
+ },
30
+ RADIUS: 16,
31
+ FLAT_RADIUS: 4,
32
+ fonts: {
33
+ title: {
34
+ face: 'sans',
35
+ size: 14,
36
+ weight: 600
37
+ },
38
+ body: {
39
+ face: 'sans',
40
+ size: 11,
41
+ weight: 400
42
+ },
43
+ caption: {
44
+ face: 'sans',
45
+ size: 11,
46
+ weight: 500
47
+ },
48
+ boxLabel: {
49
+ face: 'mono',
50
+ size: 12,
51
+ weight: 500
52
+ },
53
+ note: {
54
+ face: 'sans',
55
+ size: 10,
56
+ weight: 600
57
+ },
58
+ marker: {
59
+ face: 'sans',
60
+ size: 11,
61
+ weight: 700
33
62
  },
34
- MARKER_ICON: 34,
35
- CONNECTOR_ICON: 16,
36
- BADGE_ICON: 22,
37
- JUNCTION: 16,
38
- APPLIANCE: {
39
- w: 112,
40
- h: 72
63
+ connector: {
64
+ face: 'sans',
65
+ size: 10,
66
+ weight: 700
41
67
  },
42
- RADIUS: 16,
43
- FLAT_RADIUS: 4,
44
- fonts: {
45
- title: {
46
- face: 'sans',
47
- size: 14,
48
- weight: 600
49
- },
50
- body: {
51
- face: 'sans',
52
- size: 11,
53
- weight: 400
54
- },
55
- caption: {
56
- face: 'sans',
57
- size: 11,
58
- weight: 500
59
- },
60
- boxLabel: {
61
- face: 'mono',
62
- size: 12,
63
- weight: 500
64
- },
65
- note: {
66
- face: 'sans',
67
- size: 10,
68
- weight: 600
69
- },
70
- marker: {
71
- face: 'sans',
72
- size: 11,
73
- weight: 700
74
- },
75
- connector: {
76
- face: 'sans',
77
- size: 10,
78
- weight: 700
79
- },
80
- appliance: {
81
- face: 'sans',
82
- size: 12,
83
- weight: 600
84
- },
85
- groupLabel: {
86
- face: 'sans',
87
- size: 12,
88
- weight: 600
89
- },
90
- edgeLabel: {
91
- face: 'mono',
92
- size: 10,
93
- weight: 400
94
- },
95
- badge: {
96
- face: 'sans',
97
- size: 10,
98
- weight: 600
99
- },
100
- portLabel: {
101
- face: 'sans',
102
- size: 9,
103
- weight: 600
104
- }
68
+ appliance: {
69
+ face: 'sans',
70
+ size: 12,
71
+ weight: 600
72
+ },
73
+ groupLabel: {
74
+ face: 'sans',
75
+ size: 12,
76
+ weight: 600
77
+ },
78
+ edgeLabel: {
79
+ face: 'mono',
80
+ size: 10,
81
+ weight: 400
82
+ },
83
+ badge: {
84
+ face: 'sans',
85
+ size: 10,
86
+ weight: 600
87
+ },
88
+ portLabel: {
89
+ face: 'sans',
90
+ size: 9,
91
+ weight: 600
105
92
  }
106
- };
107
- }
93
+ }
94
+ };
108
95
  //# sourceMappingURL=tokens.js.map