@diagrammo/dgmo 0.76.0 → 0.77.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/dist/advanced.d.ts +142 -12
  2. package/dist/advanced.js +104 -59
  3. package/dist/block.d.ts +2 -2
  4. package/dist/block.js +8 -8
  5. package/dist/{chart-meta-lP8Rl19E.d.ts → chart-meta-Cf_jkApJ.d.ts} +2 -2
  6. package/dist/chart-meta.d.ts +3 -3
  7. package/dist/{charts-d3-SQEVMIAM.js → charts-d3-HMEMHSSW.js} +5 -5
  8. package/dist/{chunk-E3BJVEMZ.js → chunk-2MTM4E6M.js} +2 -2
  9. package/dist/{chunk-UBW53CNS.js → chunk-3E4YB6TY.js} +2 -2
  10. package/dist/{chunk-IFC3JXCT.js → chunk-3O7ZYVJV.js} +2 -2
  11. package/dist/{chunk-Q6BAFS7I.js → chunk-43AJKH2U.js} +3 -3
  12. package/dist/chunk-53SEVJQM.js +9 -0
  13. package/dist/{chunk-UTTRJ6KN.js → chunk-5ZD4DDG7.js} +4 -4
  14. package/dist/{chunk-AFR6GWXD.js → chunk-6BVAW7KI.js} +4 -4
  15. package/dist/{chunk-CLQJAGWL.js → chunk-6IN4F4RH.js} +4 -4
  16. package/dist/{chunk-76IBFEYW.js → chunk-6ZZKEYBS.js} +4 -4
  17. package/dist/{chunk-OBYZU23V.js → chunk-7CXW6EGX.js} +2 -2
  18. package/dist/{chunk-HOIAQ3P2.js → chunk-B52RL5VV.js} +2 -2
  19. package/dist/{chunk-GFXFRKUG.js → chunk-BH3BQICT.js} +4 -4
  20. package/dist/{chunk-3LJNQ6LR.js → chunk-CF3I5SOG.js} +5 -5
  21. package/dist/{chunk-C576CU77.js → chunk-CHOK7NCJ.js} +5 -5
  22. package/dist/{chunk-U74EGVOA.js → chunk-CIWFL2LM.js} +4 -4
  23. package/dist/{chunk-OUJG73YJ.js → chunk-CYMYZYLI.js} +5 -5
  24. package/dist/{chunk-BCB24FG7.js → chunk-D3B6YEZK.js} +3 -3
  25. package/dist/{chunk-XHROEQ23.js → chunk-DSXWJAOA.js} +4 -4
  26. package/dist/{chunk-CQKD6GOC.js → chunk-EUVUOPRC.js} +4 -4
  27. package/dist/{chunk-7G4XMHDB.js → chunk-FF7LRT5L.js} +4 -4
  28. package/dist/{chunk-BZQCAZZZ.js → chunk-FR5EVD2X.js} +4 -4
  29. package/dist/{chunk-U7AO6FRL.js → chunk-H7BYMIVK.js} +312 -118
  30. package/dist/{chunk-4CRLM3IT.js → chunk-HDLRRY3N.js} +44 -44
  31. package/dist/{chunk-JLJ7SP4X.js → chunk-J76YDS4V.js} +2 -2
  32. package/dist/{chunk-7EZ5AKBK.js → chunk-LYJ53DBK.js} +8 -6
  33. package/dist/{chunk-JQ575OAK.js → chunk-MZEGUDTA.js} +2 -2
  34. package/dist/{chunk-IHUOYDLN.js → chunk-N5NQIZ56.js} +5 -5
  35. package/dist/{chunk-32MOGTKT.js → chunk-OO2L2LWV.js} +4 -4
  36. package/dist/{chunk-PAW4RMH3.js → chunk-OZOHREFQ.js} +2 -2
  37. package/dist/{chunk-EGXJWRO6.js → chunk-QBM5BURJ.js} +4 -4
  38. package/dist/{chunk-YVDBBWEP.js → chunk-QXMHBIQG.js} +4 -4
  39. package/dist/{chunk-UWYZIGCB.js → chunk-RGW26UAR.js} +2 -2
  40. package/dist/{chunk-QI4Q5ZZH.js → chunk-RV5A3EGI.js} +4 -4
  41. package/dist/{chunk-HGFKDSKZ.js → chunk-SI3PYDL4.js} +4 -4
  42. package/dist/{chunk-CAPR5DET.js → chunk-SSEAULA5.js} +2 -2
  43. package/dist/{chunk-AYM472K3.js → chunk-SWUQJ5VR.js} +3 -3
  44. package/dist/{chunk-HFCKU73Y.js → chunk-TI4YUUW6.js} +3 -3
  45. package/dist/{chunk-3EGIU5WY.js → chunk-TKIPK5P6.js} +3 -3
  46. package/dist/{chunk-QT5UMFPE.js → chunk-U4DS2ODO.js} +3 -3
  47. package/dist/{chunk-TF76LCZS.js → chunk-UBDVAHGK.js} +4 -4
  48. package/dist/{chunk-JL7BDLC6.js → chunk-UH5YTZN7.js} +4 -4
  49. package/dist/{chunk-GEURKGZS.js → chunk-V4NHFY22.js} +4 -4
  50. package/dist/{chunk-4SXHMFFP.js → chunk-VRPV6QXR.js} +23 -12
  51. package/dist/{chunk-FMZEU7MF.js → chunk-WHWUVDYK.js} +2 -2
  52. package/dist/{chunk-U5B3TUEW.js → chunk-XCFIAGT7.js} +2 -2
  53. package/dist/{chunk-COCMMQXW.js → chunk-XFXJXLK7.js} +2 -2
  54. package/dist/{chunk-YDA46XHI.js → chunk-XPBJVSRY.js} +2 -2
  55. package/dist/{chunk-VV6HZQ5K.js → chunk-YM5RMLFO.js} +2 -2
  56. package/dist/{d3--y67plmW.d.ts → d3-BiaJtaSw.d.ts} +1 -1
  57. package/dist/{dgmo-router-CY5j16Pl.d.ts → dgmo-router-BwXHZ_P3.d.ts} +1 -1
  58. package/dist/{dimensions-7NYBSZRJ.js → dimensions-OFF4GRFL.js} +4 -4
  59. package/dist/{flowchart-renderer-QYGQ64BM.js → flowchart-renderer-BBJUPORB.js} +3 -3
  60. package/dist/index.d.ts +7 -7
  61. package/dist/index.js +8 -8
  62. package/dist/{layout-LAS67TK3.js → layout-Y2V3LYV7.js} +2 -2
  63. package/dist/{renderer-FUJNSC5X.js → renderer-2ANDPQWC.js} +3 -3
  64. package/dist/{renderer-UYZSP7MF.js → renderer-2LDT4TUX.js} +5 -5
  65. package/dist/{renderer-4EWGZLJ6.js → renderer-2NYQDW37.js} +3 -3
  66. package/dist/{renderer-LBNVKVO3.js → renderer-2RIIIO34.js} +5 -5
  67. package/dist/{renderer-PKRKLOYR.js → renderer-3HFU3DTO.js} +5 -5
  68. package/dist/{renderer-UUP6OX6F.js → renderer-4BF6ILP6.js} +5 -5
  69. package/dist/{renderer-MUW4G2N6.js → renderer-5E2AH5TO.js} +7 -7
  70. package/dist/{renderer-DKW273R7.js → renderer-62SLWRYF.js} +6 -5
  71. package/dist/{renderer-E6NHTVN6.js → renderer-ANJUDBOS.js} +5 -5
  72. package/dist/{renderer-OTHBTGBN.js → renderer-CVWQD442.js} +3 -3
  73. package/dist/{renderer-GJDVPXI3.js → renderer-D6GJ6EVK.js} +6 -6
  74. package/dist/{renderer-KMOGGMM7.js → renderer-DNFV2IQI.js} +5 -5
  75. package/dist/{renderer-IH45QV6Z.js → renderer-EDVCGIQO.js} +4 -4
  76. package/dist/{renderer-LE3ZKHNS.js → renderer-EFQSMHID.js} +6 -6
  77. package/dist/{renderer-EP4GRCDX.js → renderer-FTX67CYZ.js} +3 -3
  78. package/dist/{renderer-GF6S5ZX6.js → renderer-G2DPKJAN.js} +5 -5
  79. package/dist/{renderer-QAMOXOZ2.js → renderer-GHBF5PRH.js} +3 -3
  80. package/dist/{renderer-5W3HWIUL.js → renderer-GZLRX764.js} +5 -5
  81. package/dist/{renderer-CO5O5VR5.js → renderer-H2HYLFN3.js} +3 -3
  82. package/dist/{renderer-JMJ7Q5OC.js → renderer-IR5655M7.js} +5 -5
  83. package/dist/{renderer-4PNVGHVA.js → renderer-L237AOOZ.js} +3 -3
  84. package/dist/{renderer-F6WSR7UM.js → renderer-LSJWYGOL.js} +6 -6
  85. package/dist/{renderer-PR3KLNST.js → renderer-LWXDMZOV.js} +5 -5
  86. package/dist/{renderer-3FB56573.js → renderer-MYSVPERC.js} +5 -5
  87. package/dist/{renderer-FGGDZZFQ.js → renderer-OL5QSZPC.js} +6 -6
  88. package/dist/{renderer-XBL6CLN2.js → renderer-P26HH3NA.js} +5 -5
  89. package/dist/{renderer-D7N7PPB7.js → renderer-R5HIRN2M.js} +3 -3
  90. package/dist/{renderer-BUEFD2IF.js → renderer-RNFECJ5D.js} +5 -5
  91. package/dist/{renderer-F24V3RD3.js → renderer-RPZVNCTF.js} +5 -5
  92. package/dist/{renderer-PIEPRK6M.js → renderer-SDNWZDUY.js} +5 -5
  93. package/dist/{renderer-RUHC6D3B.js → renderer-UKHH4UWV.js} +5 -5
  94. package/dist/{renderer-CGOPX4HW.js → renderer-VF7X66SL.js} +5 -5
  95. package/dist/{renderer-ZAJ5353N.js → renderer-Y3Y7PEUS.js} +3 -3
  96. package/dist/{renderer-radial-MZP3SVTZ.js → renderer-radial-QNGCGKZP.js} +5 -5
  97. package/dist/{state-renderer-UIE3AQM6.js → state-renderer-ELWDRXD6.js} +5 -5
  98. package/dist/{tag-groups-DrHT2tEc.d.ts → tag-groups-BAtkq0b_.d.ts} +39 -1
  99. package/dist/{themes-GWhsabnx.d.ts → themes-DpsyRSO7.d.ts} +2 -2
  100. package/gallery/fixtures/sketch.dgmo +1 -1
  101. package/package.json +4 -3
  102. package/dist/chunk-UTCPNJND.js +0 -7
@@ -4,21 +4,37 @@ import {
4
4
  } from "./chunk-5GM6BZO7.js";
5
5
  import {
6
6
  CARD_RADIUS,
7
- CONTAINER_RADIUS
7
+ COLLAPSE_BAR_HEIGHT,
8
+ CONTAINER_LABEL_FONT_SIZE,
9
+ CONTAINER_RADIUS,
10
+ EDGE_LABEL_KNOCKOUT_OPACITY,
11
+ EDGE_STROKE_WIDTH,
12
+ HEADER_HEIGHT,
13
+ LABEL_FONT_SIZE,
14
+ META_FONT_SIZE,
15
+ NODE_STROKE_WIDTH
8
16
  } from "./chunk-FJ57274M.js";
17
+ import {
18
+ ScaleContext
19
+ } from "./chunk-24YPR5EH.js";
9
20
  import {
10
21
  layoutInlineHeader
11
22
  } from "./chunk-MG3DE3VO.js";
23
+ import {
24
+ TITLE_FONT_SIZE,
25
+ TITLE_FONT_WEIGHT,
26
+ TITLE_Y
27
+ } from "./chunk-DEW62ON3.js";
12
28
  import {
13
29
  renderIntegratedLegend
14
- } from "./chunk-QT5UMFPE.js";
30
+ } from "./chunk-U4DS2ODO.js";
15
31
  import {
16
32
  getLegendExtent,
17
33
  getMaxLegendReservedHeight
18
- } from "./chunk-4SXHMFFP.js";
34
+ } from "./chunk-VRPV6QXR.js";
19
35
  import {
20
36
  FONT_FAMILY
21
- } from "./chunk-UTCPNJND.js";
37
+ } from "./chunk-53SEVJQM.js";
22
38
  import {
23
39
  measureText,
24
40
  wrapTextToWidth
@@ -232,29 +248,152 @@ function drawMarkdownBlock(container, text, opts) {
232
248
  };
233
249
  }
234
250
 
251
+ // src/sketch/colors.ts
252
+ var CONTAINER_FILL_OPACITY = 1;
253
+ var CONTAINER_STROKE_OPACITY = 0.35;
254
+ var CONTAINER_STROKE_WIDTH = 1;
255
+ function sketchContainerFill(palette, _isDark) {
256
+ return mix(palette.surface, palette.bg, 40);
257
+ }
258
+ function sketchNeutralFill(palette, isDark, fillMode) {
259
+ return fillMode === "outline" ? themeBaseBg(palette, isDark) : mix(palette.textMuted, palette.bg, 12);
260
+ }
261
+ function sketchColors(opts) {
262
+ const { palette, isDark, fillMode } = opts;
263
+ const neutralFill = sketchNeutralFill(palette, isDark, fillMode);
264
+ const tagGroups = [...opts.tagGroups];
265
+ const activeName = resolveActiveTagGroup(
266
+ tagGroups,
267
+ void 0,
268
+ opts.activeTagGroup ?? void 0
269
+ );
270
+ const activeKey = activeName === null ? null : tagAttrKey(activeName);
271
+ return (metadata, isContainer = false) => {
272
+ if (isContainer) {
273
+ return {
274
+ fill: sketchContainerFill(palette, isDark),
275
+ stroke: palette.textMuted,
276
+ text: palette.text
277
+ };
278
+ }
279
+ const tagged = activeKey !== null && metadata[activeKey] !== void 0;
280
+ const tagColor = tagged ? resolveTagColor(metadata, tagGroups, activeName, isContainer) : void 0;
281
+ if (!tagColor) {
282
+ return {
283
+ fill: neutralFill,
284
+ // 🔴 The same expression `boxes-and-lines` gives an untagged node
285
+ // (`renderer.ts`): a softened text colour, not `palette.textMuted`.
286
+ // Muted is a good deal darker, and at the shared stroke width it made
287
+ // an untagged sketch card the most heavily outlined object in the
288
+ // product (2026-08-27).
289
+ stroke: mix(palette.text, palette.bg, isDark ? 60 : 40),
290
+ text: palette.text
291
+ };
292
+ }
293
+ const fill = shapeFill(palette, tagColor, isDark, { mode: fillMode });
294
+ return {
295
+ fill,
296
+ stroke: tagColor,
297
+ // 🔴 CONTRAST-DERIVED, like every other chart type. This took the tag
298
+ // colour itself in the default and `outline` modes, which made sketch the
299
+ // only chart in the product whose labels are tinted — and on the 25% blend
300
+ // a card is filled with, that is pale-green text on a pale-green card.
301
+ // `boxes-and-lines` and `org` both derive it from the fill and land on one
302
+ // of two neutral tokens; sketch now does the same, in every mode rather
303
+ // than only `solid`.
304
+ text: contrastText(fill, palette.textOnFillLight, palette.textOnFillDark)
305
+ };
306
+ };
307
+ }
308
+
309
+ // src/sketch/visuals.ts
310
+ var SKETCH_VISUALS = {
311
+ /** Air round the whole diagram. */
312
+ diagramPadding: 20,
313
+ // 🔴 SHARED, not a second answer. Sketch printed its title at 18/y-32 while
314
+ // every other chart type used 20/y-30 from `utils/title-constants` — so two
315
+ // diagrams of the same content, side by side, did not even agree on how big
316
+ // their own name was (2026-08-27, #518).
317
+ titleY: TITLE_Y,
318
+ titleFontSize: TITLE_FONT_SIZE,
319
+ titleFontWeight: Number(TITLE_FONT_WEIGHT),
320
+ // 🔴 SHARED, not overridden. These read 2 and 2 against the conventions'
321
+ // 1.5, under a comment claiming "a bolder, less-washed look" — and the
322
+ // boldness was the complaint: a sketch beside a boxes-and-lines or an org
323
+ // chart of the same content did not look like the same product (2026-08-27).
324
+ // Sketch is not in the deviation list `visual-conventions.ts` keeps, either,
325
+ // so the override was drift rather than a decision anyone had recorded.
326
+ nodeStrokeWidth: NODE_STROKE_WIDTH,
327
+ edgeStrokeWidth: EDGE_STROKE_WIDTH,
328
+ // 🔴 A FILLED polygon, not an open V — and sized in STROKE-WIDTHS, like every
329
+ // other chart type. These read 18×12 in USER SPACE, which is 2.4× the ink
330
+ // boxes-and-lines puts on the same 1.5px connector, and it was the loudest
331
+ // single difference between the two pictures (#518). `markerUnits` defaults
332
+ // to `strokeWidth`, so 5×4 here renders 7.5×6 — the same triangle
333
+ // boxes-and-lines draws.
334
+ arrowheadW: 5,
335
+ arrowheadH: 4,
336
+ dash: "6 3",
337
+ /** A card's name. Shared, and it fits DOWN to `nodeLabelFontSizeMin` before
338
+ * it wraps — it used to be allowed up to 30 on a card with no rows, which is
339
+ * more than twice what any other chart type prints. */
340
+ nodeLabelFontSize: LABEL_FONT_SIZE,
341
+ nodeLabelFontSizeMin: 11,
342
+ /** A card's description rows. */
343
+ cardMetaFontSize: META_FONT_SIZE,
344
+ /** A card's header band. */
345
+ cardHeaderHeight: HEADER_HEIGHT,
346
+ // 🔴 A container's own name: shared size, and `600` is what boxes-and-lines
347
+ // gives the same object (org gives it bold). It was 19 at weight 800 behind
348
+ // 0.55 opacity — bigger than a node's name, and the only container label in
349
+ // the product that was faded.
350
+ // 🔴 SHARED, and it stays shared even though boxes-and-lines prints 14 here.
351
+ // Going to 14 to match it was tried and reverted (#518): `sketch` keeps the
352
+ // rule that a container's name is never LOUDER than the names inside it, and
353
+ // one point is imperceptible next to the differences that actually made the
354
+ // two pictures look like different products (footprint, arrowheads, title).
355
+ // boxes-and-lines' 14 — and infra's — are the undocumented deviations here;
356
+ // the fix is those two coming to 13, not a third chart type leaving.
357
+ bandLabelFontSize: CONTAINER_LABEL_FONT_SIZE,
358
+ bandLabelFontWeight: 600,
359
+ bandLabelOpacity: 1,
360
+ /** 11 — what boxes-and-lines prints. It was 12, the only edge label in the
361
+ * product at that size. */
362
+ edgeLabelFontSize: 11,
363
+ /** The `palette.bg` halo painted under an edge label so the connector cannot
364
+ * cross its glyphs. Stroke, with `paint-order: stroke`. */
365
+ edgeLabelHaloWidth: 3,
366
+ cardRadius: CARD_RADIUS,
367
+ containerRadius: CONTAINER_RADIUS
368
+ };
369
+
235
370
  // src/sketch/renderer.ts
236
- var DIAGRAM_PADDING = 20;
237
- var TITLE_Y = 32;
238
- var TITLE_FONT_SIZE = 18;
239
- var NODE_STROKE_WIDTH = 2;
240
- var EDGE_STROKE_WIDTH = 2;
371
+ var DIAGRAM_PADDING = SKETCH_VISUALS.diagramPadding;
372
+ var TITLE_Y2 = SKETCH_VISUALS.titleY;
373
+ var TITLE_FONT_SIZE2 = SKETCH_VISUALS.titleFontSize;
374
+ var NODE_STROKE_WIDTH2 = SKETCH_VISUALS.nodeStrokeWidth;
375
+ var EDGE_STROKE_WIDTH2 = SKETCH_VISUALS.edgeStrokeWidth;
241
376
  var EDGE_HIT_WIDTH = 18;
242
- var ARROWHEAD_W = 18;
243
- var ARROWHEAD_H = 12;
244
- var DASH = "6 3";
245
- var BAND_LABEL_FONT_SIZE = 19;
246
- var BAND_LABEL_OPACITY = 0.55;
377
+ var EDGE_LABEL_H_PAD = 6;
378
+ var EDGE_LABEL_V_PAD = 3;
379
+ var CONTAINER_LABEL_BASELINE = 18;
380
+ var ARROWHEAD_W = SKETCH_VISUALS.arrowheadW;
381
+ var ARROWHEAD_H = SKETCH_VISUALS.arrowheadH;
382
+ var DASH = SKETCH_VISUALS.dash;
383
+ var BAND_LABEL_FONT_SIZE = SKETCH_VISUALS.bandLabelFontSize;
384
+ var BAND_LABEL_OPACITY = SKETCH_VISUALS.bandLabelOpacity;
385
+ var BAND_LABEL_WEIGHT = SKETCH_VISUALS.bandLabelFontWeight;
247
386
  var NOTE_FONT_SIZE = 11;
248
- var COLLAPSE_BAR_HEIGHT = 4;
249
- var EDGE_LABEL_FONT_SIZE = 12;
387
+ var COLLAPSE_BAR_HEIGHT2 = COLLAPSE_BAR_HEIGHT;
388
+ var EDGE_LABEL_FONT_SIZE = SKETCH_VISUALS.edgeLabelFontSize;
250
389
  var CURVE_HANDLE_MIN = 24;
251
390
  var CURVE_HANDLE_MAX = 90;
252
- function drawNoteBody(g, w, h, colors) {
391
+ function drawNoteBody(g, w, h, colors, strokeWidth) {
253
392
  const f = 14;
254
393
  g.append("path").attr(
255
394
  "d",
256
395
  `M0 2 a2 2 0 0 1 2 -2 h${w - f - 2} l${f} ${f} v${h - f - 2} a2 2 0 0 1 -2 2 h-${w - 4} a2 2 0 0 1 -2 -2 Z`
257
- ).attr("fill", colors.fill).attr("stroke", colors.stroke).attr("stroke-width", NODE_STROKE_WIDTH);
396
+ ).attr("fill", colors.fill).attr("stroke", colors.stroke).attr("stroke-width", strokeWidth);
258
397
  g.append("path").attr("d", `M${w - f} 0 v${f} h${f}`).attr("fill", "none").attr("stroke", colors.stroke).attr("stroke-width", 1.2);
259
398
  }
260
399
  function drawTypeBadge(g, kind, color, bx, by) {
@@ -279,12 +418,12 @@ function drawTypeBadge(g, kind, color, bx, by) {
279
418
  return;
280
419
  }
281
420
  }
282
- var CARD_HEADER_H = 34;
283
- var CARD_LABEL_MAX = 15;
284
- var CARD_LABEL_MIN = 11;
285
- var CARD_META_FONT = 12;
286
- var CARD_TITLE_MAX = 30;
287
- function fitWrapped(label, maxWidth, maxFont = CARD_LABEL_MAX, minFont = CARD_LABEL_MIN, maxLines = 2) {
421
+ var CARD_HEADER_H = SKETCH_VISUALS.cardHeaderHeight;
422
+ var CARD_LABEL_MAX = SKETCH_VISUALS.nodeLabelFontSize;
423
+ var CARD_LABEL_MIN = SKETCH_VISUALS.nodeLabelFontSizeMin;
424
+ var CARD_META_FONT = SKETCH_VISUALS.cardMetaFontSize;
425
+ var CARD_TITLE_MAX = SKETCH_VISUALS.nodeLabelFontSize;
426
+ function fitWrapped(label, maxWidth, maxFont, minFont, maxLines = 2) {
288
427
  const BOLD = { hardBreak: true, bold: true };
289
428
  for (let fs = maxFont; fs >= minFont; fs--) {
290
429
  const lines2 = wrapTextToWidth(label, fs, maxWidth, BOLD);
@@ -307,7 +446,34 @@ function renderSketch(container, parsed, layout, palette, isDark, options = {})
307
446
  splitCardIds
308
447
  } = options;
309
448
  const hideDesc = hideDescriptions || parsed.options.noDescriptions;
310
- const neutralFill = parsed.options.fillMode === "outline" ? themeBaseBg(palette, isDark) : mix(palette.textMuted, palette.bg, 12);
449
+ const sctx = ScaleContext.identity();
450
+ const sTitleFontSize = sctx.text(TITLE_FONT_SIZE2);
451
+ const sEdgeLabelFontSize = sctx.text(EDGE_LABEL_FONT_SIZE);
452
+ const sBandLabelFontSize = sctx.text(BAND_LABEL_FONT_SIZE);
453
+ const sNoteFontSize = sctx.text(NOTE_FONT_SIZE);
454
+ const sCardLabelMax = sctx.text(CARD_LABEL_MAX);
455
+ const sCardLabelMin = sctx.text(CARD_LABEL_MIN);
456
+ const sCardMetaFont = sctx.text(CARD_META_FONT);
457
+ const sCardTitleMax = sctx.text(CARD_TITLE_MAX);
458
+ const sNodeStrokeWidth = sctx.structural(NODE_STROKE_WIDTH2);
459
+ const sEdgeStrokeWidth = sctx.structural(EDGE_STROKE_WIDTH2);
460
+ const sCardRadius = sctx.structural(CARD_RADIUS);
461
+ const sContainerRadius = sctx.structural(CONTAINER_RADIUS);
462
+ const sCardHeaderH = sctx.structural(CARD_HEADER_H);
463
+ const sCollapseBarHeight = sctx.structural(COLLAPSE_BAR_HEIGHT2);
464
+ const scaled = {
465
+ nodeStrokeWidth: sNodeStrokeWidth,
466
+ cardRadius: sCardRadius,
467
+ containerRadius: sContainerRadius,
468
+ cardHeaderH: sCardHeaderH,
469
+ collapseBarHeight: sCollapseBarHeight,
470
+ cardLabelMax: sCardLabelMax,
471
+ cardLabelMin: sCardLabelMin,
472
+ cardMetaFont: sCardMetaFont,
473
+ cardTitleMax: sCardTitleMax,
474
+ bandLabelFontSize: sBandLabelFontSize,
475
+ noteFontSize: sNoteFontSize
476
+ };
311
477
  const tagGroups = [...parsed.tagGroups];
312
478
  const activeName = resolveActiveTagGroup(
313
479
  tagGroups,
@@ -315,27 +481,13 @@ function renderSketch(container, parsed, layout, palette, isDark, options = {})
315
481
  activeTagGroup
316
482
  );
317
483
  const activeKey = activeName === null ? null : tagAttrKey(activeName);
318
- const colorsFor = (metadata, isContainer = false) => {
319
- const tagged = activeKey !== null && metadata[activeKey] !== void 0;
320
- const tagColor = tagged ? resolveTagColor(metadata, tagGroups, activeName, isContainer) : void 0;
321
- if (!tagColor) {
322
- return {
323
- fill: neutralFill,
324
- stroke: palette.textMuted,
325
- text: palette.text
326
- };
327
- }
328
- const fill = shapeFill(palette, tagColor, isDark, {
329
- mode: parsed.options.fillMode
330
- });
331
- return {
332
- fill,
333
- stroke: tagColor,
334
- // Label text takes the shape's own (tag) color — but for solid fills the
335
- // tag color would vanish into the fill, so keep a contrast color there.
336
- text: parsed.options.fillMode === "solid" ? contrastText(fill, palette.textOnFillLight, palette.textOnFillDark) : tagColor
337
- };
338
- };
484
+ const colorsFor = sketchColors({
485
+ palette,
486
+ isDark,
487
+ tagGroups,
488
+ activeTagGroup,
489
+ fillMode: parsed.options.fillMode
490
+ });
339
491
  const showTitle = !!parsed.title;
340
492
  const titleOffset = showTitle ? 40 : 0;
341
493
  const legendGroups = parsed.options.noLegend ? [] : tagGroups;
@@ -356,8 +508,8 @@ function renderSketch(container, parsed, layout, palette, isDark, options = {})
356
508
  }
357
509
  const label = layout.edges[i]?.label;
358
510
  if (label) {
359
- const hw = measureText(label, EDGE_LABEL_FONT_SIZE) / 2 + 6;
360
- const hh = EDGE_LABEL_FONT_SIZE / 2 + 4;
511
+ const hw = measureText(label, sEdgeLabelFontSize) / 2 + 6;
512
+ const hh = sEdgeLabelFontSize / 2 + 4;
361
513
  minX = Math.min(minX, g.mid.x - hw);
362
514
  maxX = Math.max(maxX, g.mid.x + hw);
363
515
  minY = Math.min(minY, g.mid.y - hh);
@@ -401,8 +553,8 @@ function renderSketch(container, parsed, layout, palette, isDark, options = {})
401
553
  containerWidth: width,
402
554
  titleBandHeight: titleOffset,
403
555
  legendReserve: legendHeight,
404
- titleBaselineY: TITLE_Y,
405
- titleFontSize: TITLE_FONT_SIZE
556
+ titleBaselineY: TITLE_Y2,
557
+ titleFontSize: sTitleFontSize
406
558
  });
407
559
  const contentTop = titleOffset + (header.inline ? 0 : legendHeight) + DIAGRAM_PADDING + extraTop;
408
560
  const height = Math.max(
@@ -423,14 +575,14 @@ function renderSketch(container, parsed, layout, palette, isDark, options = {})
423
575
  const edgeColors = new Set(layout.edges.map((e) => flowColor(e)));
424
576
  for (const color of edgeColors) {
425
577
  const hex = color.replace("#", "");
426
- defs.append("marker").attr("id", `sk-arrow-${hex}`).attr("viewBox", `0 0 ${ARROWHEAD_W} ${ARROWHEAD_H}`).attr("refX", ARROWHEAD_W).attr("refY", ARROWHEAD_H / 2).attr("markerWidth", ARROWHEAD_W).attr("markerHeight", ARROWHEAD_H).attr("markerUnits", "userSpaceOnUse").attr("orient", "auto").append("polygon").attr("points", `0,0 ${ARROWHEAD_W},${ARROWHEAD_H / 2} 0,${ARROWHEAD_H}`).attr("fill", color);
427
- defs.append("marker").attr("id", `sk-arrow-rev-${hex}`).attr("viewBox", `0 0 ${ARROWHEAD_W} ${ARROWHEAD_H}`).attr("refX", 0).attr("refY", ARROWHEAD_H / 2).attr("markerWidth", ARROWHEAD_W).attr("markerHeight", ARROWHEAD_H).attr("markerUnits", "userSpaceOnUse").attr("orient", "auto").append("polygon").attr(
578
+ defs.append("marker").attr("id", `sk-arrow-${hex}`).attr("viewBox", `0 0 ${ARROWHEAD_W} ${ARROWHEAD_H}`).attr("refX", ARROWHEAD_W).attr("refY", ARROWHEAD_H / 2).attr("markerWidth", ARROWHEAD_W).attr("markerHeight", ARROWHEAD_H).attr("orient", "auto").append("polygon").attr("points", `0,0 ${ARROWHEAD_W},${ARROWHEAD_H / 2} 0,${ARROWHEAD_H}`).attr("fill", color);
579
+ defs.append("marker").attr("id", `sk-arrow-rev-${hex}`).attr("viewBox", `0 0 ${ARROWHEAD_W} ${ARROWHEAD_H}`).attr("refX", 0).attr("refY", ARROWHEAD_H / 2).attr("markerWidth", ARROWHEAD_W).attr("markerHeight", ARROWHEAD_H).attr("orient", "auto").append("polygon").attr(
428
580
  "points",
429
581
  `${ARROWHEAD_W},0 0,${ARROWHEAD_H / 2} ${ARROWHEAD_W},${ARROWHEAD_H}`
430
582
  ).attr("fill", color);
431
583
  }
432
584
  if (showTitle) {
433
- svg.append("text").attr("class", "chart-title").attr("x", header.titleX).attr("y", TITLE_Y).attr("text-anchor", header.titleAnchor).attr("font-size", TITLE_FONT_SIZE).attr("font-weight", 700).attr("fill", palette.text).text(parsed.title);
585
+ svg.append("text").attr("class", "chart-title").attr("x", header.titleX).attr("y", TITLE_Y2).attr("text-anchor", header.titleAnchor).attr("font-size", sTitleFontSize).attr("font-weight", 700).attr("fill", palette.text).text(parsed.title);
434
586
  }
435
587
  if (legendGroups.length > 0) {
436
588
  const legendG = svg.append("g").attr(
@@ -456,7 +608,7 @@ function renderSketch(container, parsed, layout, palette, isDark, options = {})
456
608
  const root = svg.append("g").attr("class", "sk-root").attr("transform", `translate(${contentX},${contentTop})`);
457
609
  const boxLayer = root.append("g").attr("class", "sk-boxes");
458
610
  for (const box of layout.boxes) {
459
- drawBoxFrame(boxLayer, box, colorsFor(box.metadata, true), palette);
611
+ drawBoxFrame(boxLayer, box, colorsFor(box.metadata, true), palette, scaled);
460
612
  }
461
613
  const edgeLayer = root.append("g").attr("class", "sk-edges");
462
614
  const labelLayerData = [];
@@ -468,7 +620,7 @@ function renderSketch(container, parsed, layout, palette, isDark, options = {})
468
620
  const hex = color.replace("#", "");
469
621
  const { d, mid } = geo;
470
622
  const g = edgeLayer.append("g").attr("class", "sk-edge-group").attr("data-from", edge.sourceId).attr("data-to", edge.targetId).attr("data-line-number", edge.lineNumber);
471
- const path = g.append("path").attr("d", geo.dRender ?? d).attr("fill", "none").attr("stroke", color).attr("stroke-width", EDGE_STROKE_WIDTH);
623
+ const path = g.append("path").attr("d", geo.dRender ?? d).attr("fill", "none").attr("stroke", color).attr("stroke-width", sEdgeStrokeWidth);
472
624
  if (edge.dashed) path.attr("stroke-dasharray", DASH);
473
625
  if (edge.heads === "one" || edge.heads === "both") {
474
626
  path.attr("marker-end", `url(#sk-arrow-${hex})`);
@@ -491,12 +643,18 @@ function renderSketch(container, parsed, layout, palette, isDark, options = {})
491
643
  }
492
644
  }
493
645
  {
494
- const labelW = (t) => t.length * EDGE_LABEL_FONT_SIZE * 0.56;
495
- const halfH = EDGE_LABEL_FONT_SIZE / 2 + 3;
646
+ const labelW = (t) => t.length * sEdgeLabelFontSize * 0.56;
647
+ const halfH = sEdgeLabelFontSize / 2 + 3;
496
648
  const GAP = 4;
497
649
  const shapeRects = [
498
650
  ...layout.nodes.map((n) => ({ x: n.x, y: n.y, w: n.w, h: n.h })),
499
- ...layout.boxes.map((b) => ({ x: b.x, y: b.y, w: b.w, h: b.h }))
651
+ ...layout.boxes.map((b) => ({
652
+ // The band the name is drawn in, not the frame below it.
653
+ x: b.x,
654
+ y: b.y,
655
+ w: b.w,
656
+ h: b.bandH
657
+ }))
500
658
  ];
501
659
  const cubicPt = (cp, t) => {
502
660
  const u = 1 - t;
@@ -518,42 +676,67 @@ function renderSketch(container, parsed, layout, palette, isDark, options = {})
518
676
  return pts;
519
677
  });
520
678
  const covers = (cx, cy, hw, ox, oy, ohw, ohh) => Math.abs(cx - ox) < hw + ohw + GAP && Math.abs(cy - oy) < halfH + ohh + GAP;
679
+ const normalAt = (cp, t) => {
680
+ const e = 0.01;
681
+ const a = cubicPt(cp, Math.max(0, t - e));
682
+ const b = cubicPt(cp, Math.min(1, t + e));
683
+ const dx = b.x - a.x;
684
+ const dy = b.y - a.y;
685
+ const len = Math.hypot(dx, dy);
686
+ return len === 0 ? { x: 0, y: -1 } : { x: -dy / len, y: dx / len };
687
+ };
521
688
  const placed = [];
522
689
  const TS = [0.5, 0.4, 0.6, 0.32, 0.68, 0.25, 0.75, 0.18, 0.82];
690
+ const PERP_STEP = 8;
691
+ const PERP_MAX = 40;
692
+ const PERP_OFFSETS = [0];
693
+ for (let d = PERP_STEP; d <= PERP_MAX; d += PERP_STEP)
694
+ PERP_OFFSETS.push(d, -d);
523
695
  for (const l of labelLayerData) {
524
696
  const hw = labelW(l.text) / 2 + 3;
525
- let bestT = 0.5;
697
+ let best = cubicPt(l.cp, 0.5);
526
698
  let bestScore = Infinity;
527
- for (const t of TS) {
528
- const p2 = cubicPt(l.cp, t);
529
- let labelHits = 0;
530
- for (const q of placed)
531
- if (covers(p2.x, p2.y, hw, q.x, q.y, q.hw, halfH)) labelHits++;
532
- let shapeHits = 0;
533
- for (const r of shapeRects)
534
- if (covers(p2.x, p2.y, hw, r.x + r.w / 2, r.y + r.h / 2, r.w / 2, r.h / 2))
535
- shapeHits++;
536
- let lineHits = 0;
537
- for (let k = 0; k < allPolys.length; k++) {
538
- if (k === l.ei) continue;
539
- const poly = allPolys[k];
540
- if (poly?.some((pt) => covers(p2.x, p2.y, hw, pt.x, pt.y, 0, 0)))
541
- lineHits++;
542
- }
543
- if (labelHits === 0 && shapeHits === 0 && lineHits === 0) {
544
- bestT = t;
545
- break;
546
- }
547
- const score = labelHits * 10 + shapeHits * 6 + lineHits * 4 + Math.abs(t - 0.5);
548
- if (score < bestScore) {
549
- bestScore = score;
550
- bestT = t;
699
+ search: for (const perp of PERP_OFFSETS) {
700
+ const n = perp === 0 ? { x: 0, y: 0 } : normalAt(l.cp, 0.5);
701
+ for (const t of TS) {
702
+ const base = cubicPt(l.cp, t);
703
+ const p = { x: base.x + n.x * perp, y: base.y + n.y * perp };
704
+ let labelHits = 0;
705
+ for (const q of placed)
706
+ if (covers(p.x, p.y, hw, q.x, q.y, q.hw, halfH)) labelHits++;
707
+ let shapeHits = 0;
708
+ for (const r of shapeRects)
709
+ if (covers(
710
+ p.x,
711
+ p.y,
712
+ hw,
713
+ r.x + r.w / 2,
714
+ r.y + r.h / 2,
715
+ r.w / 2,
716
+ r.h / 2
717
+ ))
718
+ shapeHits++;
719
+ let lineHits = 0;
720
+ for (let k = 0; k < allPolys.length; k++) {
721
+ if (k === l.ei) continue;
722
+ const poly = allPolys[k];
723
+ if (poly?.some((pt) => covers(p.x, p.y, hw, pt.x, pt.y, 0, 0)))
724
+ lineHits++;
725
+ }
726
+ if (labelHits === 0 && shapeHits === 0 && lineHits === 0) {
727
+ best = p;
728
+ break search;
729
+ }
730
+ const score = labelHits * 10 + shapeHits * 6 + lineHits * 4 + Math.abs(t - 0.5) + Math.abs(perp) / PERP_MAX;
731
+ if (score < bestScore) {
732
+ bestScore = score;
733
+ best = p;
734
+ }
551
735
  }
552
736
  }
553
- const p = cubicPt(l.cp, bestT);
554
- l.x = p.x;
555
- l.y = p.y;
556
- placed.push({ x: p.x, y: p.y, hw });
737
+ l.x = best.x;
738
+ l.y = best.y;
739
+ placed.push({ x: best.x, y: best.y, hw });
557
740
  }
558
741
  }
559
742
  const nodeLayer = root.append("g").attr("class", "sk-nodes");
@@ -569,13 +752,17 @@ function renderSketch(container, parsed, layout, palette, isDark, options = {})
569
752
  colorsFor(node.metadata),
570
753
  palette,
571
754
  isDark,
572
- !hideDesc && (splitCardIds?.includes(node.id) ?? false)
755
+ !hideDesc && (splitCardIds?.includes(node.id) ?? false),
756
+ scaled
573
757
  );
574
758
  }
575
759
  const labelLayer = root.append("g").attr("class", "sk-edge-labels");
576
760
  for (const l of labelLayerData) {
577
761
  const g = labelLayer.append("g").attr("class", "sk-edge-label").attr("data-from", l.from).attr("data-to", l.to);
578
- g.append("text").attr("x", l.x).attr("y", l.y).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", EDGE_LABEL_FONT_SIZE).attr("fill", l.color).attr("stroke", palette.bg).attr("stroke-width", 3).attr("stroke-linejoin", "round").attr("paint-order", "stroke").text(l.text);
762
+ const plateW = measureText(l.text, sEdgeLabelFontSize) + EDGE_LABEL_H_PAD * 2;
763
+ const plateH = sEdgeLabelFontSize * 1.3 + EDGE_LABEL_V_PAD * 2;
764
+ g.append("rect").attr("x", l.x - plateW / 2).attr("y", l.y - plateH / 2).attr("width", plateW).attr("height", plateH).attr("rx", 3).attr("fill", palette.bg).attr("opacity", EDGE_LABEL_KNOCKOUT_OPACITY);
765
+ g.append("text").attr("x", l.x).attr("y", l.y).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", sEdgeLabelFontSize).attr("fill", l.color).text(l.text);
579
766
  }
580
767
  if (options.onClickItem) {
581
768
  const handler = options.onClickItem;
@@ -585,18 +772,18 @@ function renderSketch(container, parsed, layout, palette, isDark, options = {})
585
772
  });
586
773
  }
587
774
  }
588
- function drawBoxFrame(layer, box, colors, palette) {
775
+ function drawBoxFrame(layer, box, colors, palette, s) {
589
776
  const g = layer.append("g").attr("class", "sk-box").attr("data-node-id", box.id).attr("data-group-toggle", box.label).attr("data-line-number", box.lineNumber);
590
- g.append("rect").attr("x", box.x).attr("y", box.y).attr("width", box.w).attr("height", box.h).attr("rx", CONTAINER_RADIUS).attr("fill", colors.fill).attr("fill-opacity", 0.4).attr("stroke", colors.stroke).attr("stroke-opacity", 0.7).attr("stroke-width", NODE_STROKE_WIDTH);
591
- const fit = fitWrapped(box.label, box.w - 16, BAND_LABEL_FONT_SIZE, 12, 2);
777
+ g.append("rect").attr("x", box.x).attr("y", box.y).attr("width", box.w).attr("height", box.h).attr("rx", s.containerRadius).attr("fill", colors.fill).attr("fill-opacity", CONTAINER_FILL_OPACITY).attr("stroke", colors.stroke).attr("stroke-opacity", CONTAINER_STROKE_OPACITY).attr("stroke-width", CONTAINER_STROKE_WIDTH);
778
+ const fit = fitWrapped(box.label, box.w - 16, s.bandLabelFontSize, 12, 2);
592
779
  const lineH = fit.fontSize * 1.2;
593
- const bandMid = box.y + box.bandH / 2;
780
+ const bandMid = box.y + CONTAINER_LABEL_BASELINE;
594
781
  const startY = bandMid - (fit.lines.length - 1) * lineH / 2;
595
782
  for (let li = 0; li < fit.lines.length; li++) {
596
- g.append("text").attr("x", box.x + box.w / 2).attr("y", startY + li * lineH).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", fit.fontSize).attr("font-weight", 800).attr("fill", palette.text).attr("opacity", BAND_LABEL_OPACITY).text(fit.lines[li]);
783
+ g.append("text").attr("x", box.x + box.w / 2).attr("y", startY + li * lineH).attr("text-anchor", "middle").attr("dominant-baseline", "central").attr("font-size", fit.fontSize).attr("font-weight", BAND_LABEL_WEIGHT).attr("fill", palette.text).attr("opacity", BAND_LABEL_OPACITY).text(fit.lines[li]);
597
784
  }
598
785
  }
599
- function drawNode(layer, node, colors, palette, isDark, splitCard) {
786
+ function drawNode(layer, node, colors, palette, isDark, splitCard, s) {
600
787
  void isDark;
601
788
  const g = layer.append("g").attr("class", node.isCollapsedBox ? "sk-node sk-box-collapsed" : "sk-node").attr("transform", `translate(${node.x},${node.y})`).attr("data-node-id", node.id).attr("data-line-number", node.lineNumber);
602
789
  for (const [k, v] of Object.entries(node.metadata)) {
@@ -606,11 +793,11 @@ function drawNode(layer, node, colors, palette, isDark, splitCard) {
606
793
  g.attr("data-group-toggle", node.label);
607
794
  }
608
795
  if (node.shape === "note") {
609
- drawNoteBody(g, node.w, node.h, colors);
610
- const lines = wrapTextToWidth(node.label, NOTE_FONT_SIZE, node.w - 34);
611
- const lineHeight = NOTE_FONT_SIZE + 4;
796
+ drawNoteBody(g, node.w, node.h, colors, s.nodeStrokeWidth);
797
+ const lines = wrapTextToWidth(node.label, s.noteFontSize, node.w - 34);
798
+ const lineHeight = s.noteFontSize + 4;
612
799
  lines.slice(0, 5).forEach((line, i) => {
613
- g.append("text").attr("x", 10).attr("y", 20 + i * lineHeight).attr("font-size", NOTE_FONT_SIZE).attr("fill", colors.text).text(line);
800
+ g.append("text").attr("x", 10).attr("y", 20 + i * lineHeight).attr("font-size", s.noteFontSize).attr("fill", colors.text).text(line);
614
801
  });
615
802
  } else {
616
803
  const badge = node.shape !== "rectangle";
@@ -621,32 +808,32 @@ function drawNode(layer, node, colors, palette, isDark, splitCard) {
621
808
  const fitH = fitWrapped(
622
809
  node.label,
623
810
  node.w - 24 - labelInset,
624
- CARD_LABEL_MAX,
625
- CARD_LABEL_MIN,
811
+ s.cardLabelMax,
812
+ s.cardLabelMin,
626
813
  1
627
814
  );
628
815
  renderNodeCard(g, {
629
816
  width: node.w,
630
817
  height: node.h,
631
- rx: CARD_RADIUS,
818
+ rx: s.cardRadius,
632
819
  fill: colors.fill,
633
820
  stroke: colors.stroke,
634
- strokeWidth: NODE_STROKE_WIDTH,
821
+ strokeWidth: s.nodeStrokeWidth,
635
822
  label: fitH.lines[0] ?? node.label,
636
823
  labelColor: colors.text,
637
824
  labelFontSize: fitH.fontSize,
638
- headerHeight: CARD_HEADER_H
825
+ headerHeight: s.cardHeaderH
639
826
  });
640
- g.append("line").attr("x1", 0).attr("y1", CARD_HEADER_H).attr("x2", node.w).attr("y2", CARD_HEADER_H).attr("stroke", ruleColor).attr("stroke-opacity", 0.3).attr("stroke-width", 1);
827
+ g.append("line").attr("x1", 0).attr("y1", s.cardHeaderH).attr("x2", node.w).attr("y2", s.cardHeaderH).attr("stroke", ruleColor).attr("stroke-opacity", 0.3).attr("stroke-width", 1);
641
828
  if (node.description) {
642
829
  const inset = 12;
643
830
  const bodyGap = 8;
644
- const lh = CARD_META_FONT + 4;
645
- const avail = node.h - CARD_HEADER_H - bodyGap - 8;
646
- const body = g.append("g").attr("class", "sk-desc").attr("transform", `translate(${inset} ${CARD_HEADER_H + bodyGap})`);
831
+ const lh = s.cardMetaFont + 4;
832
+ const avail = node.h - s.cardHeaderH - bodyGap - 8;
833
+ const body = g.append("g").attr("class", "sk-desc").attr("transform", `translate(${inset} ${s.cardHeaderH + bodyGap})`);
647
834
  const block = drawMarkdownBlock(body, node.description, {
648
835
  width: node.w - inset * 2,
649
- fontSize: CARD_META_FONT,
836
+ fontSize: s.cardMetaFont,
650
837
  lineHeight: lh,
651
838
  color: colors.text,
652
839
  // match the header label (contrast-aware in solid)
@@ -659,24 +846,24 @@ function drawNode(layer, node, colors, palette, isDark, splitCard) {
659
846
  }
660
847
  }
661
848
  if (badge) {
662
- drawTypeBadge(g, node.shape, colors.text, 10, (CARD_HEADER_H - 16) / 2);
849
+ drawTypeBadge(g, node.shape, colors.text, 10, (s.cardHeaderH - 16) / 2);
663
850
  }
664
851
  return;
665
852
  }
666
853
  const fit = fitWrapped(
667
854
  node.label,
668
855
  node.w - 24 - labelInset,
669
- CARD_TITLE_MAX,
670
- CARD_LABEL_MIN,
856
+ s.cardTitleMax,
857
+ s.cardLabelMin,
671
858
  3
672
859
  );
673
860
  renderNodeCard(g, {
674
861
  width: node.w,
675
862
  height: node.h,
676
- rx: CARD_RADIUS,
863
+ rx: s.cardRadius,
677
864
  fill: colors.fill,
678
865
  stroke: colors.stroke,
679
- strokeWidth: NODE_STROKE_WIDTH,
866
+ strokeWidth: s.nodeStrokeWidth,
680
867
  label: fit.lines.join(" "),
681
868
  labelLines: fit.lines,
682
869
  labelColor: colors.text,
@@ -684,16 +871,16 @@ function drawNode(layer, node, colors, palette, isDark, splitCard) {
684
871
  headerHeight: node.h
685
872
  });
686
873
  if (badge) {
687
- drawTypeBadge(g, node.shape, colors.text, 10, (CARD_HEADER_H - 16) / 2);
874
+ drawTypeBadge(g, node.shape, colors.text, 10, (s.cardHeaderH - 16) / 2);
688
875
  }
689
876
  }
690
877
  if (node.isCollapsedBox) {
691
878
  renderCollapseBar(g, {
692
879
  width: node.w,
693
880
  height: node.h,
694
- barHeight: COLLAPSE_BAR_HEIGHT,
881
+ barHeight: s.collapseBarHeight,
695
882
  inset: 0,
696
- rx: CARD_RADIUS,
883
+ rx: s.cardRadius,
697
884
  fill: colors.stroke === palette.textMuted ? palette.textMuted : colors.stroke,
698
885
  clipId: `sk-clip-${node.id.replace(/[^a-zA-Z0-9_-]/g, "")}-${node.lineNumber}`,
699
886
  className: "sk-collapse-bar"
@@ -1123,8 +1310,15 @@ function renderSketchForExport(container, parsed, layout, palette, isDark, optio
1123
1310
  }
1124
1311
 
1125
1312
  export {
1313
+ CONTAINER_FILL_OPACITY,
1314
+ CONTAINER_STROKE_OPACITY,
1315
+ CONTAINER_STROKE_WIDTH,
1316
+ sketchContainerFill,
1317
+ sketchNeutralFill,
1318
+ sketchColors,
1319
+ SKETCH_VISUALS,
1126
1320
  renderSketch,
1127
1321
  sketchEdgeGeometry,
1128
1322
  renderSketchForExport
1129
1323
  };
1130
- //# sourceMappingURL=chunk-U7AO6FRL.js.map
1324
+ //# sourceMappingURL=chunk-H7BYMIVK.js.map