@zukhruf/diagram 0.3.30 → 0.3.32

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 (92) hide show
  1. package/dist/lib/layouts/graph/areas.d.ts +27 -0
  2. package/dist/lib/layouts/graph/areas.d.ts.map +1 -0
  3. package/dist/lib/layouts/graph/areas.js +196 -0
  4. package/dist/lib/layouts/graph/areas.js.map +1 -0
  5. package/dist/lib/layouts/graph/graph-layout-result.d.ts +95 -0
  6. package/dist/lib/layouts/graph/graph-layout-result.d.ts.map +1 -0
  7. package/dist/lib/layouts/graph/graph-layout-result.js +2 -0
  8. package/dist/lib/layouts/graph/graph-layout-result.js.map +1 -0
  9. package/dist/lib/layouts/graph/graph-layout.d.ts +2 -1
  10. package/dist/lib/layouts/graph/graph-layout.d.ts.map +1 -1
  11. package/dist/lib/layouts/graph/graph-layout.js +5 -3
  12. package/dist/lib/layouts/graph/graph-layout.js.map +1 -1
  13. package/dist/lib/layouts/graph/gutters.d.ts +25 -0
  14. package/dist/lib/layouts/graph/gutters.d.ts.map +1 -0
  15. package/dist/lib/layouts/graph/gutters.js +124 -0
  16. package/dist/lib/layouts/graph/gutters.js.map +1 -0
  17. package/dist/lib/layouts/graph/layout.d.ts +10 -0
  18. package/dist/lib/layouts/graph/layout.d.ts.map +1 -0
  19. package/dist/lib/layouts/graph/layout.js +164 -0
  20. package/dist/lib/layouts/graph/layout.js.map +1 -0
  21. package/dist/lib/layouts/graph/legacy-graph-layout.d.ts +6 -0
  22. package/dist/lib/layouts/graph/legacy-graph-layout.d.ts.map +1 -0
  23. package/dist/lib/layouts/graph/legacy-graph-layout.js +542 -0
  24. package/dist/lib/layouts/graph/legacy-graph-layout.js.map +1 -0
  25. package/dist/lib/layouts/graph/measure.d.ts +44 -0
  26. package/dist/lib/layouts/graph/measure.d.ts.map +1 -0
  27. package/dist/lib/layouts/graph/measure.js +372 -0
  28. package/dist/lib/layouts/graph/measure.js.map +1 -0
  29. package/dist/lib/layouts/graph/node-content.d.ts +16 -0
  30. package/dist/lib/layouts/graph/node-content.d.ts.map +1 -0
  31. package/dist/lib/layouts/graph/node-content.js +323 -0
  32. package/dist/lib/layouts/graph/node-content.js.map +1 -0
  33. package/dist/lib/layouts/graph/text-block.d.ts +19 -0
  34. package/dist/lib/layouts/graph/text-block.d.ts.map +1 -0
  35. package/dist/lib/layouts/graph/text-block.js +86 -0
  36. package/dist/lib/layouts/graph/text-block.js.map +1 -0
  37. package/dist/lib/layouts/graph/tokens.d.ts +53 -0
  38. package/dist/lib/layouts/graph/tokens.d.ts.map +1 -0
  39. package/dist/lib/layouts/graph/tokens.js +95 -0
  40. package/dist/lib/layouts/graph/tokens.js.map +1 -0
  41. package/dist/lib/layouts/graph/tracks.d.ts +20 -0
  42. package/dist/lib/layouts/graph/tracks.d.ts.map +1 -0
  43. package/dist/lib/layouts/graph/tracks.js +47 -0
  44. package/dist/lib/layouts/graph/tracks.js.map +1 -0
  45. package/dist/lib/layouts/text/font-metrics.generated.d.ts +18 -0
  46. package/dist/lib/layouts/text/font-metrics.generated.d.ts.map +1 -0
  47. package/dist/lib/layouts/text/font-metrics.generated.js +1043 -0
  48. package/dist/lib/layouts/text/font-metrics.generated.js.map +1 -0
  49. package/dist/lib/layouts/text/font.d.ts +14 -0
  50. package/dist/lib/layouts/text/font.d.ts.map +1 -0
  51. package/dist/lib/layouts/text/font.js +11 -0
  52. package/dist/lib/layouts/text/font.js.map +1 -0
  53. package/dist/lib/layouts/text/measure-text.d.ts +13 -0
  54. package/dist/lib/layouts/text/measure-text.d.ts.map +1 -0
  55. package/dist/lib/layouts/text/measure-text.js +67 -0
  56. package/dist/lib/layouts/text/measure-text.js.map +1 -0
  57. package/dist/lib/model/diagram-ir.d.ts +11 -1
  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/dist/lib/renderers/canvas/graph-canvas.d.ts.map +1 -1
  61. package/dist/lib/renderers/canvas/graph-canvas.js +148 -138
  62. package/dist/lib/renderers/canvas/graph-canvas.js.map +1 -1
  63. package/dist/lib/renderers/html/graph-html.d.ts.map +1 -1
  64. package/dist/lib/renderers/html/graph-html.js +462 -511
  65. package/dist/lib/renderers/html/graph-html.js.map +1 -1
  66. package/dist/lib/renderers/shared/graph-parts.d.ts +15 -13
  67. package/dist/lib/renderers/shared/graph-parts.d.ts.map +1 -1
  68. package/dist/lib/renderers/shared/graph-parts.js +649 -644
  69. package/dist/lib/renderers/shared/graph-parts.js.map +1 -1
  70. package/dist/lib/renderers/shared/node-parts.d.ts +20 -19
  71. package/dist/lib/renderers/shared/node-parts.d.ts.map +1 -1
  72. package/dist/lib/renderers/shared/node-parts.js +678 -811
  73. package/dist/lib/renderers/shared/node-parts.js.map +1 -1
  74. package/dist/lib/renderers/shared/run-spans.d.ts +8 -0
  75. package/dist/lib/renderers/shared/run-spans.d.ts.map +1 -0
  76. package/dist/lib/renderers/shared/run-spans.js +18 -0
  77. package/dist/lib/renderers/shared/run-spans.js.map +1 -0
  78. package/dist/lib/renderers/shared/text-runs.d.ts +21 -0
  79. package/dist/lib/renderers/shared/text-runs.d.ts.map +1 -0
  80. package/dist/lib/renderers/shared/text-runs.js +44 -0
  81. package/dist/lib/renderers/shared/text-runs.js.map +1 -0
  82. package/dist/lib/renderers/svg/graph-svg.d.ts.map +1 -1
  83. package/dist/lib/renderers/svg/graph-svg.js +304 -465
  84. package/dist/lib/renderers/svg/graph-svg.js.map +1 -1
  85. package/dist/lib/renderers/svg/timeline-svg.d.ts.map +1 -1
  86. package/dist/lib/renderers/svg/timeline-svg.js +10 -5
  87. package/dist/lib/renderers/svg/timeline-svg.js.map +1 -1
  88. package/dist/lib/renderers/webgpu/graph-flow-effects.d.ts +2 -2
  89. package/dist/lib/renderers/webgpu/graph-flow-effects.d.ts.map +1 -1
  90. package/dist/lib/renderers/webgpu/graph-flow-effects.js.map +1 -1
  91. package/package.json +3 -1
  92. package/styles.css +8 -0
@@ -0,0 +1,323 @@
1
+ import { labelLines, textBlock } from "./text-block.js";
2
+
3
+ /** What a node draws inside its frame: its measured size, the padding around it, and where it goes. */
4
+
5
+ /** Mirrors the connector pill drawn before content sizing: 10px side inset, 4px above and below the text, 28px tall at least. */
6
+ const CONNECTOR_PAD = {
7
+ x: 10,
8
+ y: 4
9
+ };
10
+ const CONNECTOR_MIN_HEIGHT = 28;
11
+ const NOTHING = {
12
+ text: [],
13
+ bullets: []
14
+ };
15
+ export function nodeContent(node, tokens) {
16
+ switch (node.kind) {
17
+ case 'junction':
18
+ return junctionContent(tokens);
19
+ case 'marker':
20
+ return markerContent(node, tokens);
21
+ case 'connector':
22
+ return connectorContent(node, tokens);
23
+ case 'appliance':
24
+ return applianceContent(node, tokens);
25
+ case 'note':
26
+ return noteContent(node, tokens);
27
+ default:
28
+ return boxContent(node, tokens);
29
+ }
30
+ }
31
+ function boxContent(node, tokens) {
32
+ const pad = node.frame === 'none' ? {
33
+ x: tokens.LABEL_GAP,
34
+ y: tokens.LABEL_GAP
35
+ } : {
36
+ x: tokens.PAD_X,
37
+ y: tokens.PAD_Y
38
+ };
39
+ const isCard = node.textAlign === 'start' || node.description !== undefined || (node.items?.length ?? 0) > 0;
40
+ if (isCard) return {
41
+ ...cardContent(node, tokens),
42
+ pad
43
+ };
44
+ if (node.icon) return {
45
+ ...iconRowContent(node, tokens),
46
+ pad
47
+ };
48
+ const lines = textBlock(labelLines(node.label, node.textColor), tokens.fonts.boxLabel);
49
+ return {
50
+ w: lines.w,
51
+ h: lines.h,
52
+ pad,
53
+ place: inner => ({
54
+ text: lines.place(centreX(inner), centredTop(inner, lines.h), 'middle'),
55
+ bullets: []
56
+ })
57
+ };
58
+ }
59
+ function iconRowContent(node, tokens) {
60
+ const {
61
+ ICON,
62
+ ICON_GAP
63
+ } = tokens;
64
+ const title = textBlock(labelLines(node.label, node.textColor), tokens.fonts.title);
65
+ const w = title.w > 0 ? ICON + ICON_GAP + title.w : ICON;
66
+ const h = Math.max(ICON, title.h);
67
+ return {
68
+ w,
69
+ h,
70
+ place: inner => {
71
+ const x = inner.x + (inner.w - w) / 2;
72
+ const y = centredTop(inner, h);
73
+ return {
74
+ icon: {
75
+ x,
76
+ y: y + (h - ICON) / 2,
77
+ size: ICON
78
+ },
79
+ text: title.place(x + ICON + ICON_GAP, y + (h - title.h) / 2, 'start'),
80
+ bullets: []
81
+ };
82
+ }
83
+ };
84
+ }
85
+ function cardContent(node, tokens) {
86
+ const {
87
+ ICON,
88
+ ICON_GAP,
89
+ BLOCK_GAP,
90
+ BULLET_INDENT
91
+ } = tokens;
92
+ const title = textBlock(labelLines(node.label, node.textColor), tokens.fonts.title);
93
+ const description = textBlock(labelLines(node.description, node.textColor), tokens.fonts.body);
94
+ const items = textBlock(labelLines(node.items, node.textColor), tokens.fonts.body);
95
+ let iconW = 0;
96
+ if (node.icon) iconW = title.w > 0 ? ICON + ICON_GAP : ICON;
97
+ const headerH = Math.max(node.icon ? ICON : 0, title.h);
98
+ const sections = [{
99
+ h: headerH,
100
+ w: iconW + title.w
101
+ }, {
102
+ h: description.h,
103
+ w: description.w
104
+ }, {
105
+ h: items.h,
106
+ w: items.h > 0 ? BULLET_INDENT + items.w : 0
107
+ }].filter(section => section.h > 0);
108
+ const bulletRise = tokens.fonts.body.size * 0.3;
109
+ return {
110
+ w: Math.max(0, ...sections.map(section => section.w)),
111
+ h: sections.reduce((sum, section) => sum + section.h, 0) + Math.max(0, sections.length - 1) * BLOCK_GAP,
112
+ place: inner => {
113
+ let top = inner.y;
114
+ const next = h => {
115
+ const at = top;
116
+ if (h > 0) top += h + BLOCK_GAP;
117
+ return at;
118
+ };
119
+ const headerTop = next(headerH);
120
+ const descriptionTop = next(description.h);
121
+ const itemsTop = next(items.h);
122
+ const itemRuns = items.place(inner.x + BULLET_INDENT, itemsTop, 'start');
123
+ return {
124
+ ...(node.icon ? {
125
+ icon: {
126
+ x: inner.x,
127
+ y: headerTop + (headerH - ICON) / 2,
128
+ size: ICON
129
+ }
130
+ } : {}),
131
+ text: [...title.place(inner.x + iconW, headerTop + (headerH - title.h) / 2, 'start'), ...description.place(inner.x, descriptionTop, 'start'), ...itemRuns],
132
+ bullets: itemRuns.map(run => ({
133
+ x: inner.x + BULLET_INDENT / 4,
134
+ y: run.y - bulletRise
135
+ }))
136
+ };
137
+ }
138
+ };
139
+ }
140
+ function noteContent(node, tokens) {
141
+ const lines = textBlock(labelLines(node.label, node.textColor ?? 'dim'), tokens.fonts.note);
142
+ return {
143
+ w: lines.w,
144
+ h: lines.h,
145
+ pad: {
146
+ x: tokens.LABEL_GAP,
147
+ y: tokens.LABEL_GAP
148
+ },
149
+ place: inner => ({
150
+ text: lines.place(inner.x, inner.y, 'start'),
151
+ bullets: []
152
+ })
153
+ };
154
+ }
155
+ function markerContent(node, tokens) {
156
+ const {
157
+ MARKER_ICON,
158
+ BLOCK_GAP
159
+ } = tokens;
160
+ const lines = textBlock(labelLines(node.label, node.textColor), tokens.fonts.marker);
161
+ const gap = lines.h > 0 ? BLOCK_GAP : 0;
162
+ const h = MARKER_ICON + gap + lines.h;
163
+ return {
164
+ w: Math.max(MARKER_ICON, lines.w),
165
+ h,
166
+ pad: {
167
+ x: tokens.LABEL_GAP,
168
+ y: tokens.LABEL_GAP
169
+ },
170
+ place: inner => {
171
+ const top = centredTop(inner, h);
172
+ const cx = centreX(inner);
173
+ return {
174
+ icon: {
175
+ x: cx - MARKER_ICON / 2,
176
+ y: top,
177
+ size: MARKER_ICON
178
+ },
179
+ text: lines.place(cx, top + MARKER_ICON + gap, 'middle'),
180
+ bullets: []
181
+ };
182
+ }
183
+ };
184
+ }
185
+ function connectorContent(node, tokens) {
186
+ const {
187
+ CONNECTOR_ICON,
188
+ BLOCK_GAP
189
+ } = tokens;
190
+ const lines = textBlock(labelLines(node.label, node.textColor), tokens.fonts.connector);
191
+ const iconW = node.icon ? CONNECTOR_ICON + (lines.w > 0 ? BLOCK_GAP : 0) : 0;
192
+ const h = Math.max(CONNECTOR_MIN_HEIGHT - 2 * CONNECTOR_PAD.y, lines.h);
193
+ return {
194
+ w: iconW + lines.w,
195
+ h,
196
+ pad: CONNECTOR_PAD,
197
+ place: inner => {
198
+ const cy = inner.y + inner.h / 2;
199
+ const top = cy - lines.h / 2;
200
+ if (!node.icon) {
201
+ return {
202
+ text: lines.place(centreX(inner), top, 'middle'),
203
+ bullets: []
204
+ };
205
+ }
206
+ return {
207
+ icon: {
208
+ x: inner.x,
209
+ y: cy - CONNECTOR_ICON / 2,
210
+ size: CONNECTOR_ICON
211
+ },
212
+ text: lines.place(inner.x + iconW, top, 'start'),
213
+ bullets: []
214
+ };
215
+ }
216
+ };
217
+ }
218
+ function junctionContent(tokens) {
219
+ return {
220
+ w: tokens.JUNCTION,
221
+ h: tokens.JUNCTION,
222
+ pad: {
223
+ x: 0,
224
+ y: 0
225
+ },
226
+ place: () => NOTHING
227
+ };
228
+ }
229
+ function applianceContent(node, tokens) {
230
+ const {
231
+ APPLIANCE,
232
+ LABEL_GAP
233
+ } = tokens;
234
+ const lines = textBlock(labelLines(node.label, node.textColor), tokens.fonts.appliance);
235
+ return {
236
+ w: Math.max(APPLIANCE.w, lines.w + 2 * LABEL_GAP),
237
+ h: APPLIANCE.h + (lines.h > 0 ? lines.h + LABEL_GAP : 0),
238
+ pad: {
239
+ x: 0,
240
+ y: 0
241
+ },
242
+ place: inner => {
243
+ const glyph = {
244
+ x: centreX(inner) - APPLIANCE.w / 2,
245
+ y: inner.y,
246
+ ...APPLIANCE
247
+ };
248
+ return {
249
+ appliance: applianceGlyph(node, glyph),
250
+ text: lines.place(centreX(inner), glyph.y + glyph.h, 'middle'),
251
+ bullets: []
252
+ };
253
+ }
254
+ };
255
+ }
256
+
257
+ /** The router glyph: a slanted body, an optional antenna and a row of jacks, as the renderers drew it before content sizing. */
258
+ function applianceGlyph(node, glyph) {
259
+ const bodyX = glyph.x + 4;
260
+ const bodyY = glyph.y + Math.max(12, Math.min(22, glyph.h * 0.28));
261
+ const bodyW = glyph.w - 8;
262
+ const bodyH = glyph.h - (bodyY - glyph.y) - 12;
263
+ const slant = Math.max(4, Math.min(16, bodyW * 0.28, bodyH * 0.75));
264
+ const body = [{
265
+ x: bodyX + slant,
266
+ y: bodyY
267
+ }, {
268
+ x: bodyX + bodyW,
269
+ y: bodyY + 6
270
+ }, {
271
+ x: bodyX + bodyW - slant,
272
+ y: bodyY + bodyH
273
+ }, {
274
+ x: bodyX,
275
+ y: bodyY + bodyH - 6
276
+ }];
277
+ const mastX = bodyX + slant + bodyW * 0.2;
278
+ const antenna = node.antenna ?? true ? [[{
279
+ x: bodyX + slant + bodyW * 0.18,
280
+ y: bodyY + 1
281
+ }, {
282
+ x: mastX - 3,
283
+ y: glyph.y + 3
284
+ }], [{
285
+ x: mastX + 1,
286
+ y: bodyY + 2
287
+ }, {
288
+ x: mastX + 1,
289
+ y: glyph.y + 8
290
+ }]] : [];
291
+ const jackCount = Math.max(0, Math.floor(node.appliancePorts ?? 4));
292
+ const jackSpacing = Math.min(13, Math.max(8, (bodyW - slant - 42) / Math.max(jackCount, 1)));
293
+ const jacks = Array.from({
294
+ length: jackCount
295
+ }, (_, index) => ({
296
+ x: bodyX + slant + 16 + index * jackSpacing,
297
+ y: bodyY + bodyH - 15,
298
+ w: 5,
299
+ h: 12
300
+ }));
301
+ const face = [{
302
+ x: bodyX + slant,
303
+ y: bodyY + bodyH - 1
304
+ }, {
305
+ x: bodyX + bodyW - slant,
306
+ y: bodyY + bodyH + 3
307
+ }];
308
+ // Through a variable, not a literal, so the return skips the excess-property check against NodeLayout['appliance'].
309
+ const parts = {
310
+ body,
311
+ face,
312
+ antenna,
313
+ jacks
314
+ };
315
+ return parts;
316
+ }
317
+ function centreX(box) {
318
+ return box.x + box.w / 2;
319
+ }
320
+ function centredTop(box, h) {
321
+ return box.y + (box.h - h) / 2;
322
+ }
323
+ //# sourceMappingURL=node-content.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-content.js","names":["labelLines","textBlock","CONNECTOR_PAD","x","y","CONNECTOR_MIN_HEIGHT","NOTHING","text","bullets","nodeContent","node","tokens","kind","junctionContent","markerContent","connectorContent","applianceContent","noteContent","boxContent","pad","frame","LABEL_GAP","PAD_X","PAD_Y","isCard","textAlign","description","undefined","items","length","cardContent","icon","iconRowContent","lines","label","textColor","fonts","boxLabel","w","h","place","inner","centreX","centredTop","ICON","ICON_GAP","title","Math","max","size","BLOCK_GAP","BULLET_INDENT","body","iconW","headerH","sections","filter","section","bulletRise","map","reduce","sum","top","next","at","headerTop","descriptionTop","itemsTop","itemRuns","run","note","MARKER_ICON","marker","gap","cx","CONNECTOR_ICON","connector","cy","JUNCTION","APPLIANCE","appliance","glyph","applianceGlyph","bodyX","bodyY","min","bodyW","bodyH","slant","mastX","antenna","jackCount","floor","appliancePorts","jackSpacing","jacks","Array","from","_","index","face","parts","box"],"sources":["../../../../src/lib/layouts/graph/node-content.ts"],"sourcesContent":["import type { Box, DiagramNode, Point } from '../../model/diagram-ir.ts';\nimport type { NodeLayout } from './graph-layout-result.ts';\nimport { labelLines, textBlock } from './text-block.ts';\nimport type { LayoutTokens } from './tokens.ts';\n\nexport type ContentPlacement = Pick<NodeLayout, 'text' | 'bullets'> &\n Partial<Pick<NodeLayout, 'icon' | 'appliance'>>;\n\n/** What a node draws inside its frame: its measured size, the padding around it, and where it goes. */\nexport type NodeContent = {\n w: number;\n h: number;\n pad: { x: number; y: number };\n place(inner: Box): ContentPlacement;\n};\n\n/** Mirrors the connector pill drawn before content sizing: 10px side inset, 4px above and below the text, 28px tall at least. */\nconst CONNECTOR_PAD = { x: 10, y: 4 };\nconst CONNECTOR_MIN_HEIGHT = 28;\n\nconst NOTHING: ContentPlacement = { text: [], bullets: [] };\n\nexport function nodeContent(\n node: DiagramNode,\n tokens: LayoutTokens,\n): NodeContent {\n switch (node.kind) {\n case 'junction':\n return junctionContent(tokens);\n case 'marker':\n return markerContent(node, tokens);\n case 'connector':\n return connectorContent(node, tokens);\n case 'appliance':\n return applianceContent(node, tokens);\n case 'note':\n return noteContent(node, tokens);\n default:\n return boxContent(node, tokens);\n }\n}\n\nfunction boxContent(node: DiagramNode, tokens: LayoutTokens): NodeContent {\n const pad =\n node.frame === 'none'\n ? { x: tokens.LABEL_GAP, y: tokens.LABEL_GAP }\n : { x: tokens.PAD_X, y: tokens.PAD_Y };\n const isCard =\n node.textAlign === 'start' ||\n node.description !== undefined ||\n (node.items?.length ?? 0) > 0;\n if (isCard) return { ...cardContent(node, tokens), pad };\n if (node.icon) return { ...iconRowContent(node, tokens), pad };\n const lines = textBlock(\n labelLines(node.label, node.textColor),\n tokens.fonts.boxLabel,\n );\n return {\n w: lines.w,\n h: lines.h,\n pad,\n place: (inner) => ({\n text: lines.place(centreX(inner), centredTop(inner, lines.h), 'middle'),\n bullets: [],\n }),\n };\n}\n\nfunction iconRowContent(\n node: DiagramNode,\n tokens: LayoutTokens,\n): Omit<NodeContent, 'pad'> {\n const { ICON, ICON_GAP } = tokens;\n const title = textBlock(\n labelLines(node.label, node.textColor),\n tokens.fonts.title,\n );\n const w = title.w > 0 ? ICON + ICON_GAP + title.w : ICON;\n const h = Math.max(ICON, title.h);\n return {\n w,\n h,\n place: (inner) => {\n const x = inner.x + (inner.w - w) / 2;\n const y = centredTop(inner, h);\n return {\n icon: { x, y: y + (h - ICON) / 2, size: ICON },\n text: title.place(x + ICON + ICON_GAP, y + (h - title.h) / 2, 'start'),\n bullets: [],\n };\n },\n };\n}\n\nfunction cardContent(\n node: DiagramNode,\n tokens: LayoutTokens,\n): Omit<NodeContent, 'pad'> {\n const { ICON, ICON_GAP, BLOCK_GAP, BULLET_INDENT } = tokens;\n const title = textBlock(\n labelLines(node.label, node.textColor),\n tokens.fonts.title,\n );\n const description = textBlock(\n labelLines(node.description, node.textColor),\n tokens.fonts.body,\n );\n const items = textBlock(\n labelLines(node.items, node.textColor),\n tokens.fonts.body,\n );\n let iconW = 0;\n if (node.icon) iconW = title.w > 0 ? ICON + ICON_GAP : ICON;\n const headerH = Math.max(node.icon ? ICON : 0, title.h);\n const sections = [\n { h: headerH, w: iconW + title.w },\n { h: description.h, w: description.w },\n { h: items.h, w: items.h > 0 ? BULLET_INDENT + items.w : 0 },\n ].filter((section) => section.h > 0);\n const bulletRise = tokens.fonts.body.size * 0.3;\n return {\n w: Math.max(0, ...sections.map((section) => section.w)),\n h:\n sections.reduce((sum, section) => sum + section.h, 0) +\n Math.max(0, sections.length - 1) * BLOCK_GAP,\n place: (inner) => {\n let top = inner.y;\n const next = (h: number) => {\n const at = top;\n if (h > 0) top += h + BLOCK_GAP;\n return at;\n };\n const headerTop = next(headerH);\n const descriptionTop = next(description.h);\n const itemsTop = next(items.h);\n const itemRuns = items.place(inner.x + BULLET_INDENT, itemsTop, 'start');\n return {\n ...(node.icon\n ? {\n icon: {\n x: inner.x,\n y: headerTop + (headerH - ICON) / 2,\n size: ICON,\n },\n }\n : {}),\n text: [\n ...title.place(\n inner.x + iconW,\n headerTop + (headerH - title.h) / 2,\n 'start',\n ),\n ...description.place(inner.x, descriptionTop, 'start'),\n ...itemRuns,\n ],\n bullets: itemRuns.map((run) => ({\n x: inner.x + BULLET_INDENT / 4,\n y: run.y - bulletRise,\n })),\n };\n },\n };\n}\n\nfunction noteContent(node: DiagramNode, tokens: LayoutTokens): NodeContent {\n const lines = textBlock(\n labelLines(node.label, node.textColor ?? 'dim'),\n tokens.fonts.note,\n );\n return {\n w: lines.w,\n h: lines.h,\n pad: { x: tokens.LABEL_GAP, y: tokens.LABEL_GAP },\n place: (inner) => ({\n text: lines.place(inner.x, inner.y, 'start'),\n bullets: [],\n }),\n };\n}\n\nfunction markerContent(node: DiagramNode, tokens: LayoutTokens): NodeContent {\n const { MARKER_ICON, BLOCK_GAP } = tokens;\n const lines = textBlock(\n labelLines(node.label, node.textColor),\n tokens.fonts.marker,\n );\n const gap = lines.h > 0 ? BLOCK_GAP : 0;\n const h = MARKER_ICON + gap + lines.h;\n return {\n w: Math.max(MARKER_ICON, lines.w),\n h,\n pad: { x: tokens.LABEL_GAP, y: tokens.LABEL_GAP },\n place: (inner) => {\n const top = centredTop(inner, h);\n const cx = centreX(inner);\n return {\n icon: { x: cx - MARKER_ICON / 2, y: top, size: MARKER_ICON },\n text: lines.place(cx, top + MARKER_ICON + gap, 'middle'),\n bullets: [],\n };\n },\n };\n}\n\nfunction connectorContent(\n node: DiagramNode,\n tokens: LayoutTokens,\n): NodeContent {\n const { CONNECTOR_ICON, BLOCK_GAP } = tokens;\n const lines = textBlock(\n labelLines(node.label, node.textColor),\n tokens.fonts.connector,\n );\n const iconW = node.icon ? CONNECTOR_ICON + (lines.w > 0 ? BLOCK_GAP : 0) : 0;\n const h = Math.max(CONNECTOR_MIN_HEIGHT - 2 * CONNECTOR_PAD.y, lines.h);\n return {\n w: iconW + lines.w,\n h,\n pad: CONNECTOR_PAD,\n place: (inner) => {\n const cy = inner.y + inner.h / 2;\n const top = cy - lines.h / 2;\n if (!node.icon) {\n return {\n text: lines.place(centreX(inner), top, 'middle'),\n bullets: [],\n };\n }\n return {\n icon: { x: inner.x, y: cy - CONNECTOR_ICON / 2, size: CONNECTOR_ICON },\n text: lines.place(inner.x + iconW, top, 'start'),\n bullets: [],\n };\n },\n };\n}\n\nfunction junctionContent(tokens: LayoutTokens): NodeContent {\n return {\n w: tokens.JUNCTION,\n h: tokens.JUNCTION,\n pad: { x: 0, y: 0 },\n place: () => NOTHING,\n };\n}\n\nfunction applianceContent(\n node: DiagramNode,\n tokens: LayoutTokens,\n): NodeContent {\n const { APPLIANCE, LABEL_GAP } = tokens;\n const lines = textBlock(\n labelLines(node.label, node.textColor),\n tokens.fonts.appliance,\n );\n return {\n w: Math.max(APPLIANCE.w, lines.w + 2 * LABEL_GAP),\n h: APPLIANCE.h + (lines.h > 0 ? lines.h + LABEL_GAP : 0),\n pad: { x: 0, y: 0 },\n place: (inner) => {\n const glyph = {\n x: centreX(inner) - APPLIANCE.w / 2,\n y: inner.y,\n ...APPLIANCE,\n };\n return {\n appliance: applianceGlyph(node, glyph),\n text: lines.place(centreX(inner), glyph.y + glyph.h, 'middle'),\n bullets: [],\n };\n },\n };\n}\n\n/** The router glyph: a slanted body, an optional antenna and a row of jacks, as the renderers drew it before content sizing. */\nfunction applianceGlyph(\n node: DiagramNode,\n glyph: Box,\n): NonNullable<NodeLayout['appliance']> {\n const bodyX = glyph.x + 4;\n const bodyY = glyph.y + Math.max(12, Math.min(22, glyph.h * 0.28));\n const bodyW = glyph.w - 8;\n const bodyH = glyph.h - (bodyY - glyph.y) - 12;\n const slant = Math.max(4, Math.min(16, bodyW * 0.28, bodyH * 0.75));\n const body: Point[] = [\n { x: bodyX + slant, y: bodyY },\n { x: bodyX + bodyW, y: bodyY + 6 },\n { x: bodyX + bodyW - slant, y: bodyY + bodyH },\n { x: bodyX, y: bodyY + bodyH - 6 },\n ];\n const mastX = bodyX + slant + bodyW * 0.2;\n const antenna: [Point, Point][] =\n (node.antenna ?? true)\n ? [\n [\n { x: bodyX + slant + bodyW * 0.18, y: bodyY + 1 },\n { x: mastX - 3, y: glyph.y + 3 },\n ],\n [\n { x: mastX + 1, y: bodyY + 2 },\n { x: mastX + 1, y: glyph.y + 8 },\n ],\n ]\n : [];\n const jackCount = Math.max(0, Math.floor(node.appliancePorts ?? 4));\n const jackSpacing = Math.min(\n 13,\n Math.max(8, (bodyW - slant - 42) / Math.max(jackCount, 1)),\n );\n const jacks = Array.from({ length: jackCount }, (_, index) => ({\n x: bodyX + slant + 16 + index * jackSpacing,\n y: bodyY + bodyH - 15,\n w: 5,\n h: 12,\n }));\n const face: [Point, Point] = [\n { x: bodyX + slant, y: bodyY + bodyH - 1 },\n { x: bodyX + bodyW - slant, y: bodyY + bodyH + 3 },\n ];\n // Through a variable, not a literal, so the return skips the excess-property check against NodeLayout['appliance'].\n const parts = { body, face, antenna, jacks };\n return parts;\n}\n\nfunction centreX(box: Box): number {\n return box.x + box.w / 2;\n}\n\nfunction centredTop(box: Box, h: number): number {\n return box.y + (box.h - h) / 2;\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,19 @@
1
+ import type { DiagramLabelLine, DiagramTextColor } from '../../model/diagram-ir.ts';
2
+ import type { Font, FontWeight } from '../text/font.ts';
3
+ import type { TextAnchor, TextRun } from './graph-layout-result.ts';
4
+ export type TextLine = {
5
+ text: string;
6
+ color?: DiagramTextColor;
7
+ weight?: FontWeight;
8
+ };
9
+ /** Lines of one font stacked at its line height, measured once and placed later. */
10
+ export type TextBlock = {
11
+ w: number;
12
+ h: number;
13
+ /** `x` is the anchor of every line; `top` is the top of the first line box. */
14
+ place(x: number, top: number, anchor: TextAnchor): TextRun[];
15
+ };
16
+ /** The non-empty lines of a label, each with its own colour and weight. */
17
+ export declare function labelLines(label: string | DiagramLabelLine[] | string[] | undefined, color?: DiagramTextColor): TextLine[];
18
+ export declare function textBlock(lines: TextLine[], font: Font): TextBlock;
19
+ //# sourceMappingURL=text-block.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-block.d.ts","sourceRoot":"","sources":["../../../../src/lib/layouts/graph/text-block.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAOxD,OAAO,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAEpE,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB,CAAC;AAEF,oFAAoF;AACpF,MAAM,MAAM,SAAS,GAAG;IACtB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,+EAA+E;IAC/E,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,EAAE,CAAC;CAC9D,CAAC;AAUF,2EAA2E;AAC3E,wBAAgB,UAAU,CACxB,KAAK,EAAE,MAAM,GAAG,gBAAgB,EAAE,GAAG,MAAM,EAAE,GAAG,SAAS,EACzD,KAAK,CAAC,EAAE,gBAAgB,GACvB,QAAQ,EAAE,CAiBZ;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,GAAG,SAAS,CA+BlE"}
@@ -0,0 +1,86 @@
1
+ import { fontAscent, fontDescent, fontLineHeight, measureText } from "../text/measure-text.js";
2
+
3
+ /** Lines of one font stacked at its line height, measured once and placed later. */
4
+
5
+ const FONT_WEIGHTS = [400, 500, 600, 700];
6
+ function nearestWeight(weight) {
7
+ return FONT_WEIGHTS.reduce((best, candidate) => Math.abs(candidate - weight) < Math.abs(best - weight) ? candidate : best);
8
+ }
9
+
10
+ /** The non-empty lines of a label, each with its own colour and weight. */
11
+ export function labelLines(label, color) {
12
+ const lines = [label ?? []].flat();
13
+ return lines.flatMap(line => {
14
+ const {
15
+ text,
16
+ textColor,
17
+ fontWeight
18
+ } = typeof line === 'string' ? {
19
+ text: line
20
+ } : line;
21
+ if (text.trim().length === 0) return [];
22
+ const lineColor = textColor ?? color;
23
+ return [{
24
+ text,
25
+ ...(lineColor ? {
26
+ color: lineColor
27
+ } : {}),
28
+ ...(fontWeight === undefined ? {} : {
29
+ weight: nearestWeight(fontWeight)
30
+ })
31
+ }];
32
+ });
33
+ }
34
+ export function textBlock(lines, font) {
35
+ const lineHeight = fontLineHeight(font);
36
+ const runs = lines.map(line => {
37
+ const lineFont = line.weight ? {
38
+ ...font,
39
+ weight: line.weight
40
+ } : font;
41
+ return {
42
+ line,
43
+ font: lineFont,
44
+ width: measureText(line.text, lineFont),
45
+ ascent: fontAscent(lineFont),
46
+ ink: fontAscent(lineFont) + fontDescent(lineFont)
47
+ };
48
+ });
49
+ return {
50
+ w: Math.max(0, ...runs.map(run => run.width)),
51
+ h: runs.length * lineHeight,
52
+ place(x, top, anchor) {
53
+ return runs.map((run, index) => {
54
+ const inkTop = top + index * lineHeight + (lineHeight - run.ink) / 2;
55
+ const left = lineLeft(x, run.width, anchor);
56
+ return {
57
+ text: run.line.text,
58
+ x,
59
+ y: inkTop + run.ascent,
60
+ anchor,
61
+ font: run.font,
62
+ ...(run.line.color ? {
63
+ color: run.line.color
64
+ } : {}),
65
+ bounds: {
66
+ x: left,
67
+ y: inkTop,
68
+ w: run.width,
69
+ h: run.ink
70
+ }
71
+ };
72
+ });
73
+ }
74
+ };
75
+ }
76
+ function lineLeft(x, width, anchor) {
77
+ switch (anchor) {
78
+ case 'start':
79
+ return x;
80
+ case 'end':
81
+ return x - width;
82
+ case 'middle':
83
+ return x - width / 2;
84
+ }
85
+ }
86
+ //# sourceMappingURL=text-block.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"text-block.js","names":["fontAscent","fontDescent","fontLineHeight","measureText","FONT_WEIGHTS","nearestWeight","weight","reduce","best","candidate","Math","abs","labelLines","label","color","lines","flat","flatMap","line","text","textColor","fontWeight","trim","length","lineColor","undefined","textBlock","font","lineHeight","runs","map","lineFont","width","ascent","ink","w","max","run","h","place","x","top","anchor","index","inkTop","left","lineLeft","y","bounds"],"sources":["../../../../src/lib/layouts/graph/text-block.ts"],"sourcesContent":["import type {\n DiagramLabelLine,\n DiagramTextColor,\n} from '../../model/diagram-ir.ts';\nimport type { Font, FontWeight } from '../text/font.ts';\nimport {\n fontAscent,\n fontDescent,\n fontLineHeight,\n measureText,\n} from '../text/measure-text.ts';\nimport type { TextAnchor, TextRun } from './graph-layout-result.ts';\n\nexport type TextLine = {\n text: string;\n color?: DiagramTextColor;\n weight?: FontWeight;\n};\n\n/** Lines of one font stacked at its line height, measured once and placed later. */\nexport type TextBlock = {\n w: number;\n h: number;\n /** `x` is the anchor of every line; `top` is the top of the first line box. */\n place(x: number, top: number, anchor: TextAnchor): TextRun[];\n};\n\nconst FONT_WEIGHTS: FontWeight[] = [400, 500, 600, 700];\n\nfunction nearestWeight(weight: number): FontWeight {\n return FONT_WEIGHTS.reduce((best, candidate) =>\n Math.abs(candidate - weight) < Math.abs(best - weight) ? candidate : best,\n );\n}\n\n/** The non-empty lines of a label, each with its own colour and weight. */\nexport function labelLines(\n label: string | DiagramLabelLine[] | string[] | undefined,\n color?: DiagramTextColor,\n): TextLine[] {\n const lines = [label ?? []].flat();\n return lines.flatMap((line): TextLine[] => {\n const { text, textColor, fontWeight } =\n typeof line === 'string' ? { text: line } : line;\n if (text.trim().length === 0) return [];\n const lineColor = textColor ?? color;\n return [\n {\n text,\n ...(lineColor ? { color: lineColor } : {}),\n ...(fontWeight === undefined\n ? {}\n : { weight: nearestWeight(fontWeight) }),\n },\n ];\n });\n}\n\nexport function textBlock(lines: TextLine[], font: Font): TextBlock {\n const lineHeight = fontLineHeight(font);\n const runs = lines.map((line) => {\n const lineFont = line.weight ? { ...font, weight: line.weight } : font;\n return {\n line,\n font: lineFont,\n width: measureText(line.text, lineFont),\n ascent: fontAscent(lineFont),\n ink: fontAscent(lineFont) + fontDescent(lineFont),\n };\n });\n return {\n w: Math.max(0, ...runs.map((run) => run.width)),\n h: runs.length * lineHeight,\n place(x, top, anchor) {\n return runs.map((run, index) => {\n const inkTop = top + index * lineHeight + (lineHeight - run.ink) / 2;\n const left = lineLeft(x, run.width, anchor);\n return {\n text: run.line.text,\n x,\n y: inkTop + run.ascent,\n anchor,\n font: run.font,\n ...(run.line.color ? { color: run.line.color } : {}),\n bounds: { x: left, y: inkTop, w: run.width, h: run.ink },\n };\n });\n },\n };\n}\n\nfunction lineLeft(x: number, width: number, anchor: TextAnchor): number {\n switch (anchor) {\n case 'start':\n return x;\n case 'end':\n return x - width;\n case 'middle':\n return x - width / 2;\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,53 @@
1
+ import type { Font } from '../text/font.ts';
2
+ export type LayoutFonts = {
3
+ /** The title of a Card, or of a Box with an icon. */
4
+ title: Font;
5
+ /** A Card's description and items. */
6
+ body: Font;
7
+ caption: Font;
8
+ /** A centred Box label without an icon. */
9
+ boxLabel: Font;
10
+ note: Font;
11
+ marker: Font;
12
+ connector: Font;
13
+ appliance: Font;
14
+ groupLabel: Font;
15
+ edgeLabel: Font;
16
+ badge: Font;
17
+ portLabel: Font;
18
+ };
19
+ export type LayoutTokens = {
20
+ PAD_X: number;
21
+ PAD_Y: number;
22
+ ICON: number;
23
+ ICON_GAP: number;
24
+ GAP: number;
25
+ CHANNEL: number;
26
+ STUB: number;
27
+ LABEL_GAP: number;
28
+ CONTENT_PAD: number;
29
+ GROUP_PAD: number;
30
+ BAND_PAD: number;
31
+ BULLET_INDENT: number;
32
+ BLOCK_GAP: number;
33
+ CAPTION_GAP: number;
34
+ PORT_SPACING: number;
35
+ STACK_STEP: {
36
+ x: number;
37
+ y: number;
38
+ };
39
+ MARKER_ICON: number;
40
+ CONNECTOR_ICON: number;
41
+ BADGE_ICON: number;
42
+ JUNCTION: number;
43
+ APPLIANCE: {
44
+ w: number;
45
+ h: number;
46
+ };
47
+ RADIUS: number;
48
+ FLAT_RADIUS: number;
49
+ fonts: LayoutFonts;
50
+ };
51
+ /** The sizes the engine lays out with. */
52
+ export declare const LAYOUT_TOKENS: LayoutTokens;
53
+ //# sourceMappingURL=tokens.d.ts.map
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,95 @@
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
62
+ },
63
+ connector: {
64
+ face: 'sans',
65
+ size: 10,
66
+ weight: 700
67
+ },
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
92
+ }
93
+ }
94
+ };
95
+ //# sourceMappingURL=tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.js","names":["LAYOUT_TOKENS","PAD_X","PAD_Y","ICON","ICON_GAP","GAP","CHANNEL","STUB","LABEL_GAP","CONTENT_PAD","GROUP_PAD","BAND_PAD","BULLET_INDENT","BLOCK_GAP","CAPTION_GAP","PORT_SPACING","STACK_STEP","x","y","MARKER_ICON","CONNECTOR_ICON","BADGE_ICON","JUNCTION","APPLIANCE","w","h","RADIUS","FLAT_RADIUS","fonts","title","face","size","weight","body","caption","boxLabel","note","marker","connector","appliance","groupLabel","edgeLabel","badge","portLabel"],"sources":["../../../../src/lib/layouts/graph/tokens.ts"],"sourcesContent":["import type { Font } from '../text/font.ts';\n\nexport type LayoutFonts = {\n /** The title of a Card, or of a Box with an icon. */\n title: Font;\n /** A Card's description and items. */\n body: Font;\n caption: Font;\n /** A centred Box label without an icon. */\n boxLabel: Font;\n note: Font;\n marker: Font;\n connector: Font;\n appliance: Font;\n groupLabel: Font;\n edgeLabel: Font;\n badge: Font;\n portLabel: Font;\n};\n\nexport type LayoutTokens = {\n PAD_X: number;\n PAD_Y: number;\n ICON: number;\n ICON_GAP: number;\n GAP: number;\n CHANNEL: number;\n STUB: number;\n LABEL_GAP: number;\n CONTENT_PAD: number;\n GROUP_PAD: number;\n BAND_PAD: number;\n BULLET_INDENT: number;\n BLOCK_GAP: number;\n CAPTION_GAP: number;\n PORT_SPACING: number;\n STACK_STEP: { x: number; y: number };\n MARKER_ICON: number;\n CONNECTOR_ICON: number;\n BADGE_ICON: number;\n JUNCTION: number;\n APPLIANCE: { w: number; h: number };\n RADIUS: number;\n FLAT_RADIUS: number;\n fonts: LayoutFonts;\n};\n\n/** The sizes the engine lays out with. */\nexport const LAYOUT_TOKENS: LayoutTokens = {\n PAD_X: 16,\n PAD_Y: 12,\n ICON: 28,\n ICON_GAP: 12,\n GAP: 24,\n CHANNEL: 8,\n STUB: 16,\n LABEL_GAP: 4,\n CONTENT_PAD: 40,\n GROUP_PAD: 12,\n BAND_PAD: 6,\n BULLET_INDENT: 12,\n BLOCK_GAP: 8,\n CAPTION_GAP: 8,\n PORT_SPACING: 24,\n STACK_STEP: { x: 12, y: 8 },\n MARKER_ICON: 34,\n CONNECTOR_ICON: 16,\n BADGE_ICON: 22,\n JUNCTION: 16,\n APPLIANCE: { w: 112, h: 72 },\n RADIUS: 16,\n FLAT_RADIUS: 4,\n fonts: {\n title: { face: 'sans', size: 14, weight: 600 },\n body: { face: 'sans', size: 11, weight: 400 },\n caption: { face: 'sans', size: 11, weight: 500 },\n boxLabel: { face: 'mono', size: 12, weight: 500 },\n note: { face: 'sans', size: 10, weight: 600 },\n marker: { face: 'sans', size: 11, weight: 700 },\n connector: { face: 'sans', size: 10, weight: 700 },\n appliance: { face: 'sans', size: 12, weight: 600 },\n groupLabel: { face: 'sans', size: 12, weight: 600 },\n edgeLabel: { face: 'mono', size: 10, weight: 400 },\n badge: { face: 'sans', size: 10, weight: 600 },\n portLabel: { face: 'sans', size: 9, weight: 600 },\n },\n};\n"],"mappings":"AA+CA;AACA,OAAO,MAAMA,aAA2B,GAAG;EACzCC,KAAK,EAAE,EAAE;EACTC,KAAK,EAAE,EAAE;EACTC,IAAI,EAAE,EAAE;EACRC,QAAQ,EAAE,EAAE;EACZC,GAAG,EAAE,EAAE;EACPC,OAAO,EAAE,CAAC;EACVC,IAAI,EAAE,EAAE;EACRC,SAAS,EAAE,CAAC;EACZC,WAAW,EAAE,EAAE;EACfC,SAAS,EAAE,EAAE;EACbC,QAAQ,EAAE,CAAC;EACXC,aAAa,EAAE,EAAE;EACjBC,SAAS,EAAE,CAAC;EACZC,WAAW,EAAE,CAAC;EACdC,YAAY,EAAE,EAAE;EAChBC,UAAU,EAAE;IAAEC,CAAC,EAAE,EAAE;IAAEC,CAAC,EAAE;EAAE,CAAC;EAC3BC,WAAW,EAAE,EAAE;EACfC,cAAc,EAAE,EAAE;EAClBC,UAAU,EAAE,EAAE;EACdC,QAAQ,EAAE,EAAE;EACZC,SAAS,EAAE;IAAEC,CAAC,EAAE,GAAG;IAAEC,CAAC,EAAE;EAAG,CAAC;EAC5BC,MAAM,EAAE,EAAE;EACVC,WAAW,EAAE,CAAC;EACdC,KAAK,EAAE;IACLC,KAAK,EAAE;MAAEC,IAAI,EAAE,MAAM;MAAEC,IAAI,EAAE,EAAE;MAAEC,MAAM,EAAE;IAAI,CAAC;IAC9CC,IAAI,EAAE;MAAEH,IAAI,EAAE,MAAM;MAAEC,IAAI,EAAE,EAAE;MAAEC,MAAM,EAAE;IAAI,CAAC;IAC7CE,OAAO,EAAE;MAAEJ,IAAI,EAAE,MAAM;MAAEC,IAAI,EAAE,EAAE;MAAEC,MAAM,EAAE;IAAI,CAAC;IAChDG,QAAQ,EAAE;MAAEL,IAAI,EAAE,MAAM;MAAEC,IAAI,EAAE,EAAE;MAAEC,MAAM,EAAE;IAAI,CAAC;IACjDI,IAAI,EAAE;MAAEN,IAAI,EAAE,MAAM;MAAEC,IAAI,EAAE,EAAE;MAAEC,MAAM,EAAE;IAAI,CAAC;IAC7CK,MAAM,EAAE;MAAEP,IAAI,EAAE,MAAM;MAAEC,IAAI,EAAE,EAAE;MAAEC,MAAM,EAAE;IAAI,CAAC;IAC/CM,SAAS,EAAE;MAAER,IAAI,EAAE,MAAM;MAAEC,IAAI,EAAE,EAAE;MAAEC,MAAM,EAAE;IAAI,CAAC;IAClDO,SAAS,EAAE;MAAET,IAAI,EAAE,MAAM;MAAEC,IAAI,EAAE,EAAE;MAAEC,MAAM,EAAE;IAAI,CAAC;IAClDQ,UAAU,EAAE;MAAEV,IAAI,EAAE,MAAM;MAAEC,IAAI,EAAE,EAAE;MAAEC,MAAM,EAAE;IAAI,CAAC;IACnDS,SAAS,EAAE;MAAEX,IAAI,EAAE,MAAM;MAAEC,IAAI,EAAE,EAAE;MAAEC,MAAM,EAAE;IAAI,CAAC;IAClDU,KAAK,EAAE;MAAEZ,IAAI,EAAE,MAAM;MAAEC,IAAI,EAAE,EAAE;MAAEC,MAAM,EAAE;IAAI,CAAC;IAC9CW,SAAS,EAAE;MAAEb,IAAI,EAAE,MAAM;MAAEC,IAAI,EAAE,CAAC;MAAEC,MAAM,EAAE;IAAI;EAClD;AACF,CAAC","ignoreList":[]}