@diagrammo/dgmo 0.14.1 → 0.15.1

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 (71) hide show
  1. package/README.md +14 -1
  2. package/dist/advanced.cjs +53069 -0
  3. package/dist/advanced.d.cts +4691 -0
  4. package/dist/advanced.d.ts +4691 -0
  5. package/dist/advanced.js +52823 -0
  6. package/dist/auto.cjs +1557 -1295
  7. package/dist/auto.js +132 -713
  8. package/dist/auto.mjs +1553 -1291
  9. package/dist/cli.cjs +173 -150
  10. package/dist/editor.cjs +1 -0
  11. package/dist/editor.js +1 -0
  12. package/dist/highlight.cjs +1 -0
  13. package/dist/highlight.js +1 -0
  14. package/dist/index.cjs +2031 -4722
  15. package/dist/index.d.cts +96 -4464
  16. package/dist/index.d.ts +96 -4464
  17. package/dist/index.js +2024 -4475
  18. package/dist/internal.cjs +51930 -553
  19. package/dist/internal.d.cts +4526 -102
  20. package/dist/internal.d.ts +4526 -102
  21. package/dist/internal.js +51721 -548
  22. package/dist/pert.cjs +1 -1
  23. package/dist/pert.js +1 -1
  24. package/docs/language-reference.md +67 -17
  25. package/package.json +18 -3
  26. package/src/advanced.ts +731 -0
  27. package/src/auto/index.ts +14 -13
  28. package/src/boxes-and-lines/layout.ts +481 -445
  29. package/src/c4/parser.ts +7 -7
  30. package/src/chart-types.ts +0 -5
  31. package/src/class/parser.ts +1 -9
  32. package/src/cli.ts +9 -7
  33. package/src/completion-types.ts +28 -0
  34. package/src/completion.ts +15 -18
  35. package/src/cycle/layout.ts +2 -2
  36. package/src/d3.ts +1455 -1122
  37. package/src/echarts.ts +11 -11
  38. package/src/editor/keywords.ts +1 -0
  39. package/src/er/parser.ts +1 -9
  40. package/src/er/renderer.ts +1 -1
  41. package/src/gantt/calculator.ts +1 -11
  42. package/src/gantt/parser.ts +16 -16
  43. package/src/gantt/renderer.ts +2 -2
  44. package/src/graph/flowchart-parser.ts +1 -1
  45. package/src/graph/flowchart-renderer.ts +1 -1
  46. package/src/graph/state-renderer.ts +1 -1
  47. package/src/index.ts +213 -690
  48. package/src/infra/parser.ts +57 -25
  49. package/src/infra/renderer.ts +2 -2
  50. package/src/internal.ts +11 -17
  51. package/src/kanban/parser.ts +2 -2
  52. package/src/mindmap/layout.ts +1 -1
  53. package/src/mindmap/parser.ts +1 -1
  54. package/src/org/parser.ts +1 -1
  55. package/src/org/renderer.ts +1 -1
  56. package/src/palettes/index.ts +39 -0
  57. package/src/pert/layout.ts +1 -1
  58. package/src/pert/monte-carlo.ts +2 -2
  59. package/src/pert/parser.ts +3 -3
  60. package/src/raci/parser.ts +4 -4
  61. package/src/raci/renderer.ts +1 -1
  62. package/src/render.ts +17 -1
  63. package/src/sequence/renderer.ts +1 -4
  64. package/src/sitemap/parser.ts +1 -1
  65. package/src/tech-radar/interactive.ts +1 -1
  66. package/src/tech-radar/renderer.ts +1 -1
  67. package/src/themes.ts +22 -0
  68. package/src/utils/tag-groups.ts +11 -12
  69. package/src/wireframe/layout.ts +11 -7
  70. package/src/wireframe/parser.ts +2 -2
  71. package/src/wireframe/renderer.ts +5 -2
package/dist/auto.mjs CHANGED
@@ -1759,6 +1759,7 @@ __export(palettes_exports, {
1759
1759
  monokaiPalette: () => monokaiPalette,
1760
1760
  nordPalette: () => nordPalette,
1761
1761
  oneDarkPalette: () => oneDarkPalette,
1762
+ palettes: () => palettes,
1762
1763
  registerPalette: () => registerPalette,
1763
1764
  rosePinePalette: () => rosePinePalette,
1764
1765
  shade: () => shade,
@@ -1767,6 +1768,7 @@ __export(palettes_exports, {
1767
1768
  tint: () => tint,
1768
1769
  tokyoNightPalette: () => tokyoNightPalette
1769
1770
  });
1771
+ var palettes;
1770
1772
  var init_palettes = __esm({
1771
1773
  "src/palettes/index.ts"() {
1772
1774
  "use strict";
@@ -1782,6 +1784,28 @@ var init_palettes = __esm({
1782
1784
  init_tokyo_night();
1783
1785
  init_dracula();
1784
1786
  init_monokai();
1787
+ init_bold();
1788
+ init_catppuccin();
1789
+ init_dracula();
1790
+ init_gruvbox();
1791
+ init_monokai();
1792
+ init_nord();
1793
+ init_one_dark();
1794
+ init_rose_pine();
1795
+ init_solarized();
1796
+ init_tokyo_night();
1797
+ palettes = {
1798
+ nord: nordPalette,
1799
+ catppuccin: catppuccinPalette,
1800
+ solarized: solarizedPalette,
1801
+ gruvbox: gruvboxPalette,
1802
+ tokyoNight: tokyoNightPalette,
1803
+ oneDark: oneDarkPalette,
1804
+ rosePine: rosePinePalette,
1805
+ dracula: draculaPalette,
1806
+ monokai: monokaiPalette,
1807
+ bold: boldPalette
1808
+ };
1785
1809
  }
1786
1810
  });
1787
1811
 
@@ -2212,7 +2236,7 @@ function injectDefaultTagMetadata(entities, tagGroups, skip) {
2212
2236
  }
2213
2237
  }
2214
2238
  }
2215
- function resolveActiveTagGroup(_tagGroups, explicitActiveTag, programmaticOverride) {
2239
+ function resolveActiveTagGroup(tagGroups, explicitActiveTag, programmaticOverride) {
2216
2240
  if (programmaticOverride !== void 0) {
2217
2241
  if (!programmaticOverride) return null;
2218
2242
  if (programmaticOverride.toLowerCase() === "none") return null;
@@ -2222,6 +2246,7 @@ function resolveActiveTagGroup(_tagGroups, explicitActiveTag, programmaticOverri
2222
2246
  if (explicitActiveTag.toLowerCase() === "none") return null;
2223
2247
  return explicitActiveTag;
2224
2248
  }
2249
+ if (tagGroups.length > 0) return tagGroups[0].name;
2225
2250
  return null;
2226
2251
  }
2227
2252
  function matchTagBlockHeading(trimmed) {
@@ -5302,12 +5327,6 @@ function parseClassDiagram(content, palette) {
5302
5327
  diagnostics: [],
5303
5328
  error: null
5304
5329
  };
5305
- const _fail = (line12, message) => {
5306
- const diag = makeDgmoError(line12, message);
5307
- result.diagnostics.push(diag);
5308
- result.error = formatDgmoError(diag);
5309
- return result;
5310
- };
5311
5330
  const classMap = /* @__PURE__ */ new Map();
5312
5331
  const nameAliasMap = /* @__PURE__ */ new Map();
5313
5332
  function resolveAliasName(token) {
@@ -5702,12 +5721,6 @@ function parseERDiagram(content, palette) {
5702
5721
  diagnostics: [],
5703
5722
  error: null
5704
5723
  };
5705
- const _fail = (line12, message) => {
5706
- const diag = makeDgmoError(line12, message);
5707
- result.diagnostics.push(diag);
5708
- result.error = formatDgmoError(diag);
5709
- return result;
5710
- };
5711
5724
  const pushError = (line12, message) => {
5712
5725
  const diag = makeDgmoError(line12, message);
5713
5726
  result.diagnostics.push(diag);
@@ -7166,7 +7179,7 @@ function buildSankeyOption(parsed, textColor, colors, bg, titleConfig) {
7166
7179
  ]
7167
7180
  };
7168
7181
  }
7169
- function buildChordOption(parsed, palette, isDark, textColor, colors, bg, titleConfig) {
7182
+ function buildChordOption(parsed, palette, isDark, textColor, colors, _bg, titleConfig) {
7170
7183
  const nodeSet = /* @__PURE__ */ new Set();
7171
7184
  if (parsed.links) {
7172
7185
  for (const link of parsed.links) {
@@ -7280,7 +7293,7 @@ function evaluateExpression(expr, x) {
7280
7293
  return NaN;
7281
7294
  }
7282
7295
  }
7283
- function buildFunctionOption(parsed, palette, isDark, textColor, axisLineColor, gridOpacity, colors, titleConfig) {
7296
+ function buildFunctionOption(parsed, palette, _isDark, textColor, axisLineColor, gridOpacity, colors, titleConfig) {
7284
7297
  const xRange = parsed.xRange ?? { min: -10, max: 10 };
7285
7298
  const samples = 200;
7286
7299
  const step = (xRange.max - xRange.min) / samples;
@@ -7953,7 +7966,7 @@ function buildHeatmapOption(parsed, palette, isDark, textColor, axisLineColor, t
7953
7966
  ]
7954
7967
  };
7955
7968
  }
7956
- function buildFunnelOption(parsed, palette, isDark, textColor, colors, bg, titleConfig) {
7969
+ function buildFunnelOption(parsed, palette, isDark, textColor, colors, _bg, titleConfig) {
7957
7970
  const sorted = [...parsed.data].sort((a, b) => b.value - a.value);
7958
7971
  const data = sorted.map((d) => {
7959
7972
  const stroke2 = d.color ?? colors[parsed.data.indexOf(d) % colors.length];
@@ -8236,7 +8249,7 @@ function wrapLabel(text, maxChars) {
8236
8249
  if (current) lines.push(current);
8237
8250
  return lines.join("\n");
8238
8251
  }
8239
- function buildBarOption(parsed, palette, isDark, textColor, axisLineColor, splitLineColor, gridOpacity, colors, bg, titleConfig, chartWidth) {
8252
+ function buildBarOption(parsed, palette, isDark, textColor, axisLineColor, splitLineColor, gridOpacity, colors, _bg, titleConfig, chartWidth) {
8240
8253
  const { xLabel, yLabel } = resolveAxisLabels(parsed);
8241
8254
  const isHorizontal = parsed.orientation === "horizontal";
8242
8255
  const labels = parsed.data.map((d) => d.label);
@@ -8563,7 +8576,7 @@ function pieLabelLayout(parsed) {
8563
8576
  if (maxLen > 18) return { outerRadius: 55, fontSize: 13 };
8564
8577
  return { outerRadius: 70, fontSize: 14 };
8565
8578
  }
8566
- function buildPieOption(parsed, palette, isDark, textColor, colors, bg, titleConfig, isDoughnut) {
8579
+ function buildPieOption(parsed, palette, isDark, textColor, colors, _bg, titleConfig, isDoughnut) {
8567
8580
  const HIDE_AXES = { xAxis: { show: false }, yAxis: { show: false } };
8568
8581
  const data = parsed.data.map((d, i) => {
8569
8582
  const stroke2 = d.color ?? colors[i % colors.length];
@@ -8662,7 +8675,7 @@ function buildRadarOption(parsed, palette, isDark, textColor, gridOpacity, title
8662
8675
  ]
8663
8676
  };
8664
8677
  }
8665
- function buildPolarAreaOption(parsed, palette, isDark, textColor, colors, bg, titleConfig) {
8678
+ function buildPolarAreaOption(parsed, palette, isDark, textColor, colors, _bg, titleConfig) {
8666
8679
  const data = parsed.data.map((d, i) => {
8667
8680
  const stroke2 = d.color ?? colors[i % colors.length];
8668
8681
  return {
@@ -8705,7 +8718,7 @@ function buildPolarAreaOption(parsed, palette, isDark, textColor, colors, bg, ti
8705
8718
  ]
8706
8719
  };
8707
8720
  }
8708
- function buildBarStackedOption(parsed, palette, isDark, textColor, axisLineColor, splitLineColor, gridOpacity, colors, bg, titleConfig, chartWidth) {
8721
+ function buildBarStackedOption(parsed, palette, isDark, textColor, axisLineColor, splitLineColor, gridOpacity, colors, _bg, titleConfig, chartWidth) {
8709
8722
  const { xLabel, yLabel } = resolveAxisLabels(parsed);
8710
8723
  const isHorizontal = parsed.orientation === "horizontal";
8711
8724
  const seriesNames = parsed.seriesNames ?? [];
@@ -8845,8 +8858,8 @@ async function renderExtendedChartForExport(content, theme, palette) {
8845
8858
  const titleHeight = option.title && option.title.text ? 40 : 0;
8846
8859
  const legendY = 8 + titleHeight;
8847
8860
  const grid = option.grid;
8848
- const gridLeftPct = grid?.left ? parseFloat(String(grid.left)) : void 0;
8849
- const gridRightPct = grid?.right ? parseFloat(String(grid.right)) : void 0;
8861
+ const gridLeftPct = grid?.["left"] ? parseFloat(String(grid["left"])) : void 0;
8862
+ const gridRightPct = grid?.["right"] ? parseFloat(String(grid["right"])) : void 0;
8850
8863
  const { svg: legendSvgStr } = renderLegendSvg(legendGroups, {
8851
8864
  palette: effectivePalette,
8852
8865
  isDark,
@@ -9192,7 +9205,7 @@ function parseOrg(content, palette) {
9192
9205
  }
9193
9206
  return result;
9194
9207
  }
9195
- function parseNodeLabel(trimmed, _indent, lineNumber, palette, counter, metaAliasMap = /* @__PURE__ */ new Map(), warnFn, nameAliasMap) {
9208
+ function parseNodeLabel(trimmed, _indent, lineNumber, _palette, counter, metaAliasMap = /* @__PURE__ */ new Map(), warnFn, nameAliasMap) {
9196
9209
  const segments = trimmed.split("|").map((s) => s.trim());
9197
9210
  let label = segments[0];
9198
9211
  const asMatch = label.match(/^(.*?)\s+as\s+([A-Za-z][A-Za-z0-9_]{0,11})\s*$/);
@@ -9441,8 +9454,8 @@ function parseKanban(content, palette) {
9441
9454
  columnMetadata,
9442
9455
  parsePipeMetadata(pipeSegments, metaAliasMap)
9443
9456
  );
9444
- if (columnMetadata.wip) {
9445
- const wipVal = parseInt(columnMetadata.wip, 10);
9457
+ if (columnMetadata["wip"]) {
9458
+ const wipVal = parseInt(columnMetadata["wip"], 10);
9446
9459
  if (!isNaN(wipVal)) {
9447
9460
  wipLimit = wipVal;
9448
9461
  }
@@ -9821,7 +9834,7 @@ function parseC4(content, palette) {
9821
9834
  );
9822
9835
  const shape = inferC4Shape(
9823
9836
  nodeName,
9824
- metadata.tech ?? metadata.technology
9837
+ metadata["tech"] ?? metadata["technology"]
9825
9838
  );
9826
9839
  const dNode = {
9827
9840
  name: nodeName,
@@ -9924,11 +9937,11 @@ function parseC4(content, palette) {
9924
9937
  target = targetBody.substring(0, pipeIdx).trim();
9925
9938
  const metaPart = targetBody.substring(pipeIdx + 1).trim();
9926
9939
  const meta = parsePipeMetadata(["", metaPart], metaAliasMap);
9927
- if (meta.tech) {
9928
- technology = meta.tech;
9940
+ if (meta["tech"]) {
9941
+ technology = meta["tech"];
9929
9942
  }
9930
- if (meta.technology) {
9931
- technology = meta.technology;
9943
+ if (meta["technology"]) {
9944
+ technology = meta["technology"];
9932
9945
  }
9933
9946
  }
9934
9947
  const rel = {
@@ -10062,7 +10075,7 @@ function parseC4(content, palette) {
10062
10075
  metaAliasMap,
10063
10076
  () => pushError(lineNumber, MULTIPLE_PIPE_ERROR)
10064
10077
  );
10065
- const shape = explicitShape ?? inferC4Shape(namePart, metadata.tech ?? metadata.technology);
10078
+ const shape = explicitShape ?? inferC4Shape(namePart, metadata["tech"] ?? metadata["technology"]);
10066
10079
  let isADescription;
10067
10080
  if ("description" in metadata) {
10068
10081
  const descVal = metadata["description"].trim();
@@ -10122,7 +10135,7 @@ function parseC4(content, palette) {
10122
10135
  metaAliasMap,
10123
10136
  () => pushError(lineNumber, MULTIPLE_PIPE_ERROR)
10124
10137
  );
10125
- const shape = explicitShape ?? inferC4Shape(namePart, metadata.tech ?? metadata.technology);
10138
+ const shape = explicitShape ?? inferC4Shape(namePart, metadata["tech"] ?? metadata["technology"]);
10126
10139
  let prefixDescription;
10127
10140
  if ("description" in metadata) {
10128
10141
  const descVal = metadata["description"].trim();
@@ -10731,7 +10744,7 @@ function parseSitemap(content, palette) {
10731
10744
  }
10732
10745
  return result;
10733
10746
  }
10734
- function parseNodeLabel2(trimmed, lineNumber, palette, counter, metaAliasMap = /* @__PURE__ */ new Map(), warnFn, _diagnostics, nameAliasMap) {
10747
+ function parseNodeLabel2(trimmed, lineNumber, _palette, counter, metaAliasMap = /* @__PURE__ */ new Map(), warnFn, _diagnostics, nameAliasMap) {
10735
10748
  const segments = trimmed.split("|").map((s) => s.trim());
10736
10749
  let label = segments[0];
10737
10750
  const asMatch = label.match(/^(.*?)\s+as\s+([A-Za-z][A-Za-z0-9_]{0,11})\s*$/);
@@ -10908,6 +10921,17 @@ function parseInfra(content) {
10908
10921
  if (!m) return { label: trimmed };
10909
10922
  return { label: m[1].trim(), alias: m[2] };
10910
10923
  }
10924
+ const IS_A_SUFFIX = /^(.*?)\s+is\s+an?\s+[A-Za-z][\w-]*\s*$/i;
10925
+ function peelInfraDecorations(rawName, lineNumber) {
10926
+ const peeled = peelAlias2(rawName);
10927
+ const m = peeled.label.match(IS_A_SUFFIX);
10928
+ if (!m) return peeled;
10929
+ warn2(
10930
+ lineNumber,
10931
+ `Infra nodes don't use 'is a <type>' \u2014 types are inferred from properties (cache-hit, buffer, drain-rate, \u2026). Drop the 'is a' suffix.`
10932
+ );
10933
+ return { label: m[1].trim(), alias: peeled.alias };
10934
+ }
10911
10935
  function resolveTargetId(rawName) {
10912
10936
  const aliasResolved = nameAliasMap.get(rawName.trim());
10913
10937
  if (aliasResolved !== void 0) return aliasResolved;
@@ -11011,11 +11035,11 @@ function parseInfra(content) {
11011
11035
  continue;
11012
11036
  }
11013
11037
  if (trimmed === "animate") {
11014
- result.options.animate = "on";
11038
+ result.options["animate"] = "on";
11015
11039
  continue;
11016
11040
  }
11017
11041
  if (trimmed === "no-animate") {
11018
- result.options.animate = "off";
11042
+ result.options["animate"] = "off";
11019
11043
  continue;
11020
11044
  }
11021
11045
  if (tryParseSharedOption(trimmed, result.options)) {
@@ -11062,7 +11086,7 @@ function parseInfra(content) {
11062
11086
  finishCurrentNode();
11063
11087
  finishCurrentTagGroup();
11064
11088
  const rawName = (compMatch[1] ?? compMatch[2] ?? "").trim();
11065
- const peeled = peelAlias2(rawName);
11089
+ const peeled = peelInfraDecorations(rawName, lineNumber);
11066
11090
  const name = peeled.label;
11067
11091
  const rest = compMatch[3] || "";
11068
11092
  const { tags } = extractPipeMetadata(rest);
@@ -11133,7 +11157,7 @@ function parseInfra(content) {
11133
11157
  if (compMatch) {
11134
11158
  finishCurrentTagGroup();
11135
11159
  const rawName = (compMatch[1] ?? compMatch[2] ?? "").trim();
11136
- const peeled = peelAlias2(rawName);
11160
+ const peeled = peelInfraDecorations(rawName, lineNumber);
11137
11161
  const name = peeled.label;
11138
11162
  const rest = compMatch[3] || "";
11139
11163
  const { tags: nodeTags } = extractPipeMetadata(rest);
@@ -11169,8 +11193,8 @@ function parseInfra(content) {
11169
11193
  const pipeMeta = extractPipeMetadata(targetRaw);
11170
11194
  const targetName = pipeMeta.clean || targetRaw;
11171
11195
  warnUnparsedPipeMeta(targetName, lineNumber, warn2);
11172
- const split = pipeMeta.tags.split ? parseFloat(pipeMeta.tags.split) : null;
11173
- const fanoutRaw = pipeMeta.tags.fanout ? parseInt(pipeMeta.tags.fanout, 10) : null;
11196
+ const split = pipeMeta.tags["split"] ? parseFloat(pipeMeta.tags["split"]) : null;
11197
+ const fanoutRaw = pipeMeta.tags["fanout"] ? parseInt(pipeMeta.tags["fanout"], 10) : null;
11174
11198
  if (fanoutRaw !== null && fanoutRaw < 1) {
11175
11199
  warn2(
11176
11200
  lineNumber,
@@ -11201,8 +11225,8 @@ function parseInfra(content) {
11201
11225
  const pipeMeta = extractPipeMetadata(targetRaw);
11202
11226
  const targetName = pipeMeta.clean || targetRaw;
11203
11227
  warnUnparsedPipeMeta(targetName, lineNumber, warn2);
11204
- const split = pipeMeta.tags.split ? parseFloat(pipeMeta.tags.split) : null;
11205
- const fanoutRaw = pipeMeta.tags.fanout ? parseInt(pipeMeta.tags.fanout, 10) : null;
11228
+ const split = pipeMeta.tags["split"] ? parseFloat(pipeMeta.tags["split"]) : null;
11229
+ const fanoutRaw = pipeMeta.tags["fanout"] ? parseInt(pipeMeta.tags["fanout"], 10) : null;
11206
11230
  if (fanoutRaw !== null && fanoutRaw < 1) {
11207
11231
  warn2(
11208
11232
  lineNumber,
@@ -11236,8 +11260,8 @@ function parseInfra(content) {
11236
11260
  const pipeMeta = extractPipeMetadata(targetRaw);
11237
11261
  const targetName = pipeMeta.clean || targetRaw;
11238
11262
  warnUnparsedPipeMeta(targetName, lineNumber, warn2);
11239
- const split = pipeMeta.tags.split ? parseFloat(pipeMeta.tags.split) : null;
11240
- const fanoutRaw = pipeMeta.tags.fanout ? parseInt(pipeMeta.tags.fanout, 10) : null;
11263
+ const split = pipeMeta.tags["split"] ? parseFloat(pipeMeta.tags["split"]) : null;
11264
+ const fanoutRaw = pipeMeta.tags["fanout"] ? parseInt(pipeMeta.tags["fanout"], 10) : null;
11241
11265
  if (fanoutRaw !== null && fanoutRaw < 1) {
11242
11266
  warn2(
11243
11267
  lineNumber,
@@ -11268,8 +11292,8 @@ function parseInfra(content) {
11268
11292
  const pipeMeta = extractPipeMetadata(targetRaw);
11269
11293
  const targetName = pipeMeta.clean || targetRaw;
11270
11294
  warnUnparsedPipeMeta(targetName, lineNumber, warn2);
11271
- const split = pipeMeta.tags.split ? parseFloat(pipeMeta.tags.split) : null;
11272
- const fanoutRaw = pipeMeta.tags.fanout ? parseInt(pipeMeta.tags.fanout, 10) : null;
11295
+ const split = pipeMeta.tags["split"] ? parseFloat(pipeMeta.tags["split"]) : null;
11296
+ const fanoutRaw = pipeMeta.tags["fanout"] ? parseInt(pipeMeta.tags["fanout"], 10) : null;
11273
11297
  if (fanoutRaw !== null && fanoutRaw < 1) {
11274
11298
  warn2(
11275
11299
  lineNumber,
@@ -11352,7 +11376,7 @@ function parseInfra(content) {
11352
11376
  const compMatch = trimmed.match(COMPONENT_RE);
11353
11377
  if (compMatch) {
11354
11378
  const rawName = (compMatch[1] ?? compMatch[2] ?? "").trim();
11355
- const peeled = peelAlias2(rawName);
11379
+ const peeled = peelInfraDecorations(rawName, lineNumber);
11356
11380
  const name = peeled.label;
11357
11381
  const rest = compMatch[3] || "";
11358
11382
  const { tags: nodeTags } = extractPipeMetadata(rest);
@@ -11378,10 +11402,13 @@ function parseInfra(content) {
11378
11402
  finishCurrentNode();
11379
11403
  finishCurrentTagGroup();
11380
11404
  currentGroup = null;
11381
- const name = (compMatch[1] ?? compMatch[2] ?? "").trim();
11405
+ const rawName = (compMatch[1] ?? compMatch[2] ?? "").trim();
11406
+ const peeled = peelInfraDecorations(rawName, lineNumber);
11407
+ const name = peeled.label;
11382
11408
  const rest = compMatch[3] || "";
11383
11409
  const { tags } = extractPipeMetadata(rest);
11384
11410
  const id = nodeId2(name);
11411
+ if (peeled.alias) nameAliasMap.set(peeled.alias, id);
11385
11412
  currentNode = {
11386
11413
  id,
11387
11414
  label: name,
@@ -11431,6 +11458,14 @@ function parseInfra(content) {
11431
11458
  validateTagGroupNames(result.tagGroups, warn2, setError);
11432
11459
  return result;
11433
11460
  }
11461
+ function stripNodeDecorations(name) {
11462
+ let s = name.trim();
11463
+ const aliasMatch = s.match(/^(.*?)\s+as\s+[A-Za-z][A-Za-z0-9_]{0,11}\s*$/);
11464
+ if (aliasMatch) s = aliasMatch[1].trim();
11465
+ const isAMatch = s.match(/^(.*?)\s+is\s+an?\s+[A-Za-z][\w-]*\s*$/i);
11466
+ if (isAMatch) s = isAMatch[1].trim();
11467
+ return s;
11468
+ }
11434
11469
  function extractSymbols4(docText) {
11435
11470
  const entities = [];
11436
11471
  let inMetadata = true;
@@ -11464,7 +11499,7 @@ function extractSymbols4(docText) {
11464
11499
  if (/^\[/.test(line12)) continue;
11465
11500
  const m = COMPONENT_RE.exec(line12);
11466
11501
  if (m) {
11467
- const name = (m[1] ?? m[2] ?? "").trim();
11502
+ const name = stripNodeDecorations((m[1] ?? m[2] ?? "").trim());
11468
11503
  if (name && !entities.includes(name)) entities.push(name);
11469
11504
  }
11470
11505
  } else {
@@ -11479,7 +11514,7 @@ function extractSymbols4(docText) {
11479
11514
  continue;
11480
11515
  const m = COMPONENT_RE.exec(line12);
11481
11516
  if (m) {
11482
- const name = (m[1] ?? m[2] ?? "").trim();
11517
+ const name = stripNodeDecorations((m[1] ?? m[2] ?? "").trim());
11483
11518
  if (name && !entities.includes(name)) entities.push(name);
11484
11519
  }
11485
11520
  }
@@ -11965,15 +12000,15 @@ function parseGantt(content, palette) {
11965
12000
  metaAliasMap,
11966
12001
  () => warn2(lineNumber, MULTIPLE_PIPE_ERROR)
11967
12002
  );
11968
- if (meta.lag || meta.lead) {
11969
- const key = meta.lag ? "lag" : "lead";
12003
+ if (meta["lag"] || meta["lead"]) {
12004
+ const key = meta["lag"] ? "lag" : "lead";
11970
12005
  softError(
11971
12006
  lineNumber,
11972
12007
  `"${key}" is no longer supported \u2014 use "offset: ${meta[key]}" instead.${key === "lead" ? ' Negate the value for lead behavior: "offset: -...".' : ""}`
11973
12008
  );
11974
12009
  }
11975
- if (meta.offset) {
11976
- const raw = meta.offset;
12010
+ if (meta["offset"]) {
12011
+ const raw = meta["offset"];
11977
12012
  if (raw.trim().startsWith("+")) {
11978
12013
  warn2(
11979
12014
  lineNumber,
@@ -12360,15 +12395,15 @@ function parseGantt(content, palette) {
12360
12395
  metaAliasMap,
12361
12396
  () => warn2(lineNumber, MULTIPLE_PIPE_ERROR)
12362
12397
  );
12363
- if (meta.lag || meta.lead) {
12364
- const key = meta.lag ? "lag" : "lead";
12398
+ if (meta["lag"] || meta["lead"]) {
12399
+ const key = meta["lag"] ? "lag" : "lead";
12365
12400
  softError(
12366
12401
  lineNumber,
12367
12402
  `"${key}" is no longer supported \u2014 use "offset: ${meta[key]}" instead.${key === "lead" ? ' Negate the value for lead behavior: "offset: -...".' : ""}`
12368
12403
  );
12369
12404
  }
12370
- if (meta.offset) {
12371
- const raw = meta.offset;
12405
+ if (meta["offset"]) {
12406
+ const raw = meta["offset"];
12372
12407
  if (raw.trim().startsWith("+")) {
12373
12408
  warn2(
12374
12409
  lineNumber,
@@ -12439,9 +12474,9 @@ function parseGantt(content, palette) {
12439
12474
  () => warn2(ln, MULTIPLE_PIPE_ERROR)
12440
12475
  ) : {};
12441
12476
  let progress = null;
12442
- if (metadata.progress) {
12443
- progress = parseFloat(metadata.progress);
12444
- delete metadata.progress;
12477
+ if (metadata["progress"]) {
12478
+ progress = parseFloat(metadata["progress"]);
12479
+ delete metadata["progress"];
12445
12480
  }
12446
12481
  for (const part of segments.slice(1).join(",").split(",")) {
12447
12482
  const seg = part.trim();
@@ -12450,16 +12485,16 @@ function parseGantt(content, palette) {
12450
12485
  progress = parseInt(progressMatch[1], 10);
12451
12486
  }
12452
12487
  }
12453
- if (metadata.lag || metadata.lead) {
12454
- const key = metadata.lag ? "lag" : "lead";
12488
+ if (metadata["lag"] || metadata["lead"]) {
12489
+ const key = metadata["lag"] ? "lag" : "lead";
12455
12490
  softError(
12456
12491
  ln,
12457
12492
  `"${key}" is no longer supported \u2014 use "offset: ${metadata[key]}" instead.${key === "lead" ? ' Negate the value for lead behavior: "offset: -...".' : ""}`
12458
12493
  );
12459
12494
  }
12460
12495
  let taskOffset;
12461
- if (metadata.offset) {
12462
- const raw = metadata.offset;
12496
+ if (metadata["offset"]) {
12497
+ const raw = metadata["offset"];
12463
12498
  if (raw.trim().startsWith("+")) {
12464
12499
  warn2(
12465
12500
  ln,
@@ -12474,7 +12509,7 @@ function parseGantt(content, palette) {
12474
12509
  );
12475
12510
  }
12476
12511
  }
12477
- delete metadata.offset;
12512
+ delete metadata["offset"];
12478
12513
  }
12479
12514
  const groupPath = currentGroupPath();
12480
12515
  const inheritedMeta = {};
@@ -12997,7 +13032,7 @@ function parsePert(content, parseOpts = {}) {
12997
13032
  id,
12998
13033
  name,
12999
13034
  activityIds: [],
13000
- collapsed: meta.collapsed === "true",
13035
+ collapsed: meta["collapsed"] === "true",
13001
13036
  lineNumber,
13002
13037
  ...Object.keys(tags).length > 0 && { tags }
13003
13038
  });
@@ -13259,7 +13294,7 @@ function parsePert(content, parseOpts = {}) {
13259
13294
  name: decl.name,
13260
13295
  ...decl.alias !== void 0 && { alias: decl.alias },
13261
13296
  duration: estimate,
13262
- ...meta.confidence && { confidence: meta.confidence },
13297
+ ...meta["confidence"] && { confidence: meta["confidence"] },
13263
13298
  ...decl.groupHint !== void 0 && { groupId: decl.groupHint },
13264
13299
  lineNumber: decl.lineNumber,
13265
13300
  isMilestone,
@@ -14590,7 +14625,7 @@ function parseMindmap(content, palette) {
14590
14625
  }
14591
14626
  return result;
14592
14627
  }
14593
- function parseNodeLine2(trimmed, lineNumber, palette, counter, aliasMap, warnFn) {
14628
+ function parseNodeLine2(trimmed, lineNumber, _palette, counter, aliasMap, warnFn) {
14594
14629
  const segments = trimmed.split("|").map((s) => s.trim());
14595
14630
  const label = segments[0];
14596
14631
  const metadata = parsePipeMetadata(
@@ -15034,7 +15069,7 @@ function parseWireframe(content) {
15034
15069
  wrapper.isContainer = true;
15035
15070
  wrapper.orientation = "horizontal";
15036
15071
  wrapper.children = children;
15037
- wrapper.metadata._inlineRow = "true";
15072
+ wrapper.metadata["_inlineRow"] = "true";
15038
15073
  pushElement(wrapper);
15039
15074
  }
15040
15075
  for (let i = 0; i < lines.length; i++) {
@@ -15185,7 +15220,7 @@ function parseWireframe(content) {
15185
15220
  wrapper.isContainer = true;
15186
15221
  wrapper.orientation = "horizontal";
15187
15222
  wrapper.children.push(labelEl, fieldEl);
15188
- wrapper.metadata._labelField = "true";
15223
+ wrapper.metadata["_labelField"] = "true";
15189
15224
  pushElement(wrapper);
15190
15225
  }
15191
15226
  } else {
@@ -17006,9 +17041,9 @@ function parseRaci(content, palette) {
17006
17041
  let roleColor;
17007
17042
  if (segments.length > 1) {
17008
17043
  const meta = parsePipeMetadata(segments);
17009
- if (meta.color) {
17044
+ if (meta["color"]) {
17010
17045
  roleColor = resolveColorWithDiagnostic(
17011
- meta.color,
17046
+ meta["color"],
17012
17047
  j + 1,
17013
17048
  result.diagnostics,
17014
17049
  palette
@@ -17075,9 +17110,9 @@ function parseRaci(content, palette) {
17075
17110
  let phaseColor;
17076
17111
  if (phaseMatch[2]) {
17077
17112
  const meta = parsePipeMetadata(["", phaseMatch[2]]);
17078
- if (meta.color) {
17113
+ if (meta["color"]) {
17079
17114
  phaseColor = resolveColorWithDiagnostic(
17080
- meta.color,
17115
+ meta["color"],
17081
17116
  lineNumber,
17082
17117
  result.diagnostics,
17083
17118
  palette
@@ -19087,7 +19122,7 @@ function renderOrg(container, parsed, layout, palette, isDark, onClickItem, expo
19087
19122
  displayNames.set(group.name.toLowerCase(), group.name);
19088
19123
  }
19089
19124
  const rootNodeIds = new Set(parsed.roots.map((r) => r.id));
19090
- const colorOff = parsed.options?.color === "off";
19125
+ const colorOff = parsed.options?.["color"] === "off";
19091
19126
  for (const c of layout.containers) {
19092
19127
  const cG = contentG.append("g").attr("transform", `translate(${c.x}, ${c.y})`).attr("class", "org-container").attr("data-line-number", String(c.lineNumber));
19093
19128
  if (activeTagGroup) {
@@ -22188,7 +22223,7 @@ function renderERDiagram(container, parsed, layout, palette, isDark, onClickItem
22188
22223
  const seriesColors2 = getSeriesColors(palette);
22189
22224
  const semanticRoles = useSemanticColors ? classifyEREntities(parsed.tables, parsed.relationships) : null;
22190
22225
  const semanticActive = semanticRoles !== null && (semanticColorsActive ?? true);
22191
- const useLabels = parsed.options.notation === "labels";
22226
+ const useLabels = parsed.options["notation"] === "labels";
22192
22227
  for (const edge of layout.edges) {
22193
22228
  if (edge.points.length < 2) continue;
22194
22229
  const edgeG = contentG.append("g").attr("class", "er-edge-group").attr("data-line-number", String(edge.lineNumber));
@@ -22401,495 +22436,6 @@ var init_renderer5 = __esm({
22401
22436
  }
22402
22437
  });
22403
22438
 
22404
- // src/boxes-and-lines/layout.ts
22405
- var layout_exports5 = {};
22406
- __export(layout_exports5, {
22407
- layoutBoxesAndLines: () => layoutBoxesAndLines
22408
- });
22409
- import dagre4 from "@dagrejs/dagre";
22410
- function clipToRectBorder2(cx, cy, w, h, tx, ty) {
22411
- const dx = tx - cx;
22412
- const dy = ty - cy;
22413
- if (dx === 0 && dy === 0) return { x: cx, y: cy };
22414
- const hw = w / 2;
22415
- const hh = h / 2;
22416
- const sx = dx !== 0 ? hw / Math.abs(dx) : Infinity;
22417
- const sy = dy !== 0 ? hh / Math.abs(dy) : Infinity;
22418
- const s = Math.min(sx, sy);
22419
- return { x: cx + dx * s, y: cy + dy * s };
22420
- }
22421
- function splitCamelCase(word) {
22422
- const parts = [];
22423
- let start = 0;
22424
- for (let i = 1; i < word.length; i++) {
22425
- const prev = word[i - 1];
22426
- const curr = word[i];
22427
- const next = i + 1 < word.length ? word[i + 1] : "";
22428
- const lowerToUpper = prev >= "a" && prev <= "z" && curr >= "A" && curr <= "Z";
22429
- const upperRunEnd = prev >= "A" && prev <= "Z" && curr >= "A" && curr <= "Z" && next >= "a" && next <= "z";
22430
- if (lowerToUpper || upperRunEnd) {
22431
- parts.push(word.slice(start, i));
22432
- start = i;
22433
- }
22434
- }
22435
- parts.push(word.slice(start));
22436
- return parts.length > 1 ? parts : [word];
22437
- }
22438
- function estimateLabelLines(label, nodeWidth2 = NODE_WIDTH) {
22439
- const rawParts = label.split(/[\s-]+/);
22440
- const words = [];
22441
- for (const part of rawParts) {
22442
- if (!part) continue;
22443
- words.push(...splitCamelCase(part));
22444
- }
22445
- for (let fontSize = 13; fontSize >= 9; fontSize--) {
22446
- const charWidth = fontSize * 0.6;
22447
- const maxChars = Math.floor((nodeWidth2 - 24) / charWidth);
22448
- if (maxChars < 2) continue;
22449
- let lines = 1;
22450
- let current = "";
22451
- for (const word of words) {
22452
- const test = current ? `${current} ${word}` : word;
22453
- if (test.length <= maxChars) {
22454
- current = test;
22455
- } else {
22456
- lines++;
22457
- current = word;
22458
- }
22459
- }
22460
- if (lines <= MAX_LABEL_LINES) return Math.min(lines, MAX_LABEL_LINES);
22461
- }
22462
- return MAX_LABEL_LINES;
22463
- }
22464
- function computeNodeSize(node) {
22465
- if (!node.description || node.description.length === 0) {
22466
- return { width: NODE_WIDTH, height: NODE_HEIGHT };
22467
- }
22468
- const w = DESC_NODE_WIDTH;
22469
- const labelLines = estimateLabelLines(node.label, w);
22470
- const labelHeight = labelLines * 13 * LABEL_LINE_HEIGHT + LABEL_PAD;
22471
- const charsPerLine = Math.floor((w - 24) / (DESC_FONT_SIZE * 0.6));
22472
- let totalRenderedLines = 0;
22473
- for (const line12 of node.description) {
22474
- if (line12.length <= charsPerLine) {
22475
- totalRenderedLines += 1;
22476
- } else {
22477
- const words = line12.split(/\s+/);
22478
- let current = "";
22479
- let lineCount = 0;
22480
- for (const word of words) {
22481
- const fitted = word.length > charsPerLine ? word.slice(0, charsPerLine) : word;
22482
- const test = current ? `${current} ${fitted}` : fitted;
22483
- if (test.length <= charsPerLine) {
22484
- current = test;
22485
- } else {
22486
- if (current) lineCount++;
22487
- current = fitted;
22488
- }
22489
- }
22490
- if (current) lineCount++;
22491
- totalRenderedLines += lineCount;
22492
- }
22493
- }
22494
- totalRenderedLines = Math.min(totalRenderedLines, MAX_DESC_LINES);
22495
- const descriptionHeight = totalRenderedLines * DESC_FONT_SIZE * DESC_LINE_HEIGHT;
22496
- const totalHeight = labelHeight + SEPARATOR_GAP5 + DESC_PADDING + descriptionHeight + DESC_PADDING;
22497
- return { width: w, height: Math.max(NODE_HEIGHT, totalHeight) };
22498
- }
22499
- function layoutBoxesAndLines(parsed, collapseInfo, layoutOptions) {
22500
- const hideDescriptions = layoutOptions?.hideDescriptions ?? false;
22501
- const g = new dagre4.graphlib.Graph({ compound: true, multigraph: true });
22502
- g.setGraph({
22503
- rankdir: parsed.direction,
22504
- nodesep: NODESEP,
22505
- ranksep: RANKSEP,
22506
- marginx: MARGIN3,
22507
- marginy: MARGIN3
22508
- });
22509
- g.setDefaultEdgeLabel(() => ({}));
22510
- const collapsedGroupLabels = /* @__PURE__ */ new Set();
22511
- if (collapseInfo) {
22512
- const missingGroups = /* @__PURE__ */ new Set();
22513
- for (const og of collapseInfo.originalGroups) {
22514
- if (!parsed.groups.some((g2) => g2.label === og.label)) {
22515
- missingGroups.add(og.label);
22516
- }
22517
- }
22518
- for (const label of missingGroups) {
22519
- const og = collapseInfo.originalGroups.find((g2) => g2.label === label);
22520
- const parentLabel = og?.parentGroup;
22521
- if (!parentLabel || !missingGroups.has(parentLabel)) {
22522
- collapsedGroupLabels.add(label);
22523
- }
22524
- }
22525
- }
22526
- for (const label of collapsedGroupLabels) {
22527
- const gid = `__group_${label}`;
22528
- g.setNode(gid, { label, width: NODE_WIDTH, height: NODE_HEIGHT });
22529
- }
22530
- for (const group of parsed.groups) {
22531
- const gid = `__group_${group.label}`;
22532
- g.setNode(gid, {
22533
- label: group.label,
22534
- paddingLeft: CONTAINER_PAD_X3,
22535
- paddingRight: CONTAINER_PAD_X3,
22536
- paddingTop: CONTAINER_PAD_TOP2,
22537
- paddingBottom: CONTAINER_PAD_BOTTOM3
22538
- });
22539
- }
22540
- const originalGroupByLabel = /* @__PURE__ */ new Map();
22541
- if (collapseInfo) {
22542
- for (const og of collapseInfo.originalGroups) {
22543
- originalGroupByLabel.set(og.label, og);
22544
- }
22545
- }
22546
- for (const label of collapsedGroupLabels) {
22547
- const og = originalGroupByLabel.get(label);
22548
- if (og?.parentGroup && !collapsedGroupLabels.has(og.parentGroup)) {
22549
- const gid = `__group_${label}`;
22550
- const parentGid = `__group_${og.parentGroup}`;
22551
- if (g.hasNode(parentGid)) {
22552
- g.setParent(gid, parentGid);
22553
- }
22554
- }
22555
- }
22556
- const nodeSizes = /* @__PURE__ */ new Map();
22557
- let maxDescHeight = 0;
22558
- for (const node of parsed.nodes) {
22559
- const size = hideDescriptions ? { width: NODE_WIDTH, height: NODE_HEIGHT } : computeNodeSize(node);
22560
- nodeSizes.set(node.label, size);
22561
- if (!hideDescriptions && node.description && node.description.length > 0) {
22562
- maxDescHeight = Math.max(maxDescHeight, size.height);
22563
- }
22564
- }
22565
- if (maxDescHeight > 0) {
22566
- for (const node of parsed.nodes) {
22567
- if (node.description && node.description.length > 0) {
22568
- const size = nodeSizes.get(node.label);
22569
- nodeSizes.set(node.label, { width: size.width, height: maxDescHeight });
22570
- }
22571
- }
22572
- }
22573
- for (const node of parsed.nodes) {
22574
- const size = nodeSizes.get(node.label);
22575
- g.setNode(node.label, {
22576
- label: node.label,
22577
- width: size.width,
22578
- height: size.height
22579
- });
22580
- }
22581
- for (const group of parsed.groups) {
22582
- if (group.parentGroup) {
22583
- const childGid = `__group_${group.label}`;
22584
- const parentGid = `__group_${group.parentGroup}`;
22585
- if (g.hasNode(childGid) && g.hasNode(parentGid)) {
22586
- g.setParent(childGid, parentGid);
22587
- }
22588
- }
22589
- }
22590
- const groupLabelSet = new Set(parsed.groups.map((gr) => gr.label));
22591
- for (const group of parsed.groups) {
22592
- const gid = `__group_${group.label}`;
22593
- for (const child of group.children) {
22594
- if (groupLabelSet.has(child)) continue;
22595
- if (g.hasNode(child)) {
22596
- g.setParent(child, gid);
22597
- }
22598
- }
22599
- }
22600
- const expandedGroupIds = /* @__PURE__ */ new Set();
22601
- for (const group of parsed.groups) {
22602
- expandedGroupIds.add(`__group_${group.label}`);
22603
- }
22604
- const groupFirstChild = /* @__PURE__ */ new Map();
22605
- for (const group of parsed.groups) {
22606
- const gid = `__group_${group.label}`;
22607
- const firstChild = group.children.find(
22608
- (c) => !groupLabelSet.has(c) && g.hasNode(c)
22609
- );
22610
- if (firstChild) {
22611
- groupFirstChild.set(gid, firstChild);
22612
- }
22613
- }
22614
- const deferredEdgeIndices = [];
22615
- let proxyIdx = 0;
22616
- for (let i = 0; i < parsed.edges.length; i++) {
22617
- const edge = parsed.edges[i];
22618
- const src = edge.source;
22619
- const tgt = edge.target;
22620
- if (!g.hasNode(src) || !g.hasNode(tgt)) continue;
22621
- if (expandedGroupIds.has(src) || expandedGroupIds.has(tgt)) {
22622
- deferredEdgeIndices.push(i);
22623
- const proxySrc = expandedGroupIds.has(src) ? groupFirstChild.get(src) : src;
22624
- const proxyTgt = expandedGroupIds.has(tgt) ? groupFirstChild.get(tgt) : tgt;
22625
- if (proxySrc && proxyTgt && proxySrc !== proxyTgt) {
22626
- g.setEdge(
22627
- proxySrc,
22628
- proxyTgt,
22629
- { label: "", minlen: 1 },
22630
- `proxy${proxyIdx++}`
22631
- );
22632
- }
22633
- continue;
22634
- }
22635
- g.setEdge(src, tgt, { label: edge.label ?? "", minlen: 1 }, `e${i}`);
22636
- }
22637
- dagre4.layout(g);
22638
- const layoutNodes = [];
22639
- for (const node of parsed.nodes) {
22640
- const dagreNode = g.node(node.label);
22641
- if (!dagreNode) continue;
22642
- layoutNodes.push({
22643
- label: node.label,
22644
- x: dagreNode.x,
22645
- y: dagreNode.y,
22646
- width: dagreNode.width,
22647
- height: dagreNode.height
22648
- });
22649
- }
22650
- const layoutGroups = [];
22651
- for (const group of parsed.groups) {
22652
- const gid = `__group_${group.label}`;
22653
- const dagreNode = g.node(gid);
22654
- if (!dagreNode) continue;
22655
- layoutGroups.push({
22656
- label: group.label,
22657
- lineNumber: group.lineNumber,
22658
- x: dagreNode.x,
22659
- y: dagreNode.y,
22660
- width: dagreNode.width,
22661
- height: dagreNode.height,
22662
- collapsed: false
22663
- });
22664
- }
22665
- for (const label of collapsedGroupLabels) {
22666
- const gid = `__group_${label}`;
22667
- const dagreNode = g.node(gid);
22668
- if (!dagreNode) continue;
22669
- const og = collapseInfo?.originalGroups.find((g2) => g2.label === label);
22670
- layoutGroups.push({
22671
- label,
22672
- lineNumber: og?.lineNumber ?? 0,
22673
- x: dagreNode.x,
22674
- y: dagreNode.y,
22675
- width: dagreNode.width,
22676
- height: dagreNode.height,
22677
- collapsed: true,
22678
- childCount: collapseInfo?.collapsedChildCounts.get(label) ?? 0
22679
- });
22680
- }
22681
- const groupAlignShifts = /* @__PURE__ */ new Map();
22682
- {
22683
- const groupEdges = [];
22684
- for (const edge of parsed.edges) {
22685
- if (edge.source.startsWith("__group_") && edge.target.startsWith("__group_")) {
22686
- groupEdges.push(edge);
22687
- }
22688
- }
22689
- if (groupEdges.length > 0) {
22690
- const groupParent = /* @__PURE__ */ new Map();
22691
- const find = (x) => {
22692
- while (groupParent.has(x) && groupParent.get(x) !== x) {
22693
- groupParent.set(x, groupParent.get(groupParent.get(x)));
22694
- x = groupParent.get(x);
22695
- }
22696
- return x;
22697
- };
22698
- const union = (a, b) => {
22699
- const ra = find(a), rb = find(b);
22700
- if (ra !== rb) groupParent.set(ra, rb);
22701
- };
22702
- for (const edge of groupEdges) {
22703
- if (!groupParent.has(edge.source))
22704
- groupParent.set(edge.source, edge.source);
22705
- if (!groupParent.has(edge.target))
22706
- groupParent.set(edge.target, edge.target);
22707
- union(edge.source, edge.target);
22708
- }
22709
- const components = /* @__PURE__ */ new Map();
22710
- for (const lg of layoutGroups) {
22711
- const gid = `__group_${lg.label}`;
22712
- if (!groupParent.has(gid)) continue;
22713
- const root = find(gid);
22714
- if (!components.has(root)) components.set(root, []);
22715
- components.get(root).push(lg);
22716
- }
22717
- const axis = parsed.direction === "TB" ? "x" : "y";
22718
- for (const groups of components.values()) {
22719
- if (groups.length < 2) continue;
22720
- const dim = axis === "x" ? "width" : "height";
22721
- let widest = groups[0];
22722
- for (const g2 of groups) {
22723
- if (g2[dim] > widest[dim]) widest = g2;
22724
- }
22725
- const targetCenter = widest[axis];
22726
- for (const grp of groups) {
22727
- const dx = targetCenter - grp[axis];
22728
- if (dx === 0) continue;
22729
- grp[axis] += dx;
22730
- groupAlignShifts.set(`__group_${grp.label}`, dx);
22731
- const parsedGroup = parsed.groups.find(
22732
- (pg) => pg.label === grp.label
22733
- );
22734
- if (parsedGroup) {
22735
- for (const childLabel of parsedGroup.children) {
22736
- const childNode = layoutNodes.find((n) => n.label === childLabel);
22737
- if (childNode) childNode[axis] += dx;
22738
- }
22739
- }
22740
- }
22741
- }
22742
- }
22743
- }
22744
- const edgeYOffsets = new Array(parsed.edges.length).fill(0);
22745
- const edgeParallelCounts = new Array(parsed.edges.length).fill(1);
22746
- const parallelGroups = /* @__PURE__ */ new Map();
22747
- for (let i = 0; i < parsed.edges.length; i++) {
22748
- const edge = parsed.edges[i];
22749
- const [a, b] = edge.source < edge.target ? [edge.source, edge.target] : [edge.target, edge.source];
22750
- const key = `${a}\0${b}`;
22751
- if (!parallelGroups.has(key)) parallelGroups.set(key, []);
22752
- parallelGroups.get(key).push(i);
22753
- }
22754
- for (const group of parallelGroups.values()) {
22755
- const capped = group.slice(0, MAX_PARALLEL_EDGES);
22756
- for (const idx of group.slice(MAX_PARALLEL_EDGES)) {
22757
- edgeParallelCounts[idx] = 0;
22758
- }
22759
- if (capped.length < 2) continue;
22760
- const effectiveSpacing = PARALLEL_SPACING;
22761
- for (let j = 0; j < capped.length; j++) {
22762
- edgeYOffsets[capped[j]] = (j - (capped.length - 1) / 2) * effectiveSpacing;
22763
- edgeParallelCounts[capped[j]] = capped.length;
22764
- }
22765
- }
22766
- const deferredSet = new Set(deferredEdgeIndices);
22767
- const layoutEdges = [];
22768
- for (let i = 0; i < parsed.edges.length; i++) {
22769
- const edge = parsed.edges[i];
22770
- if (edgeParallelCounts[i] === 0) continue;
22771
- let points;
22772
- if (deferredSet.has(i)) {
22773
- const srcLayout = layoutGroups.find(
22774
- (lg) => `__group_${lg.label}` === edge.source
22775
- );
22776
- const tgtLayout = layoutGroups.find(
22777
- (lg) => `__group_${lg.label}` === edge.target
22778
- );
22779
- if (!srcLayout || !tgtLayout) {
22780
- const srcNode = g.node(edge.source);
22781
- const tgtNode = g.node(edge.target);
22782
- if (!srcNode || !tgtNode) continue;
22783
- const srcPt = clipToRectBorder2(
22784
- srcNode.x,
22785
- srcNode.y,
22786
- srcNode.width,
22787
- srcNode.height,
22788
- tgtNode.x,
22789
- tgtNode.y
22790
- );
22791
- const tgtPt = clipToRectBorder2(
22792
- tgtNode.x,
22793
- tgtNode.y,
22794
- tgtNode.width,
22795
- tgtNode.height,
22796
- srcNode.x,
22797
- srcNode.y
22798
- );
22799
- const midX = (srcPt.x + tgtPt.x) / 2;
22800
- const midY = (srcPt.y + tgtPt.y) / 2;
22801
- points = [srcPt, { x: midX, y: midY }, tgtPt];
22802
- } else if (parsed.direction === "TB") {
22803
- const cx = (srcLayout.x + tgtLayout.x) / 2;
22804
- const srcPt = { x: cx, y: srcLayout.y + srcLayout.height / 2 };
22805
- const tgtPt = { x: cx, y: tgtLayout.y - tgtLayout.height / 2 };
22806
- const midY = (srcPt.y + tgtPt.y) / 2;
22807
- points = [srcPt, { x: cx, y: midY }, tgtPt];
22808
- } else {
22809
- const cy = (srcLayout.y + tgtLayout.y) / 2;
22810
- const srcPt = { x: srcLayout.x + srcLayout.width / 2, y: cy };
22811
- const tgtPt = { x: tgtLayout.x - tgtLayout.width / 2, y: cy };
22812
- const midX = (srcPt.x + tgtPt.x) / 2;
22813
- points = [srcPt, { x: midX, y: cy }, tgtPt];
22814
- }
22815
- } else {
22816
- const dagreEdge = g.edge(edge.source, edge.target, `e${i}`);
22817
- points = dagreEdge?.points ?? [];
22818
- const srcShift = groupAlignShifts.get(edge.source) ?? 0;
22819
- const tgtShift = groupAlignShifts.get(edge.target) ?? 0;
22820
- if (srcShift !== 0 || tgtShift !== 0) {
22821
- const avgShift = (srcShift + tgtShift) / 2;
22822
- const prop = parsed.direction === "TB" ? "x" : "y";
22823
- points = points.map((p) => ({ ...p, [prop]: p[prop] + avgShift }));
22824
- }
22825
- }
22826
- let labelX;
22827
- let labelY;
22828
- if (edge.label && points.length >= 2) {
22829
- const mid = Math.floor(points.length / 2);
22830
- labelX = points[mid].x;
22831
- labelY = points[mid].y - 10;
22832
- }
22833
- layoutEdges.push({
22834
- source: edge.source,
22835
- target: edge.target,
22836
- label: edge.label,
22837
- bidirectional: edge.bidirectional,
22838
- lineNumber: edge.lineNumber,
22839
- points,
22840
- labelX,
22841
- labelY,
22842
- yOffset: edgeYOffsets[i],
22843
- parallelCount: edgeParallelCounts[i],
22844
- metadata: edge.metadata,
22845
- deferred: deferredSet.has(i) || void 0
22846
- });
22847
- }
22848
- let maxX = 0;
22849
- let maxY = 0;
22850
- for (const node of layoutNodes) {
22851
- maxX = Math.max(maxX, node.x + node.width / 2);
22852
- maxY = Math.max(maxY, node.y + node.height / 2);
22853
- }
22854
- for (const group of layoutGroups) {
22855
- maxX = Math.max(maxX, group.x + group.width / 2);
22856
- maxY = Math.max(maxY, group.y + group.height / 2);
22857
- }
22858
- return {
22859
- nodes: layoutNodes,
22860
- edges: layoutEdges,
22861
- groups: layoutGroups,
22862
- width: maxX + MARGIN3,
22863
- height: maxY + MARGIN3
22864
- };
22865
- }
22866
- var NODESEP, RANKSEP, MARGIN3, CONTAINER_PAD_X3, CONTAINER_PAD_TOP2, CONTAINER_PAD_BOTTOM3, MAX_PARALLEL_EDGES, PARALLEL_SPACING, PHI, NODE_HEIGHT, NODE_WIDTH, DESC_NODE_WIDTH, DESC_FONT_SIZE, DESC_LINE_HEIGHT, DESC_PADDING, SEPARATOR_GAP5, MAX_DESC_LINES, MAX_LABEL_LINES, LABEL_LINE_HEIGHT, LABEL_PAD;
22867
- var init_layout5 = __esm({
22868
- "src/boxes-and-lines/layout.ts"() {
22869
- "use strict";
22870
- NODESEP = 60;
22871
- RANKSEP = 100;
22872
- MARGIN3 = 40;
22873
- CONTAINER_PAD_X3 = 30;
22874
- CONTAINER_PAD_TOP2 = 40;
22875
- CONTAINER_PAD_BOTTOM3 = 24;
22876
- MAX_PARALLEL_EDGES = 5;
22877
- PARALLEL_SPACING = 22;
22878
- PHI = 1.618;
22879
- NODE_HEIGHT = 60;
22880
- NODE_WIDTH = Math.round(NODE_HEIGHT * PHI);
22881
- DESC_NODE_WIDTH = 140;
22882
- DESC_FONT_SIZE = 10;
22883
- DESC_LINE_HEIGHT = 1.4;
22884
- DESC_PADDING = 8;
22885
- SEPARATOR_GAP5 = 4;
22886
- MAX_DESC_LINES = 6;
22887
- MAX_LABEL_LINES = 3;
22888
- LABEL_LINE_HEIGHT = 1.3;
22889
- LABEL_PAD = 12;
22890
- }
22891
- });
22892
-
22893
22439
  // src/utils/wrapped-desc.ts
22894
22440
  function wrapDescriptionLines(lines, charsPerLine, lengthFn = (s) => s.length) {
22895
22441
  const result = [];
@@ -22941,7 +22487,7 @@ __export(renderer_exports6, {
22941
22487
  });
22942
22488
  import * as d3Selection6 from "d3-selection";
22943
22489
  import * as d3Shape4 from "d3-shape";
22944
- function splitCamelCase2(word) {
22490
+ function splitCamelCase(word) {
22945
22491
  const parts = [];
22946
22492
  let start = 0;
22947
22493
  for (let i = 1; i < word.length; i++) {
@@ -22964,7 +22510,7 @@ function fitLabelToHeader(label, nodeWidth2, maxLines) {
22964
22510
  const words = [];
22965
22511
  for (const part of rawParts) {
22966
22512
  if (!part || /^\s+$/.test(part) || part === "-") continue;
22967
- words.push(...splitCamelCase2(part));
22513
+ words.push(...splitCamelCase(part));
22968
22514
  }
22969
22515
  for (let fontSize = NODE_FONT_SIZE; fontSize >= MIN_NODE_FONT_SIZE; fontSize--) {
22970
22516
  const charWidth2 = fontSize * CHAR_WIDTH_RATIO2;
@@ -23340,12 +22886,12 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
23340
22886
  }
23341
22887
  const sepY = -ln.height / 2 + headerH;
23342
22888
  nodeG.append("line").attr("x1", -ln.width / 2).attr("y1", sepY).attr("x2", ln.width / 2).attr("y2", sepY).attr("stroke", colors.stroke).attr("stroke-opacity", 0.3).attr("stroke-width", 1);
23343
- const descStartY = sepY + 4 + DESC_FONT_SIZE2;
22889
+ const descStartY = sepY + 4 + DESC_FONT_SIZE;
23344
22890
  const maxTextWidth = ln.width - NODE_TEXT_PADDING * 2;
23345
22891
  const charsPerLine = Math.floor(
23346
- maxTextWidth / (DESC_FONT_SIZE2 * CHAR_WIDTH_RATIO2)
22892
+ maxTextWidth / (DESC_FONT_SIZE * CHAR_WIDTH_RATIO2)
23347
22893
  );
23348
- const descLineH = DESC_FONT_SIZE2 * DESC_LINE_HEIGHT2;
22894
+ const descLineH = DESC_FONT_SIZE * DESC_LINE_HEIGHT;
23349
22895
  const displayLen = (text) => text.replace(/\[([^\]]+)\]\([^)]+\)/g, "$1").replace(/\*\*(.+?)\*\*/g, "$1").replace(/\*(.+?)\*/g, "$1").replace(/`(.+?)`/g, "$1").replace(/https?:\/\/\S+/g, (u) => u.slice(0, 20)).length;
23350
22896
  const normalizedLines = [];
23351
22897
  for (const descLine of desc) {
@@ -23361,8 +22907,8 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
23361
22907
  charsPerLine,
23362
22908
  displayLen
23363
22909
  );
23364
- const truncated = wrappedLinesShared.length > MAX_DESC_LINES2;
23365
- const visibleLines = truncated ? wrappedLinesShared.slice(0, MAX_DESC_LINES2) : wrappedLinesShared;
22910
+ const truncated = wrappedLinesShared.length > MAX_DESC_LINES;
22911
+ const visibleLines = truncated ? wrappedLinesShared.slice(0, MAX_DESC_LINES) : wrappedLinesShared;
23366
22912
  const BULLET_GLYPH_X = -ln.width / 2 + 6;
23367
22913
  const BULLET_BODY_X = BULLET_GLYPH_X + 10;
23368
22914
  for (let li = 0; li < visibleLines.length; li++) {
@@ -23373,11 +22919,11 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
23373
22919
  }
23374
22920
  const y2 = descStartY + li * descLineH;
23375
22921
  if (line12.kind === "bullet-first") {
23376
- nodeG.append("text").attr("x", BULLET_GLYPH_X).attr("y", y2).attr("text-anchor", "start").attr("dominant-baseline", "central").attr("font-size", DESC_FONT_SIZE2).attr("fill", palette.textMuted).text("\u2022");
22922
+ nodeG.append("text").attr("x", BULLET_GLYPH_X).attr("y", y2).attr("text-anchor", "start").attr("dominant-baseline", "central").attr("font-size", DESC_FONT_SIZE).attr("fill", palette.textMuted).text("\u2022");
23377
22923
  }
23378
22924
  const isBullet = line12.kind === "bullet-first" || line12.kind === "bullet-cont";
23379
- const textEl = nodeG.append("text").attr("x", isBullet ? BULLET_BODY_X : 0).attr("y", y2).attr("text-anchor", isBullet ? "start" : "middle").attr("dominant-baseline", "central").attr("font-size", DESC_FONT_SIZE2).attr("fill", palette.textMuted);
23380
- renderInlineText(textEl, lineText, palette, DESC_FONT_SIZE2);
22925
+ const textEl = nodeG.append("text").attr("x", isBullet ? BULLET_BODY_X : 0).attr("y", y2).attr("text-anchor", isBullet ? "start" : "middle").attr("dominant-baseline", "central").attr("font-size", DESC_FONT_SIZE).attr("fill", palette.textMuted);
22926
+ renderInlineText(textEl, lineText, palette, DESC_FONT_SIZE);
23381
22927
  }
23382
22928
  if (truncated) {
23383
22929
  const fullText = desc.join(" ");
@@ -23455,7 +23001,7 @@ function renderBoxesAndLinesForExport(container, parsed, layout, palette, isDark
23455
23001
  hiddenTagValues: options?.hiddenTagValues
23456
23002
  });
23457
23003
  }
23458
- var DIAGRAM_PADDING6, NODE_FONT_SIZE, MIN_NODE_FONT_SIZE, EDGE_LABEL_FONT_SIZE4, EDGE_STROKE_WIDTH5, NODE_STROKE_WIDTH5, NODE_RX, COLLAPSE_BAR_HEIGHT3, ARROWHEAD_W2, ARROWHEAD_H2, DESC_FONT_SIZE2, DESC_LINE_HEIGHT2, MAX_DESC_LINES2, CHAR_WIDTH_RATIO2, NODE_TEXT_PADDING, GROUP_RX, GROUP_LABEL_FONT_SIZE, GROUP_LABEL_ZONE, lineGeneratorLR, lineGeneratorTB;
23004
+ var DIAGRAM_PADDING6, NODE_FONT_SIZE, MIN_NODE_FONT_SIZE, EDGE_LABEL_FONT_SIZE4, EDGE_STROKE_WIDTH5, NODE_STROKE_WIDTH5, NODE_RX, COLLAPSE_BAR_HEIGHT3, ARROWHEAD_W2, ARROWHEAD_H2, DESC_FONT_SIZE, DESC_LINE_HEIGHT, MAX_DESC_LINES, CHAR_WIDTH_RATIO2, NODE_TEXT_PADDING, GROUP_RX, GROUP_LABEL_FONT_SIZE, GROUP_LABEL_ZONE, lineGeneratorLR, lineGeneratorTB;
23459
23005
  var init_renderer6 = __esm({
23460
23006
  "src/boxes-and-lines/renderer.ts"() {
23461
23007
  "use strict";
@@ -23477,9 +23023,9 @@ var init_renderer6 = __esm({
23477
23023
  COLLAPSE_BAR_HEIGHT3 = 4;
23478
23024
  ARROWHEAD_W2 = 5;
23479
23025
  ARROWHEAD_H2 = 4;
23480
- DESC_FONT_SIZE2 = 10;
23481
- DESC_LINE_HEIGHT2 = 1.4;
23482
- MAX_DESC_LINES2 = 6;
23026
+ DESC_FONT_SIZE = 10;
23027
+ DESC_LINE_HEIGHT = 1.4;
23028
+ MAX_DESC_LINES = 6;
23483
23029
  CHAR_WIDTH_RATIO2 = 0.6;
23484
23030
  NODE_TEXT_PADDING = 12;
23485
23031
  GROUP_RX = 8;
@@ -23490,6 +23036,523 @@ var init_renderer6 = __esm({
23490
23036
  }
23491
23037
  });
23492
23038
 
23039
+ // src/boxes-and-lines/layout.ts
23040
+ var layout_exports5 = {};
23041
+ __export(layout_exports5, {
23042
+ layoutBoxesAndLines: () => layoutBoxesAndLines
23043
+ });
23044
+ import ELK from "elkjs/lib/elk.bundled.js";
23045
+ function splitCamelCase2(word) {
23046
+ const parts = [];
23047
+ let start = 0;
23048
+ for (let i = 1; i < word.length; i++) {
23049
+ const prev = word[i - 1];
23050
+ const curr = word[i];
23051
+ const next = i + 1 < word.length ? word[i + 1] : "";
23052
+ const lowerToUpper = prev >= "a" && prev <= "z" && curr >= "A" && curr <= "Z";
23053
+ const upperRunEnd = prev >= "A" && prev <= "Z" && curr >= "A" && curr <= "Z" && next >= "a" && next <= "z";
23054
+ if (lowerToUpper || upperRunEnd) {
23055
+ parts.push(word.slice(start, i));
23056
+ start = i;
23057
+ }
23058
+ }
23059
+ parts.push(word.slice(start));
23060
+ return parts.length > 1 ? parts : [word];
23061
+ }
23062
+ function estimateLabelLines(label, nodeWidth2 = NODE_WIDTH) {
23063
+ const rawParts = label.split(/[\s-]+/);
23064
+ const words = [];
23065
+ for (const part of rawParts) {
23066
+ if (!part) continue;
23067
+ words.push(...splitCamelCase2(part));
23068
+ }
23069
+ for (let fontSize = 13; fontSize >= 9; fontSize--) {
23070
+ const charWidth = fontSize * 0.6;
23071
+ const maxChars = Math.floor((nodeWidth2 - 24) / charWidth);
23072
+ if (maxChars < 2) continue;
23073
+ let lines = 1;
23074
+ let current = "";
23075
+ for (const word of words) {
23076
+ const test = current ? `${current} ${word}` : word;
23077
+ if (test.length <= maxChars) {
23078
+ current = test;
23079
+ } else {
23080
+ lines++;
23081
+ current = word;
23082
+ }
23083
+ }
23084
+ if (lines <= MAX_LABEL_LINES) return Math.min(lines, MAX_LABEL_LINES);
23085
+ }
23086
+ return MAX_LABEL_LINES;
23087
+ }
23088
+ function computeNodeSize(node) {
23089
+ if (!node.description || node.description.length === 0) {
23090
+ return { width: NODE_WIDTH, height: NODE_HEIGHT };
23091
+ }
23092
+ const w = DESC_NODE_WIDTH;
23093
+ const labelLines = estimateLabelLines(node.label, w);
23094
+ const labelHeight = labelLines * 13 * LABEL_LINE_HEIGHT + LABEL_PAD;
23095
+ const charsPerLine = Math.floor((w - 24) / (DESC_FONT_SIZE2 * 0.6));
23096
+ let totalRenderedLines = 0;
23097
+ for (const line12 of node.description) {
23098
+ if (line12.length <= charsPerLine) {
23099
+ totalRenderedLines += 1;
23100
+ } else {
23101
+ const words = line12.split(/\s+/);
23102
+ let current = "";
23103
+ let lineCount = 0;
23104
+ for (const word of words) {
23105
+ const fitted = word.length > charsPerLine ? word.slice(0, charsPerLine) : word;
23106
+ const test = current ? `${current} ${fitted}` : fitted;
23107
+ if (test.length <= charsPerLine) {
23108
+ current = test;
23109
+ } else {
23110
+ if (current) lineCount++;
23111
+ current = fitted;
23112
+ }
23113
+ }
23114
+ if (current) lineCount++;
23115
+ totalRenderedLines += lineCount;
23116
+ }
23117
+ }
23118
+ totalRenderedLines = Math.min(totalRenderedLines, MAX_DESC_LINES2);
23119
+ const descriptionHeight = totalRenderedLines * DESC_FONT_SIZE2 * DESC_LINE_HEIGHT2;
23120
+ const totalHeight = labelHeight + SEPARATOR_GAP5 + DESC_PADDING + descriptionHeight + DESC_PADDING;
23121
+ return { width: w, height: Math.max(NODE_HEIGHT, totalHeight) };
23122
+ }
23123
+ function getElk() {
23124
+ if (!elkInstance) elkInstance = new ELK();
23125
+ return elkInstance;
23126
+ }
23127
+ function baseOptions() {
23128
+ return {
23129
+ "elk.algorithm": "layered",
23130
+ // INCLUDE_CHILDREN lets ELK route edges across container boundaries.
23131
+ "elk.hierarchyHandling": "INCLUDE_CHILDREN",
23132
+ "elk.edgeRouting": "ORTHOGONAL",
23133
+ "elk.layered.unnecessaryBendpoints": "true",
23134
+ // Let edges leave from top/bottom of nodes (not just the flow-direction
23135
+ // sides) when it reduces crossings.
23136
+ "elk.layered.allowNonFlowPortsToSwitchSides": "true"
23137
+ };
23138
+ }
23139
+ function bkBaseline() {
23140
+ return {
23141
+ ...baseOptions(),
23142
+ "elk.layered.nodePlacement.strategy": "BRANDES_KOEPF",
23143
+ "elk.layered.nodePlacement.bk.fixedAlignment": "BALANCED",
23144
+ "elk.layered.nodePlacement.bk.edgeStraightening": "IMPROVE_STRAIGHTNESS",
23145
+ "elk.layered.compaction.connectedComponents": "true",
23146
+ "elk.layered.spacing.nodeNodeBetweenLayers": "90",
23147
+ "elk.spacing.nodeNode": "55",
23148
+ "elk.spacing.edgeNode": "55",
23149
+ "elk.spacing.edgeEdge": "18"
23150
+ };
23151
+ }
23152
+ function getVariants() {
23153
+ const bk = bkBaseline();
23154
+ return [
23155
+ {
23156
+ name: "bk-baseline",
23157
+ options: {
23158
+ ...bk,
23159
+ "elk.layered.crossingMinimization.greedySwitch.type": "ONE_SIDED"
23160
+ }
23161
+ },
23162
+ {
23163
+ name: "bk-aggressive",
23164
+ options: {
23165
+ ...bk,
23166
+ "elk.layered.crossingMinimization.greedySwitch.type": "TWO_SIDED",
23167
+ "elk.layered.thoroughness": "50"
23168
+ }
23169
+ },
23170
+ {
23171
+ name: "bk-wide",
23172
+ options: {
23173
+ ...bk,
23174
+ "elk.layered.crossingMinimization.greedySwitch.type": "TWO_SIDED",
23175
+ "elk.layered.thoroughness": "50",
23176
+ "elk.spacing.nodeNode": "70",
23177
+ "elk.spacing.edgeNode": "75",
23178
+ "elk.spacing.edgeEdge": "22",
23179
+ "elk.layered.spacing.nodeNodeBetweenLayers": "120"
23180
+ }
23181
+ },
23182
+ {
23183
+ name: "longest-path",
23184
+ options: {
23185
+ ...bk,
23186
+ "elk.layered.layering.strategy": "LONGEST_PATH",
23187
+ "elk.layered.crossingMinimization.greedySwitch.type": "TWO_SIDED",
23188
+ "elk.layered.thoroughness": "50"
23189
+ }
23190
+ },
23191
+ {
23192
+ name: "bounded-width",
23193
+ options: {
23194
+ ...bk,
23195
+ "elk.layered.layering.strategy": "COFFMAN_GRAHAM",
23196
+ "elk.layered.layering.coffmanGraham.layerBound": "3",
23197
+ "elk.layered.crossingMinimization.greedySwitch.type": "TWO_SIDED",
23198
+ "elk.layered.thoroughness": "50"
23199
+ }
23200
+ }
23201
+ ];
23202
+ }
23203
+ function countCrossings(edges) {
23204
+ let count = 0;
23205
+ for (let i = 0; i < edges.length; i++) {
23206
+ const a = edges[i].points;
23207
+ if (a.length < 2) continue;
23208
+ for (let j = i + 1; j < edges.length; j++) {
23209
+ const b = edges[j].points;
23210
+ if (b.length < 2) continue;
23211
+ if (edges[i].source === edges[j].source) continue;
23212
+ if (edges[i].source === edges[j].target) continue;
23213
+ if (edges[i].target === edges[j].source) continue;
23214
+ if (edges[i].target === edges[j].target) continue;
23215
+ for (let ai = 0; ai < a.length - 1; ai++) {
23216
+ for (let bi = 0; bi < b.length - 1; bi++) {
23217
+ if (segmentsCross(a[ai], a[ai + 1], b[bi], b[bi + 1])) count++;
23218
+ }
23219
+ }
23220
+ }
23221
+ }
23222
+ return count;
23223
+ }
23224
+ function segmentsCross(p1, p2, p3, p4) {
23225
+ const d1x = p2.x - p1.x;
23226
+ const d1y = p2.y - p1.y;
23227
+ const d2x = p4.x - p3.x;
23228
+ const d2y = p4.y - p3.y;
23229
+ const denom = d1x * d2y - d1y * d2x;
23230
+ if (Math.abs(denom) < 1e-9) return false;
23231
+ const t = ((p3.x - p1.x) * d2y - (p3.y - p1.y) * d2x) / denom;
23232
+ const s = ((p3.x - p1.x) * d1y - (p3.y - p1.y) * d1x) / denom;
23233
+ const EPS = 1e-3;
23234
+ return t > EPS && t < 1 - EPS && s > EPS && s < 1 - EPS;
23235
+ }
23236
+ function countTotalBends(edges) {
23237
+ let bends = 0;
23238
+ for (const e of edges) bends += Math.max(0, e.points.length - 2);
23239
+ return bends;
23240
+ }
23241
+ function scoreLayout(layout) {
23242
+ return {
23243
+ crossings: countCrossings(layout.edges),
23244
+ bends: countTotalBends(layout.edges),
23245
+ area: layout.width * layout.height
23246
+ };
23247
+ }
23248
+ function cmpScore(a, b) {
23249
+ const aBucket = a.crossings <= CROSSINGS_FORGIVENESS ? 0 : a.crossings;
23250
+ const bBucket = b.crossings <= CROSSINGS_FORGIVENESS ? 0 : b.crossings;
23251
+ if (aBucket !== bBucket) return aBucket - bBucket;
23252
+ if (a.area !== b.area) return a.area - b.area;
23253
+ return a.bends - b.bends;
23254
+ }
23255
+ async function layoutBoxesAndLines(parsed, collapseInfo, layoutOptions) {
23256
+ const hideDescriptions = layoutOptions?.hideDescriptions ?? false;
23257
+ const direction = parsed.direction === "TB" ? "DOWN" : "RIGHT";
23258
+ const collapsedGroupLabels = /* @__PURE__ */ new Set();
23259
+ if (collapseInfo) {
23260
+ const missingGroups = /* @__PURE__ */ new Set();
23261
+ for (const og of collapseInfo.originalGroups) {
23262
+ if (!parsed.groups.some((g) => g.label === og.label)) {
23263
+ missingGroups.add(og.label);
23264
+ }
23265
+ }
23266
+ for (const label of missingGroups) {
23267
+ const og = collapseInfo.originalGroups.find((g) => g.label === label);
23268
+ const parentLabel = og?.parentGroup;
23269
+ if (!parentLabel || !missingGroups.has(parentLabel)) {
23270
+ collapsedGroupLabels.add(label);
23271
+ }
23272
+ }
23273
+ }
23274
+ const nodeSizes = /* @__PURE__ */ new Map();
23275
+ let maxDescHeight = 0;
23276
+ for (const node of parsed.nodes) {
23277
+ const size = hideDescriptions ? { width: NODE_WIDTH, height: NODE_HEIGHT } : computeNodeSize(node);
23278
+ nodeSizes.set(node.label, size);
23279
+ if (!hideDescriptions && node.description && node.description.length > 0) {
23280
+ maxDescHeight = Math.max(maxDescHeight, size.height);
23281
+ }
23282
+ }
23283
+ if (maxDescHeight > 0) {
23284
+ for (const node of parsed.nodes) {
23285
+ if (node.description && node.description.length > 0) {
23286
+ const size = nodeSizes.get(node.label);
23287
+ nodeSizes.set(node.label, { width: size.width, height: maxDescHeight });
23288
+ }
23289
+ }
23290
+ }
23291
+ const expandedGroupSet = new Set(parsed.groups.map((g) => g.label));
23292
+ const gid = (label) => `__group_${label}`;
23293
+ function buildGraph() {
23294
+ const nodeById = /* @__PURE__ */ new Map();
23295
+ const parentOf = /* @__PURE__ */ new Map();
23296
+ for (const node of parsed.nodes) {
23297
+ const size = nodeSizes.get(node.label);
23298
+ nodeById.set(node.label, {
23299
+ id: node.label,
23300
+ width: size.width,
23301
+ height: size.height,
23302
+ labels: [{ text: node.label }]
23303
+ });
23304
+ }
23305
+ for (const group of parsed.groups) {
23306
+ nodeById.set(gid(group.label), {
23307
+ id: gid(group.label),
23308
+ labels: [{ text: group.label }],
23309
+ layoutOptions: {
23310
+ "elk.padding": `[top=${CONTAINER_PAD_TOP2},left=${CONTAINER_PAD_X3},bottom=${CONTAINER_PAD_BOTTOM3},right=${CONTAINER_PAD_X3}]`,
23311
+ // Suggest square-ish containers — has limited effect with
23312
+ // INCLUDE_CHILDREN but doesn't hurt.
23313
+ "elk.aspectRatio": "1.4"
23314
+ },
23315
+ children: [],
23316
+ edges: []
23317
+ });
23318
+ }
23319
+ for (const label of collapsedGroupLabels) {
23320
+ nodeById.set(gid(label), {
23321
+ id: gid(label),
23322
+ width: NODE_WIDTH,
23323
+ height: NODE_HEIGHT,
23324
+ labels: [{ text: label }]
23325
+ });
23326
+ }
23327
+ for (const group of parsed.groups) {
23328
+ if (group.parentGroup && nodeById.has(gid(group.parentGroup))) {
23329
+ parentOf.set(gid(group.label), gid(group.parentGroup));
23330
+ }
23331
+ }
23332
+ if (collapseInfo) {
23333
+ for (const label of collapsedGroupLabels) {
23334
+ const og = collapseInfo.originalGroups.find((g) => g.label === label);
23335
+ if (og?.parentGroup && !collapsedGroupLabels.has(og.parentGroup) && nodeById.has(gid(og.parentGroup))) {
23336
+ parentOf.set(gid(label), gid(og.parentGroup));
23337
+ }
23338
+ }
23339
+ }
23340
+ for (const group of parsed.groups) {
23341
+ for (const child of group.children) {
23342
+ if (expandedGroupSet.has(child)) continue;
23343
+ if (nodeById.has(child)) {
23344
+ parentOf.set(child, gid(group.label));
23345
+ }
23346
+ }
23347
+ }
23348
+ const roots = [];
23349
+ for (const [id, node] of nodeById) {
23350
+ const parentId = parentOf.get(id);
23351
+ if (parentId) {
23352
+ const parent = nodeById.get(parentId);
23353
+ parent.children = parent.children ?? [];
23354
+ parent.children.push(node);
23355
+ } else {
23356
+ roots.push(node);
23357
+ }
23358
+ }
23359
+ const rootEdges = [];
23360
+ for (let i = 0; i < parsed.edges.length; i++) {
23361
+ const edge = parsed.edges[i];
23362
+ if (!nodeById.has(edge.source) || !nodeById.has(edge.target)) continue;
23363
+ rootEdges.push({
23364
+ id: `e${i}`,
23365
+ sources: [edge.source],
23366
+ targets: [edge.target]
23367
+ });
23368
+ }
23369
+ return { roots, rootEdges };
23370
+ }
23371
+ async function runVariant(variant) {
23372
+ const { roots, rootEdges } = buildGraph();
23373
+ const elkRoot = {
23374
+ id: "root",
23375
+ layoutOptions: {
23376
+ ...variant.options,
23377
+ "elk.direction": direction,
23378
+ "elk.padding": `[top=${MARGIN3},left=${MARGIN3},bottom=${MARGIN3},right=${MARGIN3}]`
23379
+ },
23380
+ children: roots,
23381
+ edges: rootEdges
23382
+ };
23383
+ const result = await getElk().layout(elkRoot);
23384
+ return extractLayout(result);
23385
+ }
23386
+ function extractLayout(result) {
23387
+ const layoutNodes = [];
23388
+ const layoutGroups = [];
23389
+ const allEdges = [];
23390
+ const containerAbs = /* @__PURE__ */ new Map();
23391
+ function walk(n, offsetX, offsetY, isRoot) {
23392
+ const nx = (n.x ?? 0) + offsetX;
23393
+ const ny = (n.y ?? 0) + offsetY;
23394
+ const nw = n.width ?? 0;
23395
+ const nh = n.height ?? 0;
23396
+ if (isRoot) {
23397
+ containerAbs.set("root", { x: nx, y: ny });
23398
+ } else {
23399
+ const isGroup = n.id.startsWith("__group_");
23400
+ if (isGroup) {
23401
+ const label = n.id.slice("__group_".length);
23402
+ const collapsed = collapsedGroupLabels.has(label);
23403
+ const og = collapseInfo?.originalGroups.find(
23404
+ (g) => g.label === label
23405
+ );
23406
+ const pg = parsed.groups.find((g) => g.label === label);
23407
+ layoutGroups.push({
23408
+ label,
23409
+ lineNumber: pg?.lineNumber ?? og?.lineNumber ?? 0,
23410
+ x: nx + nw / 2,
23411
+ y: ny + nh / 2,
23412
+ width: nw,
23413
+ height: nh,
23414
+ collapsed,
23415
+ childCount: collapsed ? collapseInfo?.collapsedChildCounts.get(label) ?? 0 : void 0
23416
+ });
23417
+ if (!collapsed) containerAbs.set(n.id, { x: nx, y: ny });
23418
+ } else {
23419
+ layoutNodes.push({
23420
+ label: n.id,
23421
+ x: nx + nw / 2,
23422
+ y: ny + nh / 2,
23423
+ width: nw,
23424
+ height: nh
23425
+ });
23426
+ }
23427
+ }
23428
+ if (n.edges) for (const e of n.edges) allEdges.push(e);
23429
+ if (n.children) for (const c of n.children) walk(c, nx, ny, false);
23430
+ }
23431
+ walk(result, 0, 0, true);
23432
+ const edgeYOffsets = new Array(parsed.edges.length).fill(0);
23433
+ const edgeParallelCounts = new Array(parsed.edges.length).fill(1);
23434
+ const parallelGroups = /* @__PURE__ */ new Map();
23435
+ for (let i = 0; i < parsed.edges.length; i++) {
23436
+ const edge = parsed.edges[i];
23437
+ const [a, b] = edge.source < edge.target ? [edge.source, edge.target] : [edge.target, edge.source];
23438
+ const key = `${a}\0${b}`;
23439
+ if (!parallelGroups.has(key)) parallelGroups.set(key, []);
23440
+ parallelGroups.get(key).push(i);
23441
+ }
23442
+ for (const group of parallelGroups.values()) {
23443
+ const capped = group.slice(0, MAX_PARALLEL_EDGES);
23444
+ for (const idx of group.slice(MAX_PARALLEL_EDGES)) {
23445
+ edgeParallelCounts[idx] = 0;
23446
+ }
23447
+ if (capped.length < 2) continue;
23448
+ for (let j = 0; j < capped.length; j++) {
23449
+ edgeYOffsets[capped[j]] = (j - (capped.length - 1) / 2) * PARALLEL_SPACING;
23450
+ edgeParallelCounts[capped[j]] = capped.length;
23451
+ }
23452
+ }
23453
+ const edgeById = /* @__PURE__ */ new Map();
23454
+ for (const e of allEdges) edgeById.set(e.id, e);
23455
+ const layoutEdges = [];
23456
+ for (let i = 0; i < parsed.edges.length; i++) {
23457
+ const edge = parsed.edges[i];
23458
+ if (edgeParallelCounts[i] === 0) continue;
23459
+ const elkEdge = edgeById.get(`e${i}`);
23460
+ if (!elkEdge || !elkEdge.sections || elkEdge.sections.length === 0)
23461
+ continue;
23462
+ const container = elkEdge.container ?? "root";
23463
+ const off = containerAbs.get(container) ?? { x: 0, y: 0 };
23464
+ const s = elkEdge.sections[0];
23465
+ const points = [
23466
+ { x: s.startPoint.x + off.x, y: s.startPoint.y + off.y },
23467
+ ...(s.bendPoints ?? []).map((p) => ({
23468
+ x: p.x + off.x,
23469
+ y: p.y + off.y
23470
+ })),
23471
+ { x: s.endPoint.x + off.x, y: s.endPoint.y + off.y }
23472
+ ];
23473
+ let labelX;
23474
+ let labelY;
23475
+ if (edge.label && points.length >= 2) {
23476
+ const mid = Math.floor(points.length / 2);
23477
+ labelX = points[mid].x;
23478
+ labelY = points[mid].y - 10;
23479
+ }
23480
+ layoutEdges.push({
23481
+ source: edge.source,
23482
+ target: edge.target,
23483
+ label: edge.label,
23484
+ bidirectional: edge.bidirectional,
23485
+ lineNumber: edge.lineNumber,
23486
+ points,
23487
+ labelX,
23488
+ labelY,
23489
+ yOffset: edgeYOffsets[i],
23490
+ parallelCount: edgeParallelCounts[i],
23491
+ metadata: edge.metadata,
23492
+ deferred: true
23493
+ });
23494
+ }
23495
+ let maxX = 0;
23496
+ let maxY = 0;
23497
+ for (const node of layoutNodes) {
23498
+ maxX = Math.max(maxX, node.x + node.width / 2);
23499
+ maxY = Math.max(maxY, node.y + node.height / 2);
23500
+ }
23501
+ for (const group of layoutGroups) {
23502
+ maxX = Math.max(maxX, group.x + group.width / 2);
23503
+ maxY = Math.max(maxY, group.y + group.height / 2);
23504
+ }
23505
+ return {
23506
+ nodes: layoutNodes,
23507
+ edges: layoutEdges,
23508
+ groups: layoutGroups,
23509
+ width: maxX + MARGIN3,
23510
+ height: maxY + MARGIN3
23511
+ };
23512
+ }
23513
+ const N = parsed.nodes.length + parsed.groups.length;
23514
+ const E = parsed.edges.length;
23515
+ const trivial = N < 8 && E < 10;
23516
+ const variants = trivial ? [getVariants()[1]] : getVariants();
23517
+ const results = await Promise.all(variants.map((v) => runVariant(v)));
23518
+ let best = results[0];
23519
+ let bestScore = scoreLayout(best);
23520
+ for (let i = 1; i < results.length; i++) {
23521
+ const s = scoreLayout(results[i]);
23522
+ if (cmpScore(s, bestScore) < 0) {
23523
+ best = results[i];
23524
+ bestScore = s;
23525
+ }
23526
+ }
23527
+ return best;
23528
+ }
23529
+ var MARGIN3, CONTAINER_PAD_X3, CONTAINER_PAD_TOP2, CONTAINER_PAD_BOTTOM3, MAX_PARALLEL_EDGES, PARALLEL_SPACING, PHI, NODE_HEIGHT, NODE_WIDTH, DESC_NODE_WIDTH, DESC_FONT_SIZE2, DESC_LINE_HEIGHT2, DESC_PADDING, SEPARATOR_GAP5, MAX_DESC_LINES2, MAX_LABEL_LINES, LABEL_LINE_HEIGHT, LABEL_PAD, elkInstance, CROSSINGS_FORGIVENESS;
23530
+ var init_layout5 = __esm({
23531
+ "src/boxes-and-lines/layout.ts"() {
23532
+ "use strict";
23533
+ MARGIN3 = 40;
23534
+ CONTAINER_PAD_X3 = 30;
23535
+ CONTAINER_PAD_TOP2 = 40;
23536
+ CONTAINER_PAD_BOTTOM3 = 24;
23537
+ MAX_PARALLEL_EDGES = 5;
23538
+ PARALLEL_SPACING = 22;
23539
+ PHI = 1.618;
23540
+ NODE_HEIGHT = 60;
23541
+ NODE_WIDTH = Math.round(NODE_HEIGHT * PHI);
23542
+ DESC_NODE_WIDTH = 140;
23543
+ DESC_FONT_SIZE2 = 10;
23544
+ DESC_LINE_HEIGHT2 = 1.4;
23545
+ DESC_PADDING = 8;
23546
+ SEPARATOR_GAP5 = 4;
23547
+ MAX_DESC_LINES2 = 6;
23548
+ MAX_LABEL_LINES = 3;
23549
+ LABEL_LINE_HEIGHT = 1.3;
23550
+ LABEL_PAD = 12;
23551
+ elkInstance = null;
23552
+ CROSSINGS_FORGIVENESS = 1;
23553
+ }
23554
+ });
23555
+
23493
23556
  // src/mindmap/text-wrap.ts
23494
23557
  function tokenize(text) {
23495
23558
  const tokens = [];
@@ -23628,7 +23691,7 @@ var layout_exports6 = {};
23628
23691
  __export(layout_exports6, {
23629
23692
  layoutMindmap: () => layoutMindmap
23630
23693
  });
23631
- function layoutMindmap(parsed, palette, options) {
23694
+ function layoutMindmap(parsed, _palette, options) {
23632
23695
  const roots = parsed.roots;
23633
23696
  if (roots.length === 0) {
23634
23697
  return { nodes: [], edges: [], width: 0, height: 0 };
@@ -24524,7 +24587,7 @@ function layoutElement(el, x, y, width) {
24524
24587
  node.height = getElementHeight(el);
24525
24588
  return node;
24526
24589
  }
24527
- const isInlineRow = el.metadata._inlineRow === "true" || el.metadata._labelField === "true";
24590
+ const isInlineRow = el.metadata["_inlineRow"] === "true" || el.metadata["_labelField"] === "true";
24528
24591
  const padTop = isInlineRow ? 0 : GROUP_PADDING_TOP;
24529
24592
  const padBottom = isInlineRow ? 0 : GROUP_PADDING_BOTTOM;
24530
24593
  const padX = isInlineRow ? 0 : GROUP_PADDING_X;
@@ -24573,7 +24636,7 @@ function allocateEqualWidths(children, totalWidth) {
24573
24636
  }
24574
24637
  function getElementHeight(el) {
24575
24638
  if (el.type === "heading") {
24576
- return el.headingLevel === 2 ? ELEMENT_HEIGHTS.subheading ?? 36 : ELEMENT_HEIGHTS.heading ?? 48;
24639
+ return el.headingLevel === 2 ? ELEMENT_HEIGHTS["subheading"] ?? 36 : ELEMENT_HEIGHTS["heading"] ?? 48;
24577
24640
  }
24578
24641
  if (el.type === "textInput" && el.fieldVariant === "textarea") {
24579
24642
  return 80;
@@ -24587,16 +24650,16 @@ function getElementHeight(el) {
24587
24650
  if (el.type === "image") {
24588
24651
  if (el.imageHint === "round") return 80;
24589
24652
  if (el.imageHint === "wide") return 80;
24590
- return ELEMENT_HEIGHTS.image ?? 120;
24653
+ return ELEMENT_HEIGHTS["image"] ?? 120;
24591
24654
  }
24592
- if (el.metadata._labelField === "true") {
24655
+ if (el.metadata["_labelField"] === "true") {
24593
24656
  return 36;
24594
24657
  }
24595
24658
  return ELEMENT_HEIGHTS[el.type] ?? 24;
24596
24659
  }
24597
24660
  function getSpacingAfter(el) {
24598
24661
  if (el.type === "heading" && el.headingLevel === 2) {
24599
- return SPACING_AFTER.subheading ?? 12;
24662
+ return SPACING_AFTER["subheading"] ?? 12;
24600
24663
  }
24601
24664
  return SPACING_AFTER[el.type] ?? 8;
24602
24665
  }
@@ -24604,7 +24667,7 @@ function computeFieldAlignX(children) {
24604
24667
  let maxLabelWidth = 0;
24605
24668
  let labelFieldCount = 0;
24606
24669
  for (const child of children) {
24607
- if (child.metadata._labelField === "true" && child.children.length >= 2) {
24670
+ if (child.metadata["_labelField"] === "true" && child.children.length >= 2) {
24608
24671
  const labelEl = child.children[0];
24609
24672
  const labelWidth = labelEl.label.length * CHAR_WIDTH5;
24610
24673
  maxLabelWidth = Math.max(maxLabelWidth, labelWidth);
@@ -24816,7 +24879,7 @@ function renderNode(parent, node, ctx, depth) {
24816
24879
  function renderGroup(g, node, ctx, depth) {
24817
24880
  const { palette, isTransparent } = ctx;
24818
24881
  const el = node.element;
24819
- if (el.metadata._inlineRow === "true" || el.metadata._labelField === "true") {
24882
+ if (el.metadata["_inlineRow"] === "true" || el.metadata["_labelField"] === "true") {
24820
24883
  for (const child of node.children) {
24821
24884
  renderNode(g, child, ctx, depth);
24822
24885
  }
@@ -24944,7 +25007,7 @@ function renderDivider(g, node, ctx) {
24944
25007
  function renderText(g, node, ctx) {
24945
25008
  const { palette } = ctx;
24946
25009
  const el = node.element;
24947
- if (el.metadata._labelField === "true" && el.children.length >= 2) {
25010
+ if (el.metadata["_labelField"] === "true" && el.children.length >= 2) {
24948
25011
  for (const child of node.children) {
24949
25012
  renderNode(g, child, ctx, 0);
24950
25013
  }
@@ -25238,7 +25301,7 @@ __export(layout_exports8, {
25238
25301
  layoutC4Deployment: () => layoutC4Deployment,
25239
25302
  rollUpContextRelationships: () => rollUpContextRelationships
25240
25303
  });
25241
- import dagre5 from "@dagrejs/dagre";
25304
+ import dagre4 from "@dagrejs/dagre";
25242
25305
  function computeEdgePenalty(edgeList, nodePositions, degrees, nodeGeometry) {
25243
25306
  let penalty = 0;
25244
25307
  for (const edge of edgeList) {
@@ -25679,7 +25742,7 @@ function layoutC4Context(parsed, activeTagGroup) {
25679
25742
  }
25680
25743
  const contextRels = rollUpContextRelationships(parsed);
25681
25744
  const spacing = computeAdaptiveSpacing(contextRels);
25682
- const g = new dagre5.graphlib.Graph();
25745
+ const g = new dagre4.graphlib.Graph();
25683
25746
  g.setGraph({
25684
25747
  rankdir: "TB",
25685
25748
  nodesep: spacing.nodesep,
@@ -25700,7 +25763,7 @@ function layoutC4Context(parsed, activeTagGroup) {
25700
25763
  g.setEdge(rel.sourceName, rel.targetName, { label: rel.label ?? "" });
25701
25764
  }
25702
25765
  }
25703
- dagre5.layout(g);
25766
+ dagre4.layout(g);
25704
25767
  reduceCrossings(
25705
25768
  g,
25706
25769
  validRels.map((r) => ({ source: r.sourceName, target: r.targetName }))
@@ -25872,7 +25935,7 @@ function layoutC4Containers(parsed, systemName, activeTagGroup) {
25872
25935
  }
25873
25936
  }
25874
25937
  const hasGroups = elementToGroup.size > 0;
25875
- const g = hasGroups ? new dagre5.graphlib.Graph({ compound: true }) : new dagre5.graphlib.Graph();
25938
+ const g = hasGroups ? new dagre4.graphlib.Graph({ compound: true }) : new dagre4.graphlib.Graph();
25876
25939
  g.setDefaultEdgeLabel(() => ({}));
25877
25940
  if (hasGroups) {
25878
25941
  const seenGroups = /* @__PURE__ */ new Set();
@@ -25950,7 +26013,7 @@ function layoutC4Containers(parsed, systemName, activeTagGroup) {
25950
26013
  g.setEdge(rel.sourceName, rel.targetName, { label: rel.label ?? "" });
25951
26014
  }
25952
26015
  }
25953
- dagre5.layout(g);
26016
+ dagre4.layout(g);
25954
26017
  const nodeGroupMap = hasGroups ? new Map([...elementToGroup.entries()].map(([k, v]) => [k, v.name])) : void 0;
25955
26018
  reduceCrossings(
25956
26019
  g,
@@ -26276,7 +26339,7 @@ function layoutC4Components(parsed, systemName, containerName, activeTagGroup) {
26276
26339
  }
26277
26340
  }
26278
26341
  const hasGroups = elementToGroup.size > 0;
26279
- const g = hasGroups ? new dagre5.graphlib.Graph({ compound: true }) : new dagre5.graphlib.Graph();
26342
+ const g = hasGroups ? new dagre4.graphlib.Graph({ compound: true }) : new dagre4.graphlib.Graph();
26280
26343
  g.setDefaultEdgeLabel(() => ({}));
26281
26344
  if (hasGroups) {
26282
26345
  const seenGroups = /* @__PURE__ */ new Set();
@@ -26360,7 +26423,7 @@ function layoutC4Components(parsed, systemName, containerName, activeTagGroup) {
26360
26423
  g.setEdge(rel.sourceName, rel.targetName, { label: rel.label ?? "" });
26361
26424
  }
26362
26425
  }
26363
- dagre5.layout(g);
26426
+ dagre4.layout(g);
26364
26427
  const nodeGroupMap = hasGroups ? new Map([...elementToGroup.entries()].map(([k, v]) => [k, v.name])) : void 0;
26365
26428
  reduceCrossings(
26366
26429
  g,
@@ -26649,7 +26712,7 @@ function layoutC4Deployment(parsed, activeTagGroup) {
26649
26712
  for (const r of refEntries) {
26650
26713
  nameToElement.set(r.element.name, r.element);
26651
26714
  }
26652
- const g = new dagre5.graphlib.Graph({ compound: true });
26715
+ const g = new dagre4.graphlib.Graph({ compound: true });
26653
26716
  g.setDefaultEdgeLabel(() => ({}));
26654
26717
  for (const [infraId] of infraIds) {
26655
26718
  g.setNode(infraId, {});
@@ -26693,7 +26756,7 @@ function layoutC4Deployment(parsed, activeTagGroup) {
26693
26756
  g.setEdge(rel.sourceName, rel.targetName, { label: rel.label ?? "" });
26694
26757
  }
26695
26758
  }
26696
- dagre5.layout(g);
26759
+ dagre4.layout(g);
26697
26760
  const nodeInfraMap = /* @__PURE__ */ new Map();
26698
26761
  for (const r of refEntries) nodeInfraMap.set(r.element.name, r.infraId);
26699
26762
  reduceCrossings(
@@ -27925,7 +27988,7 @@ var layout_exports9 = {};
27925
27988
  __export(layout_exports9, {
27926
27989
  layoutGraph: () => layoutGraph
27927
27990
  });
27928
- import dagre6 from "@dagrejs/dagre";
27991
+ import dagre5 from "@dagrejs/dagre";
27929
27992
  function computeNodeWidth(label, shape) {
27930
27993
  if (shape === "pseudostate") return 24;
27931
27994
  const base = Math.max(120, label.length * 9 + 40);
@@ -27958,7 +28021,7 @@ function layoutGraph(graph, options) {
27958
28021
  if (allNodes.length === 0) {
27959
28022
  return { nodes: [], edges: [], groups: [], width: 0, height: 0 };
27960
28023
  }
27961
- const g = new dagre6.graphlib.Graph({ compound: true });
28024
+ const g = new dagre5.graphlib.Graph({ compound: true });
27962
28025
  g.setGraph({
27963
28026
  rankdir: graph.direction,
27964
28027
  nodesep: 50,
@@ -27994,7 +28057,7 @@ function layoutGraph(graph, options) {
27994
28057
  label: edge.label ?? ""
27995
28058
  });
27996
28059
  }
27997
- dagre6.layout(g);
28060
+ dagre5.layout(g);
27998
28061
  const collapsedGroupIds = collapsedChildCounts ? new Set(collapsedChildCounts.keys()) : /* @__PURE__ */ new Set();
27999
28062
  const layoutNodes = allNodes.map((node) => {
28000
28063
  const pos = g.node(node.id);
@@ -28428,7 +28491,7 @@ function renderFlowchart(container, graph, layout, palette, isDark, onClickItem,
28428
28491
  endTerminalIds.add(node.id);
28429
28492
  }
28430
28493
  }
28431
- const colorOff = graph.options?.color === "off";
28494
+ const colorOff = graph.options?.["color"] === "off";
28432
28495
  const solid = graph.options?.["solid-fill"] === "on";
28433
28496
  for (const node of layout.nodes) {
28434
28497
  const nodeG = contentG.append("g").attr("transform", `translate(${node.x}, ${node.y})`).attr("class", "fc-node").attr("data-line-number", String(node.lineNumber)).attr("data-node-id", node.id);
@@ -29357,7 +29420,7 @@ __export(layout_exports10, {
29357
29420
  layoutInfra: () => layoutInfra,
29358
29421
  separateGroups: () => separateGroups
29359
29422
  });
29360
- import dagre7 from "@dagrejs/dagre";
29423
+ import dagre6 from "@dagrejs/dagre";
29361
29424
  function countDisplayProps(node, expanded, options) {
29362
29425
  if (!expanded) return 0;
29363
29426
  let count = node.properties.filter((p) => DISPLAY_KEYS.has(p.key)).length;
@@ -29660,7 +29723,7 @@ function layoutInfra(computed, expandedNodeIds, collapsedNodes) {
29660
29723
  };
29661
29724
  }
29662
29725
  const isLR = computed.direction !== "TB";
29663
- const g = new dagre7.graphlib.Graph();
29726
+ const g = new dagre6.graphlib.Graph();
29664
29727
  g.setGraph({
29665
29728
  rankdir: computed.direction === "TB" ? "TB" : "LR",
29666
29729
  nodesep: isLR ? 70 : 60,
@@ -29711,7 +29774,7 @@ function layoutInfra(computed, expandedNodeIds, collapsedNodes) {
29711
29774
  g.setEdge(edge.sourceId, edge.targetId, { label: edge.label });
29712
29775
  }
29713
29776
  }
29714
- dagre7.layout(g);
29777
+ dagre6.layout(g);
29715
29778
  const layoutNodes = computed.nodes.map((node) => {
29716
29779
  const pos = g.node(node.id);
29717
29780
  return {
@@ -30620,7 +30683,7 @@ function renderGroups(svg, groups, palette, _isDark) {
30620
30683
  }
30621
30684
  }
30622
30685
  }
30623
- function renderEdgePaths(svg, edges, nodes, groups, palette, isDark, animate, direction, speedMultiplier = 1) {
30686
+ function renderEdgePaths(svg, edges, nodes, groups, palette, _isDark, animate, direction, speedMultiplier = 1) {
30624
30687
  const nodeMap = new Map(nodes.map((n) => [n.id, n]));
30625
30688
  const maxRps = Math.max(...edges.map((e) => e.computedRps), 1);
30626
30689
  const { srcPts, tgtPts } = computePortPts(edges, nodeMap, direction);
@@ -30661,7 +30724,7 @@ function renderEdgePaths(svg, edges, nodes, groups, palette, isDark, animate, di
30661
30724
  }
30662
30725
  }
30663
30726
  }
30664
- function renderEdgeLabels(svg, edges, nodes, groups, palette, isDark, animate, direction) {
30727
+ function renderEdgeLabels(svg, edges, nodes, groups, palette, _isDark, animate, direction) {
30665
30728
  const nodeMap = new Map(nodes.map((n) => [n.id, n]));
30666
30729
  const { srcPts, tgtPts } = computePortPts(edges, nodeMap, direction);
30667
30730
  for (const edge of edges) {
@@ -31400,7 +31463,7 @@ function sampleBetaPert(o, m, p, rng) {
31400
31463
  const beta = 1 + 4 * (p - m) / range;
31401
31464
  return o + sampleBeta(alpha, beta, rng) * range;
31402
31465
  }
31403
- function simulate(resolved, expanded, predecessors, successors, topo, terminals, poisoned, opts) {
31466
+ function simulate(resolved, expanded, _predecessors, _successors, topo, terminals, poisoned, opts) {
31404
31467
  const rng = mulberry32(opts.seed);
31405
31468
  const expById = /* @__PURE__ */ new Map();
31406
31469
  for (const e of expanded) expById.set(e.id, e);
@@ -32413,7 +32476,7 @@ __export(layout_exports11, {
32413
32476
  layoutPert: () => layoutPert,
32414
32477
  relayoutPert: () => relayoutPert
32415
32478
  });
32416
- import dagre8 from "@dagrejs/dagre";
32479
+ import dagre7 from "@dagrejs/dagre";
32417
32480
  function computeNodeSizing(resolved) {
32418
32481
  const unit = resolved.options.timeUnit;
32419
32482
  const sprintMode = resolved.options.sprintMode;
@@ -32521,7 +32584,7 @@ function relayoutPert(resolved, overrides, collapsedGroupIds = /* @__PURE__ */ n
32521
32584
  }
32522
32585
  }
32523
32586
  const dagreId = (id) => memberToGroup.get(id) ?? id;
32524
- const g = new dagre8.graphlib.Graph();
32587
+ const g = new dagre7.graphlib.Graph();
32525
32588
  g.setGraph({
32526
32589
  rankdir: resolved.options.direction,
32527
32590
  nodesep: 50,
@@ -32560,7 +32623,7 @@ function relayoutPert(resolved, overrides, collapsedGroupIds = /* @__PURE__ */ n
32560
32623
  seenEdges.add(k);
32561
32624
  g.setEdge(src, tgt, {});
32562
32625
  }
32563
- dagre8.layout(g);
32626
+ dagre7.layout(g);
32564
32627
  const swimApplied = applySwimLanes(
32565
32628
  g,
32566
32629
  resolved,
@@ -32680,7 +32743,7 @@ function relayoutPert(resolved, overrides, collapsedGroupIds = /* @__PURE__ */ n
32680
32743
  height: totalH + DIAGRAM_PADDING10
32681
32744
  };
32682
32745
  }
32683
- function applySwimLanes(g, resolved, memberToGroup, collapsedGroupIds) {
32746
+ function applySwimLanes(g, resolved, _memberToGroup, collapsedGroupIds) {
32684
32747
  const expanded = resolved.groups.filter(
32685
32748
  (rg) => !collapsedGroupIds.has(rg.group.id)
32686
32749
  );
@@ -32906,7 +32969,7 @@ function reduceCrossings2(g, direction) {
32906
32969
  buckets.get(key).push(id);
32907
32970
  }
32908
32971
  const edges = g.edges().map((e) => ({ v: e.v, w: e.w }));
32909
- const countCrossings = () => {
32972
+ const countCrossings2 = () => {
32910
32973
  let total = 0;
32911
32974
  for (let i = 0; i < edges.length; i++) {
32912
32975
  const a = edges[i];
@@ -32919,13 +32982,13 @@ function reduceCrossings2(g, direction) {
32919
32982
  const b1 = g.node(b.v);
32920
32983
  const b2 = g.node(b.w);
32921
32984
  if (!b1 || !b2) continue;
32922
- if (segmentsCross(a1, a2, b1, b2)) total++;
32985
+ if (segmentsCross2(a1, a2, b1, b2)) total++;
32923
32986
  }
32924
32987
  }
32925
32988
  return total;
32926
32989
  };
32927
32990
  const MAX_ITER = 8;
32928
- let baseline = countCrossings();
32991
+ let baseline = countCrossings2();
32929
32992
  if (baseline === 0) return;
32930
32993
  for (let iter = 0; iter < MAX_ITER; iter++) {
32931
32994
  let improved = false;
@@ -32943,7 +33006,7 @@ function reduceCrossings2(g, direction) {
32943
33006
  const bv = bn[slotAxis];
32944
33007
  an[slotAxis] = bv;
32945
33008
  bn[slotAxis] = av;
32946
- const after = countCrossings();
33009
+ const after = countCrossings2();
32947
33010
  if (after < baseline) {
32948
33011
  baseline = after;
32949
33012
  improved = true;
@@ -32964,7 +33027,7 @@ function reduceCrossings2(g, direction) {
32964
33027
  data.points = smoothEdge(src, tgt, direction);
32965
33028
  }
32966
33029
  }
32967
- function segmentsCross(a1, a2, b1, b2) {
33030
+ function segmentsCross2(a1, a2, b1, b2) {
32968
33031
  const ccw = (p, q, r) => (q.x - p.x) * (r.y - p.y) - (q.y - p.y) * (r.x - p.x);
32969
33032
  const d1 = ccw(b1, b2, a1);
32970
33033
  const d2 = ccw(b1, b2, a2);
@@ -34972,12 +35035,6 @@ function calculateSchedule(parsed) {
34972
35035
  const warn2 = (line12, message) => {
34973
35036
  diagnostics.push(makeDgmoError(line12, message, "warning"));
34974
35037
  };
34975
- const _fail = (line12, message) => {
34976
- const diag = makeDgmoError(line12, message);
34977
- diagnostics.push(diag);
34978
- result.error = formatDgmoError(diag);
34979
- return result;
34980
- };
34981
35038
  const holidaySet = buildHolidaySet(parsed.holidays);
34982
35039
  let projectStart;
34983
35040
  if (parsed.options.start) {
@@ -35002,7 +35059,6 @@ function calculateSchedule(parsed) {
35002
35059
  }
35003
35060
  buildImplicitDeps(parsed.nodes, taskMap);
35004
35061
  for (const task of allTasks2) {
35005
- const _node = taskMap.get(task.id);
35006
35062
  for (const dep of task.dependencies) {
35007
35063
  const resolved = resolveTaskName(dep.targetName, allTasks2);
35008
35064
  if (isResolverError(resolved)) {
@@ -36543,7 +36599,7 @@ function buildControlsToggles(hasCriticalPath, criticalPathActive, hasDependenci
36543
36599
  }
36544
36600
  return toggles;
36545
36601
  }
36546
- function renderTagLegend(svg, chartG, tagGroups, activeGroupName, chartLeftMargin, chartInnerWidth, legendY, palette, isDark, hasCriticalPath, criticalPathActive, optionLineNumbers, onToggle, onToggleControlsExpand, currentSwimlaneGroup, onSwimlaneChange, legendViewMode, resolvedTasks, controlsExpanded = false, hasDependencies = false, dependenciesActive = false, onControlsToggle) {
36602
+ function renderTagLegend(svg, chartG, tagGroups, activeGroupName, chartLeftMargin, chartInnerWidth, legendY, palette, isDark, hasCriticalPath, criticalPathActive, _optionLineNumbers, onToggle, onToggleControlsExpand, currentSwimlaneGroup, onSwimlaneChange, legendViewMode, resolvedTasks, controlsExpanded = false, hasDependencies = false, dependenciesActive = false, onControlsToggle) {
36547
36603
  let visibleGroups;
36548
36604
  if (activeGroupName) {
36549
36605
  const activeGroup = tagGroups.filter(
@@ -37506,7 +37562,7 @@ function resolveTaskColor(rt, activeTagGroup, resolved, seriesColors2, palette)
37506
37562
  }
37507
37563
  return palette.accent || seriesColors2[0] || "#4a90d9";
37508
37564
  }
37509
- function renderTimeScaleHorizontal(g, scale, innerWidth, innerHeight, textColor) {
37565
+ function renderTimeScaleHorizontal(g, scale, _innerWidth, innerHeight, textColor) {
37510
37566
  const [domainMin, domainMax] = scale.domain();
37511
37567
  const ticks = computeTimeTicks(domainMin, domainMax, scale);
37512
37568
  if (ticks.length < 2) return;
@@ -37753,7 +37809,7 @@ function renderState(container, graph, layout, palette, isDark, onClickItem, exp
37753
37809
  for (const group of layout.groups) {
37754
37810
  if (group.collapsed) collapsedGroupIds.add(group.id);
37755
37811
  }
37756
- const colorOff = graph.options?.color === "off";
37812
+ const colorOff = graph.options?.["color"] === "off";
37757
37813
  const solid = graph.options?.["solid-fill"] === "on";
37758
37814
  for (const node of layout.nodes) {
37759
37815
  const isCollapsedGroup = collapsedGroupIds.has(node.id);
@@ -38152,7 +38208,7 @@ function renderQuadrantFocus(container, parsed, quadrantPosition, palette, isDar
38152
38208
  }
38153
38209
  }
38154
38210
  }
38155
- function renderQuarterCircle(svg, parsed, quadrant, qColor, palette, isDark, width, height, mutedColor, tooltip, rootContainer, onClickItem) {
38211
+ function renderQuarterCircle(svg, parsed, quadrant, qColor, palette, isDark, width, height, mutedColor, _tooltip, rootContainer, onClickItem) {
38156
38212
  const padding = 8;
38157
38213
  const size = Math.min(width - padding, height - padding);
38158
38214
  const maxRadius = size * 0.95;
@@ -39022,7 +39078,7 @@ function estimateListingHeight(parsed) {
39022
39078
  );
39023
39079
  return LISTING_LINE_HEIGHT * (maxBlipsInQuadrant + 1) + LISTING_LINE_HEIGHT + LISTING_TOP_MARGIN;
39024
39080
  }
39025
- function createBlipPopover(container, palette, isDark) {
39081
+ function createBlipPopover(container, _palette, isDark) {
39026
39082
  container.style.position = "relative";
39027
39083
  const existing = container.querySelector(
39028
39084
  "[data-blip-popover]"
@@ -40889,7 +40945,7 @@ function computeEdgeLabelPosition(midAngle, radius, cx, cy, lineCount, maxCharLe
40889
40945
  labelAngle: best.labelAngle
40890
40946
  };
40891
40947
  }
40892
- function fitToCanvas(nodes, edges, parsed, cx, cy, radius, width, height, _isClockwise) {
40948
+ function fitToCanvas(nodes, edges, parsed, _cx, _cy, radius, width, height, _isClockwise) {
40893
40949
  const PADDING3 = 30;
40894
40950
  let contentMinX = Infinity, contentMaxX = -Infinity;
40895
40951
  let contentMinY = Infinity, contentMaxY = -Infinity;
@@ -42399,7 +42455,7 @@ function renderPhaseBar(svg, phase, x, y, width, palette, collapsed, autoColor,
42399
42455
  });
42400
42456
  }
42401
42457
  }
42402
- function renderTaskRow(svg, task, parsed, x, y, labelW, roleX, roleColW, palette, surfaceBg, solid, taskDiagnostics, hasAnyDiagnostic, rowContent, onClickLine, _onMarkerDragStart) {
42458
+ function renderTaskRow(svg, task, parsed, x, y, labelW, roleX, roleColW, palette, surfaceBg, solid, taskDiagnostics, _hasAnyDiagnostic, rowContent, onClickLine, _onMarkerDragStart) {
42403
42459
  const rowG = svg.append("g").attr("class", "raci-task-row").attr("data-task-id", task.id).attr("data-line-number", String(task.lineNumber));
42404
42460
  const labelX = x + 8;
42405
42461
  const labelMaxW = labelW - 16;
@@ -43205,7 +43261,6 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
43205
43261
  const messages = collapsed ? collapsed.messages : parsed.messages;
43206
43262
  const elements = collapsed ? collapsed.elements : parsed.elements;
43207
43263
  const groups = collapsed ? collapsed.groups : parsed.groups;
43208
- const collapsedGroupIds = collapsed?.collapsedGroupIds ?? /* @__PURE__ */ new Map();
43209
43264
  const collapsedSections = options?.collapsedSections;
43210
43265
  const sourceParticipants = collapsed ? collapsed.participants : parsed.participants;
43211
43266
  const participants = applyPositionOverrides(
@@ -43233,7 +43288,7 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
43233
43288
  return Math.min(NOTE_MAX_W, laneMax);
43234
43289
  };
43235
43290
  const charsForWidth = (maxW) => Math.floor((maxW - NOTE_PAD_H * 2 - NOTE_FOLD) / NOTE_CHAR_W);
43236
- const activationsOff = parsedOptions.activations?.toLowerCase() === "off";
43291
+ const activationsOff = parsedOptions["activations"]?.toLowerCase() === "off";
43237
43292
  const activeTagGroup = resolveActiveTagGroup(
43238
43293
  parsed.tagGroups,
43239
43294
  parsedOptions["active-tag"],
@@ -46189,7 +46244,7 @@ function renderTimelineGroupLegend(g, groups, groupColorMap, textColor, palette,
46189
46244
  legendX += pillW + GAP;
46190
46245
  }
46191
46246
  }
46192
- function renderTimeline(container, parsed, palette, isDark, onClickItem, exportDims, activeTagGroup, swimlaneTagGroup, onTagStateChange, viewMode) {
46247
+ function setupTimeline(container, parsed, palette, isDark, exportDims, activeTagGroup, swimlaneTagGroup) {
46193
46248
  d3Selection22.select(container).selectAll(":not([data-d3-tooltip])").remove();
46194
46249
  const solid = parsed.solidFill === true;
46195
46250
  const {
@@ -46198,19 +46253,17 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
46198
46253
  timelineEras,
46199
46254
  timelineMarkers,
46200
46255
  timelineSort,
46201
- timelineScale,
46202
- timelineSwimlanes,
46203
46256
  orientation
46204
46257
  } = parsed;
46205
- const title = parsed.noTitle ? null : parsed.title;
46206
- if (timelineEvents.length === 0) return;
46207
- if (swimlaneTagGroup == null && timelineSort === "tag" && parsed.timelineDefaultSwimlaneTG) {
46208
- swimlaneTagGroup = parsed.timelineDefaultSwimlaneTG;
46258
+ if (timelineEvents.length === 0) return null;
46259
+ let resolvedSwimlaneTG = swimlaneTagGroup ?? null;
46260
+ if (resolvedSwimlaneTG == null && timelineSort === "tag" && parsed.timelineDefaultSwimlaneTG) {
46261
+ resolvedSwimlaneTG = parsed.timelineDefaultSwimlaneTG;
46209
46262
  }
46210
46263
  const tooltip = createTooltip2(container, palette, isDark);
46211
46264
  const width = exportDims?.width ?? container.clientWidth;
46212
46265
  const height = exportDims?.height ?? container.clientHeight;
46213
- if (width <= 0 || height <= 0) return;
46266
+ if (width <= 0 || height <= 0) return null;
46214
46267
  const isVertical = orientation === "vertical";
46215
46268
  const textColor = palette.text;
46216
46269
  const mutedColor = palette.border;
@@ -46222,8 +46275,8 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
46222
46275
  groupColorMap.set(grp.name, grp.color ?? colors[i % colors.length]);
46223
46276
  });
46224
46277
  let tagLanes = null;
46225
- if (swimlaneTagGroup) {
46226
- const tagKey = swimlaneTagGroup.toLowerCase();
46278
+ if (resolvedSwimlaneTG) {
46279
+ const tagKey = resolvedSwimlaneTG.toLowerCase();
46227
46280
  const tagGroup = parsed.timelineTagGroups.find(
46228
46281
  (g) => g.name.toLowerCase() === tagKey
46229
46282
  );
@@ -46254,7 +46307,7 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
46254
46307
  }
46255
46308
  }
46256
46309
  }
46257
- const effectiveColorTG = activeTagGroup ?? swimlaneTagGroup ?? null;
46310
+ const effectiveColorTG = activeTagGroup ?? resolvedSwimlaneTG ?? null;
46258
46311
  function eventColor(ev) {
46259
46312
  if (effectiveColorTG) {
46260
46313
  const tagColor = resolveTagColor(
@@ -46310,6 +46363,30 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
46310
46363
  }
46311
46364
  }
46312
46365
  const datePadding = (maxDate - minDate) * 0.05 || 0.5;
46366
+ const tagLegendReserve = parsed.timelineTagGroups.length > 0 ? 36 : 0;
46367
+ return {
46368
+ width,
46369
+ height,
46370
+ isVertical,
46371
+ tooltip,
46372
+ solid,
46373
+ textColor,
46374
+ mutedColor,
46375
+ bgColor,
46376
+ bg,
46377
+ swimlaneTagGroup: resolvedSwimlaneTG,
46378
+ groupColorMap,
46379
+ tagLanes,
46380
+ eventColor,
46381
+ minDate,
46382
+ maxDate,
46383
+ datePadding,
46384
+ earliestStartDateStr,
46385
+ latestEndDateStr,
46386
+ tagLegendReserve
46387
+ };
46388
+ }
46389
+ function makeTimelineHoverHelpers() {
46313
46390
  const FADE_OPACITY3 = 0.1;
46314
46391
  function fadeToGroup(g, groupName) {
46315
46392
  g.selectAll(".tl-event").each(function() {
@@ -46409,337 +46486,683 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
46409
46486
  evG.attr(`data-tag-${key}`, value.toLowerCase());
46410
46487
  }
46411
46488
  }
46412
- const tagLegendReserve = parsed.timelineTagGroups.length > 0 ? 36 : 0;
46413
- if (isVertical) {
46414
- const useGroupedVertical = tagLanes != null || timelineSort === "group" && timelineGroups.length > 0;
46415
- if (useGroupedVertical) {
46416
- let laneNames;
46417
- let laneEventsByName;
46418
- if (tagLanes) {
46419
- laneNames = tagLanes.map((l) => l.name);
46420
- laneEventsByName = new Map(tagLanes.map((l) => [l.name, l.events]));
46421
- } else {
46422
- const groupNames = timelineGroups.map((gr) => gr.name);
46423
- const ungroupedEvents = timelineEvents.filter(
46424
- (ev) => ev.group === null || !groupNames.includes(ev.group)
46425
- );
46426
- laneNames = ungroupedEvents.length > 0 ? [...groupNames, "(Other)"] : groupNames;
46427
- laneEventsByName = new Map(
46428
- laneNames.map((name) => [
46429
- name,
46430
- timelineEvents.filter(
46431
- (ev) => name === "(Other)" ? ev.group === null || !groupNames.includes(ev.group) : ev.group === name
46432
- )
46433
- ])
46434
- );
46489
+ return {
46490
+ FADE_OPACITY: FADE_OPACITY3,
46491
+ fadeToGroup,
46492
+ fadeToEra,
46493
+ fadeToMarker,
46494
+ fadeReset,
46495
+ fadeToTagValue,
46496
+ setTagAttrs
46497
+ };
46498
+ }
46499
+ function renderTimelineTagLegendOverlay(container, parsed, palette, isDark, setup, hovers, onClickItem, exportDims, swimlaneTagGroup, activeTagGroup, onTagStateChange, viewMode) {
46500
+ if (parsed.timelineTagGroups.length === 0) return;
46501
+ const { width, textColor, groupColorMap, solid } = setup;
46502
+ const { FADE_OPACITY: FADE_OPACITY3, fadeReset, fadeToTagValue } = hovers;
46503
+ const title = parsed.noTitle ? null : parsed.title;
46504
+ const { timelineEvents } = parsed;
46505
+ const LG_HEIGHT = LEGEND_HEIGHT;
46506
+ const LG_PILL_PAD = LEGEND_PILL_PAD;
46507
+ const LG_PILL_FONT_SIZE = LEGEND_PILL_FONT_SIZE;
46508
+ const LG_CAPSULE_PAD = LEGEND_CAPSULE_PAD;
46509
+ const LG_DOT_R = LEGEND_DOT_R;
46510
+ const LG_ENTRY_FONT_SIZE = LEGEND_ENTRY_FONT_SIZE;
46511
+ const LG_ENTRY_DOT_GAP = LEGEND_ENTRY_DOT_GAP;
46512
+ const LG_ENTRY_TRAIL = LEGEND_ENTRY_TRAIL;
46513
+ const LG_ICON_W = 20;
46514
+ const mainSvg = d3Selection22.select(container).select("svg");
46515
+ const mainG = mainSvg.select("g");
46516
+ if (!mainSvg.empty() && !mainG.empty()) {
46517
+ let drawSwimlaneIcon4 = function(parent, x, y, isSwimActive) {
46518
+ const iconG = parent.append("g").attr("class", "tl-swimlane-icon").attr("transform", `translate(${x}, ${y})`).style("cursor", "pointer");
46519
+ const barColor = isSwimActive ? palette.primary : palette.textMuted;
46520
+ const barOpacity = isSwimActive ? 1 : 0.35;
46521
+ const bars = [
46522
+ { y: 0, w: 8 },
46523
+ { y: 4, w: 12 },
46524
+ { y: 8, w: 6 }
46525
+ ];
46526
+ for (const bar of bars) {
46527
+ iconG.append("rect").attr("x", 0).attr("y", bar.y).attr("width", bar.w).attr("height", 2).attr("rx", 1).attr("fill", barColor).attr("opacity", barOpacity);
46435
46528
  }
46436
- const laneCount = laneNames.length;
46437
- const scaleMargin = timelineScale ? 40 : 0;
46438
- const markerMargin = timelineMarkers.length > 0 ? 30 : 0;
46439
- const margin = {
46440
- top: 104 + markerMargin + tagLegendReserve,
46441
- right: 40 + scaleMargin,
46442
- bottom: 40,
46443
- left: 60 + scaleMargin
46444
- };
46445
- const innerWidth = width - margin.left - margin.right;
46446
- const innerHeight = height - margin.top - margin.bottom;
46447
- const laneWidth = innerWidth / laneCount;
46448
- const yScale = d3Scale2.scaleLinear().domain([minDate - datePadding, maxDate + datePadding]).range([0, innerHeight]);
46449
- const svg = d3Selection22.select(container).append("svg").attr("viewBox", `0 0 ${width} ${height}`).attr("width", exportDims ? width : "100%").attr("preserveAspectRatio", "xMidYMin meet").style("background", bgColor);
46450
- const g = svg.append("g").attr("transform", `translate(${margin.left},${margin.top})`);
46451
- renderChartTitle(
46452
- svg,
46453
- title,
46454
- parsed.titleLineNumber,
46455
- width,
46456
- textColor,
46457
- onClickItem
46458
- );
46459
- renderEras(
46460
- g,
46461
- timelineEras,
46462
- yScale,
46463
- true,
46464
- innerWidth,
46465
- innerHeight,
46466
- (s, e) => fadeToEra(g, s, e),
46467
- () => fadeReset(g),
46468
- timelineScale,
46469
- tooltip,
46470
- palette
46471
- );
46472
- renderMarkers(
46473
- g,
46474
- timelineMarkers,
46475
- yScale,
46476
- true,
46477
- innerWidth,
46478
- innerHeight,
46479
- (d) => fadeToMarker(g, d),
46480
- () => fadeReset(g),
46481
- timelineScale,
46482
- tooltip,
46483
- palette
46529
+ return iconG;
46530
+ }, relayout2 = function() {
46531
+ renderTimeline(
46532
+ container,
46533
+ parsed,
46534
+ palette,
46535
+ isDark,
46536
+ onClickItem,
46537
+ exportDims,
46538
+ currentActiveGroup,
46539
+ currentSwimlaneGroup,
46540
+ onTagStateChange,
46541
+ viewMode
46484
46542
  );
46485
- if (timelineScale) {
46486
- renderTimeScale(
46487
- g,
46488
- yScale,
46489
- true,
46490
- innerWidth,
46491
- innerHeight,
46492
- textColor,
46493
- minDate,
46494
- maxDate,
46495
- formatBoundaryLabel(earliestStartDateStr, latestEndDateStr),
46496
- formatBoundaryLabel(latestEndDateStr, earliestStartDateStr)
46543
+ }, drawLegend2 = function() {
46544
+ mainSvg.selectAll(".tl-tag-legend-group").remove();
46545
+ mainSvg.selectAll(".tl-tag-legend-container").remove();
46546
+ const effectiveColorKey = (currentActiveGroup ?? currentSwimlaneGroup)?.toLowerCase() ?? null;
46547
+ const visibleGroups = viewMode ? legendGroups.filter(
46548
+ (lg) => effectiveColorKey != null && lg.group.name.toLowerCase() === effectiveColorKey
46549
+ ) : legendGroups;
46550
+ if (visibleGroups.length === 0) return;
46551
+ const legendContainer = mainSvg.append("g").attr("class", "tl-tag-legend-container");
46552
+ if (currentActiveGroup) {
46553
+ legendContainer.attr(
46554
+ "data-legend-active",
46555
+ currentActiveGroup.toLowerCase()
46497
46556
  );
46498
46557
  }
46499
- if (timelineSwimlanes || tagLanes) {
46500
- laneNames.forEach((laneName, laneIdx) => {
46501
- const laneX = laneIdx * laneWidth;
46502
- const fillColor = laneIdx % 2 === 0 ? textColor : "transparent";
46503
- g.append("rect").attr("class", "tl-swimlane").attr("data-group", laneName).attr("x", laneX).attr("y", 0).attr("width", laneWidth).attr("height", innerHeight).attr("fill", fillColor).attr("opacity", 0.06);
46504
- });
46505
- }
46506
- laneNames.forEach((laneName, laneIdx) => {
46507
- const laneX = laneIdx * laneWidth;
46508
- const laneColor = groupColorMap.get(laneName) ?? textColor;
46509
- const laneCenter = laneX + laneWidth / 2;
46510
- const headerG = g.append("g").attr("class", "tl-lane-header").attr("data-group", laneName).style("cursor", "pointer").on("mouseenter", () => fadeToGroup(g, laneName)).on("mouseleave", () => fadeReset(g));
46511
- headerG.append("text").attr("x", laneCenter).attr("y", -15).attr("text-anchor", "middle").attr("fill", laneColor).attr("font-size", "12px").attr("font-weight", "600").text(laneName);
46512
- g.append("line").attr("x1", laneCenter).attr("y1", 0).attr("x2", laneCenter).attr("y2", innerHeight).attr("stroke", mutedColor).attr("stroke-width", 1).attr("stroke-dasharray", "4,4");
46513
- const laneEvents = laneEventsByName.get(laneName) ?? [];
46514
- for (const ev of laneEvents) {
46515
- const y = yScale(parseTimelineDate(ev.date));
46516
- const evG = g.append("g").attr("class", "tl-event").attr("data-group", laneName).attr("data-line-number", String(ev.lineNumber)).attr("data-date", String(parseTimelineDate(ev.date))).attr(
46517
- "data-end-date",
46518
- ev.endDate ? String(parseTimelineDate(ev.endDate)) : null
46519
- ).style("cursor", "pointer").on("mouseenter", function(event) {
46520
- fadeToGroup(g, laneName);
46521
- showTooltip(tooltip, buildEventTooltipHtml(ev), event);
46522
- }).on("mouseleave", function() {
46523
- fadeReset(g);
46524
- hideTooltip(tooltip);
46525
- }).on("mousemove", function(event) {
46526
- showTooltip(tooltip, buildEventTooltipHtml(ev), event);
46527
- }).on("click", () => {
46528
- if (onClickItem && ev.lineNumber) onClickItem(ev.lineNumber);
46529
- });
46530
- setTagAttrs(evG, ev);
46531
- const evColor = eventColor(ev);
46532
- if (ev.endDate) {
46533
- const y2 = yScale(parseTimelineDate(ev.endDate));
46534
- const rectH = Math.max(y2 - y, 4);
46535
- let fill2 = shapeFill(palette, evColor, isDark, { solid });
46536
- let stroke2 = evColor;
46537
- if (ev.uncertain) {
46538
- const gradientId = `uncertain-vg-${ev.lineNumber}`;
46539
- const strokeGradientId = `uncertain-vg-s-${ev.lineNumber}`;
46540
- const defs = svg.select("defs").node() || svg.append("defs").node();
46541
- const defsEl = d3Selection22.select(defs);
46542
- defsEl.append("linearGradient").attr("id", gradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "0%").attr("y2", "100%").selectAll("stop").data([
46543
- { offset: "0%", opacity: 1 },
46544
- { offset: "80%", opacity: 1 },
46545
- { offset: "100%", opacity: 0 }
46546
- ]).enter().append("stop").attr("offset", (d) => d.offset).attr("stop-color", mix(laneColor, bg, 30)).attr("stop-opacity", (d) => d.opacity);
46547
- defsEl.append("linearGradient").attr("id", strokeGradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "0%").attr("y2", "100%").selectAll("stop").data([
46548
- { offset: "0%", opacity: 1 },
46549
- { offset: "80%", opacity: 1 },
46550
- { offset: "100%", opacity: 0 }
46551
- ]).enter().append("stop").attr("offset", (d) => d.offset).attr("stop-color", evColor).attr("stop-opacity", (d) => d.opacity);
46552
- fill2 = `url(#${gradientId})`;
46553
- stroke2 = `url(#${strokeGradientId})`;
46554
- }
46555
- evG.append("rect").attr("x", laneCenter - 6).attr("y", y).attr("width", 12).attr("height", rectH).attr("rx", 4).attr("fill", fill2).attr("stroke", stroke2).attr("stroke-width", 2);
46556
- evG.append("text").attr("x", laneCenter + 14).attr("y", y + rectH / 2).attr("dy", "0.35em").attr("fill", textColor).attr("font-size", "10px").text(ev.label);
46558
+ const iconAddon = viewMode ? 0 : LG_ICON_W;
46559
+ const centralGroups = visibleGroups.map((lg) => ({
46560
+ name: lg.group.name,
46561
+ entries: lg.group.entries.map((e) => ({
46562
+ value: e.value,
46563
+ color: e.color
46564
+ }))
46565
+ }));
46566
+ const centralActive = viewMode ? effectiveColorKey : currentActiveGroup;
46567
+ const centralConfig = {
46568
+ groups: centralGroups,
46569
+ position: { placement: "top-center", titleRelation: "below-title" },
46570
+ mode: "fixed",
46571
+ capsulePillAddonWidth: iconAddon
46572
+ };
46573
+ const centralState = { activeGroup: centralActive };
46574
+ const centralCallbacks = viewMode ? {} : {
46575
+ onGroupToggle: (groupName) => {
46576
+ currentActiveGroup = currentActiveGroup === groupName.toLowerCase() ? null : groupName.toLowerCase();
46577
+ drawLegend2();
46578
+ recolorEvents2();
46579
+ onTagStateChange?.(currentActiveGroup, currentSwimlaneGroup);
46580
+ },
46581
+ onEntryHover: (groupName, entryValue) => {
46582
+ const tagKey = groupName.toLowerCase();
46583
+ if (entryValue) {
46584
+ const tagVal = entryValue.toLowerCase();
46585
+ fadeToTagValue(mainG, tagKey, tagVal);
46586
+ mainSvg.selectAll("[data-legend-entry]").each(function() {
46587
+ const el = d3Selection22.select(this);
46588
+ const ev = el.attr("data-legend-entry");
46589
+ const eg = el.attr("data-tag-group") ?? el.node()?.closest?.("[data-tag-group]")?.getAttribute("data-tag-group");
46590
+ el.attr(
46591
+ "opacity",
46592
+ eg === tagKey && ev === tagVal ? 1 : FADE_OPACITY3
46593
+ );
46594
+ });
46557
46595
  } else {
46558
- evG.append("circle").attr("cx", laneCenter).attr("cy", y).attr("r", 4).attr("fill", shapeFill(palette, evColor, isDark, { solid })).attr("stroke", evColor).attr("stroke-width", 2);
46559
- evG.append("text").attr("x", laneCenter + 10).attr("y", y).attr("dy", "0.35em").attr("fill", textColor).attr("font-size", "10px").text(ev.label);
46596
+ fadeReset(mainG);
46597
+ mainSvg.selectAll("[data-legend-entry]").attr("opacity", 1);
46598
+ }
46599
+ },
46600
+ onGroupRendered: (groupName, groupEl, isActive) => {
46601
+ const groupKey = groupName.toLowerCase();
46602
+ groupEl.attr("data-tag-group", groupKey);
46603
+ if (isActive && !viewMode) {
46604
+ const isSwimActive = currentSwimlaneGroup != null && currentSwimlaneGroup.toLowerCase() === groupKey;
46605
+ const pillWidth3 = measureLegendText(groupName, LG_PILL_FONT_SIZE) + LG_PILL_PAD;
46606
+ const pillXOff = LG_CAPSULE_PAD;
46607
+ const iconX = pillXOff + pillWidth3 + 5;
46608
+ const iconY = (LG_HEIGHT - 10) / 2;
46609
+ const iconEl = drawSwimlaneIcon4(
46610
+ groupEl,
46611
+ iconX,
46612
+ iconY,
46613
+ isSwimActive
46614
+ );
46615
+ iconEl.attr("data-swimlane-toggle", groupKey).on("click", (event) => {
46616
+ event.stopPropagation();
46617
+ currentSwimlaneGroup = currentSwimlaneGroup === groupKey ? null : groupKey;
46618
+ onTagStateChange?.(
46619
+ currentActiveGroup,
46620
+ currentSwimlaneGroup
46621
+ );
46622
+ relayout2();
46623
+ });
46560
46624
  }
46561
46625
  }
46562
- });
46563
- } else {
46564
- const scaleMargin = timelineScale ? 40 : 0;
46565
- const markerMargin = timelineMarkers.length > 0 ? 30 : 0;
46566
- const margin = {
46567
- top: 104 + markerMargin + tagLegendReserve,
46568
- right: 200,
46569
- bottom: 40,
46570
- left: 60 + scaleMargin
46571
46626
  };
46572
- const innerWidth = width - margin.left - margin.right;
46573
- const innerHeight = height - margin.top - margin.bottom;
46574
- const axisX = 20;
46575
- const yScale = d3Scale2.scaleLinear().domain([minDate - datePadding, maxDate + datePadding]).range([0, innerHeight]);
46576
- const sorted = timelineEvents.slice().sort((a, b) => parseTimelineDate(a.date) - parseTimelineDate(b.date));
46577
- const svg = d3Selection22.select(container).append("svg").attr("viewBox", `0 0 ${width} ${height}`).attr("width", exportDims ? width : "100%").attr("preserveAspectRatio", "xMidYMin meet").style("background", bgColor);
46578
- const g = svg.append("g").attr("transform", `translate(${margin.left},${margin.top})`);
46579
- renderChartTitle(
46580
- svg,
46581
- title,
46582
- parsed.titleLineNumber,
46583
- width,
46584
- textColor,
46585
- onClickItem
46586
- );
46587
- renderEras(
46588
- g,
46589
- timelineEras,
46590
- yScale,
46591
- true,
46592
- innerWidth,
46593
- innerHeight,
46594
- (s, e) => fadeToEra(g, s, e),
46595
- () => fadeReset(g),
46596
- timelineScale,
46597
- tooltip,
46598
- palette
46599
- );
46600
- renderMarkers(
46601
- g,
46602
- timelineMarkers,
46603
- yScale,
46604
- true,
46605
- innerWidth,
46606
- innerHeight,
46607
- (d) => fadeToMarker(g, d),
46608
- () => fadeReset(g),
46609
- timelineScale,
46610
- tooltip,
46611
- palette
46627
+ const legendInnerG = legendContainer.append("g").attr("transform", `translate(0, ${legendY})`);
46628
+ renderLegendD3(
46629
+ legendInnerG,
46630
+ centralConfig,
46631
+ centralState,
46632
+ palette,
46633
+ isDark,
46634
+ centralCallbacks,
46635
+ width
46612
46636
  );
46637
+ }, recolorEvents2 = function() {
46638
+ const colorTG = currentActiveGroup ?? swimlaneTagGroup ?? null;
46639
+ mainG.selectAll(".tl-event").each(function() {
46640
+ const el = d3Selection22.select(this);
46641
+ const lineNum = el.attr("data-line-number");
46642
+ const ev = lineNum ? eventByLine.get(lineNum) : void 0;
46643
+ if (!ev) return;
46644
+ let color;
46645
+ if (colorTG) {
46646
+ const tagColor = resolveTagColor(
46647
+ ev.metadata,
46648
+ parsed.timelineTagGroups,
46649
+ colorTG
46650
+ );
46651
+ color = tagColor ?? (ev.group && groupColorMap.has(ev.group) ? groupColorMap.get(ev.group) : textColor);
46652
+ } else {
46653
+ color = ev.group && groupColorMap.has(ev.group) ? groupColorMap.get(ev.group) : textColor;
46654
+ }
46655
+ el.selectAll("rect").attr("fill", shapeFill(palette, color, isDark, { solid })).attr("stroke", color);
46656
+ el.selectAll("circle:not(.tl-event-point-outline)").attr("fill", shapeFill(palette, color, isDark, { solid })).attr("stroke", color);
46657
+ });
46658
+ };
46659
+ var drawSwimlaneIcon3 = drawSwimlaneIcon4, relayout = relayout2, drawLegend = drawLegend2, recolorEvents = recolorEvents2;
46660
+ const legendY = title ? 50 : 10;
46661
+ const legendGroups = parsed.timelineTagGroups.map((g) => {
46662
+ const pillW = measureLegendText(g.name, LG_PILL_FONT_SIZE) + LG_PILL_PAD;
46663
+ const iconSpace = viewMode ? 8 : LG_ICON_W + 4;
46664
+ let entryX = LG_CAPSULE_PAD + pillW + iconSpace;
46665
+ for (const entry of g.entries) {
46666
+ const textX = entryX + LG_DOT_R * 2 + LG_ENTRY_DOT_GAP;
46667
+ entryX = textX + measureLegendText(entry.value, LG_ENTRY_FONT_SIZE) + LG_ENTRY_TRAIL;
46668
+ }
46669
+ return {
46670
+ group: g,
46671
+ minifiedWidth: pillW,
46672
+ expandedWidth: entryX + LG_CAPSULE_PAD
46673
+ };
46674
+ });
46675
+ let currentActiveGroup = activeTagGroup ?? null;
46676
+ let currentSwimlaneGroup = swimlaneTagGroup ?? null;
46677
+ const eventByLine = /* @__PURE__ */ new Map();
46678
+ for (const ev of timelineEvents) {
46679
+ eventByLine.set(String(ev.lineNumber), ev);
46680
+ }
46681
+ drawLegend2();
46682
+ }
46683
+ }
46684
+ function renderTimelineHorizontalTimeSort(container, parsed, palette, isDark, setup, hovers, onClickItem, _exportDims, _swimlaneTagGroup, _activeTagGroup, _onTagStateChange, _viewMode) {
46685
+ const {
46686
+ width,
46687
+ height,
46688
+ tooltip,
46689
+ solid,
46690
+ textColor,
46691
+ bgColor,
46692
+ bg,
46693
+ groupColorMap,
46694
+ eventColor,
46695
+ minDate,
46696
+ maxDate,
46697
+ datePadding,
46698
+ earliestStartDateStr,
46699
+ latestEndDateStr,
46700
+ tagLegendReserve
46701
+ } = setup;
46702
+ const { fadeToGroup, fadeToEra, fadeToMarker, fadeReset, setTagAttrs } = hovers;
46703
+ const {
46704
+ timelineEvents,
46705
+ timelineGroups,
46706
+ timelineEras,
46707
+ timelineMarkers,
46708
+ timelineScale
46709
+ } = parsed;
46710
+ const title = parsed.noTitle ? null : parsed.title;
46711
+ const BAR_H2 = 22;
46712
+ const sorted = timelineEvents.slice().sort((a, b) => parseTimelineDate(a.date) - parseTimelineDate(b.date));
46713
+ const scaleMargin = timelineScale ? 24 : 0;
46714
+ const ERA_ROW_H = 22;
46715
+ const MARKER_ROW_H = 22;
46716
+ const eraReserve = timelineEras.length > 0 ? ERA_ROW_H : 0;
46717
+ const markerReserve = timelineMarkers.length > 0 ? MARKER_ROW_H : 0;
46718
+ const topScaleH = timelineScale ? 40 : 0;
46719
+ const margin = {
46720
+ top: 104 + topScaleH + eraReserve + markerReserve + tagLegendReserve,
46721
+ right: 40,
46722
+ bottom: 40 + scaleMargin,
46723
+ left: 60
46724
+ };
46725
+ const markerLabelY = markerReserve ? -(topScaleH + MARKER_ROW_H / 2) : 0;
46726
+ const eraLabelY = eraReserve ? -(topScaleH + markerReserve + ERA_ROW_H / 2) : 0;
46727
+ const innerWidth = width - margin.left - margin.right;
46728
+ const innerHeight = height - margin.top - margin.bottom;
46729
+ const rowH = Math.min(28, innerHeight / sorted.length);
46730
+ const xScale = d3Scale2.scaleLinear().domain([minDate - datePadding, maxDate + datePadding]).range([0, innerWidth]);
46731
+ const svg = d3Selection22.select(container).append("svg").attr("width", width).attr("height", height).style("background", bgColor);
46732
+ const g = svg.append("g").attr("transform", `translate(${margin.left},${margin.top})`);
46733
+ renderChartTitle(
46734
+ svg,
46735
+ title,
46736
+ parsed.titleLineNumber,
46737
+ width,
46738
+ textColor,
46739
+ onClickItem
46740
+ );
46741
+ renderEras(
46742
+ g,
46743
+ timelineEras,
46744
+ xScale,
46745
+ false,
46746
+ innerWidth,
46747
+ innerHeight,
46748
+ (s, e) => fadeToEra(g, s, e),
46749
+ () => fadeReset(g),
46750
+ timelineScale,
46751
+ tooltip,
46752
+ palette,
46753
+ eraReserve ? eraLabelY : void 0
46754
+ );
46755
+ renderMarkers(
46756
+ g,
46757
+ timelineMarkers,
46758
+ xScale,
46759
+ false,
46760
+ innerWidth,
46761
+ innerHeight,
46762
+ (d) => fadeToMarker(g, d),
46763
+ () => fadeReset(g),
46764
+ timelineScale,
46765
+ tooltip,
46766
+ palette,
46767
+ markerReserve ? markerLabelY : void 0
46768
+ );
46769
+ if (timelineScale) {
46770
+ renderTimeScale(
46771
+ g,
46772
+ xScale,
46773
+ false,
46774
+ innerWidth,
46775
+ innerHeight,
46776
+ textColor,
46777
+ minDate,
46778
+ maxDate,
46779
+ formatBoundaryLabel(earliestStartDateStr, latestEndDateStr),
46780
+ formatBoundaryLabel(latestEndDateStr, earliestStartDateStr)
46781
+ );
46782
+ }
46783
+ if (timelineGroups.length > 0) {
46784
+ const legendY = timelineScale ? -75 : -55;
46785
+ renderTimelineGroupLegend(
46786
+ g,
46787
+ timelineGroups,
46788
+ groupColorMap,
46789
+ textColor,
46790
+ palette,
46791
+ isDark,
46792
+ legendY,
46793
+ (name) => fadeToGroup(g, name),
46794
+ () => fadeReset(g)
46795
+ );
46796
+ }
46797
+ sorted.forEach((ev, i) => {
46798
+ const y = i * rowH + rowH / 2;
46799
+ const x = xScale(parseTimelineDate(ev.date));
46800
+ const color = eventColor(ev);
46801
+ const evG = g.append("g").attr("class", "tl-event").attr("data-group", ev.group || "").attr("data-line-number", String(ev.lineNumber)).attr("data-date", String(parseTimelineDate(ev.date))).attr(
46802
+ "data-end-date",
46803
+ ev.endDate ? String(parseTimelineDate(ev.endDate)) : null
46804
+ ).style("cursor", "pointer").on("mouseenter", function(event) {
46805
+ if (ev.group && timelineGroups.length > 0) fadeToGroup(g, ev.group);
46613
46806
  if (timelineScale) {
46614
- renderTimeScale(
46807
+ showEventDatesOnScale(
46615
46808
  g,
46616
- yScale,
46617
- true,
46618
- innerWidth,
46809
+ xScale,
46810
+ ev.date,
46811
+ ev.endDate,
46619
46812
  innerHeight,
46620
- textColor,
46621
- minDate,
46622
- maxDate,
46623
- formatBoundaryLabel(earliestStartDateStr, latestEndDateStr),
46624
- formatBoundaryLabel(latestEndDateStr, earliestStartDateStr)
46813
+ color
46625
46814
  );
46815
+ } else {
46816
+ showTooltip(tooltip, buildEventTooltipHtml(ev), event);
46626
46817
  }
46627
- if (timelineGroups.length > 0) {
46628
- renderTimelineGroupLegend(
46629
- g,
46630
- timelineGroups,
46631
- groupColorMap,
46632
- textColor,
46633
- palette,
46634
- isDark,
46635
- -55,
46636
- (name) => fadeToGroup(g, name),
46637
- () => fadeReset(g)
46638
- );
46818
+ }).on("mouseleave", function() {
46819
+ fadeReset(g);
46820
+ if (timelineScale) {
46821
+ hideEventDatesOnScale(g);
46822
+ } else {
46823
+ hideTooltip(tooltip);
46639
46824
  }
46640
- g.append("line").attr("x1", axisX).attr("y1", 0).attr("x2", axisX).attr("y2", innerHeight).attr("stroke", mutedColor).attr("stroke-width", 1).attr("stroke-dasharray", "4,4");
46641
- for (const ev of sorted) {
46642
- const y = yScale(parseTimelineDate(ev.date));
46643
- const color = eventColor(ev);
46644
- const evG = g.append("g").attr("class", "tl-event").attr("data-group", ev.group || "").attr("data-line-number", String(ev.lineNumber)).attr("data-date", String(parseTimelineDate(ev.date))).attr(
46645
- "data-end-date",
46646
- ev.endDate ? String(parseTimelineDate(ev.endDate)) : null
46647
- ).style("cursor", "pointer").on("mouseenter", function(event) {
46648
- if (ev.group && timelineGroups.length > 0) fadeToGroup(g, ev.group);
46825
+ }).on("mousemove", function(event) {
46826
+ if (!timelineScale) {
46827
+ showTooltip(tooltip, buildEventTooltipHtml(ev), event);
46828
+ }
46829
+ }).on("click", () => {
46830
+ if (onClickItem && ev.lineNumber) onClickItem(ev.lineNumber);
46831
+ });
46832
+ setTagAttrs(evG, ev);
46833
+ if (ev.endDate) {
46834
+ const x2 = xScale(parseTimelineDate(ev.endDate));
46835
+ const rectW = Math.max(x2 - x, 4);
46836
+ const estLabelWidth = ev.label.length * 7 + 16;
46837
+ const labelFitsInside = rectW >= estLabelWidth;
46838
+ let fill2 = shapeFill(palette, color, isDark, { solid });
46839
+ let stroke2 = color;
46840
+ if (ev.uncertain) {
46841
+ const gradientId = `uncertain-ts-${ev.lineNumber}`;
46842
+ const strokeGradientId = `uncertain-ts-s-${ev.lineNumber}`;
46843
+ const defs = svg.select("defs").node() || svg.append("defs").node();
46844
+ const defsEl = d3Selection22.select(defs);
46845
+ defsEl.append("linearGradient").attr("id", gradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "100%").attr("y2", "0%").selectAll("stop").data([
46846
+ { offset: "0%", opacity: 1 },
46847
+ { offset: "80%", opacity: 1 },
46848
+ { offset: "100%", opacity: 0 }
46849
+ ]).enter().append("stop").attr("offset", (d) => d.offset).attr("stop-color", mix(color, bg, 30)).attr("stop-opacity", (d) => d.opacity);
46850
+ defsEl.append("linearGradient").attr("id", strokeGradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "100%").attr("y2", "0%").selectAll("stop").data([
46851
+ { offset: "0%", opacity: 1 },
46852
+ { offset: "80%", opacity: 1 },
46853
+ { offset: "100%", opacity: 0 }
46854
+ ]).enter().append("stop").attr("offset", (d) => d.offset).attr("stop-color", color).attr("stop-opacity", (d) => d.opacity);
46855
+ fill2 = `url(#${gradientId})`;
46856
+ stroke2 = `url(#${strokeGradientId})`;
46857
+ }
46858
+ evG.append("rect").attr("x", x).attr("y", y - BAR_H2 / 2).attr("width", rectW).attr("height", BAR_H2).attr("rx", 4).attr("fill", fill2).attr("stroke", stroke2).attr("stroke-width", 2);
46859
+ if (labelFitsInside) {
46860
+ evG.append("text").attr("x", x + 8).attr("y", y).attr("dy", "0.35em").attr("text-anchor", "start").attr("fill", textColor).attr("font-size", "13px").text(ev.label);
46861
+ } else {
46862
+ const wouldFlipLeft = x + rectW > innerWidth * 0.6;
46863
+ const labelFitsLeft = x - 6 - estLabelWidth > 0;
46864
+ const flipLeft = wouldFlipLeft && labelFitsLeft;
46865
+ evG.append("text").attr("x", flipLeft ? x - 6 : x + rectW + 6).attr("y", y).attr("dy", "0.35em").attr("text-anchor", flipLeft ? "end" : "start").attr("fill", textColor).attr("font-size", "13px").text(ev.label);
46866
+ }
46867
+ } else {
46868
+ const estLabelWidth = ev.label.length * 7;
46869
+ const wouldFlipLeft = x > innerWidth * 0.6;
46870
+ const labelFitsLeft = x - 10 - estLabelWidth > 0;
46871
+ const flipLeft = wouldFlipLeft && labelFitsLeft;
46872
+ evG.append("circle").attr("cx", x).attr("cy", y).attr("r", 5).attr("fill", shapeFill(palette, color, isDark, { solid })).attr("stroke", color).attr("stroke-width", 2);
46873
+ evG.append("text").attr("x", flipLeft ? x - 10 : x + 10).attr("y", y).attr("dy", "0.35em").attr("text-anchor", flipLeft ? "end" : "start").attr("fill", textColor).attr("font-size", "12px").text(ev.label);
46874
+ }
46875
+ });
46876
+ }
46877
+ function renderTimelineHorizontalGrouped(container, parsed, palette, isDark, setup, hovers, onClickItem, _exportDims, _swimlaneTagGroup, _activeTagGroup, _onTagStateChange, _viewMode) {
46878
+ const {
46879
+ width,
46880
+ height,
46881
+ tooltip,
46882
+ solid,
46883
+ textColor,
46884
+ bgColor,
46885
+ bg,
46886
+ groupColorMap,
46887
+ tagLanes,
46888
+ eventColor,
46889
+ minDate,
46890
+ maxDate,
46891
+ datePadding,
46892
+ earliestStartDateStr,
46893
+ latestEndDateStr,
46894
+ tagLegendReserve
46895
+ } = setup;
46896
+ const { fadeToGroup, fadeToEra, fadeToMarker, fadeReset, setTagAttrs } = hovers;
46897
+ const {
46898
+ timelineEvents,
46899
+ timelineGroups,
46900
+ timelineEras,
46901
+ timelineMarkers,
46902
+ timelineScale,
46903
+ timelineSwimlanes
46904
+ } = parsed;
46905
+ const title = parsed.noTitle ? null : parsed.title;
46906
+ const BAR_H2 = 22;
46907
+ const GROUP_GAP3 = 12;
46908
+ let lanes;
46909
+ if (tagLanes) {
46910
+ lanes = tagLanes;
46911
+ } else {
46912
+ const groupNames = timelineGroups.map((gr) => gr.name);
46913
+ const ungroupedEvents = timelineEvents.filter(
46914
+ (ev) => ev.group === null || !groupNames.includes(ev.group)
46915
+ );
46916
+ const laneNames = ungroupedEvents.length > 0 ? [...groupNames, "(Other)"] : groupNames;
46917
+ lanes = laneNames.map((name) => ({
46918
+ name,
46919
+ events: timelineEvents.filter(
46920
+ (ev) => name === "(Other)" ? ev.group === null || !groupNames.includes(ev.group) : ev.group === name
46921
+ )
46922
+ }));
46923
+ }
46924
+ const totalEventRows = lanes.reduce((s, l) => s + l.events.length, 0);
46925
+ const scaleMargin = timelineScale ? 24 : 0;
46926
+ const ERA_ROW_H = 22;
46927
+ const MARKER_ROW_H = 22;
46928
+ const eraReserve = timelineEras.length > 0 ? ERA_ROW_H : 0;
46929
+ const markerReserve = timelineMarkers.length > 0 ? MARKER_ROW_H : 0;
46930
+ const topScaleH = timelineScale ? 40 : 0;
46931
+ const maxGroupNameLen = Math.max(...lanes.map((l) => l.name.length));
46932
+ const dynamicLeftMargin = Math.max(120, maxGroupNameLen * 7 + 30);
46933
+ const baseTopMargin = title ? 50 : 20;
46934
+ const margin = {
46935
+ top: baseTopMargin + topScaleH + eraReserve + markerReserve + tagLegendReserve,
46936
+ right: 40,
46937
+ bottom: 40 + scaleMargin,
46938
+ left: dynamicLeftMargin
46939
+ };
46940
+ const markerLabelY = markerReserve ? -(topScaleH + MARKER_ROW_H / 2) : 0;
46941
+ const eraLabelY = eraReserve ? -(topScaleH + markerReserve + ERA_ROW_H / 2) : 0;
46942
+ const innerWidth = width - margin.left - margin.right;
46943
+ const innerHeight = height - margin.top - margin.bottom;
46944
+ const totalGaps = (lanes.length - 1) * GROUP_GAP3;
46945
+ const rowH = Math.min(28, (innerHeight - totalGaps) / totalEventRows);
46946
+ const xScale = d3Scale2.scaleLinear().domain([minDate - datePadding, maxDate + datePadding]).range([0, innerWidth]);
46947
+ const svg = d3Selection22.select(container).append("svg").attr("width", width).attr("height", height).style("background", bgColor);
46948
+ const g = svg.append("g").attr("transform", `translate(${margin.left},${margin.top})`);
46949
+ renderChartTitle(
46950
+ svg,
46951
+ title,
46952
+ parsed.titleLineNumber,
46953
+ width,
46954
+ textColor,
46955
+ onClickItem
46956
+ );
46957
+ renderEras(
46958
+ g,
46959
+ timelineEras,
46960
+ xScale,
46961
+ false,
46962
+ innerWidth,
46963
+ innerHeight,
46964
+ (s, e) => fadeToEra(g, s, e),
46965
+ () => fadeReset(g),
46966
+ timelineScale,
46967
+ tooltip,
46968
+ palette,
46969
+ eraReserve ? eraLabelY : void 0
46970
+ );
46971
+ renderMarkers(
46972
+ g,
46973
+ timelineMarkers,
46974
+ xScale,
46975
+ false,
46976
+ innerWidth,
46977
+ innerHeight,
46978
+ (d) => fadeToMarker(g, d),
46979
+ () => fadeReset(g),
46980
+ timelineScale,
46981
+ tooltip,
46982
+ palette,
46983
+ markerReserve ? markerLabelY : void 0
46984
+ );
46985
+ if (timelineScale) {
46986
+ renderTimeScale(
46987
+ g,
46988
+ xScale,
46989
+ false,
46990
+ innerWidth,
46991
+ innerHeight,
46992
+ textColor,
46993
+ minDate,
46994
+ maxDate,
46995
+ formatBoundaryLabel(earliestStartDateStr, latestEndDateStr),
46996
+ formatBoundaryLabel(latestEndDateStr, earliestStartDateStr)
46997
+ );
46998
+ }
46999
+ let curY = 0;
47000
+ if (timelineSwimlanes || tagLanes) {
47001
+ let swimY = 0;
47002
+ lanes.forEach((lane, idx) => {
47003
+ const laneSpan = lane.events.length * rowH;
47004
+ const fillColor = idx % 2 === 0 ? textColor : "transparent";
47005
+ g.append("rect").attr("class", "tl-swimlane").attr("data-group", lane.name).attr("x", -margin.left).attr("y", swimY).attr("width", innerWidth + margin.left).attr("height", laneSpan + (idx < lanes.length - 1 ? GROUP_GAP3 : 0)).attr("fill", fillColor).attr("opacity", 0.06);
47006
+ swimY += laneSpan + GROUP_GAP3;
47007
+ });
47008
+ }
47009
+ for (const lane of lanes) {
47010
+ const laneColor = groupColorMap.get(lane.name) ?? textColor;
47011
+ const laneSpan = lane.events.length * rowH;
47012
+ const group = timelineGroups.find((grp) => grp.name === lane.name);
47013
+ const headerG = g.append("g").attr("class", "tl-lane-header").attr("data-group", lane.name).style("cursor", "pointer").on("mouseenter", () => fadeToGroup(g, lane.name)).on("mouseleave", () => fadeReset(g)).on("click", () => {
47014
+ if (onClickItem && group?.lineNumber) onClickItem(group.lineNumber);
47015
+ });
47016
+ headerG.append("text").attr("x", -margin.left + 10).attr("y", curY + laneSpan / 2).attr("dy", "0.35em").attr("text-anchor", "start").attr("fill", laneColor).attr("font-size", "12px").attr("font-weight", "600").text(lane.name);
47017
+ lane.events.forEach((ev, i) => {
47018
+ const y = curY + i * rowH + rowH / 2;
47019
+ const x = xScale(parseTimelineDate(ev.date));
47020
+ const evG = g.append("g").attr("class", "tl-event").attr("data-group", lane.name).attr("data-line-number", String(ev.lineNumber)).attr("data-date", String(parseTimelineDate(ev.date))).attr(
47021
+ "data-end-date",
47022
+ ev.endDate ? String(parseTimelineDate(ev.endDate)) : null
47023
+ ).style("cursor", "pointer").on("mouseenter", function(event) {
47024
+ fadeToGroup(g, lane.name);
47025
+ if (timelineScale) {
47026
+ showEventDatesOnScale(
47027
+ g,
47028
+ xScale,
47029
+ ev.date,
47030
+ ev.endDate,
47031
+ innerHeight,
47032
+ laneColor
47033
+ );
47034
+ } else {
46649
47035
  showTooltip(tooltip, buildEventTooltipHtml(ev), event);
46650
- }).on("mouseleave", function() {
46651
- fadeReset(g);
47036
+ }
47037
+ }).on("mouseleave", function() {
47038
+ fadeReset(g);
47039
+ if (timelineScale) {
47040
+ hideEventDatesOnScale(g);
47041
+ } else {
46652
47042
  hideTooltip(tooltip);
46653
- }).on("mousemove", function(event) {
47043
+ }
47044
+ }).on("mousemove", function(event) {
47045
+ if (!timelineScale) {
46654
47046
  showTooltip(tooltip, buildEventTooltipHtml(ev), event);
46655
- }).on("click", () => {
46656
- if (onClickItem && ev.lineNumber) onClickItem(ev.lineNumber);
46657
- });
46658
- setTagAttrs(evG, ev);
46659
- if (ev.endDate) {
46660
- const y2 = yScale(parseTimelineDate(ev.endDate));
46661
- const rectH = Math.max(y2 - y, 4);
46662
- let fill2 = shapeFill(palette, color, isDark, { solid });
46663
- let stroke2 = color;
46664
- if (ev.uncertain) {
46665
- const gradientId = `uncertain-v-${ev.lineNumber}`;
46666
- const strokeGradientId = `uncertain-v-s-${ev.lineNumber}`;
46667
- const defs = svg.select("defs").node() || svg.append("defs").node();
46668
- const defsEl = d3Selection22.select(defs);
46669
- defsEl.append("linearGradient").attr("id", gradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "0%").attr("y2", "100%").selectAll("stop").data([
46670
- { offset: "0%", opacity: 1 },
46671
- { offset: "80%", opacity: 1 },
46672
- { offset: "100%", opacity: 0 }
46673
- ]).enter().append("stop").attr("offset", (d) => d.offset).attr("stop-color", mix(color, bg, 30)).attr("stop-opacity", (d) => d.opacity);
46674
- defsEl.append("linearGradient").attr("id", strokeGradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "0%").attr("y2", "100%").selectAll("stop").data([
46675
- { offset: "0%", opacity: 1 },
46676
- { offset: "80%", opacity: 1 },
46677
- { offset: "100%", opacity: 0 }
46678
- ]).enter().append("stop").attr("offset", (d) => d.offset).attr("stop-color", color).attr("stop-opacity", (d) => d.opacity);
46679
- fill2 = `url(#${gradientId})`;
46680
- stroke2 = `url(#${strokeGradientId})`;
46681
- }
46682
- evG.append("rect").attr("x", axisX - 6).attr("y", y).attr("width", 12).attr("height", rectH).attr("rx", 4).attr("fill", fill2).attr("stroke", stroke2).attr("stroke-width", 2);
46683
- evG.append("text").attr("x", axisX + 16).attr("y", y + rectH / 2).attr("dy", "0.35em").attr("fill", textColor).attr("font-size", "11px").text(ev.label);
47047
+ }
47048
+ }).on("click", () => {
47049
+ if (onClickItem && ev.lineNumber) onClickItem(ev.lineNumber);
47050
+ });
47051
+ setTagAttrs(evG, ev);
47052
+ const evColor = eventColor(ev);
47053
+ if (ev.endDate) {
47054
+ const x2 = xScale(parseTimelineDate(ev.endDate));
47055
+ const rectW = Math.max(x2 - x, 4);
47056
+ const estLabelWidth = ev.label.length * 7 + 16;
47057
+ const labelFitsInside = rectW >= estLabelWidth;
47058
+ let fill2 = shapeFill(palette, evColor, isDark, { solid });
47059
+ let stroke2 = evColor;
47060
+ if (ev.uncertain) {
47061
+ const gradientId = `uncertain-${ev.lineNumber}`;
47062
+ const strokeGradientId = `uncertain-s-${ev.lineNumber}`;
47063
+ const defs = svg.select("defs").node() || svg.append("defs").node();
47064
+ const defsEl = d3Selection22.select(defs);
47065
+ defsEl.append("linearGradient").attr("id", gradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "100%").attr("y2", "0%").selectAll("stop").data([
47066
+ { offset: "0%", opacity: 1 },
47067
+ { offset: "80%", opacity: 1 },
47068
+ { offset: "100%", opacity: 0 }
47069
+ ]).enter().append("stop").attr("offset", (d) => d.offset).attr("stop-color", mix(evColor, bg, 30)).attr("stop-opacity", (d) => d.opacity);
47070
+ defsEl.append("linearGradient").attr("id", strokeGradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "100%").attr("y2", "0%").selectAll("stop").data([
47071
+ { offset: "0%", opacity: 1 },
47072
+ { offset: "80%", opacity: 1 },
47073
+ { offset: "100%", opacity: 0 }
47074
+ ]).enter().append("stop").attr("offset", (d) => d.offset).attr("stop-color", evColor).attr("stop-opacity", (d) => d.opacity);
47075
+ fill2 = `url(#${gradientId})`;
47076
+ stroke2 = `url(#${strokeGradientId})`;
47077
+ }
47078
+ evG.append("rect").attr("x", x).attr("y", y - BAR_H2 / 2).attr("width", rectW).attr("height", BAR_H2).attr("rx", 4).attr("fill", fill2).attr("stroke", stroke2).attr("stroke-width", 2);
47079
+ if (labelFitsInside) {
47080
+ evG.append("text").attr("x", x + 8).attr("y", y).attr("dy", "0.35em").attr("text-anchor", "start").attr("fill", textColor).attr("font-size", "13px").text(ev.label);
46684
47081
  } else {
46685
- evG.append("circle").attr("cx", axisX).attr("cy", y).attr("r", 4).attr("fill", shapeFill(palette, color, isDark, { solid })).attr("stroke", color).attr("stroke-width", 2);
46686
- evG.append("text").attr("x", axisX + 16).attr("y", y).attr("dy", "0.35em").attr("fill", textColor).attr("font-size", "11px").text(ev.label);
47082
+ const wouldFlipLeft = x + rectW > innerWidth * 0.6;
47083
+ const labelFitsLeft = x - 6 - estLabelWidth > 0;
47084
+ const flipLeft = wouldFlipLeft && labelFitsLeft;
47085
+ evG.append("text").attr("x", flipLeft ? x - 6 : x + rectW + 6).attr("y", y).attr("dy", "0.35em").attr("text-anchor", flipLeft ? "end" : "start").attr("fill", textColor).attr("font-size", "13px").text(ev.label);
46687
47086
  }
46688
- evG.append("text").attr("x", axisX - 14).attr(
46689
- "y",
46690
- ev.endDate ? yScale(parseTimelineDate(ev.date)) + Math.max(
46691
- yScale(parseTimelineDate(ev.endDate)) - yScale(parseTimelineDate(ev.date)),
46692
- 4
46693
- ) / 2 : y
46694
- ).attr("dy", "0.35em").attr("text-anchor", "end").attr("fill", mutedColor).attr("font-size", "10px").text(ev.date + (ev.endDate ? `\u2192${ev.endDate}` : ""));
47087
+ } else {
47088
+ const estLabelWidth = ev.label.length * 7;
47089
+ const wouldFlipLeft = x > innerWidth * 0.6;
47090
+ const labelFitsLeft = x - 10 - estLabelWidth > 0;
47091
+ const flipLeft = wouldFlipLeft && labelFitsLeft;
47092
+ evG.append("circle").attr("cx", x).attr("cy", y).attr("r", 5).attr("fill", shapeFill(palette, evColor, isDark, { solid })).attr("stroke", evColor).attr("stroke-width", 2);
47093
+ evG.append("text").attr("x", flipLeft ? x - 10 : x + 10).attr("y", y).attr("dy", "0.35em").attr("text-anchor", flipLeft ? "end" : "start").attr("fill", textColor).attr("font-size", "12px").text(ev.label);
46695
47094
  }
46696
- }
46697
- return;
47095
+ });
47096
+ curY += laneSpan + GROUP_GAP3;
46698
47097
  }
46699
- const BAR_H2 = 22;
46700
- const GROUP_GAP3 = 12;
46701
- const useGroupedHorizontal = tagLanes != null || timelineSort === "group" && timelineGroups.length > 0;
46702
- if (useGroupedHorizontal) {
46703
- let lanes;
47098
+ }
47099
+ function renderTimelineVertical(container, parsed, palette, isDark, setup, hovers, onClickItem, exportDims, _swimlaneTagGroup, _activeTagGroup, _onTagStateChange, _viewMode) {
47100
+ const {
47101
+ width,
47102
+ height,
47103
+ tooltip,
47104
+ solid,
47105
+ textColor,
47106
+ mutedColor,
47107
+ bgColor,
47108
+ bg,
47109
+ groupColorMap,
47110
+ tagLanes,
47111
+ eventColor,
47112
+ minDate,
47113
+ maxDate,
47114
+ datePadding,
47115
+ earliestStartDateStr,
47116
+ latestEndDateStr,
47117
+ tagLegendReserve
47118
+ } = setup;
47119
+ const { fadeToGroup, fadeToEra, fadeToMarker, fadeReset, setTagAttrs } = hovers;
47120
+ const {
47121
+ timelineEvents,
47122
+ timelineGroups,
47123
+ timelineEras,
47124
+ timelineMarkers,
47125
+ timelineSort,
47126
+ timelineScale,
47127
+ timelineSwimlanes
47128
+ } = parsed;
47129
+ const title = parsed.noTitle ? null : parsed.title;
47130
+ const useGroupedVertical = tagLanes != null || timelineSort === "group" && timelineGroups.length > 0;
47131
+ if (useGroupedVertical) {
47132
+ let laneNames;
47133
+ let laneEventsByName;
46704
47134
  if (tagLanes) {
46705
- lanes = tagLanes;
47135
+ laneNames = tagLanes.map((l) => l.name);
47136
+ laneEventsByName = new Map(tagLanes.map((l) => [l.name, l.events]));
46706
47137
  } else {
46707
47138
  const groupNames = timelineGroups.map((gr) => gr.name);
46708
47139
  const ungroupedEvents = timelineEvents.filter(
46709
47140
  (ev) => ev.group === null || !groupNames.includes(ev.group)
46710
47141
  );
46711
- const laneNames = ungroupedEvents.length > 0 ? [...groupNames, "(Other)"] : groupNames;
46712
- lanes = laneNames.map((name) => ({
46713
- name,
46714
- events: timelineEvents.filter(
46715
- (ev) => name === "(Other)" ? ev.group === null || !groupNames.includes(ev.group) : ev.group === name
46716
- )
46717
- }));
47142
+ laneNames = ungroupedEvents.length > 0 ? [...groupNames, "(Other)"] : groupNames;
47143
+ laneEventsByName = new Map(
47144
+ laneNames.map((name) => [
47145
+ name,
47146
+ timelineEvents.filter(
47147
+ (ev) => name === "(Other)" ? ev.group === null || !groupNames.includes(ev.group) : ev.group === name
47148
+ )
47149
+ ])
47150
+ );
46718
47151
  }
46719
- const totalEventRows = lanes.reduce((s, l) => s + l.events.length, 0);
46720
- const scaleMargin = timelineScale ? 24 : 0;
46721
- const ERA_ROW_H = 22;
46722
- const MARKER_ROW_H = 22;
46723
- const eraReserve = timelineEras.length > 0 ? ERA_ROW_H : 0;
46724
- const markerReserve = timelineMarkers.length > 0 ? MARKER_ROW_H : 0;
46725
- const topScaleH = timelineScale ? 40 : 0;
46726
- const maxGroupNameLen = Math.max(...lanes.map((l) => l.name.length));
46727
- const dynamicLeftMargin = Math.max(120, maxGroupNameLen * 7 + 30);
46728
- const baseTopMargin = title ? 50 : 20;
47152
+ const laneCount = laneNames.length;
47153
+ const scaleMargin = timelineScale ? 40 : 0;
47154
+ const markerMargin = timelineMarkers.length > 0 ? 30 : 0;
46729
47155
  const margin = {
46730
- top: baseTopMargin + topScaleH + eraReserve + markerReserve + tagLegendReserve,
46731
- right: 40,
46732
- bottom: 40 + scaleMargin,
46733
- left: dynamicLeftMargin
47156
+ top: 104 + markerMargin + tagLegendReserve,
47157
+ right: 40 + scaleMargin,
47158
+ bottom: 40,
47159
+ left: 60 + scaleMargin
46734
47160
  };
46735
- const markerLabelY = markerReserve ? -(topScaleH + MARKER_ROW_H / 2) : 0;
46736
- const eraLabelY = eraReserve ? -(topScaleH + markerReserve + ERA_ROW_H / 2) : 0;
46737
47161
  const innerWidth = width - margin.left - margin.right;
46738
47162
  const innerHeight = height - margin.top - margin.bottom;
46739
- const totalGaps = (lanes.length - 1) * GROUP_GAP3;
46740
- const rowH = Math.min(28, (innerHeight - totalGaps) / totalEventRows);
46741
- const xScale = d3Scale2.scaleLinear().domain([minDate - datePadding, maxDate + datePadding]).range([0, innerWidth]);
46742
- const svg = d3Selection22.select(container).append("svg").attr("width", width).attr("height", height).style("background", bgColor);
47163
+ const laneWidth = innerWidth / laneCount;
47164
+ const yScale = d3Scale2.scaleLinear().domain([minDate - datePadding, maxDate + datePadding]).range([0, innerHeight]);
47165
+ const svg = d3Selection22.select(container).append("svg").attr("viewBox", `0 0 ${width} ${height}`).attr("width", exportDims ? width : "100%").attr("preserveAspectRatio", "xMidYMin meet").style("background", bgColor);
46743
47166
  const g = svg.append("g").attr("transform", `translate(${margin.left},${margin.top})`);
46744
47167
  renderChartTitle(
46745
47168
  svg,
@@ -46752,36 +47175,34 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
46752
47175
  renderEras(
46753
47176
  g,
46754
47177
  timelineEras,
46755
- xScale,
46756
- false,
47178
+ yScale,
47179
+ true,
46757
47180
  innerWidth,
46758
47181
  innerHeight,
46759
47182
  (s, e) => fadeToEra(g, s, e),
46760
47183
  () => fadeReset(g),
46761
47184
  timelineScale,
46762
47185
  tooltip,
46763
- palette,
46764
- eraReserve ? eraLabelY : void 0
47186
+ palette
46765
47187
  );
46766
47188
  renderMarkers(
46767
47189
  g,
46768
47190
  timelineMarkers,
46769
- xScale,
46770
- false,
47191
+ yScale,
47192
+ true,
46771
47193
  innerWidth,
46772
47194
  innerHeight,
46773
47195
  (d) => fadeToMarker(g, d),
46774
47196
  () => fadeReset(g),
46775
47197
  timelineScale,
46776
47198
  tooltip,
46777
- palette,
46778
- markerReserve ? markerLabelY : void 0
47199
+ palette
46779
47200
  );
46780
47201
  if (timelineScale) {
46781
47202
  renderTimeScale(
46782
47203
  g,
46783
- xScale,
46784
- false,
47204
+ yScale,
47205
+ true,
46785
47206
  innerWidth,
46786
47207
  innerHeight,
46787
47208
  textColor,
@@ -46791,78 +47212,55 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
46791
47212
  formatBoundaryLabel(latestEndDateStr, earliestStartDateStr)
46792
47213
  );
46793
47214
  }
46794
- let curY = 0;
46795
47215
  if (timelineSwimlanes || tagLanes) {
46796
- let swimY = 0;
46797
- lanes.forEach((lane, idx) => {
46798
- const laneSpan = lane.events.length * rowH;
46799
- const fillColor = idx % 2 === 0 ? textColor : "transparent";
46800
- g.append("rect").attr("class", "tl-swimlane").attr("data-group", lane.name).attr("x", -margin.left).attr("y", swimY).attr("width", innerWidth + margin.left).attr("height", laneSpan + (idx < lanes.length - 1 ? GROUP_GAP3 : 0)).attr("fill", fillColor).attr("opacity", 0.06);
46801
- swimY += laneSpan + GROUP_GAP3;
47216
+ laneNames.forEach((laneName, laneIdx) => {
47217
+ const laneX = laneIdx * laneWidth;
47218
+ const fillColor = laneIdx % 2 === 0 ? textColor : "transparent";
47219
+ g.append("rect").attr("class", "tl-swimlane").attr("data-group", laneName).attr("x", laneX).attr("y", 0).attr("width", laneWidth).attr("height", innerHeight).attr("fill", fillColor).attr("opacity", 0.06);
46802
47220
  });
46803
47221
  }
46804
- for (const lane of lanes) {
46805
- const laneColor = groupColorMap.get(lane.name) ?? textColor;
46806
- const laneSpan = lane.events.length * rowH;
46807
- const group = timelineGroups.find((grp) => grp.name === lane.name);
46808
- const headerG = g.append("g").attr("class", "tl-lane-header").attr("data-group", lane.name).style("cursor", "pointer").on("mouseenter", () => fadeToGroup(g, lane.name)).on("mouseleave", () => fadeReset(g)).on("click", () => {
46809
- if (onClickItem && group?.lineNumber) onClickItem(group.lineNumber);
46810
- });
46811
- headerG.append("text").attr("x", -margin.left + 10).attr("y", curY + laneSpan / 2).attr("dy", "0.35em").attr("text-anchor", "start").attr("fill", laneColor).attr("font-size", "12px").attr("font-weight", "600").text(lane.name);
46812
- lane.events.forEach((ev, i) => {
46813
- const y = curY + i * rowH + rowH / 2;
46814
- const x = xScale(parseTimelineDate(ev.date));
46815
- const evG = g.append("g").attr("class", "tl-event").attr("data-group", lane.name).attr("data-line-number", String(ev.lineNumber)).attr("data-date", String(parseTimelineDate(ev.date))).attr(
47222
+ laneNames.forEach((laneName, laneIdx) => {
47223
+ const laneX = laneIdx * laneWidth;
47224
+ const laneColor = groupColorMap.get(laneName) ?? textColor;
47225
+ const laneCenter = laneX + laneWidth / 2;
47226
+ const headerG = g.append("g").attr("class", "tl-lane-header").attr("data-group", laneName).style("cursor", "pointer").on("mouseenter", () => fadeToGroup(g, laneName)).on("mouseleave", () => fadeReset(g));
47227
+ headerG.append("text").attr("x", laneCenter).attr("y", -15).attr("text-anchor", "middle").attr("fill", laneColor).attr("font-size", "12px").attr("font-weight", "600").text(laneName);
47228
+ g.append("line").attr("x1", laneCenter).attr("y1", 0).attr("x2", laneCenter).attr("y2", innerHeight).attr("stroke", mutedColor).attr("stroke-width", 1).attr("stroke-dasharray", "4,4");
47229
+ const laneEvents = laneEventsByName.get(laneName) ?? [];
47230
+ for (const ev of laneEvents) {
47231
+ const y = yScale(parseTimelineDate(ev.date));
47232
+ const evG = g.append("g").attr("class", "tl-event").attr("data-group", laneName).attr("data-line-number", String(ev.lineNumber)).attr("data-date", String(parseTimelineDate(ev.date))).attr(
46816
47233
  "data-end-date",
46817
47234
  ev.endDate ? String(parseTimelineDate(ev.endDate)) : null
46818
47235
  ).style("cursor", "pointer").on("mouseenter", function(event) {
46819
- fadeToGroup(g, lane.name);
46820
- if (timelineScale) {
46821
- showEventDatesOnScale(
46822
- g,
46823
- xScale,
46824
- ev.date,
46825
- ev.endDate,
46826
- innerHeight,
46827
- laneColor
46828
- );
46829
- } else {
46830
- showTooltip(tooltip, buildEventTooltipHtml(ev), event);
46831
- }
47236
+ fadeToGroup(g, laneName);
47237
+ showTooltip(tooltip, buildEventTooltipHtml(ev), event);
46832
47238
  }).on("mouseleave", function() {
46833
47239
  fadeReset(g);
46834
- if (timelineScale) {
46835
- hideEventDatesOnScale(g);
46836
- } else {
46837
- hideTooltip(tooltip);
46838
- }
47240
+ hideTooltip(tooltip);
46839
47241
  }).on("mousemove", function(event) {
46840
- if (!timelineScale) {
46841
- showTooltip(tooltip, buildEventTooltipHtml(ev), event);
46842
- }
47242
+ showTooltip(tooltip, buildEventTooltipHtml(ev), event);
46843
47243
  }).on("click", () => {
46844
47244
  if (onClickItem && ev.lineNumber) onClickItem(ev.lineNumber);
46845
47245
  });
46846
47246
  setTagAttrs(evG, ev);
46847
47247
  const evColor = eventColor(ev);
46848
47248
  if (ev.endDate) {
46849
- const x2 = xScale(parseTimelineDate(ev.endDate));
46850
- const rectW = Math.max(x2 - x, 4);
46851
- const estLabelWidth = ev.label.length * 7 + 16;
46852
- const labelFitsInside = rectW >= estLabelWidth;
47249
+ const y2 = yScale(parseTimelineDate(ev.endDate));
47250
+ const rectH = Math.max(y2 - y, 4);
46853
47251
  let fill2 = shapeFill(palette, evColor, isDark, { solid });
46854
47252
  let stroke2 = evColor;
46855
47253
  if (ev.uncertain) {
46856
- const gradientId = `uncertain-${ev.lineNumber}`;
46857
- const strokeGradientId = `uncertain-s-${ev.lineNumber}`;
47254
+ const gradientId = `uncertain-vg-${ev.lineNumber}`;
47255
+ const strokeGradientId = `uncertain-vg-s-${ev.lineNumber}`;
46858
47256
  const defs = svg.select("defs").node() || svg.append("defs").node();
46859
47257
  const defsEl = d3Selection22.select(defs);
46860
- defsEl.append("linearGradient").attr("id", gradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "100%").attr("y2", "0%").selectAll("stop").data([
47258
+ defsEl.append("linearGradient").attr("id", gradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "0%").attr("y2", "100%").selectAll("stop").data([
46861
47259
  { offset: "0%", opacity: 1 },
46862
47260
  { offset: "80%", opacity: 1 },
46863
47261
  { offset: "100%", opacity: 0 }
46864
- ]).enter().append("stop").attr("offset", (d) => d.offset).attr("stop-color", mix(evColor, bg, 30)).attr("stop-opacity", (d) => d.opacity);
46865
- defsEl.append("linearGradient").attr("id", strokeGradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "100%").attr("y2", "0%").selectAll("stop").data([
47262
+ ]).enter().append("stop").attr("offset", (d) => d.offset).attr("stop-color", mix(laneColor, bg, 30)).attr("stop-opacity", (d) => d.opacity);
47263
+ defsEl.append("linearGradient").attr("id", strokeGradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "0%").attr("y2", "100%").selectAll("stop").data([
46866
47264
  { offset: "0%", opacity: 1 },
46867
47265
  { offset: "80%", opacity: 1 },
46868
47266
  { offset: "100%", opacity: 0 }
@@ -46870,47 +47268,29 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
46870
47268
  fill2 = `url(#${gradientId})`;
46871
47269
  stroke2 = `url(#${strokeGradientId})`;
46872
47270
  }
46873
- evG.append("rect").attr("x", x).attr("y", y - BAR_H2 / 2).attr("width", rectW).attr("height", BAR_H2).attr("rx", 4).attr("fill", fill2).attr("stroke", stroke2).attr("stroke-width", 2);
46874
- if (labelFitsInside) {
46875
- evG.append("text").attr("x", x + 8).attr("y", y).attr("dy", "0.35em").attr("text-anchor", "start").attr("fill", textColor).attr("font-size", "13px").text(ev.label);
46876
- } else {
46877
- const wouldFlipLeft = x + rectW > innerWidth * 0.6;
46878
- const labelFitsLeft = x - 6 - estLabelWidth > 0;
46879
- const flipLeft = wouldFlipLeft && labelFitsLeft;
46880
- evG.append("text").attr("x", flipLeft ? x - 6 : x + rectW + 6).attr("y", y).attr("dy", "0.35em").attr("text-anchor", flipLeft ? "end" : "start").attr("fill", textColor).attr("font-size", "13px").text(ev.label);
46881
- }
47271
+ evG.append("rect").attr("x", laneCenter - 6).attr("y", y).attr("width", 12).attr("height", rectH).attr("rx", 4).attr("fill", fill2).attr("stroke", stroke2).attr("stroke-width", 2);
47272
+ evG.append("text").attr("x", laneCenter + 14).attr("y", y + rectH / 2).attr("dy", "0.35em").attr("fill", textColor).attr("font-size", "10px").text(ev.label);
46882
47273
  } else {
46883
- const estLabelWidth = ev.label.length * 7;
46884
- const wouldFlipLeft = x > innerWidth * 0.6;
46885
- const labelFitsLeft = x - 10 - estLabelWidth > 0;
46886
- const flipLeft = wouldFlipLeft && labelFitsLeft;
46887
- evG.append("circle").attr("cx", x).attr("cy", y).attr("r", 5).attr("fill", shapeFill(palette, evColor, isDark, { solid })).attr("stroke", evColor).attr("stroke-width", 2);
46888
- evG.append("text").attr("x", flipLeft ? x - 10 : x + 10).attr("y", y).attr("dy", "0.35em").attr("text-anchor", flipLeft ? "end" : "start").attr("fill", textColor).attr("font-size", "12px").text(ev.label);
47274
+ evG.append("circle").attr("cx", laneCenter).attr("cy", y).attr("r", 4).attr("fill", shapeFill(palette, evColor, isDark, { solid })).attr("stroke", evColor).attr("stroke-width", 2);
47275
+ evG.append("text").attr("x", laneCenter + 10).attr("y", y).attr("dy", "0.35em").attr("fill", textColor).attr("font-size", "10px").text(ev.label);
46889
47276
  }
46890
- });
46891
- curY += laneSpan + GROUP_GAP3;
46892
- }
47277
+ }
47278
+ });
46893
47279
  } else {
46894
- const sorted = timelineEvents.slice().sort((a, b) => parseTimelineDate(a.date) - parseTimelineDate(b.date));
46895
- const scaleMargin = timelineScale ? 24 : 0;
46896
- const ERA_ROW_H = 22;
46897
- const MARKER_ROW_H = 22;
46898
- const eraReserve = timelineEras.length > 0 ? ERA_ROW_H : 0;
46899
- const markerReserve = timelineMarkers.length > 0 ? MARKER_ROW_H : 0;
46900
- const topScaleH = timelineScale ? 40 : 0;
47280
+ const scaleMargin = timelineScale ? 40 : 0;
47281
+ const markerMargin = timelineMarkers.length > 0 ? 30 : 0;
46901
47282
  const margin = {
46902
- top: 104 + topScaleH + eraReserve + markerReserve + tagLegendReserve,
46903
- right: 40,
46904
- bottom: 40 + scaleMargin,
46905
- left: 60
47283
+ top: 104 + markerMargin + tagLegendReserve,
47284
+ right: 200,
47285
+ bottom: 40,
47286
+ left: 60 + scaleMargin
46906
47287
  };
46907
- const markerLabelY = markerReserve ? -(topScaleH + MARKER_ROW_H / 2) : 0;
46908
- const eraLabelY = eraReserve ? -(topScaleH + markerReserve + ERA_ROW_H / 2) : 0;
46909
47288
  const innerWidth = width - margin.left - margin.right;
46910
47289
  const innerHeight = height - margin.top - margin.bottom;
46911
- const rowH = Math.min(28, innerHeight / sorted.length);
46912
- const xScale = d3Scale2.scaleLinear().domain([minDate - datePadding, maxDate + datePadding]).range([0, innerWidth]);
46913
- const svg = d3Selection22.select(container).append("svg").attr("width", width).attr("height", height).style("background", bgColor);
47290
+ const axisX = 20;
47291
+ const yScale = d3Scale2.scaleLinear().domain([minDate - datePadding, maxDate + datePadding]).range([0, innerHeight]);
47292
+ const sorted = timelineEvents.slice().sort((a, b) => parseTimelineDate(a.date) - parseTimelineDate(b.date));
47293
+ const svg = d3Selection22.select(container).append("svg").attr("viewBox", `0 0 ${width} ${height}`).attr("width", exportDims ? width : "100%").attr("preserveAspectRatio", "xMidYMin meet").style("background", bgColor);
46914
47294
  const g = svg.append("g").attr("transform", `translate(${margin.left},${margin.top})`);
46915
47295
  renderChartTitle(
46916
47296
  svg,
@@ -46923,36 +47303,34 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
46923
47303
  renderEras(
46924
47304
  g,
46925
47305
  timelineEras,
46926
- xScale,
46927
- false,
47306
+ yScale,
47307
+ true,
46928
47308
  innerWidth,
46929
47309
  innerHeight,
46930
47310
  (s, e) => fadeToEra(g, s, e),
46931
47311
  () => fadeReset(g),
46932
47312
  timelineScale,
46933
47313
  tooltip,
46934
- palette,
46935
- eraReserve ? eraLabelY : void 0
47314
+ palette
46936
47315
  );
46937
47316
  renderMarkers(
46938
47317
  g,
46939
47318
  timelineMarkers,
46940
- xScale,
46941
- false,
47319
+ yScale,
47320
+ true,
46942
47321
  innerWidth,
46943
47322
  innerHeight,
46944
47323
  (d) => fadeToMarker(g, d),
46945
47324
  () => fadeReset(g),
46946
47325
  timelineScale,
46947
47326
  tooltip,
46948
- palette,
46949
- markerReserve ? markerLabelY : void 0
47327
+ palette
46950
47328
  );
46951
47329
  if (timelineScale) {
46952
47330
  renderTimeScale(
46953
47331
  g,
46954
- xScale,
46955
- false,
47332
+ yScale,
47333
+ true,
46956
47334
  innerWidth,
46957
47335
  innerHeight,
46958
47336
  textColor,
@@ -46963,7 +47341,6 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
46963
47341
  );
46964
47342
  }
46965
47343
  if (timelineGroups.length > 0) {
46966
- const legendY = timelineScale ? -75 : -55;
46967
47344
  renderTimelineGroupLegend(
46968
47345
  g,
46969
47346
  timelineGroups,
@@ -46971,65 +47348,46 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
46971
47348
  textColor,
46972
47349
  palette,
46973
47350
  isDark,
46974
- legendY,
47351
+ -55,
46975
47352
  (name) => fadeToGroup(g, name),
46976
47353
  () => fadeReset(g)
46977
47354
  );
46978
47355
  }
46979
- sorted.forEach((ev, i) => {
46980
- const y = i * rowH + rowH / 2;
46981
- const x = xScale(parseTimelineDate(ev.date));
47356
+ g.append("line").attr("x1", axisX).attr("y1", 0).attr("x2", axisX).attr("y2", innerHeight).attr("stroke", mutedColor).attr("stroke-width", 1).attr("stroke-dasharray", "4,4");
47357
+ for (const ev of sorted) {
47358
+ const y = yScale(parseTimelineDate(ev.date));
46982
47359
  const color = eventColor(ev);
46983
47360
  const evG = g.append("g").attr("class", "tl-event").attr("data-group", ev.group || "").attr("data-line-number", String(ev.lineNumber)).attr("data-date", String(parseTimelineDate(ev.date))).attr(
46984
47361
  "data-end-date",
46985
47362
  ev.endDate ? String(parseTimelineDate(ev.endDate)) : null
46986
47363
  ).style("cursor", "pointer").on("mouseenter", function(event) {
46987
47364
  if (ev.group && timelineGroups.length > 0) fadeToGroup(g, ev.group);
46988
- if (timelineScale) {
46989
- showEventDatesOnScale(
46990
- g,
46991
- xScale,
46992
- ev.date,
46993
- ev.endDate,
46994
- innerHeight,
46995
- color
46996
- );
46997
- } else {
46998
- showTooltip(tooltip, buildEventTooltipHtml(ev), event);
46999
- }
47365
+ showTooltip(tooltip, buildEventTooltipHtml(ev), event);
47000
47366
  }).on("mouseleave", function() {
47001
47367
  fadeReset(g);
47002
- if (timelineScale) {
47003
- hideEventDatesOnScale(g);
47004
- } else {
47005
- hideTooltip(tooltip);
47006
- }
47368
+ hideTooltip(tooltip);
47007
47369
  }).on("mousemove", function(event) {
47008
- if (!timelineScale) {
47009
- showTooltip(tooltip, buildEventTooltipHtml(ev), event);
47010
- }
47370
+ showTooltip(tooltip, buildEventTooltipHtml(ev), event);
47011
47371
  }).on("click", () => {
47012
47372
  if (onClickItem && ev.lineNumber) onClickItem(ev.lineNumber);
47013
47373
  });
47014
47374
  setTagAttrs(evG, ev);
47015
47375
  if (ev.endDate) {
47016
- const x2 = xScale(parseTimelineDate(ev.endDate));
47017
- const rectW = Math.max(x2 - x, 4);
47018
- const estLabelWidth = ev.label.length * 7 + 16;
47019
- const labelFitsInside = rectW >= estLabelWidth;
47376
+ const y2 = yScale(parseTimelineDate(ev.endDate));
47377
+ const rectH = Math.max(y2 - y, 4);
47020
47378
  let fill2 = shapeFill(palette, color, isDark, { solid });
47021
47379
  let stroke2 = color;
47022
47380
  if (ev.uncertain) {
47023
- const gradientId = `uncertain-ts-${ev.lineNumber}`;
47024
- const strokeGradientId = `uncertain-ts-s-${ev.lineNumber}`;
47381
+ const gradientId = `uncertain-v-${ev.lineNumber}`;
47382
+ const strokeGradientId = `uncertain-v-s-${ev.lineNumber}`;
47025
47383
  const defs = svg.select("defs").node() || svg.append("defs").node();
47026
47384
  const defsEl = d3Selection22.select(defs);
47027
- defsEl.append("linearGradient").attr("id", gradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "100%").attr("y2", "0%").selectAll("stop").data([
47385
+ defsEl.append("linearGradient").attr("id", gradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "0%").attr("y2", "100%").selectAll("stop").data([
47028
47386
  { offset: "0%", opacity: 1 },
47029
47387
  { offset: "80%", opacity: 1 },
47030
47388
  { offset: "100%", opacity: 0 }
47031
47389
  ]).enter().append("stop").attr("offset", (d) => d.offset).attr("stop-color", mix(color, bg, 30)).attr("stop-opacity", (d) => d.opacity);
47032
- defsEl.append("linearGradient").attr("id", strokeGradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "100%").attr("y2", "0%").selectAll("stop").data([
47390
+ defsEl.append("linearGradient").attr("id", strokeGradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "0%").attr("y2", "100%").selectAll("stop").data([
47033
47391
  { offset: "0%", opacity: 1 },
47034
47392
  { offset: "80%", opacity: 1 },
47035
47393
  { offset: "100%", opacity: 0 }
@@ -47037,206 +47395,100 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
47037
47395
  fill2 = `url(#${gradientId})`;
47038
47396
  stroke2 = `url(#${strokeGradientId})`;
47039
47397
  }
47040
- evG.append("rect").attr("x", x).attr("y", y - BAR_H2 / 2).attr("width", rectW).attr("height", BAR_H2).attr("rx", 4).attr("fill", fill2).attr("stroke", stroke2).attr("stroke-width", 2);
47041
- if (labelFitsInside) {
47042
- evG.append("text").attr("x", x + 8).attr("y", y).attr("dy", "0.35em").attr("text-anchor", "start").attr("fill", textColor).attr("font-size", "13px").text(ev.label);
47043
- } else {
47044
- const wouldFlipLeft = x + rectW > innerWidth * 0.6;
47045
- const labelFitsLeft = x - 6 - estLabelWidth > 0;
47046
- const flipLeft = wouldFlipLeft && labelFitsLeft;
47047
- evG.append("text").attr("x", flipLeft ? x - 6 : x + rectW + 6).attr("y", y).attr("dy", "0.35em").attr("text-anchor", flipLeft ? "end" : "start").attr("fill", textColor).attr("font-size", "13px").text(ev.label);
47048
- }
47398
+ evG.append("rect").attr("x", axisX - 6).attr("y", y).attr("width", 12).attr("height", rectH).attr("rx", 4).attr("fill", fill2).attr("stroke", stroke2).attr("stroke-width", 2);
47399
+ evG.append("text").attr("x", axisX + 16).attr("y", y + rectH / 2).attr("dy", "0.35em").attr("fill", textColor).attr("font-size", "11px").text(ev.label);
47049
47400
  } else {
47050
- const estLabelWidth = ev.label.length * 7;
47051
- const wouldFlipLeft = x > innerWidth * 0.6;
47052
- const labelFitsLeft = x - 10 - estLabelWidth > 0;
47053
- const flipLeft = wouldFlipLeft && labelFitsLeft;
47054
- evG.append("circle").attr("cx", x).attr("cy", y).attr("r", 5).attr("fill", shapeFill(palette, color, isDark, { solid })).attr("stroke", color).attr("stroke-width", 2);
47055
- evG.append("text").attr("x", flipLeft ? x - 10 : x + 10).attr("y", y).attr("dy", "0.35em").attr("text-anchor", flipLeft ? "end" : "start").attr("fill", textColor).attr("font-size", "12px").text(ev.label);
47056
- }
47057
- });
47058
- }
47059
- if (parsed.timelineTagGroups.length > 0) {
47060
- const LG_HEIGHT = LEGEND_HEIGHT;
47061
- const LG_PILL_PAD = LEGEND_PILL_PAD;
47062
- const LG_PILL_FONT_SIZE = LEGEND_PILL_FONT_SIZE;
47063
- const LG_CAPSULE_PAD = LEGEND_CAPSULE_PAD;
47064
- const LG_DOT_R = LEGEND_DOT_R;
47065
- const LG_ENTRY_FONT_SIZE = LEGEND_ENTRY_FONT_SIZE;
47066
- const LG_ENTRY_DOT_GAP = LEGEND_ENTRY_DOT_GAP;
47067
- const LG_ENTRY_TRAIL = LEGEND_ENTRY_TRAIL;
47068
- const LG_ICON_W = 20;
47069
- const mainSvg = d3Selection22.select(container).select("svg");
47070
- const mainG = mainSvg.select("g");
47071
- if (!mainSvg.empty() && !mainG.empty()) {
47072
- let drawSwimlaneIcon4 = function(parent, x, y, isSwimActive) {
47073
- const iconG = parent.append("g").attr("class", "tl-swimlane-icon").attr("transform", `translate(${x}, ${y})`).style("cursor", "pointer");
47074
- const barColor = isSwimActive ? palette.primary : palette.textMuted;
47075
- const barOpacity = isSwimActive ? 1 : 0.35;
47076
- const bars = [
47077
- { y: 0, w: 8 },
47078
- { y: 4, w: 12 },
47079
- { y: 8, w: 6 }
47080
- ];
47081
- for (const bar of bars) {
47082
- iconG.append("rect").attr("x", 0).attr("y", bar.y).attr("width", bar.w).attr("height", 2).attr("rx", 1).attr("fill", barColor).attr("opacity", barOpacity);
47083
- }
47084
- return iconG;
47085
- }, relayout2 = function() {
47086
- renderTimeline(
47087
- container,
47088
- parsed,
47089
- palette,
47090
- isDark,
47091
- onClickItem,
47092
- exportDims,
47093
- currentActiveGroup,
47094
- currentSwimlaneGroup,
47095
- onTagStateChange,
47096
- viewMode
47097
- );
47098
- }, drawLegend2 = function() {
47099
- mainSvg.selectAll(".tl-tag-legend-group").remove();
47100
- mainSvg.selectAll(".tl-tag-legend-container").remove();
47101
- const effectiveColorKey = (currentActiveGroup ?? currentSwimlaneGroup)?.toLowerCase() ?? null;
47102
- const visibleGroups = viewMode ? legendGroups.filter(
47103
- (lg) => effectiveColorKey != null && lg.group.name.toLowerCase() === effectiveColorKey
47104
- ) : legendGroups;
47105
- if (visibleGroups.length === 0) return;
47106
- const legendContainer = mainSvg.append("g").attr("class", "tl-tag-legend-container");
47107
- if (currentActiveGroup) {
47108
- legendContainer.attr(
47109
- "data-legend-active",
47110
- currentActiveGroup.toLowerCase()
47111
- );
47112
- }
47113
- const iconAddon = viewMode ? 0 : LG_ICON_W;
47114
- const centralGroups = visibleGroups.map((lg) => ({
47115
- name: lg.group.name,
47116
- entries: lg.group.entries.map((e) => ({
47117
- value: e.value,
47118
- color: e.color
47119
- }))
47120
- }));
47121
- const centralActive = viewMode ? effectiveColorKey : currentActiveGroup;
47122
- const centralConfig = {
47123
- groups: centralGroups,
47124
- position: { placement: "top-center", titleRelation: "below-title" },
47125
- mode: "fixed",
47126
- capsulePillAddonWidth: iconAddon
47127
- };
47128
- const centralState = { activeGroup: centralActive };
47129
- const centralCallbacks = viewMode ? {} : {
47130
- onGroupToggle: (groupName) => {
47131
- currentActiveGroup = currentActiveGroup === groupName.toLowerCase() ? null : groupName.toLowerCase();
47132
- drawLegend2();
47133
- recolorEvents2();
47134
- onTagStateChange?.(currentActiveGroup, currentSwimlaneGroup);
47135
- },
47136
- onEntryHover: (groupName, entryValue) => {
47137
- const tagKey = groupName.toLowerCase();
47138
- if (entryValue) {
47139
- const tagVal = entryValue.toLowerCase();
47140
- fadeToTagValue(mainG, tagKey, tagVal);
47141
- mainSvg.selectAll("[data-legend-entry]").each(function() {
47142
- const el = d3Selection22.select(this);
47143
- const ev = el.attr("data-legend-entry");
47144
- const eg = el.attr("data-tag-group") ?? el.node()?.closest?.("[data-tag-group]")?.getAttribute("data-tag-group");
47145
- el.attr(
47146
- "opacity",
47147
- eg === tagKey && ev === tagVal ? 1 : FADE_OPACITY3
47148
- );
47149
- });
47150
- } else {
47151
- fadeReset(mainG);
47152
- mainSvg.selectAll("[data-legend-entry]").attr("opacity", 1);
47153
- }
47154
- },
47155
- onGroupRendered: (groupName, groupEl, isActive) => {
47156
- const groupKey = groupName.toLowerCase();
47157
- groupEl.attr("data-tag-group", groupKey);
47158
- if (isActive && !viewMode) {
47159
- const isSwimActive = currentSwimlaneGroup != null && currentSwimlaneGroup.toLowerCase() === groupKey;
47160
- const pillWidth3 = measureLegendText(groupName, LG_PILL_FONT_SIZE) + LG_PILL_PAD;
47161
- const pillXOff = LG_CAPSULE_PAD;
47162
- const iconX = pillXOff + pillWidth3 + 5;
47163
- const iconY = (LG_HEIGHT - 10) / 2;
47164
- const iconEl = drawSwimlaneIcon4(
47165
- groupEl,
47166
- iconX,
47167
- iconY,
47168
- isSwimActive
47169
- );
47170
- iconEl.attr("data-swimlane-toggle", groupKey).on("click", (event) => {
47171
- event.stopPropagation();
47172
- currentSwimlaneGroup = currentSwimlaneGroup === groupKey ? null : groupKey;
47173
- onTagStateChange?.(
47174
- currentActiveGroup,
47175
- currentSwimlaneGroup
47176
- );
47177
- relayout2();
47178
- });
47179
- }
47180
- }
47181
- };
47182
- const legendInnerG = legendContainer.append("g").attr("transform", `translate(0, ${legendY})`);
47183
- renderLegendD3(
47184
- legendInnerG,
47185
- centralConfig,
47186
- centralState,
47187
- palette,
47188
- isDark,
47189
- centralCallbacks,
47190
- width
47191
- );
47192
- }, recolorEvents2 = function() {
47193
- const colorTG = currentActiveGroup ?? swimlaneTagGroup ?? null;
47194
- mainG.selectAll(".tl-event").each(function() {
47195
- const el = d3Selection22.select(this);
47196
- const lineNum = el.attr("data-line-number");
47197
- const ev = lineNum ? eventByLine.get(lineNum) : void 0;
47198
- if (!ev) return;
47199
- let color;
47200
- if (colorTG) {
47201
- const tagColor = resolveTagColor(
47202
- ev.metadata,
47203
- parsed.timelineTagGroups,
47204
- colorTG
47205
- );
47206
- color = tagColor ?? (ev.group && groupColorMap.has(ev.group) ? groupColorMap.get(ev.group) : textColor);
47207
- } else {
47208
- color = ev.group && groupColorMap.has(ev.group) ? groupColorMap.get(ev.group) : textColor;
47209
- }
47210
- el.selectAll("rect").attr("fill", shapeFill(palette, color, isDark, { solid })).attr("stroke", color);
47211
- el.selectAll("circle:not(.tl-event-point-outline)").attr("fill", shapeFill(palette, color, isDark, { solid })).attr("stroke", color);
47212
- });
47213
- };
47214
- var drawSwimlaneIcon3 = drawSwimlaneIcon4, relayout = relayout2, drawLegend = drawLegend2, recolorEvents = recolorEvents2;
47215
- const legendY = title ? 50 : 10;
47216
- const legendGroups = parsed.timelineTagGroups.map((g) => {
47217
- const pillW = measureLegendText(g.name, LG_PILL_FONT_SIZE) + LG_PILL_PAD;
47218
- const iconSpace = viewMode ? 8 : LG_ICON_W + 4;
47219
- let entryX = LG_CAPSULE_PAD + pillW + iconSpace;
47220
- for (const entry of g.entries) {
47221
- const textX = entryX + LG_DOT_R * 2 + LG_ENTRY_DOT_GAP;
47222
- entryX = textX + measureLegendText(entry.value, LG_ENTRY_FONT_SIZE) + LG_ENTRY_TRAIL;
47223
- }
47224
- return {
47225
- group: g,
47226
- minifiedWidth: pillW,
47227
- expandedWidth: entryX + LG_CAPSULE_PAD
47228
- };
47229
- });
47230
- let currentActiveGroup = activeTagGroup ?? null;
47231
- let currentSwimlaneGroup = swimlaneTagGroup ?? null;
47232
- const eventByLine = /* @__PURE__ */ new Map();
47233
- for (const ev of timelineEvents) {
47234
- eventByLine.set(String(ev.lineNumber), ev);
47401
+ evG.append("circle").attr("cx", axisX).attr("cy", y).attr("r", 4).attr("fill", shapeFill(palette, color, isDark, { solid })).attr("stroke", color).attr("stroke-width", 2);
47402
+ evG.append("text").attr("x", axisX + 16).attr("y", y).attr("dy", "0.35em").attr("fill", textColor).attr("font-size", "11px").text(ev.label);
47235
47403
  }
47236
- drawLegend2();
47404
+ evG.append("text").attr("x", axisX - 14).attr(
47405
+ "y",
47406
+ ev.endDate ? yScale(parseTimelineDate(ev.date)) + Math.max(
47407
+ yScale(parseTimelineDate(ev.endDate)) - yScale(parseTimelineDate(ev.date)),
47408
+ 4
47409
+ ) / 2 : y
47410
+ ).attr("dy", "0.35em").attr("text-anchor", "end").attr("fill", mutedColor).attr("font-size", "10px").text(ev.date + (ev.endDate ? `\u2192${ev.endDate}` : ""));
47237
47411
  }
47238
47412
  }
47239
47413
  }
47414
+ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportDims, activeTagGroup, swimlaneTagGroup, onTagStateChange, viewMode) {
47415
+ const setup = setupTimeline(
47416
+ container,
47417
+ parsed,
47418
+ palette,
47419
+ isDark,
47420
+ exportDims,
47421
+ activeTagGroup,
47422
+ swimlaneTagGroup
47423
+ );
47424
+ if (!setup) return;
47425
+ swimlaneTagGroup = setup.swimlaneTagGroup;
47426
+ const { isVertical, tagLanes } = setup;
47427
+ const hovers = makeTimelineHoverHelpers();
47428
+ if (isVertical) {
47429
+ renderTimelineVertical(
47430
+ container,
47431
+ parsed,
47432
+ palette,
47433
+ isDark,
47434
+ setup,
47435
+ hovers,
47436
+ onClickItem,
47437
+ exportDims,
47438
+ swimlaneTagGroup,
47439
+ activeTagGroup,
47440
+ onTagStateChange,
47441
+ viewMode
47442
+ );
47443
+ return;
47444
+ }
47445
+ const useGroupedHorizontal = tagLanes != null || parsed.timelineSort === "group" && parsed.timelineGroups.length > 0;
47446
+ if (useGroupedHorizontal) {
47447
+ renderTimelineHorizontalGrouped(
47448
+ container,
47449
+ parsed,
47450
+ palette,
47451
+ isDark,
47452
+ setup,
47453
+ hovers,
47454
+ onClickItem,
47455
+ exportDims,
47456
+ swimlaneTagGroup,
47457
+ activeTagGroup,
47458
+ onTagStateChange,
47459
+ viewMode
47460
+ );
47461
+ } else {
47462
+ renderTimelineHorizontalTimeSort(
47463
+ container,
47464
+ parsed,
47465
+ palette,
47466
+ isDark,
47467
+ setup,
47468
+ hovers,
47469
+ onClickItem,
47470
+ exportDims,
47471
+ swimlaneTagGroup,
47472
+ activeTagGroup,
47473
+ onTagStateChange,
47474
+ viewMode
47475
+ );
47476
+ }
47477
+ renderTimelineTagLegendOverlay(
47478
+ container,
47479
+ parsed,
47480
+ palette,
47481
+ isDark,
47482
+ setup,
47483
+ hovers,
47484
+ onClickItem,
47485
+ exportDims,
47486
+ swimlaneTagGroup,
47487
+ activeTagGroup,
47488
+ onTagStateChange,
47489
+ viewMode
47490
+ );
47491
+ }
47240
47492
  function getRotateFn(mode) {
47241
47493
  if (mode === "mixed") return () => Math.random() > 0.5 ? 0 : 90;
47242
47494
  if (mode === "angled") return () => Math.round(Math.random() * 30 - 15);
@@ -47360,7 +47612,7 @@ function regionCentroid(circles, inside) {
47360
47612
  }
47361
47613
  return { x: sx / count, y: sy / count };
47362
47614
  }
47363
- function renderVenn(container, parsed, palette, isDark, onClickItem, exportDims) {
47615
+ function renderVenn(container, parsed, palette, _isDark, onClickItem, exportDims) {
47364
47616
  const { vennSets, vennOverlaps } = parsed;
47365
47617
  const title = parsed.noTitle ? null : parsed.title;
47366
47618
  if (vennSets.length < 2 || vennSets.length > 3) return;
@@ -47594,7 +47846,7 @@ function renderVenn(container, parsed, palette, isDark, onClickItem, exportDims)
47594
47846
  };
47595
47847
  const gcx = circles.reduce((s, c) => s + c.x, 0) / n;
47596
47848
  const gcy = circles.reduce((s, c) => s + c.y, 0) / n;
47597
- function exclusiveHSpan(px, py, ci) {
47849
+ function exclusiveHSpan(_px, py, ci) {
47598
47850
  const dy = py - circles[ci].y;
47599
47851
  const halfChord = Math.sqrt(
47600
47852
  Math.max(0, circles[ci].r * circles[ci].r - dy * dy)
@@ -48507,9 +48759,9 @@ async function renderForExport(content, theme, palette, viewState, options) {
48507
48759
  blHiddenTagValues.set(k, new Set(v));
48508
48760
  }
48509
48761
  }
48510
- const { layoutBoxesAndLines: layoutBoxesAndLines2 } = await Promise.resolve().then(() => (init_layout5(), layout_exports5));
48511
48762
  const { renderBoxesAndLinesForExport: renderBoxesAndLinesForExport2 } = await Promise.resolve().then(() => (init_renderer6(), renderer_exports6));
48512
- const blLayout = layoutBoxesAndLines2(blParsed);
48763
+ const { layoutBoxesAndLines: layoutBoxesAndLines2 } = await Promise.resolve().then(() => (init_layout5(), layout_exports5));
48764
+ const blLayout = await layoutBoxesAndLines2(blParsed);
48513
48765
  const PADDING3 = 20;
48514
48766
  const titleOffset = blParsed.title ? 40 : 0;
48515
48767
  const exportWidth = blLayout.width + PADDING3 * 2;
@@ -49597,7 +49849,7 @@ init_dgmo_router();
49597
49849
  init_registry();
49598
49850
  async function ensureDom() {
49599
49851
  if (typeof document !== "undefined") return;
49600
- const { JSDOM } = await import("jsdom");
49852
+ const { JSDOM } = await loadJsdom();
49601
49853
  const dom = new JSDOM("<!DOCTYPE html><html><body></body></html>");
49602
49854
  const win = dom.window;
49603
49855
  Object.defineProperty(globalThis, "document", {
@@ -49621,6 +49873,14 @@ async function ensureDom() {
49621
49873
  configurable: true
49622
49874
  });
49623
49875
  }
49876
+ async function loadJsdom() {
49877
+ const spec = ["js", "dom"].join("");
49878
+ return import(
49879
+ /* @vite-ignore */
49880
+ /* webpackIgnore: true */
49881
+ spec
49882
+ );
49883
+ }
49624
49884
  async function render(content, options) {
49625
49885
  const theme = options?.theme ?? "light";
49626
49886
  const paletteName = options?.palette ?? "nord";
@@ -49802,6 +50062,7 @@ var DIRECTIVE_KEYWORDS = /* @__PURE__ */ new Set([
49802
50062
  "split",
49803
50063
  "slo-p90-latency-ms",
49804
50064
  "slo-availability",
50065
+ "slo-warning-margin",
49805
50066
  "cache-hit",
49806
50067
  "concurrency",
49807
50068
  "duration-ms",
@@ -50425,7 +50686,7 @@ pre.dgmo, code.language-dgmo, pre > code.language-dgmo,
50425
50686
 
50426
50687
  // src/auto/index.ts
50427
50688
  init_safe_href();
50428
- var VERSION = "0.14.1";
50689
+ var VERSION = "0.15.1";
50429
50690
  var DEFAULTS = {
50430
50691
  theme: "auto",
50431
50692
  palette: "nord",
@@ -50742,8 +51003,8 @@ function determineReplaceTarget(matched) {
50742
51003
  }
50743
51004
  async function processElement(el) {
50744
51005
  if (!(el instanceof HTMLElement)) return {};
50745
- if (el.dataset.dgmoProcessed === "true") return {};
50746
- el.dataset.dgmoProcessed = "true";
51006
+ if (el.dataset["dgmoProcessed"] === "true") return {};
51007
+ el.dataset["dgmoProcessed"] = "true";
50747
51008
  const source = el.textContent || "";
50748
51009
  const sourceBytes = new TextEncoder().encode(source).byteLength;
50749
51010
  if (sourceBytes > SOURCE_BYTE_CAP) {
@@ -50760,7 +51021,7 @@ async function processElement(el) {
50760
51021
  const resolvedTheme = cfg.theme === "transparent" ? "transparent" : resolveTheme(cfg.theme);
50761
51022
  const renderTheme = resolvedTheme === "transparent" ? "transparent" : resolvedTheme;
50762
51023
  const ariaLabel = deriveAriaLabel(source);
50763
- const perElementShowSource = el.dataset.showSource;
51024
+ const perElementShowSource = el.dataset["showSource"];
50764
51025
  let showSource = cfg.showSource;
50765
51026
  if (perElementShowSource === "true") showSource = true;
50766
51027
  else if (perElementShowSource === "false") showSource = false;
@@ -50810,7 +51071,7 @@ async function processElement(el) {
50810
51071
  const wrapper = document.createElement("div");
50811
51072
  const themeClass = resolvedTheme === "dark" ? "dgmo-theme-dark" : resolvedTheme === "transparent" ? "dgmo-theme-transparent" : "dgmo-theme-light";
50812
51073
  wrapper.className = `dgmo-rendered ${themeClass}`;
50813
- wrapper.dataset.dgmoProcessed = "true";
51074
+ wrapper.dataset["dgmoProcessed"] = "true";
50814
51075
  const svgHolder = document.createElement("div");
50815
51076
  svgHolder.innerHTML = result.svg;
50816
51077
  const svgEl = svgHolder.querySelector("svg");
@@ -50879,15 +51140,16 @@ function initialize(opts = {}) {
50879
51140
  }
50880
51141
  }
50881
51142
  const next = { ...activeConfig };
50882
- if (isValidTheme(opts.theme)) {
50883
- next.theme = opts.theme;
51143
+ if (isValidTheme(opts["theme"])) {
51144
+ next.theme = opts["theme"];
50884
51145
  }
50885
- if (typeof opts.palette === "string" && paletteExists(opts.palette)) {
50886
- next.palette = opts.palette;
51146
+ if (typeof opts["palette"] === "string" && paletteExists(opts["palette"])) {
51147
+ next.palette = opts["palette"];
50887
51148
  }
50888
- if (typeof opts.showSource === "boolean") next.showSource = opts.showSource;
50889
- if (typeof opts.showEditorLink === "boolean")
50890
- next.showEditorLink = opts.showEditorLink;
51149
+ if (typeof opts["showSource"] === "boolean")
51150
+ next.showSource = opts["showSource"];
51151
+ if (typeof opts["showEditorLink"] === "boolean")
51152
+ next.showEditorLink = opts["showEditorLink"];
50891
51153
  activeConfig = next;
50892
51154
  }
50893
51155
  async function run(opts = {}) {
@@ -50926,7 +51188,7 @@ function rerenderAllForTheme() {
50926
51188
  placeholder.className = "dgmo";
50927
51189
  placeholder.textContent = t.source;
50928
51190
  if (t.perElementShowSource !== null) {
50929
- placeholder.dataset.showSource = String(t.perElementShowSource);
51191
+ placeholder.dataset["showSource"] = String(t.perElementShowSource);
50930
51192
  }
50931
51193
  t.wrapper.replaceWith(placeholder);
50932
51194
  wrappers.delete(t);
@@ -50953,7 +51215,7 @@ function unhideAllSources() {
50953
51215
  el.style.visibility = "visible";
50954
51216
  });
50955
51217
  if (document.documentElement && document.documentElement.dataset) {
50956
- document.documentElement.dataset.dgmoAutoFailed = "1";
51218
+ document.documentElement.dataset["dgmoAutoFailed"] = "1";
50957
51219
  }
50958
51220
  }
50959
51221
  function bootstrap() {