@diagrammo/dgmo 0.15.0 → 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 (64) 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 +1495 -1288
  7. package/dist/auto.js +132 -109
  8. package/dist/auto.mjs +1491 -1284
  9. package/dist/cli.cjs +173 -150
  10. package/dist/index.cjs +1486 -1276
  11. package/dist/index.d.cts +45 -1
  12. package/dist/index.d.ts +45 -1
  13. package/dist/index.js +1481 -1272
  14. package/dist/internal.cjs +1497 -1289
  15. package/dist/internal.d.cts +80 -79
  16. package/dist/internal.d.ts +80 -79
  17. package/dist/internal.js +1492 -1285
  18. package/dist/pert.cjs +325 -0
  19. package/dist/pert.d.cts +542 -0
  20. package/dist/pert.d.ts +542 -0
  21. package/dist/pert.js +294 -0
  22. package/package.json +28 -3
  23. package/src/advanced.ts +731 -0
  24. package/src/auto/index.ts +14 -13
  25. package/src/boxes-and-lines/layout.ts +481 -445
  26. package/src/c4/parser.ts +7 -7
  27. package/src/chart-types.ts +0 -5
  28. package/src/class/parser.ts +1 -9
  29. package/src/cli.ts +9 -7
  30. package/src/completion-types.ts +28 -0
  31. package/src/completion.ts +15 -18
  32. package/src/cycle/layout.ts +2 -2
  33. package/src/d3.ts +1455 -1122
  34. package/src/echarts.ts +11 -11
  35. package/src/er/parser.ts +1 -9
  36. package/src/er/renderer.ts +1 -1
  37. package/src/gantt/calculator.ts +1 -11
  38. package/src/gantt/parser.ts +16 -16
  39. package/src/gantt/renderer.ts +2 -2
  40. package/src/graph/flowchart-parser.ts +1 -1
  41. package/src/graph/flowchart-renderer.ts +1 -1
  42. package/src/graph/state-renderer.ts +1 -1
  43. package/src/index.ts +17 -1
  44. package/src/infra/parser.ts +19 -19
  45. package/src/infra/renderer.ts +2 -2
  46. package/src/internal.ts +9 -721
  47. package/src/kanban/parser.ts +2 -2
  48. package/src/mindmap/layout.ts +1 -1
  49. package/src/mindmap/parser.ts +1 -1
  50. package/src/org/parser.ts +1 -1
  51. package/src/org/renderer.ts +1 -1
  52. package/src/pert/layout.ts +1 -1
  53. package/src/pert/monte-carlo.ts +2 -2
  54. package/src/pert/parser.ts +3 -3
  55. package/src/raci/parser.ts +4 -4
  56. package/src/raci/renderer.ts +1 -1
  57. package/src/sequence/renderer.ts +1 -4
  58. package/src/sitemap/parser.ts +1 -1
  59. package/src/tech-radar/interactive.ts +1 -1
  60. package/src/tech-radar/renderer.ts +1 -1
  61. package/src/utils/tag-groups.ts +11 -12
  62. package/src/wireframe/layout.ts +11 -7
  63. package/src/wireframe/parser.ts +2 -2
  64. package/src/wireframe/renderer.ts +5 -2
package/dist/internal.cjs CHANGED
@@ -2345,7 +2345,7 @@ function injectDefaultTagMetadata(entities, tagGroups, skip) {
2345
2345
  }
2346
2346
  }
2347
2347
  }
2348
- function resolveActiveTagGroup(_tagGroups, explicitActiveTag, programmaticOverride) {
2348
+ function resolveActiveTagGroup(tagGroups, explicitActiveTag, programmaticOverride) {
2349
2349
  if (programmaticOverride !== void 0) {
2350
2350
  if (!programmaticOverride) return null;
2351
2351
  if (programmaticOverride.toLowerCase() === "none") return null;
@@ -2355,6 +2355,7 @@ function resolveActiveTagGroup(_tagGroups, explicitActiveTag, programmaticOverri
2355
2355
  if (explicitActiveTag.toLowerCase() === "none") return null;
2356
2356
  return explicitActiveTag;
2357
2357
  }
2358
+ if (tagGroups.length > 0) return tagGroups[0].name;
2358
2359
  return null;
2359
2360
  }
2360
2361
  function matchTagBlockHeading(trimmed) {
@@ -5364,12 +5365,6 @@ function parseClassDiagram(content, palette) {
5364
5365
  diagnostics: [],
5365
5366
  error: null
5366
5367
  };
5367
- const _fail = (line12, message) => {
5368
- const diag = makeDgmoError(line12, message);
5369
- result.diagnostics.push(diag);
5370
- result.error = formatDgmoError(diag);
5371
- return result;
5372
- };
5373
5368
  const classMap = /* @__PURE__ */ new Map();
5374
5369
  const nameAliasMap = /* @__PURE__ */ new Map();
5375
5370
  function resolveAliasName(token) {
@@ -5764,12 +5759,6 @@ function parseERDiagram(content, palette) {
5764
5759
  diagnostics: [],
5765
5760
  error: null
5766
5761
  };
5767
- const _fail = (line12, message) => {
5768
- const diag = makeDgmoError(line12, message);
5769
- result.diagnostics.push(diag);
5770
- result.error = formatDgmoError(diag);
5771
- return result;
5772
- };
5773
5762
  const pushError = (line12, message) => {
5774
5763
  const diag = makeDgmoError(line12, message);
5775
5764
  result.diagnostics.push(diag);
@@ -7219,7 +7208,7 @@ function buildSankeyOption(parsed, textColor, colors, bg, titleConfig) {
7219
7208
  ]
7220
7209
  };
7221
7210
  }
7222
- function buildChordOption(parsed, palette, isDark, textColor, colors, bg, titleConfig) {
7211
+ function buildChordOption(parsed, palette, isDark, textColor, colors, _bg, titleConfig) {
7223
7212
  const nodeSet = /* @__PURE__ */ new Set();
7224
7213
  if (parsed.links) {
7225
7214
  for (const link of parsed.links) {
@@ -7333,7 +7322,7 @@ function evaluateExpression(expr, x) {
7333
7322
  return NaN;
7334
7323
  }
7335
7324
  }
7336
- function buildFunctionOption(parsed, palette, isDark, textColor, axisLineColor, gridOpacity, colors, titleConfig) {
7325
+ function buildFunctionOption(parsed, palette, _isDark, textColor, axisLineColor, gridOpacity, colors, titleConfig) {
7337
7326
  const xRange = parsed.xRange ?? { min: -10, max: 10 };
7338
7327
  const samples = 200;
7339
7328
  const step = (xRange.max - xRange.min) / samples;
@@ -8006,7 +7995,7 @@ function buildHeatmapOption(parsed, palette, isDark, textColor, axisLineColor, t
8006
7995
  ]
8007
7996
  };
8008
7997
  }
8009
- function buildFunnelOption(parsed, palette, isDark, textColor, colors, bg, titleConfig) {
7998
+ function buildFunnelOption(parsed, palette, isDark, textColor, colors, _bg, titleConfig) {
8010
7999
  const sorted = [...parsed.data].sort((a, b) => b.value - a.value);
8011
8000
  const data = sorted.map((d) => {
8012
8001
  const stroke2 = d.color ?? colors[parsed.data.indexOf(d) % colors.length];
@@ -8289,7 +8278,7 @@ function wrapLabel(text, maxChars) {
8289
8278
  if (current) lines.push(current);
8290
8279
  return lines.join("\n");
8291
8280
  }
8292
- function buildBarOption(parsed, palette, isDark, textColor, axisLineColor, splitLineColor, gridOpacity, colors, bg, titleConfig, chartWidth) {
8281
+ function buildBarOption(parsed, palette, isDark, textColor, axisLineColor, splitLineColor, gridOpacity, colors, _bg, titleConfig, chartWidth) {
8293
8282
  const { xLabel, yLabel } = resolveAxisLabels(parsed);
8294
8283
  const isHorizontal = parsed.orientation === "horizontal";
8295
8284
  const labels = parsed.data.map((d) => d.label);
@@ -8616,7 +8605,7 @@ function pieLabelLayout(parsed) {
8616
8605
  if (maxLen > 18) return { outerRadius: 55, fontSize: 13 };
8617
8606
  return { outerRadius: 70, fontSize: 14 };
8618
8607
  }
8619
- function buildPieOption(parsed, palette, isDark, textColor, colors, bg, titleConfig, isDoughnut) {
8608
+ function buildPieOption(parsed, palette, isDark, textColor, colors, _bg, titleConfig, isDoughnut) {
8620
8609
  const HIDE_AXES = { xAxis: { show: false }, yAxis: { show: false } };
8621
8610
  const data = parsed.data.map((d, i) => {
8622
8611
  const stroke2 = d.color ?? colors[i % colors.length];
@@ -8715,7 +8704,7 @@ function buildRadarOption(parsed, palette, isDark, textColor, gridOpacity, title
8715
8704
  ]
8716
8705
  };
8717
8706
  }
8718
- function buildPolarAreaOption(parsed, palette, isDark, textColor, colors, bg, titleConfig) {
8707
+ function buildPolarAreaOption(parsed, palette, isDark, textColor, colors, _bg, titleConfig) {
8719
8708
  const data = parsed.data.map((d, i) => {
8720
8709
  const stroke2 = d.color ?? colors[i % colors.length];
8721
8710
  return {
@@ -8758,7 +8747,7 @@ function buildPolarAreaOption(parsed, palette, isDark, textColor, colors, bg, ti
8758
8747
  ]
8759
8748
  };
8760
8749
  }
8761
- function buildBarStackedOption(parsed, palette, isDark, textColor, axisLineColor, splitLineColor, gridOpacity, colors, bg, titleConfig, chartWidth) {
8750
+ function buildBarStackedOption(parsed, palette, isDark, textColor, axisLineColor, splitLineColor, gridOpacity, colors, _bg, titleConfig, chartWidth) {
8762
8751
  const { xLabel, yLabel } = resolveAxisLabels(parsed);
8763
8752
  const isHorizontal = parsed.orientation === "horizontal";
8764
8753
  const seriesNames = parsed.seriesNames ?? [];
@@ -8898,8 +8887,8 @@ async function renderExtendedChartForExport(content, theme, palette) {
8898
8887
  const titleHeight = option.title && option.title.text ? 40 : 0;
8899
8888
  const legendY = 8 + titleHeight;
8900
8889
  const grid = option.grid;
8901
- const gridLeftPct = grid?.left ? parseFloat(String(grid.left)) : void 0;
8902
- const gridRightPct = grid?.right ? parseFloat(String(grid.right)) : void 0;
8890
+ const gridLeftPct = grid?.["left"] ? parseFloat(String(grid["left"])) : void 0;
8891
+ const gridRightPct = grid?.["right"] ? parseFloat(String(grid["right"])) : void 0;
8903
8892
  const { svg: legendSvgStr } = renderLegendSvg(legendGroups, {
8904
8893
  palette: effectivePalette,
8905
8894
  isDark,
@@ -9249,7 +9238,7 @@ function parseOrg(content, palette) {
9249
9238
  }
9250
9239
  return result;
9251
9240
  }
9252
- function parseNodeLabel(trimmed, _indent, lineNumber, palette, counter, metaAliasMap = /* @__PURE__ */ new Map(), warnFn, nameAliasMap) {
9241
+ function parseNodeLabel(trimmed, _indent, lineNumber, _palette, counter, metaAliasMap = /* @__PURE__ */ new Map(), warnFn, nameAliasMap) {
9253
9242
  const segments = trimmed.split("|").map((s) => s.trim());
9254
9243
  let label = segments[0];
9255
9244
  const asMatch = label.match(/^(.*?)\s+as\s+([A-Za-z][A-Za-z0-9_]{0,11})\s*$/);
@@ -9498,8 +9487,8 @@ function parseKanban(content, palette) {
9498
9487
  columnMetadata,
9499
9488
  parsePipeMetadata(pipeSegments, metaAliasMap)
9500
9489
  );
9501
- if (columnMetadata.wip) {
9502
- const wipVal = parseInt(columnMetadata.wip, 10);
9490
+ if (columnMetadata["wip"]) {
9491
+ const wipVal = parseInt(columnMetadata["wip"], 10);
9503
9492
  if (!isNaN(wipVal)) {
9504
9493
  wipLimit = wipVal;
9505
9494
  }
@@ -9878,7 +9867,7 @@ function parseC4(content, palette) {
9878
9867
  );
9879
9868
  const shape = inferC4Shape(
9880
9869
  nodeName,
9881
- metadata.tech ?? metadata.technology
9870
+ metadata["tech"] ?? metadata["technology"]
9882
9871
  );
9883
9872
  const dNode = {
9884
9873
  name: nodeName,
@@ -9981,11 +9970,11 @@ function parseC4(content, palette) {
9981
9970
  target = targetBody.substring(0, pipeIdx).trim();
9982
9971
  const metaPart = targetBody.substring(pipeIdx + 1).trim();
9983
9972
  const meta = parsePipeMetadata(["", metaPart], metaAliasMap);
9984
- if (meta.tech) {
9985
- technology = meta.tech;
9973
+ if (meta["tech"]) {
9974
+ technology = meta["tech"];
9986
9975
  }
9987
- if (meta.technology) {
9988
- technology = meta.technology;
9976
+ if (meta["technology"]) {
9977
+ technology = meta["technology"];
9989
9978
  }
9990
9979
  }
9991
9980
  const rel = {
@@ -10119,7 +10108,7 @@ function parseC4(content, palette) {
10119
10108
  metaAliasMap,
10120
10109
  () => pushError(lineNumber, MULTIPLE_PIPE_ERROR)
10121
10110
  );
10122
- const shape = explicitShape ?? inferC4Shape(namePart, metadata.tech ?? metadata.technology);
10111
+ const shape = explicitShape ?? inferC4Shape(namePart, metadata["tech"] ?? metadata["technology"]);
10123
10112
  let isADescription;
10124
10113
  if ("description" in metadata) {
10125
10114
  const descVal = metadata["description"].trim();
@@ -10179,7 +10168,7 @@ function parseC4(content, palette) {
10179
10168
  metaAliasMap,
10180
10169
  () => pushError(lineNumber, MULTIPLE_PIPE_ERROR)
10181
10170
  );
10182
- const shape = explicitShape ?? inferC4Shape(namePart, metadata.tech ?? metadata.technology);
10171
+ const shape = explicitShape ?? inferC4Shape(namePart, metadata["tech"] ?? metadata["technology"]);
10183
10172
  let prefixDescription;
10184
10173
  if ("description" in metadata) {
10185
10174
  const descVal = metadata["description"].trim();
@@ -10788,7 +10777,7 @@ function parseSitemap(content, palette) {
10788
10777
  }
10789
10778
  return result;
10790
10779
  }
10791
- function parseNodeLabel2(trimmed, lineNumber, palette, counter, metaAliasMap = /* @__PURE__ */ new Map(), warnFn, _diagnostics, nameAliasMap) {
10780
+ function parseNodeLabel2(trimmed, lineNumber, _palette, counter, metaAliasMap = /* @__PURE__ */ new Map(), warnFn, _diagnostics, nameAliasMap) {
10792
10781
  const segments = trimmed.split("|").map((s) => s.trim());
10793
10782
  let label = segments[0];
10794
10783
  const asMatch = label.match(/^(.*?)\s+as\s+([A-Za-z][A-Za-z0-9_]{0,11})\s*$/);
@@ -11079,11 +11068,11 @@ function parseInfra(content) {
11079
11068
  continue;
11080
11069
  }
11081
11070
  if (trimmed === "animate") {
11082
- result.options.animate = "on";
11071
+ result.options["animate"] = "on";
11083
11072
  continue;
11084
11073
  }
11085
11074
  if (trimmed === "no-animate") {
11086
- result.options.animate = "off";
11075
+ result.options["animate"] = "off";
11087
11076
  continue;
11088
11077
  }
11089
11078
  if (tryParseSharedOption(trimmed, result.options)) {
@@ -11237,8 +11226,8 @@ function parseInfra(content) {
11237
11226
  const pipeMeta = extractPipeMetadata(targetRaw);
11238
11227
  const targetName = pipeMeta.clean || targetRaw;
11239
11228
  warnUnparsedPipeMeta(targetName, lineNumber, warn);
11240
- const split = pipeMeta.tags.split ? parseFloat(pipeMeta.tags.split) : null;
11241
- const fanoutRaw = pipeMeta.tags.fanout ? parseInt(pipeMeta.tags.fanout, 10) : null;
11229
+ const split = pipeMeta.tags["split"] ? parseFloat(pipeMeta.tags["split"]) : null;
11230
+ const fanoutRaw = pipeMeta.tags["fanout"] ? parseInt(pipeMeta.tags["fanout"], 10) : null;
11242
11231
  if (fanoutRaw !== null && fanoutRaw < 1) {
11243
11232
  warn(
11244
11233
  lineNumber,
@@ -11269,8 +11258,8 @@ function parseInfra(content) {
11269
11258
  const pipeMeta = extractPipeMetadata(targetRaw);
11270
11259
  const targetName = pipeMeta.clean || targetRaw;
11271
11260
  warnUnparsedPipeMeta(targetName, lineNumber, warn);
11272
- const split = pipeMeta.tags.split ? parseFloat(pipeMeta.tags.split) : null;
11273
- const fanoutRaw = pipeMeta.tags.fanout ? parseInt(pipeMeta.tags.fanout, 10) : null;
11261
+ const split = pipeMeta.tags["split"] ? parseFloat(pipeMeta.tags["split"]) : null;
11262
+ const fanoutRaw = pipeMeta.tags["fanout"] ? parseInt(pipeMeta.tags["fanout"], 10) : null;
11274
11263
  if (fanoutRaw !== null && fanoutRaw < 1) {
11275
11264
  warn(
11276
11265
  lineNumber,
@@ -11304,8 +11293,8 @@ function parseInfra(content) {
11304
11293
  const pipeMeta = extractPipeMetadata(targetRaw);
11305
11294
  const targetName = pipeMeta.clean || targetRaw;
11306
11295
  warnUnparsedPipeMeta(targetName, lineNumber, warn);
11307
- const split = pipeMeta.tags.split ? parseFloat(pipeMeta.tags.split) : null;
11308
- const fanoutRaw = pipeMeta.tags.fanout ? parseInt(pipeMeta.tags.fanout, 10) : null;
11296
+ const split = pipeMeta.tags["split"] ? parseFloat(pipeMeta.tags["split"]) : null;
11297
+ const fanoutRaw = pipeMeta.tags["fanout"] ? parseInt(pipeMeta.tags["fanout"], 10) : null;
11309
11298
  if (fanoutRaw !== null && fanoutRaw < 1) {
11310
11299
  warn(
11311
11300
  lineNumber,
@@ -11336,8 +11325,8 @@ function parseInfra(content) {
11336
11325
  const pipeMeta = extractPipeMetadata(targetRaw);
11337
11326
  const targetName = pipeMeta.clean || targetRaw;
11338
11327
  warnUnparsedPipeMeta(targetName, lineNumber, warn);
11339
- const split = pipeMeta.tags.split ? parseFloat(pipeMeta.tags.split) : null;
11340
- const fanoutRaw = pipeMeta.tags.fanout ? parseInt(pipeMeta.tags.fanout, 10) : null;
11328
+ const split = pipeMeta.tags["split"] ? parseFloat(pipeMeta.tags["split"]) : null;
11329
+ const fanoutRaw = pipeMeta.tags["fanout"] ? parseInt(pipeMeta.tags["fanout"], 10) : null;
11341
11330
  if (fanoutRaw !== null && fanoutRaw < 1) {
11342
11331
  warn(
11343
11332
  lineNumber,
@@ -12044,15 +12033,15 @@ function parseGantt(content, palette) {
12044
12033
  metaAliasMap,
12045
12034
  () => warn(lineNumber, MULTIPLE_PIPE_ERROR)
12046
12035
  );
12047
- if (meta.lag || meta.lead) {
12048
- const key = meta.lag ? "lag" : "lead";
12036
+ if (meta["lag"] || meta["lead"]) {
12037
+ const key = meta["lag"] ? "lag" : "lead";
12049
12038
  softError(
12050
12039
  lineNumber,
12051
12040
  `"${key}" is no longer supported \u2014 use "offset: ${meta[key]}" instead.${key === "lead" ? ' Negate the value for lead behavior: "offset: -...".' : ""}`
12052
12041
  );
12053
12042
  }
12054
- if (meta.offset) {
12055
- const raw = meta.offset;
12043
+ if (meta["offset"]) {
12044
+ const raw = meta["offset"];
12056
12045
  if (raw.trim().startsWith("+")) {
12057
12046
  warn(
12058
12047
  lineNumber,
@@ -12439,15 +12428,15 @@ function parseGantt(content, palette) {
12439
12428
  metaAliasMap,
12440
12429
  () => warn(lineNumber, MULTIPLE_PIPE_ERROR)
12441
12430
  );
12442
- if (meta.lag || meta.lead) {
12443
- const key = meta.lag ? "lag" : "lead";
12431
+ if (meta["lag"] || meta["lead"]) {
12432
+ const key = meta["lag"] ? "lag" : "lead";
12444
12433
  softError(
12445
12434
  lineNumber,
12446
12435
  `"${key}" is no longer supported \u2014 use "offset: ${meta[key]}" instead.${key === "lead" ? ' Negate the value for lead behavior: "offset: -...".' : ""}`
12447
12436
  );
12448
12437
  }
12449
- if (meta.offset) {
12450
- const raw = meta.offset;
12438
+ if (meta["offset"]) {
12439
+ const raw = meta["offset"];
12451
12440
  if (raw.trim().startsWith("+")) {
12452
12441
  warn(
12453
12442
  lineNumber,
@@ -12518,9 +12507,9 @@ function parseGantt(content, palette) {
12518
12507
  () => warn(ln, MULTIPLE_PIPE_ERROR)
12519
12508
  ) : {};
12520
12509
  let progress = null;
12521
- if (metadata.progress) {
12522
- progress = parseFloat(metadata.progress);
12523
- delete metadata.progress;
12510
+ if (metadata["progress"]) {
12511
+ progress = parseFloat(metadata["progress"]);
12512
+ delete metadata["progress"];
12524
12513
  }
12525
12514
  for (const part of segments.slice(1).join(",").split(",")) {
12526
12515
  const seg = part.trim();
@@ -12529,16 +12518,16 @@ function parseGantt(content, palette) {
12529
12518
  progress = parseInt(progressMatch[1], 10);
12530
12519
  }
12531
12520
  }
12532
- if (metadata.lag || metadata.lead) {
12533
- const key = metadata.lag ? "lag" : "lead";
12521
+ if (metadata["lag"] || metadata["lead"]) {
12522
+ const key = metadata["lag"] ? "lag" : "lead";
12534
12523
  softError(
12535
12524
  ln,
12536
12525
  `"${key}" is no longer supported \u2014 use "offset: ${metadata[key]}" instead.${key === "lead" ? ' Negate the value for lead behavior: "offset: -...".' : ""}`
12537
12526
  );
12538
12527
  }
12539
12528
  let taskOffset;
12540
- if (metadata.offset) {
12541
- const raw = metadata.offset;
12529
+ if (metadata["offset"]) {
12530
+ const raw = metadata["offset"];
12542
12531
  if (raw.trim().startsWith("+")) {
12543
12532
  warn(
12544
12533
  ln,
@@ -12553,7 +12542,7 @@ function parseGantt(content, palette) {
12553
12542
  );
12554
12543
  }
12555
12544
  }
12556
- delete metadata.offset;
12545
+ delete metadata["offset"];
12557
12546
  }
12558
12547
  const groupPath = currentGroupPath();
12559
12548
  const inheritedMeta = {};
@@ -13076,7 +13065,7 @@ function parsePert(content, parseOpts = {}) {
13076
13065
  id,
13077
13066
  name,
13078
13067
  activityIds: [],
13079
- collapsed: meta.collapsed === "true",
13068
+ collapsed: meta["collapsed"] === "true",
13080
13069
  lineNumber,
13081
13070
  ...Object.keys(tags).length > 0 && { tags }
13082
13071
  });
@@ -13338,7 +13327,7 @@ function parsePert(content, parseOpts = {}) {
13338
13327
  name: decl.name,
13339
13328
  ...decl.alias !== void 0 && { alias: decl.alias },
13340
13329
  duration: estimate,
13341
- ...meta.confidence && { confidence: meta.confidence },
13330
+ ...meta["confidence"] && { confidence: meta["confidence"] },
13342
13331
  ...decl.groupHint !== void 0 && { groupId: decl.groupHint },
13343
13332
  lineNumber: decl.lineNumber,
13344
13333
  isMilestone,
@@ -14669,7 +14658,7 @@ function parseMindmap(content, palette) {
14669
14658
  }
14670
14659
  return result;
14671
14660
  }
14672
- function parseNodeLine2(trimmed, lineNumber, palette, counter, aliasMap, warnFn) {
14661
+ function parseNodeLine2(trimmed, lineNumber, _palette, counter, aliasMap, warnFn) {
14673
14662
  const segments = trimmed.split("|").map((s) => s.trim());
14674
14663
  const label = segments[0];
14675
14664
  const metadata = parsePipeMetadata(
@@ -15113,7 +15102,7 @@ function parseWireframe(content) {
15113
15102
  wrapper.isContainer = true;
15114
15103
  wrapper.orientation = "horizontal";
15115
15104
  wrapper.children = children;
15116
- wrapper.metadata._inlineRow = "true";
15105
+ wrapper.metadata["_inlineRow"] = "true";
15117
15106
  pushElement(wrapper);
15118
15107
  }
15119
15108
  for (let i = 0; i < lines.length; i++) {
@@ -15264,7 +15253,7 @@ function parseWireframe(content) {
15264
15253
  wrapper.isContainer = true;
15265
15254
  wrapper.orientation = "horizontal";
15266
15255
  wrapper.children.push(labelEl, fieldEl);
15267
- wrapper.metadata._labelField = "true";
15256
+ wrapper.metadata["_labelField"] = "true";
15268
15257
  pushElement(wrapper);
15269
15258
  }
15270
15259
  } else {
@@ -17085,9 +17074,9 @@ function parseRaci(content, palette) {
17085
17074
  let roleColor;
17086
17075
  if (segments.length > 1) {
17087
17076
  const meta = parsePipeMetadata(segments);
17088
- if (meta.color) {
17077
+ if (meta["color"]) {
17089
17078
  roleColor = resolveColorWithDiagnostic(
17090
- meta.color,
17079
+ meta["color"],
17091
17080
  j + 1,
17092
17081
  result.diagnostics,
17093
17082
  palette
@@ -17154,9 +17143,9 @@ function parseRaci(content, palette) {
17154
17143
  let phaseColor;
17155
17144
  if (phaseMatch[2]) {
17156
17145
  const meta = parsePipeMetadata(["", phaseMatch[2]]);
17157
- if (meta.color) {
17146
+ if (meta["color"]) {
17158
17147
  phaseColor = resolveColorWithDiagnostic(
17159
- meta.color,
17148
+ meta["color"],
17160
17149
  lineNumber,
17161
17150
  result.diagnostics,
17162
17151
  palette
@@ -17399,7 +17388,7 @@ var init_parser19 = __esm({
17399
17388
  });
17400
17389
 
17401
17390
  // src/chart-types.ts
17402
- var chartTypes, BETA_CHART_IDS;
17391
+ var chartTypes;
17403
17392
  var init_chart_types = __esm({
17404
17393
  "src/chart-types.ts"() {
17405
17394
  "use strict";
@@ -17858,7 +17847,6 @@ var init_chart_types = __esm({
17858
17847
  fallback: true
17859
17848
  }
17860
17849
  ];
17861
- BETA_CHART_IDS = /* @__PURE__ */ new Set(["c4", "venn"]);
17862
17850
  }
17863
17851
  });
17864
17852
 
@@ -19166,7 +19154,7 @@ function renderOrg(container, parsed, layout, palette, isDark, onClickItem, expo
19166
19154
  displayNames.set(group.name.toLowerCase(), group.name);
19167
19155
  }
19168
19156
  const rootNodeIds = new Set(parsed.roots.map((r) => r.id));
19169
- const colorOff = parsed.options?.color === "off";
19157
+ const colorOff = parsed.options?.["color"] === "off";
19170
19158
  for (const c of layout.containers) {
19171
19159
  const cG = contentG.append("g").attr("transform", `translate(${c.x}, ${c.y})`).attr("class", "org-container").attr("data-line-number", String(c.lineNumber));
19172
19160
  if (activeTagGroup) {
@@ -22366,7 +22354,7 @@ function renderERDiagram(container, parsed, layout, palette, isDark, onClickItem
22366
22354
  const seriesColors2 = getSeriesColors(palette);
22367
22355
  const semanticRoles = useSemanticColors ? classifyEREntities(parsed.tables, parsed.relationships) : null;
22368
22356
  const semanticActive = semanticRoles !== null && (semanticColorsActive ?? true);
22369
- const useLabels = parsed.options.notation === "labels";
22357
+ const useLabels = parsed.options["notation"] === "labels";
22370
22358
  for (const edge of layout.edges) {
22371
22359
  if (edge.points.length < 2) continue;
22372
22360
  const edgeG = contentG.append("g").attr("class", "er-edge-group").attr("data-line-number", String(edge.lineNumber));
@@ -22581,495 +22569,6 @@ var init_renderer5 = __esm({
22581
22569
  }
22582
22570
  });
22583
22571
 
22584
- // src/boxes-and-lines/layout.ts
22585
- var layout_exports5 = {};
22586
- __export(layout_exports5, {
22587
- layoutBoxesAndLines: () => layoutBoxesAndLines
22588
- });
22589
- function clipToRectBorder2(cx, cy, w, h, tx, ty) {
22590
- const dx = tx - cx;
22591
- const dy = ty - cy;
22592
- if (dx === 0 && dy === 0) return { x: cx, y: cy };
22593
- const hw = w / 2;
22594
- const hh = h / 2;
22595
- const sx = dx !== 0 ? hw / Math.abs(dx) : Infinity;
22596
- const sy = dy !== 0 ? hh / Math.abs(dy) : Infinity;
22597
- const s = Math.min(sx, sy);
22598
- return { x: cx + dx * s, y: cy + dy * s };
22599
- }
22600
- function splitCamelCase(word) {
22601
- const parts = [];
22602
- let start = 0;
22603
- for (let i = 1; i < word.length; i++) {
22604
- const prev = word[i - 1];
22605
- const curr = word[i];
22606
- const next = i + 1 < word.length ? word[i + 1] : "";
22607
- const lowerToUpper = prev >= "a" && prev <= "z" && curr >= "A" && curr <= "Z";
22608
- const upperRunEnd = prev >= "A" && prev <= "Z" && curr >= "A" && curr <= "Z" && next >= "a" && next <= "z";
22609
- if (lowerToUpper || upperRunEnd) {
22610
- parts.push(word.slice(start, i));
22611
- start = i;
22612
- }
22613
- }
22614
- parts.push(word.slice(start));
22615
- return parts.length > 1 ? parts : [word];
22616
- }
22617
- function estimateLabelLines(label, nodeWidth2 = NODE_WIDTH) {
22618
- const rawParts = label.split(/[\s-]+/);
22619
- const words = [];
22620
- for (const part of rawParts) {
22621
- if (!part) continue;
22622
- words.push(...splitCamelCase(part));
22623
- }
22624
- for (let fontSize = 13; fontSize >= 9; fontSize--) {
22625
- const charWidth = fontSize * 0.6;
22626
- const maxChars = Math.floor((nodeWidth2 - 24) / charWidth);
22627
- if (maxChars < 2) continue;
22628
- let lines = 1;
22629
- let current = "";
22630
- for (const word of words) {
22631
- const test = current ? `${current} ${word}` : word;
22632
- if (test.length <= maxChars) {
22633
- current = test;
22634
- } else {
22635
- lines++;
22636
- current = word;
22637
- }
22638
- }
22639
- if (lines <= MAX_LABEL_LINES) return Math.min(lines, MAX_LABEL_LINES);
22640
- }
22641
- return MAX_LABEL_LINES;
22642
- }
22643
- function computeNodeSize(node) {
22644
- if (!node.description || node.description.length === 0) {
22645
- return { width: NODE_WIDTH, height: NODE_HEIGHT };
22646
- }
22647
- const w = DESC_NODE_WIDTH;
22648
- const labelLines = estimateLabelLines(node.label, w);
22649
- const labelHeight = labelLines * 13 * LABEL_LINE_HEIGHT + LABEL_PAD;
22650
- const charsPerLine = Math.floor((w - 24) / (DESC_FONT_SIZE * 0.6));
22651
- let totalRenderedLines = 0;
22652
- for (const line12 of node.description) {
22653
- if (line12.length <= charsPerLine) {
22654
- totalRenderedLines += 1;
22655
- } else {
22656
- const words = line12.split(/\s+/);
22657
- let current = "";
22658
- let lineCount = 0;
22659
- for (const word of words) {
22660
- const fitted = word.length > charsPerLine ? word.slice(0, charsPerLine) : word;
22661
- const test = current ? `${current} ${fitted}` : fitted;
22662
- if (test.length <= charsPerLine) {
22663
- current = test;
22664
- } else {
22665
- if (current) lineCount++;
22666
- current = fitted;
22667
- }
22668
- }
22669
- if (current) lineCount++;
22670
- totalRenderedLines += lineCount;
22671
- }
22672
- }
22673
- totalRenderedLines = Math.min(totalRenderedLines, MAX_DESC_LINES);
22674
- const descriptionHeight = totalRenderedLines * DESC_FONT_SIZE * DESC_LINE_HEIGHT;
22675
- const totalHeight = labelHeight + SEPARATOR_GAP5 + DESC_PADDING + descriptionHeight + DESC_PADDING;
22676
- return { width: w, height: Math.max(NODE_HEIGHT, totalHeight) };
22677
- }
22678
- function layoutBoxesAndLines(parsed, collapseInfo, layoutOptions) {
22679
- const hideDescriptions = layoutOptions?.hideDescriptions ?? false;
22680
- const g = new import_dagre4.default.graphlib.Graph({ compound: true, multigraph: true });
22681
- g.setGraph({
22682
- rankdir: parsed.direction,
22683
- nodesep: NODESEP,
22684
- ranksep: RANKSEP,
22685
- marginx: MARGIN3,
22686
- marginy: MARGIN3
22687
- });
22688
- g.setDefaultEdgeLabel(() => ({}));
22689
- const collapsedGroupLabels = /* @__PURE__ */ new Set();
22690
- if (collapseInfo) {
22691
- const missingGroups = /* @__PURE__ */ new Set();
22692
- for (const og of collapseInfo.originalGroups) {
22693
- if (!parsed.groups.some((g2) => g2.label === og.label)) {
22694
- missingGroups.add(og.label);
22695
- }
22696
- }
22697
- for (const label of missingGroups) {
22698
- const og = collapseInfo.originalGroups.find((g2) => g2.label === label);
22699
- const parentLabel = og?.parentGroup;
22700
- if (!parentLabel || !missingGroups.has(parentLabel)) {
22701
- collapsedGroupLabels.add(label);
22702
- }
22703
- }
22704
- }
22705
- for (const label of collapsedGroupLabels) {
22706
- const gid = `__group_${label}`;
22707
- g.setNode(gid, { label, width: NODE_WIDTH, height: NODE_HEIGHT });
22708
- }
22709
- for (const group of parsed.groups) {
22710
- const gid = `__group_${group.label}`;
22711
- g.setNode(gid, {
22712
- label: group.label,
22713
- paddingLeft: CONTAINER_PAD_X3,
22714
- paddingRight: CONTAINER_PAD_X3,
22715
- paddingTop: CONTAINER_PAD_TOP2,
22716
- paddingBottom: CONTAINER_PAD_BOTTOM3
22717
- });
22718
- }
22719
- const originalGroupByLabel = /* @__PURE__ */ new Map();
22720
- if (collapseInfo) {
22721
- for (const og of collapseInfo.originalGroups) {
22722
- originalGroupByLabel.set(og.label, og);
22723
- }
22724
- }
22725
- for (const label of collapsedGroupLabels) {
22726
- const og = originalGroupByLabel.get(label);
22727
- if (og?.parentGroup && !collapsedGroupLabels.has(og.parentGroup)) {
22728
- const gid = `__group_${label}`;
22729
- const parentGid = `__group_${og.parentGroup}`;
22730
- if (g.hasNode(parentGid)) {
22731
- g.setParent(gid, parentGid);
22732
- }
22733
- }
22734
- }
22735
- const nodeSizes = /* @__PURE__ */ new Map();
22736
- let maxDescHeight = 0;
22737
- for (const node of parsed.nodes) {
22738
- const size = hideDescriptions ? { width: NODE_WIDTH, height: NODE_HEIGHT } : computeNodeSize(node);
22739
- nodeSizes.set(node.label, size);
22740
- if (!hideDescriptions && node.description && node.description.length > 0) {
22741
- maxDescHeight = Math.max(maxDescHeight, size.height);
22742
- }
22743
- }
22744
- if (maxDescHeight > 0) {
22745
- for (const node of parsed.nodes) {
22746
- if (node.description && node.description.length > 0) {
22747
- const size = nodeSizes.get(node.label);
22748
- nodeSizes.set(node.label, { width: size.width, height: maxDescHeight });
22749
- }
22750
- }
22751
- }
22752
- for (const node of parsed.nodes) {
22753
- const size = nodeSizes.get(node.label);
22754
- g.setNode(node.label, {
22755
- label: node.label,
22756
- width: size.width,
22757
- height: size.height
22758
- });
22759
- }
22760
- for (const group of parsed.groups) {
22761
- if (group.parentGroup) {
22762
- const childGid = `__group_${group.label}`;
22763
- const parentGid = `__group_${group.parentGroup}`;
22764
- if (g.hasNode(childGid) && g.hasNode(parentGid)) {
22765
- g.setParent(childGid, parentGid);
22766
- }
22767
- }
22768
- }
22769
- const groupLabelSet = new Set(parsed.groups.map((gr) => gr.label));
22770
- for (const group of parsed.groups) {
22771
- const gid = `__group_${group.label}`;
22772
- for (const child of group.children) {
22773
- if (groupLabelSet.has(child)) continue;
22774
- if (g.hasNode(child)) {
22775
- g.setParent(child, gid);
22776
- }
22777
- }
22778
- }
22779
- const expandedGroupIds = /* @__PURE__ */ new Set();
22780
- for (const group of parsed.groups) {
22781
- expandedGroupIds.add(`__group_${group.label}`);
22782
- }
22783
- const groupFirstChild = /* @__PURE__ */ new Map();
22784
- for (const group of parsed.groups) {
22785
- const gid = `__group_${group.label}`;
22786
- const firstChild = group.children.find(
22787
- (c) => !groupLabelSet.has(c) && g.hasNode(c)
22788
- );
22789
- if (firstChild) {
22790
- groupFirstChild.set(gid, firstChild);
22791
- }
22792
- }
22793
- const deferredEdgeIndices = [];
22794
- let proxyIdx = 0;
22795
- for (let i = 0; i < parsed.edges.length; i++) {
22796
- const edge = parsed.edges[i];
22797
- const src = edge.source;
22798
- const tgt = edge.target;
22799
- if (!g.hasNode(src) || !g.hasNode(tgt)) continue;
22800
- if (expandedGroupIds.has(src) || expandedGroupIds.has(tgt)) {
22801
- deferredEdgeIndices.push(i);
22802
- const proxySrc = expandedGroupIds.has(src) ? groupFirstChild.get(src) : src;
22803
- const proxyTgt = expandedGroupIds.has(tgt) ? groupFirstChild.get(tgt) : tgt;
22804
- if (proxySrc && proxyTgt && proxySrc !== proxyTgt) {
22805
- g.setEdge(
22806
- proxySrc,
22807
- proxyTgt,
22808
- { label: "", minlen: 1 },
22809
- `proxy${proxyIdx++}`
22810
- );
22811
- }
22812
- continue;
22813
- }
22814
- g.setEdge(src, tgt, { label: edge.label ?? "", minlen: 1 }, `e${i}`);
22815
- }
22816
- import_dagre4.default.layout(g);
22817
- const layoutNodes = [];
22818
- for (const node of parsed.nodes) {
22819
- const dagreNode = g.node(node.label);
22820
- if (!dagreNode) continue;
22821
- layoutNodes.push({
22822
- label: node.label,
22823
- x: dagreNode.x,
22824
- y: dagreNode.y,
22825
- width: dagreNode.width,
22826
- height: dagreNode.height
22827
- });
22828
- }
22829
- const layoutGroups = [];
22830
- for (const group of parsed.groups) {
22831
- const gid = `__group_${group.label}`;
22832
- const dagreNode = g.node(gid);
22833
- if (!dagreNode) continue;
22834
- layoutGroups.push({
22835
- label: group.label,
22836
- lineNumber: group.lineNumber,
22837
- x: dagreNode.x,
22838
- y: dagreNode.y,
22839
- width: dagreNode.width,
22840
- height: dagreNode.height,
22841
- collapsed: false
22842
- });
22843
- }
22844
- for (const label of collapsedGroupLabels) {
22845
- const gid = `__group_${label}`;
22846
- const dagreNode = g.node(gid);
22847
- if (!dagreNode) continue;
22848
- const og = collapseInfo?.originalGroups.find((g2) => g2.label === label);
22849
- layoutGroups.push({
22850
- label,
22851
- lineNumber: og?.lineNumber ?? 0,
22852
- x: dagreNode.x,
22853
- y: dagreNode.y,
22854
- width: dagreNode.width,
22855
- height: dagreNode.height,
22856
- collapsed: true,
22857
- childCount: collapseInfo?.collapsedChildCounts.get(label) ?? 0
22858
- });
22859
- }
22860
- const groupAlignShifts = /* @__PURE__ */ new Map();
22861
- {
22862
- const groupEdges = [];
22863
- for (const edge of parsed.edges) {
22864
- if (edge.source.startsWith("__group_") && edge.target.startsWith("__group_")) {
22865
- groupEdges.push(edge);
22866
- }
22867
- }
22868
- if (groupEdges.length > 0) {
22869
- const groupParent = /* @__PURE__ */ new Map();
22870
- const find = (x) => {
22871
- while (groupParent.has(x) && groupParent.get(x) !== x) {
22872
- groupParent.set(x, groupParent.get(groupParent.get(x)));
22873
- x = groupParent.get(x);
22874
- }
22875
- return x;
22876
- };
22877
- const union = (a, b) => {
22878
- const ra = find(a), rb = find(b);
22879
- if (ra !== rb) groupParent.set(ra, rb);
22880
- };
22881
- for (const edge of groupEdges) {
22882
- if (!groupParent.has(edge.source))
22883
- groupParent.set(edge.source, edge.source);
22884
- if (!groupParent.has(edge.target))
22885
- groupParent.set(edge.target, edge.target);
22886
- union(edge.source, edge.target);
22887
- }
22888
- const components = /* @__PURE__ */ new Map();
22889
- for (const lg of layoutGroups) {
22890
- const gid = `__group_${lg.label}`;
22891
- if (!groupParent.has(gid)) continue;
22892
- const root = find(gid);
22893
- if (!components.has(root)) components.set(root, []);
22894
- components.get(root).push(lg);
22895
- }
22896
- const axis = parsed.direction === "TB" ? "x" : "y";
22897
- for (const groups of components.values()) {
22898
- if (groups.length < 2) continue;
22899
- const dim = axis === "x" ? "width" : "height";
22900
- let widest = groups[0];
22901
- for (const g2 of groups) {
22902
- if (g2[dim] > widest[dim]) widest = g2;
22903
- }
22904
- const targetCenter = widest[axis];
22905
- for (const grp of groups) {
22906
- const dx = targetCenter - grp[axis];
22907
- if (dx === 0) continue;
22908
- grp[axis] += dx;
22909
- groupAlignShifts.set(`__group_${grp.label}`, dx);
22910
- const parsedGroup = parsed.groups.find(
22911
- (pg) => pg.label === grp.label
22912
- );
22913
- if (parsedGroup) {
22914
- for (const childLabel of parsedGroup.children) {
22915
- const childNode = layoutNodes.find((n) => n.label === childLabel);
22916
- if (childNode) childNode[axis] += dx;
22917
- }
22918
- }
22919
- }
22920
- }
22921
- }
22922
- }
22923
- const edgeYOffsets = new Array(parsed.edges.length).fill(0);
22924
- const edgeParallelCounts = new Array(parsed.edges.length).fill(1);
22925
- const parallelGroups = /* @__PURE__ */ new Map();
22926
- for (let i = 0; i < parsed.edges.length; i++) {
22927
- const edge = parsed.edges[i];
22928
- const [a, b] = edge.source < edge.target ? [edge.source, edge.target] : [edge.target, edge.source];
22929
- const key = `${a}\0${b}`;
22930
- if (!parallelGroups.has(key)) parallelGroups.set(key, []);
22931
- parallelGroups.get(key).push(i);
22932
- }
22933
- for (const group of parallelGroups.values()) {
22934
- const capped = group.slice(0, MAX_PARALLEL_EDGES);
22935
- for (const idx of group.slice(MAX_PARALLEL_EDGES)) {
22936
- edgeParallelCounts[idx] = 0;
22937
- }
22938
- if (capped.length < 2) continue;
22939
- const effectiveSpacing = PARALLEL_SPACING;
22940
- for (let j = 0; j < capped.length; j++) {
22941
- edgeYOffsets[capped[j]] = (j - (capped.length - 1) / 2) * effectiveSpacing;
22942
- edgeParallelCounts[capped[j]] = capped.length;
22943
- }
22944
- }
22945
- const deferredSet = new Set(deferredEdgeIndices);
22946
- const layoutEdges = [];
22947
- for (let i = 0; i < parsed.edges.length; i++) {
22948
- const edge = parsed.edges[i];
22949
- if (edgeParallelCounts[i] === 0) continue;
22950
- let points;
22951
- if (deferredSet.has(i)) {
22952
- const srcLayout = layoutGroups.find(
22953
- (lg) => `__group_${lg.label}` === edge.source
22954
- );
22955
- const tgtLayout = layoutGroups.find(
22956
- (lg) => `__group_${lg.label}` === edge.target
22957
- );
22958
- if (!srcLayout || !tgtLayout) {
22959
- const srcNode = g.node(edge.source);
22960
- const tgtNode = g.node(edge.target);
22961
- if (!srcNode || !tgtNode) continue;
22962
- const srcPt = clipToRectBorder2(
22963
- srcNode.x,
22964
- srcNode.y,
22965
- srcNode.width,
22966
- srcNode.height,
22967
- tgtNode.x,
22968
- tgtNode.y
22969
- );
22970
- const tgtPt = clipToRectBorder2(
22971
- tgtNode.x,
22972
- tgtNode.y,
22973
- tgtNode.width,
22974
- tgtNode.height,
22975
- srcNode.x,
22976
- srcNode.y
22977
- );
22978
- const midX = (srcPt.x + tgtPt.x) / 2;
22979
- const midY = (srcPt.y + tgtPt.y) / 2;
22980
- points = [srcPt, { x: midX, y: midY }, tgtPt];
22981
- } else if (parsed.direction === "TB") {
22982
- const cx = (srcLayout.x + tgtLayout.x) / 2;
22983
- const srcPt = { x: cx, y: srcLayout.y + srcLayout.height / 2 };
22984
- const tgtPt = { x: cx, y: tgtLayout.y - tgtLayout.height / 2 };
22985
- const midY = (srcPt.y + tgtPt.y) / 2;
22986
- points = [srcPt, { x: cx, y: midY }, tgtPt];
22987
- } else {
22988
- const cy = (srcLayout.y + tgtLayout.y) / 2;
22989
- const srcPt = { x: srcLayout.x + srcLayout.width / 2, y: cy };
22990
- const tgtPt = { x: tgtLayout.x - tgtLayout.width / 2, y: cy };
22991
- const midX = (srcPt.x + tgtPt.x) / 2;
22992
- points = [srcPt, { x: midX, y: cy }, tgtPt];
22993
- }
22994
- } else {
22995
- const dagreEdge = g.edge(edge.source, edge.target, `e${i}`);
22996
- points = dagreEdge?.points ?? [];
22997
- const srcShift = groupAlignShifts.get(edge.source) ?? 0;
22998
- const tgtShift = groupAlignShifts.get(edge.target) ?? 0;
22999
- if (srcShift !== 0 || tgtShift !== 0) {
23000
- const avgShift = (srcShift + tgtShift) / 2;
23001
- const prop = parsed.direction === "TB" ? "x" : "y";
23002
- points = points.map((p) => ({ ...p, [prop]: p[prop] + avgShift }));
23003
- }
23004
- }
23005
- let labelX;
23006
- let labelY;
23007
- if (edge.label && points.length >= 2) {
23008
- const mid = Math.floor(points.length / 2);
23009
- labelX = points[mid].x;
23010
- labelY = points[mid].y - 10;
23011
- }
23012
- layoutEdges.push({
23013
- source: edge.source,
23014
- target: edge.target,
23015
- label: edge.label,
23016
- bidirectional: edge.bidirectional,
23017
- lineNumber: edge.lineNumber,
23018
- points,
23019
- labelX,
23020
- labelY,
23021
- yOffset: edgeYOffsets[i],
23022
- parallelCount: edgeParallelCounts[i],
23023
- metadata: edge.metadata,
23024
- deferred: deferredSet.has(i) || void 0
23025
- });
23026
- }
23027
- let maxX = 0;
23028
- let maxY = 0;
23029
- for (const node of layoutNodes) {
23030
- maxX = Math.max(maxX, node.x + node.width / 2);
23031
- maxY = Math.max(maxY, node.y + node.height / 2);
23032
- }
23033
- for (const group of layoutGroups) {
23034
- maxX = Math.max(maxX, group.x + group.width / 2);
23035
- maxY = Math.max(maxY, group.y + group.height / 2);
23036
- }
23037
- return {
23038
- nodes: layoutNodes,
23039
- edges: layoutEdges,
23040
- groups: layoutGroups,
23041
- width: maxX + MARGIN3,
23042
- height: maxY + MARGIN3
23043
- };
23044
- }
23045
- var import_dagre4, 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;
23046
- var init_layout5 = __esm({
23047
- "src/boxes-and-lines/layout.ts"() {
23048
- "use strict";
23049
- import_dagre4 = __toESM(require("@dagrejs/dagre"), 1);
23050
- NODESEP = 60;
23051
- RANKSEP = 100;
23052
- MARGIN3 = 40;
23053
- CONTAINER_PAD_X3 = 30;
23054
- CONTAINER_PAD_TOP2 = 40;
23055
- CONTAINER_PAD_BOTTOM3 = 24;
23056
- MAX_PARALLEL_EDGES = 5;
23057
- PARALLEL_SPACING = 22;
23058
- PHI = 1.618;
23059
- NODE_HEIGHT = 60;
23060
- NODE_WIDTH = Math.round(NODE_HEIGHT * PHI);
23061
- DESC_NODE_WIDTH = 140;
23062
- DESC_FONT_SIZE = 10;
23063
- DESC_LINE_HEIGHT = 1.4;
23064
- DESC_PADDING = 8;
23065
- SEPARATOR_GAP5 = 4;
23066
- MAX_DESC_LINES = 6;
23067
- MAX_LABEL_LINES = 3;
23068
- LABEL_LINE_HEIGHT = 1.3;
23069
- LABEL_PAD = 12;
23070
- }
23071
- });
23072
-
23073
22572
  // src/utils/wrapped-desc.ts
23074
22573
  function wrapDescriptionLines(lines, charsPerLine, lengthFn = (s) => s.length) {
23075
22574
  const result = [];
@@ -23119,7 +22618,7 @@ __export(renderer_exports6, {
23119
22618
  renderBoxesAndLines: () => renderBoxesAndLines,
23120
22619
  renderBoxesAndLinesForExport: () => renderBoxesAndLinesForExport
23121
22620
  });
23122
- function splitCamelCase2(word) {
22621
+ function splitCamelCase(word) {
23123
22622
  const parts = [];
23124
22623
  let start = 0;
23125
22624
  for (let i = 1; i < word.length; i++) {
@@ -23142,7 +22641,7 @@ function fitLabelToHeader(label, nodeWidth2, maxLines) {
23142
22641
  const words = [];
23143
22642
  for (const part of rawParts) {
23144
22643
  if (!part || /^\s+$/.test(part) || part === "-") continue;
23145
- words.push(...splitCamelCase2(part));
22644
+ words.push(...splitCamelCase(part));
23146
22645
  }
23147
22646
  for (let fontSize = NODE_FONT_SIZE; fontSize >= MIN_NODE_FONT_SIZE; fontSize--) {
23148
22647
  const charWidth2 = fontSize * CHAR_WIDTH_RATIO2;
@@ -23518,12 +23017,12 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
23518
23017
  }
23519
23018
  const sepY = -ln.height / 2 + headerH;
23520
23019
  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);
23521
- const descStartY = sepY + 4 + DESC_FONT_SIZE2;
23020
+ const descStartY = sepY + 4 + DESC_FONT_SIZE;
23522
23021
  const maxTextWidth = ln.width - NODE_TEXT_PADDING * 2;
23523
23022
  const charsPerLine = Math.floor(
23524
- maxTextWidth / (DESC_FONT_SIZE2 * CHAR_WIDTH_RATIO2)
23023
+ maxTextWidth / (DESC_FONT_SIZE * CHAR_WIDTH_RATIO2)
23525
23024
  );
23526
- const descLineH = DESC_FONT_SIZE2 * DESC_LINE_HEIGHT2;
23025
+ const descLineH = DESC_FONT_SIZE * DESC_LINE_HEIGHT;
23527
23026
  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;
23528
23027
  const normalizedLines = [];
23529
23028
  for (const descLine of desc) {
@@ -23539,8 +23038,8 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
23539
23038
  charsPerLine,
23540
23039
  displayLen
23541
23040
  );
23542
- const truncated = wrappedLinesShared.length > MAX_DESC_LINES2;
23543
- const visibleLines = truncated ? wrappedLinesShared.slice(0, MAX_DESC_LINES2) : wrappedLinesShared;
23041
+ const truncated = wrappedLinesShared.length > MAX_DESC_LINES;
23042
+ const visibleLines = truncated ? wrappedLinesShared.slice(0, MAX_DESC_LINES) : wrappedLinesShared;
23544
23043
  const BULLET_GLYPH_X = -ln.width / 2 + 6;
23545
23044
  const BULLET_BODY_X = BULLET_GLYPH_X + 10;
23546
23045
  for (let li = 0; li < visibleLines.length; li++) {
@@ -23551,11 +23050,11 @@ function renderBoxesAndLines(container, parsed, layout, palette, isDark, options
23551
23050
  }
23552
23051
  const y2 = descStartY + li * descLineH;
23553
23052
  if (line12.kind === "bullet-first") {
23554
- 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");
23053
+ 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");
23555
23054
  }
23556
23055
  const isBullet = line12.kind === "bullet-first" || line12.kind === "bullet-cont";
23557
- 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);
23558
- renderInlineText(textEl, lineText, palette, DESC_FONT_SIZE2);
23056
+ 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);
23057
+ renderInlineText(textEl, lineText, palette, DESC_FONT_SIZE);
23559
23058
  }
23560
23059
  if (truncated) {
23561
23060
  const fullText = desc.join(" ");
@@ -23633,7 +23132,7 @@ function renderBoxesAndLinesForExport(container, parsed, layout, palette, isDark
23633
23132
  hiddenTagValues: options?.hiddenTagValues
23634
23133
  });
23635
23134
  }
23636
- var d3Selection6, d3Shape4, 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;
23135
+ var d3Selection6, d3Shape4, 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;
23637
23136
  var init_renderer6 = __esm({
23638
23137
  "src/boxes-and-lines/renderer.ts"() {
23639
23138
  "use strict";
@@ -23657,9 +23156,9 @@ var init_renderer6 = __esm({
23657
23156
  COLLAPSE_BAR_HEIGHT3 = 4;
23658
23157
  ARROWHEAD_W2 = 5;
23659
23158
  ARROWHEAD_H2 = 4;
23660
- DESC_FONT_SIZE2 = 10;
23661
- DESC_LINE_HEIGHT2 = 1.4;
23662
- MAX_DESC_LINES2 = 6;
23159
+ DESC_FONT_SIZE = 10;
23160
+ DESC_LINE_HEIGHT = 1.4;
23161
+ MAX_DESC_LINES = 6;
23663
23162
  CHAR_WIDTH_RATIO2 = 0.6;
23664
23163
  NODE_TEXT_PADDING = 12;
23665
23164
  GROUP_RX = 8;
@@ -23670,6 +23169,523 @@ var init_renderer6 = __esm({
23670
23169
  }
23671
23170
  });
23672
23171
 
23172
+ // src/boxes-and-lines/layout.ts
23173
+ var layout_exports5 = {};
23174
+ __export(layout_exports5, {
23175
+ layoutBoxesAndLines: () => layoutBoxesAndLines
23176
+ });
23177
+ function splitCamelCase2(word) {
23178
+ const parts = [];
23179
+ let start = 0;
23180
+ for (let i = 1; i < word.length; i++) {
23181
+ const prev = word[i - 1];
23182
+ const curr = word[i];
23183
+ const next = i + 1 < word.length ? word[i + 1] : "";
23184
+ const lowerToUpper = prev >= "a" && prev <= "z" && curr >= "A" && curr <= "Z";
23185
+ const upperRunEnd = prev >= "A" && prev <= "Z" && curr >= "A" && curr <= "Z" && next >= "a" && next <= "z";
23186
+ if (lowerToUpper || upperRunEnd) {
23187
+ parts.push(word.slice(start, i));
23188
+ start = i;
23189
+ }
23190
+ }
23191
+ parts.push(word.slice(start));
23192
+ return parts.length > 1 ? parts : [word];
23193
+ }
23194
+ function estimateLabelLines(label, nodeWidth2 = NODE_WIDTH) {
23195
+ const rawParts = label.split(/[\s-]+/);
23196
+ const words = [];
23197
+ for (const part of rawParts) {
23198
+ if (!part) continue;
23199
+ words.push(...splitCamelCase2(part));
23200
+ }
23201
+ for (let fontSize = 13; fontSize >= 9; fontSize--) {
23202
+ const charWidth = fontSize * 0.6;
23203
+ const maxChars = Math.floor((nodeWidth2 - 24) / charWidth);
23204
+ if (maxChars < 2) continue;
23205
+ let lines = 1;
23206
+ let current = "";
23207
+ for (const word of words) {
23208
+ const test = current ? `${current} ${word}` : word;
23209
+ if (test.length <= maxChars) {
23210
+ current = test;
23211
+ } else {
23212
+ lines++;
23213
+ current = word;
23214
+ }
23215
+ }
23216
+ if (lines <= MAX_LABEL_LINES) return Math.min(lines, MAX_LABEL_LINES);
23217
+ }
23218
+ return MAX_LABEL_LINES;
23219
+ }
23220
+ function computeNodeSize(node) {
23221
+ if (!node.description || node.description.length === 0) {
23222
+ return { width: NODE_WIDTH, height: NODE_HEIGHT };
23223
+ }
23224
+ const w = DESC_NODE_WIDTH;
23225
+ const labelLines = estimateLabelLines(node.label, w);
23226
+ const labelHeight = labelLines * 13 * LABEL_LINE_HEIGHT + LABEL_PAD;
23227
+ const charsPerLine = Math.floor((w - 24) / (DESC_FONT_SIZE2 * 0.6));
23228
+ let totalRenderedLines = 0;
23229
+ for (const line12 of node.description) {
23230
+ if (line12.length <= charsPerLine) {
23231
+ totalRenderedLines += 1;
23232
+ } else {
23233
+ const words = line12.split(/\s+/);
23234
+ let current = "";
23235
+ let lineCount = 0;
23236
+ for (const word of words) {
23237
+ const fitted = word.length > charsPerLine ? word.slice(0, charsPerLine) : word;
23238
+ const test = current ? `${current} ${fitted}` : fitted;
23239
+ if (test.length <= charsPerLine) {
23240
+ current = test;
23241
+ } else {
23242
+ if (current) lineCount++;
23243
+ current = fitted;
23244
+ }
23245
+ }
23246
+ if (current) lineCount++;
23247
+ totalRenderedLines += lineCount;
23248
+ }
23249
+ }
23250
+ totalRenderedLines = Math.min(totalRenderedLines, MAX_DESC_LINES2);
23251
+ const descriptionHeight = totalRenderedLines * DESC_FONT_SIZE2 * DESC_LINE_HEIGHT2;
23252
+ const totalHeight = labelHeight + SEPARATOR_GAP5 + DESC_PADDING + descriptionHeight + DESC_PADDING;
23253
+ return { width: w, height: Math.max(NODE_HEIGHT, totalHeight) };
23254
+ }
23255
+ function getElk() {
23256
+ if (!elkInstance) elkInstance = new import_elk_bundled.default();
23257
+ return elkInstance;
23258
+ }
23259
+ function baseOptions() {
23260
+ return {
23261
+ "elk.algorithm": "layered",
23262
+ // INCLUDE_CHILDREN lets ELK route edges across container boundaries.
23263
+ "elk.hierarchyHandling": "INCLUDE_CHILDREN",
23264
+ "elk.edgeRouting": "ORTHOGONAL",
23265
+ "elk.layered.unnecessaryBendpoints": "true",
23266
+ // Let edges leave from top/bottom of nodes (not just the flow-direction
23267
+ // sides) when it reduces crossings.
23268
+ "elk.layered.allowNonFlowPortsToSwitchSides": "true"
23269
+ };
23270
+ }
23271
+ function bkBaseline() {
23272
+ return {
23273
+ ...baseOptions(),
23274
+ "elk.layered.nodePlacement.strategy": "BRANDES_KOEPF",
23275
+ "elk.layered.nodePlacement.bk.fixedAlignment": "BALANCED",
23276
+ "elk.layered.nodePlacement.bk.edgeStraightening": "IMPROVE_STRAIGHTNESS",
23277
+ "elk.layered.compaction.connectedComponents": "true",
23278
+ "elk.layered.spacing.nodeNodeBetweenLayers": "90",
23279
+ "elk.spacing.nodeNode": "55",
23280
+ "elk.spacing.edgeNode": "55",
23281
+ "elk.spacing.edgeEdge": "18"
23282
+ };
23283
+ }
23284
+ function getVariants() {
23285
+ const bk = bkBaseline();
23286
+ return [
23287
+ {
23288
+ name: "bk-baseline",
23289
+ options: {
23290
+ ...bk,
23291
+ "elk.layered.crossingMinimization.greedySwitch.type": "ONE_SIDED"
23292
+ }
23293
+ },
23294
+ {
23295
+ name: "bk-aggressive",
23296
+ options: {
23297
+ ...bk,
23298
+ "elk.layered.crossingMinimization.greedySwitch.type": "TWO_SIDED",
23299
+ "elk.layered.thoroughness": "50"
23300
+ }
23301
+ },
23302
+ {
23303
+ name: "bk-wide",
23304
+ options: {
23305
+ ...bk,
23306
+ "elk.layered.crossingMinimization.greedySwitch.type": "TWO_SIDED",
23307
+ "elk.layered.thoroughness": "50",
23308
+ "elk.spacing.nodeNode": "70",
23309
+ "elk.spacing.edgeNode": "75",
23310
+ "elk.spacing.edgeEdge": "22",
23311
+ "elk.layered.spacing.nodeNodeBetweenLayers": "120"
23312
+ }
23313
+ },
23314
+ {
23315
+ name: "longest-path",
23316
+ options: {
23317
+ ...bk,
23318
+ "elk.layered.layering.strategy": "LONGEST_PATH",
23319
+ "elk.layered.crossingMinimization.greedySwitch.type": "TWO_SIDED",
23320
+ "elk.layered.thoroughness": "50"
23321
+ }
23322
+ },
23323
+ {
23324
+ name: "bounded-width",
23325
+ options: {
23326
+ ...bk,
23327
+ "elk.layered.layering.strategy": "COFFMAN_GRAHAM",
23328
+ "elk.layered.layering.coffmanGraham.layerBound": "3",
23329
+ "elk.layered.crossingMinimization.greedySwitch.type": "TWO_SIDED",
23330
+ "elk.layered.thoroughness": "50"
23331
+ }
23332
+ }
23333
+ ];
23334
+ }
23335
+ function countCrossings(edges) {
23336
+ let count = 0;
23337
+ for (let i = 0; i < edges.length; i++) {
23338
+ const a = edges[i].points;
23339
+ if (a.length < 2) continue;
23340
+ for (let j = i + 1; j < edges.length; j++) {
23341
+ const b = edges[j].points;
23342
+ if (b.length < 2) continue;
23343
+ if (edges[i].source === edges[j].source) continue;
23344
+ if (edges[i].source === edges[j].target) continue;
23345
+ if (edges[i].target === edges[j].source) continue;
23346
+ if (edges[i].target === edges[j].target) continue;
23347
+ for (let ai = 0; ai < a.length - 1; ai++) {
23348
+ for (let bi = 0; bi < b.length - 1; bi++) {
23349
+ if (segmentsCross(a[ai], a[ai + 1], b[bi], b[bi + 1])) count++;
23350
+ }
23351
+ }
23352
+ }
23353
+ }
23354
+ return count;
23355
+ }
23356
+ function segmentsCross(p1, p2, p3, p4) {
23357
+ const d1x = p2.x - p1.x;
23358
+ const d1y = p2.y - p1.y;
23359
+ const d2x = p4.x - p3.x;
23360
+ const d2y = p4.y - p3.y;
23361
+ const denom = d1x * d2y - d1y * d2x;
23362
+ if (Math.abs(denom) < 1e-9) return false;
23363
+ const t = ((p3.x - p1.x) * d2y - (p3.y - p1.y) * d2x) / denom;
23364
+ const s = ((p3.x - p1.x) * d1y - (p3.y - p1.y) * d1x) / denom;
23365
+ const EPS = 1e-3;
23366
+ return t > EPS && t < 1 - EPS && s > EPS && s < 1 - EPS;
23367
+ }
23368
+ function countTotalBends(edges) {
23369
+ let bends = 0;
23370
+ for (const e of edges) bends += Math.max(0, e.points.length - 2);
23371
+ return bends;
23372
+ }
23373
+ function scoreLayout(layout) {
23374
+ return {
23375
+ crossings: countCrossings(layout.edges),
23376
+ bends: countTotalBends(layout.edges),
23377
+ area: layout.width * layout.height
23378
+ };
23379
+ }
23380
+ function cmpScore(a, b) {
23381
+ const aBucket = a.crossings <= CROSSINGS_FORGIVENESS ? 0 : a.crossings;
23382
+ const bBucket = b.crossings <= CROSSINGS_FORGIVENESS ? 0 : b.crossings;
23383
+ if (aBucket !== bBucket) return aBucket - bBucket;
23384
+ if (a.area !== b.area) return a.area - b.area;
23385
+ return a.bends - b.bends;
23386
+ }
23387
+ async function layoutBoxesAndLines(parsed, collapseInfo, layoutOptions) {
23388
+ const hideDescriptions = layoutOptions?.hideDescriptions ?? false;
23389
+ const direction = parsed.direction === "TB" ? "DOWN" : "RIGHT";
23390
+ const collapsedGroupLabels = /* @__PURE__ */ new Set();
23391
+ if (collapseInfo) {
23392
+ const missingGroups = /* @__PURE__ */ new Set();
23393
+ for (const og of collapseInfo.originalGroups) {
23394
+ if (!parsed.groups.some((g) => g.label === og.label)) {
23395
+ missingGroups.add(og.label);
23396
+ }
23397
+ }
23398
+ for (const label of missingGroups) {
23399
+ const og = collapseInfo.originalGroups.find((g) => g.label === label);
23400
+ const parentLabel = og?.parentGroup;
23401
+ if (!parentLabel || !missingGroups.has(parentLabel)) {
23402
+ collapsedGroupLabels.add(label);
23403
+ }
23404
+ }
23405
+ }
23406
+ const nodeSizes = /* @__PURE__ */ new Map();
23407
+ let maxDescHeight = 0;
23408
+ for (const node of parsed.nodes) {
23409
+ const size = hideDescriptions ? { width: NODE_WIDTH, height: NODE_HEIGHT } : computeNodeSize(node);
23410
+ nodeSizes.set(node.label, size);
23411
+ if (!hideDescriptions && node.description && node.description.length > 0) {
23412
+ maxDescHeight = Math.max(maxDescHeight, size.height);
23413
+ }
23414
+ }
23415
+ if (maxDescHeight > 0) {
23416
+ for (const node of parsed.nodes) {
23417
+ if (node.description && node.description.length > 0) {
23418
+ const size = nodeSizes.get(node.label);
23419
+ nodeSizes.set(node.label, { width: size.width, height: maxDescHeight });
23420
+ }
23421
+ }
23422
+ }
23423
+ const expandedGroupSet = new Set(parsed.groups.map((g) => g.label));
23424
+ const gid = (label) => `__group_${label}`;
23425
+ function buildGraph() {
23426
+ const nodeById = /* @__PURE__ */ new Map();
23427
+ const parentOf = /* @__PURE__ */ new Map();
23428
+ for (const node of parsed.nodes) {
23429
+ const size = nodeSizes.get(node.label);
23430
+ nodeById.set(node.label, {
23431
+ id: node.label,
23432
+ width: size.width,
23433
+ height: size.height,
23434
+ labels: [{ text: node.label }]
23435
+ });
23436
+ }
23437
+ for (const group of parsed.groups) {
23438
+ nodeById.set(gid(group.label), {
23439
+ id: gid(group.label),
23440
+ labels: [{ text: group.label }],
23441
+ layoutOptions: {
23442
+ "elk.padding": `[top=${CONTAINER_PAD_TOP2},left=${CONTAINER_PAD_X3},bottom=${CONTAINER_PAD_BOTTOM3},right=${CONTAINER_PAD_X3}]`,
23443
+ // Suggest square-ish containers — has limited effect with
23444
+ // INCLUDE_CHILDREN but doesn't hurt.
23445
+ "elk.aspectRatio": "1.4"
23446
+ },
23447
+ children: [],
23448
+ edges: []
23449
+ });
23450
+ }
23451
+ for (const label of collapsedGroupLabels) {
23452
+ nodeById.set(gid(label), {
23453
+ id: gid(label),
23454
+ width: NODE_WIDTH,
23455
+ height: NODE_HEIGHT,
23456
+ labels: [{ text: label }]
23457
+ });
23458
+ }
23459
+ for (const group of parsed.groups) {
23460
+ if (group.parentGroup && nodeById.has(gid(group.parentGroup))) {
23461
+ parentOf.set(gid(group.label), gid(group.parentGroup));
23462
+ }
23463
+ }
23464
+ if (collapseInfo) {
23465
+ for (const label of collapsedGroupLabels) {
23466
+ const og = collapseInfo.originalGroups.find((g) => g.label === label);
23467
+ if (og?.parentGroup && !collapsedGroupLabels.has(og.parentGroup) && nodeById.has(gid(og.parentGroup))) {
23468
+ parentOf.set(gid(label), gid(og.parentGroup));
23469
+ }
23470
+ }
23471
+ }
23472
+ for (const group of parsed.groups) {
23473
+ for (const child of group.children) {
23474
+ if (expandedGroupSet.has(child)) continue;
23475
+ if (nodeById.has(child)) {
23476
+ parentOf.set(child, gid(group.label));
23477
+ }
23478
+ }
23479
+ }
23480
+ const roots = [];
23481
+ for (const [id, node] of nodeById) {
23482
+ const parentId = parentOf.get(id);
23483
+ if (parentId) {
23484
+ const parent = nodeById.get(parentId);
23485
+ parent.children = parent.children ?? [];
23486
+ parent.children.push(node);
23487
+ } else {
23488
+ roots.push(node);
23489
+ }
23490
+ }
23491
+ const rootEdges = [];
23492
+ for (let i = 0; i < parsed.edges.length; i++) {
23493
+ const edge = parsed.edges[i];
23494
+ if (!nodeById.has(edge.source) || !nodeById.has(edge.target)) continue;
23495
+ rootEdges.push({
23496
+ id: `e${i}`,
23497
+ sources: [edge.source],
23498
+ targets: [edge.target]
23499
+ });
23500
+ }
23501
+ return { roots, rootEdges };
23502
+ }
23503
+ async function runVariant(variant) {
23504
+ const { roots, rootEdges } = buildGraph();
23505
+ const elkRoot = {
23506
+ id: "root",
23507
+ layoutOptions: {
23508
+ ...variant.options,
23509
+ "elk.direction": direction,
23510
+ "elk.padding": `[top=${MARGIN3},left=${MARGIN3},bottom=${MARGIN3},right=${MARGIN3}]`
23511
+ },
23512
+ children: roots,
23513
+ edges: rootEdges
23514
+ };
23515
+ const result = await getElk().layout(elkRoot);
23516
+ return extractLayout(result);
23517
+ }
23518
+ function extractLayout(result) {
23519
+ const layoutNodes = [];
23520
+ const layoutGroups = [];
23521
+ const allEdges = [];
23522
+ const containerAbs = /* @__PURE__ */ new Map();
23523
+ function walk(n, offsetX, offsetY, isRoot) {
23524
+ const nx = (n.x ?? 0) + offsetX;
23525
+ const ny = (n.y ?? 0) + offsetY;
23526
+ const nw = n.width ?? 0;
23527
+ const nh = n.height ?? 0;
23528
+ if (isRoot) {
23529
+ containerAbs.set("root", { x: nx, y: ny });
23530
+ } else {
23531
+ const isGroup = n.id.startsWith("__group_");
23532
+ if (isGroup) {
23533
+ const label = n.id.slice("__group_".length);
23534
+ const collapsed = collapsedGroupLabels.has(label);
23535
+ const og = collapseInfo?.originalGroups.find(
23536
+ (g) => g.label === label
23537
+ );
23538
+ const pg = parsed.groups.find((g) => g.label === label);
23539
+ layoutGroups.push({
23540
+ label,
23541
+ lineNumber: pg?.lineNumber ?? og?.lineNumber ?? 0,
23542
+ x: nx + nw / 2,
23543
+ y: ny + nh / 2,
23544
+ width: nw,
23545
+ height: nh,
23546
+ collapsed,
23547
+ childCount: collapsed ? collapseInfo?.collapsedChildCounts.get(label) ?? 0 : void 0
23548
+ });
23549
+ if (!collapsed) containerAbs.set(n.id, { x: nx, y: ny });
23550
+ } else {
23551
+ layoutNodes.push({
23552
+ label: n.id,
23553
+ x: nx + nw / 2,
23554
+ y: ny + nh / 2,
23555
+ width: nw,
23556
+ height: nh
23557
+ });
23558
+ }
23559
+ }
23560
+ if (n.edges) for (const e of n.edges) allEdges.push(e);
23561
+ if (n.children) for (const c of n.children) walk(c, nx, ny, false);
23562
+ }
23563
+ walk(result, 0, 0, true);
23564
+ const edgeYOffsets = new Array(parsed.edges.length).fill(0);
23565
+ const edgeParallelCounts = new Array(parsed.edges.length).fill(1);
23566
+ const parallelGroups = /* @__PURE__ */ new Map();
23567
+ for (let i = 0; i < parsed.edges.length; i++) {
23568
+ const edge = parsed.edges[i];
23569
+ const [a, b] = edge.source < edge.target ? [edge.source, edge.target] : [edge.target, edge.source];
23570
+ const key = `${a}\0${b}`;
23571
+ if (!parallelGroups.has(key)) parallelGroups.set(key, []);
23572
+ parallelGroups.get(key).push(i);
23573
+ }
23574
+ for (const group of parallelGroups.values()) {
23575
+ const capped = group.slice(0, MAX_PARALLEL_EDGES);
23576
+ for (const idx of group.slice(MAX_PARALLEL_EDGES)) {
23577
+ edgeParallelCounts[idx] = 0;
23578
+ }
23579
+ if (capped.length < 2) continue;
23580
+ for (let j = 0; j < capped.length; j++) {
23581
+ edgeYOffsets[capped[j]] = (j - (capped.length - 1) / 2) * PARALLEL_SPACING;
23582
+ edgeParallelCounts[capped[j]] = capped.length;
23583
+ }
23584
+ }
23585
+ const edgeById = /* @__PURE__ */ new Map();
23586
+ for (const e of allEdges) edgeById.set(e.id, e);
23587
+ const layoutEdges = [];
23588
+ for (let i = 0; i < parsed.edges.length; i++) {
23589
+ const edge = parsed.edges[i];
23590
+ if (edgeParallelCounts[i] === 0) continue;
23591
+ const elkEdge = edgeById.get(`e${i}`);
23592
+ if (!elkEdge || !elkEdge.sections || elkEdge.sections.length === 0)
23593
+ continue;
23594
+ const container = elkEdge.container ?? "root";
23595
+ const off = containerAbs.get(container) ?? { x: 0, y: 0 };
23596
+ const s = elkEdge.sections[0];
23597
+ const points = [
23598
+ { x: s.startPoint.x + off.x, y: s.startPoint.y + off.y },
23599
+ ...(s.bendPoints ?? []).map((p) => ({
23600
+ x: p.x + off.x,
23601
+ y: p.y + off.y
23602
+ })),
23603
+ { x: s.endPoint.x + off.x, y: s.endPoint.y + off.y }
23604
+ ];
23605
+ let labelX;
23606
+ let labelY;
23607
+ if (edge.label && points.length >= 2) {
23608
+ const mid = Math.floor(points.length / 2);
23609
+ labelX = points[mid].x;
23610
+ labelY = points[mid].y - 10;
23611
+ }
23612
+ layoutEdges.push({
23613
+ source: edge.source,
23614
+ target: edge.target,
23615
+ label: edge.label,
23616
+ bidirectional: edge.bidirectional,
23617
+ lineNumber: edge.lineNumber,
23618
+ points,
23619
+ labelX,
23620
+ labelY,
23621
+ yOffset: edgeYOffsets[i],
23622
+ parallelCount: edgeParallelCounts[i],
23623
+ metadata: edge.metadata,
23624
+ deferred: true
23625
+ });
23626
+ }
23627
+ let maxX = 0;
23628
+ let maxY = 0;
23629
+ for (const node of layoutNodes) {
23630
+ maxX = Math.max(maxX, node.x + node.width / 2);
23631
+ maxY = Math.max(maxY, node.y + node.height / 2);
23632
+ }
23633
+ for (const group of layoutGroups) {
23634
+ maxX = Math.max(maxX, group.x + group.width / 2);
23635
+ maxY = Math.max(maxY, group.y + group.height / 2);
23636
+ }
23637
+ return {
23638
+ nodes: layoutNodes,
23639
+ edges: layoutEdges,
23640
+ groups: layoutGroups,
23641
+ width: maxX + MARGIN3,
23642
+ height: maxY + MARGIN3
23643
+ };
23644
+ }
23645
+ const N = parsed.nodes.length + parsed.groups.length;
23646
+ const E = parsed.edges.length;
23647
+ const trivial = N < 8 && E < 10;
23648
+ const variants = trivial ? [getVariants()[1]] : getVariants();
23649
+ const results = await Promise.all(variants.map((v) => runVariant(v)));
23650
+ let best = results[0];
23651
+ let bestScore = scoreLayout(best);
23652
+ for (let i = 1; i < results.length; i++) {
23653
+ const s = scoreLayout(results[i]);
23654
+ if (cmpScore(s, bestScore) < 0) {
23655
+ best = results[i];
23656
+ bestScore = s;
23657
+ }
23658
+ }
23659
+ return best;
23660
+ }
23661
+ var import_elk_bundled, 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;
23662
+ var init_layout5 = __esm({
23663
+ "src/boxes-and-lines/layout.ts"() {
23664
+ "use strict";
23665
+ import_elk_bundled = __toESM(require("elkjs/lib/elk.bundled.js"), 1);
23666
+ MARGIN3 = 40;
23667
+ CONTAINER_PAD_X3 = 30;
23668
+ CONTAINER_PAD_TOP2 = 40;
23669
+ CONTAINER_PAD_BOTTOM3 = 24;
23670
+ MAX_PARALLEL_EDGES = 5;
23671
+ PARALLEL_SPACING = 22;
23672
+ PHI = 1.618;
23673
+ NODE_HEIGHT = 60;
23674
+ NODE_WIDTH = Math.round(NODE_HEIGHT * PHI);
23675
+ DESC_NODE_WIDTH = 140;
23676
+ DESC_FONT_SIZE2 = 10;
23677
+ DESC_LINE_HEIGHT2 = 1.4;
23678
+ DESC_PADDING = 8;
23679
+ SEPARATOR_GAP5 = 4;
23680
+ MAX_DESC_LINES2 = 6;
23681
+ MAX_LABEL_LINES = 3;
23682
+ LABEL_LINE_HEIGHT = 1.3;
23683
+ LABEL_PAD = 12;
23684
+ elkInstance = null;
23685
+ CROSSINGS_FORGIVENESS = 1;
23686
+ }
23687
+ });
23688
+
23673
23689
  // src/mindmap/text-wrap.ts
23674
23690
  function tokenize(text) {
23675
23691
  const tokens = [];
@@ -23808,7 +23824,7 @@ var layout_exports6 = {};
23808
23824
  __export(layout_exports6, {
23809
23825
  layoutMindmap: () => layoutMindmap
23810
23826
  });
23811
- function layoutMindmap(parsed, palette, options) {
23827
+ function layoutMindmap(parsed, _palette, options) {
23812
23828
  const roots = parsed.roots;
23813
23829
  if (roots.length === 0) {
23814
23830
  return { nodes: [], edges: [], width: 0, height: 0 };
@@ -24704,7 +24720,7 @@ function layoutElement(el, x, y, width) {
24704
24720
  node.height = getElementHeight(el);
24705
24721
  return node;
24706
24722
  }
24707
- const isInlineRow = el.metadata._inlineRow === "true" || el.metadata._labelField === "true";
24723
+ const isInlineRow = el.metadata["_inlineRow"] === "true" || el.metadata["_labelField"] === "true";
24708
24724
  const padTop = isInlineRow ? 0 : GROUP_PADDING_TOP;
24709
24725
  const padBottom = isInlineRow ? 0 : GROUP_PADDING_BOTTOM;
24710
24726
  const padX = isInlineRow ? 0 : GROUP_PADDING_X;
@@ -24753,7 +24769,7 @@ function allocateEqualWidths(children, totalWidth) {
24753
24769
  }
24754
24770
  function getElementHeight(el) {
24755
24771
  if (el.type === "heading") {
24756
- return el.headingLevel === 2 ? ELEMENT_HEIGHTS.subheading ?? 36 : ELEMENT_HEIGHTS.heading ?? 48;
24772
+ return el.headingLevel === 2 ? ELEMENT_HEIGHTS["subheading"] ?? 36 : ELEMENT_HEIGHTS["heading"] ?? 48;
24757
24773
  }
24758
24774
  if (el.type === "textInput" && el.fieldVariant === "textarea") {
24759
24775
  return 80;
@@ -24767,16 +24783,16 @@ function getElementHeight(el) {
24767
24783
  if (el.type === "image") {
24768
24784
  if (el.imageHint === "round") return 80;
24769
24785
  if (el.imageHint === "wide") return 80;
24770
- return ELEMENT_HEIGHTS.image ?? 120;
24786
+ return ELEMENT_HEIGHTS["image"] ?? 120;
24771
24787
  }
24772
- if (el.metadata._labelField === "true") {
24788
+ if (el.metadata["_labelField"] === "true") {
24773
24789
  return 36;
24774
24790
  }
24775
24791
  return ELEMENT_HEIGHTS[el.type] ?? 24;
24776
24792
  }
24777
24793
  function getSpacingAfter(el) {
24778
24794
  if (el.type === "heading" && el.headingLevel === 2) {
24779
- return SPACING_AFTER.subheading ?? 12;
24795
+ return SPACING_AFTER["subheading"] ?? 12;
24780
24796
  }
24781
24797
  return SPACING_AFTER[el.type] ?? 8;
24782
24798
  }
@@ -24784,7 +24800,7 @@ function computeFieldAlignX(children) {
24784
24800
  let maxLabelWidth = 0;
24785
24801
  let labelFieldCount = 0;
24786
24802
  for (const child of children) {
24787
- if (child.metadata._labelField === "true" && child.children.length >= 2) {
24803
+ if (child.metadata["_labelField"] === "true" && child.children.length >= 2) {
24788
24804
  const labelEl = child.children[0];
24789
24805
  const labelWidth = labelEl.label.length * CHAR_WIDTH5;
24790
24806
  maxLabelWidth = Math.max(maxLabelWidth, labelWidth);
@@ -24995,7 +25011,7 @@ function renderNode(parent, node, ctx, depth) {
24995
25011
  function renderGroup(g, node, ctx, depth) {
24996
25012
  const { palette, isTransparent } = ctx;
24997
25013
  const el = node.element;
24998
- if (el.metadata._inlineRow === "true" || el.metadata._labelField === "true") {
25014
+ if (el.metadata["_inlineRow"] === "true" || el.metadata["_labelField"] === "true") {
24999
25015
  for (const child of node.children) {
25000
25016
  renderNode(g, child, ctx, depth);
25001
25017
  }
@@ -25123,7 +25139,7 @@ function renderDivider(g, node, ctx) {
25123
25139
  function renderText(g, node, ctx) {
25124
25140
  const { palette } = ctx;
25125
25141
  const el = node.element;
25126
- if (el.metadata._labelField === "true" && el.children.length >= 2) {
25142
+ if (el.metadata["_labelField"] === "true" && el.children.length >= 2) {
25127
25143
  for (const child of node.children) {
25128
25144
  renderNode(g, child, ctx, 0);
25129
25145
  }
@@ -25858,7 +25874,7 @@ function layoutC4Context(parsed, activeTagGroup) {
25858
25874
  }
25859
25875
  const contextRels = rollUpContextRelationships(parsed);
25860
25876
  const spacing = computeAdaptiveSpacing(contextRels);
25861
- const g = new import_dagre5.default.graphlib.Graph();
25877
+ const g = new import_dagre4.default.graphlib.Graph();
25862
25878
  g.setGraph({
25863
25879
  rankdir: "TB",
25864
25880
  nodesep: spacing.nodesep,
@@ -25879,7 +25895,7 @@ function layoutC4Context(parsed, activeTagGroup) {
25879
25895
  g.setEdge(rel.sourceName, rel.targetName, { label: rel.label ?? "" });
25880
25896
  }
25881
25897
  }
25882
- import_dagre5.default.layout(g);
25898
+ import_dagre4.default.layout(g);
25883
25899
  reduceCrossings(
25884
25900
  g,
25885
25901
  validRels.map((r) => ({ source: r.sourceName, target: r.targetName }))
@@ -26051,7 +26067,7 @@ function layoutC4Containers(parsed, systemName, activeTagGroup) {
26051
26067
  }
26052
26068
  }
26053
26069
  const hasGroups = elementToGroup.size > 0;
26054
- const g = hasGroups ? new import_dagre5.default.graphlib.Graph({ compound: true }) : new import_dagre5.default.graphlib.Graph();
26070
+ const g = hasGroups ? new import_dagre4.default.graphlib.Graph({ compound: true }) : new import_dagre4.default.graphlib.Graph();
26055
26071
  g.setDefaultEdgeLabel(() => ({}));
26056
26072
  if (hasGroups) {
26057
26073
  const seenGroups = /* @__PURE__ */ new Set();
@@ -26129,7 +26145,7 @@ function layoutC4Containers(parsed, systemName, activeTagGroup) {
26129
26145
  g.setEdge(rel.sourceName, rel.targetName, { label: rel.label ?? "" });
26130
26146
  }
26131
26147
  }
26132
- import_dagre5.default.layout(g);
26148
+ import_dagre4.default.layout(g);
26133
26149
  const nodeGroupMap = hasGroups ? new Map([...elementToGroup.entries()].map(([k, v]) => [k, v.name])) : void 0;
26134
26150
  reduceCrossings(
26135
26151
  g,
@@ -26455,7 +26471,7 @@ function layoutC4Components(parsed, systemName, containerName, activeTagGroup) {
26455
26471
  }
26456
26472
  }
26457
26473
  const hasGroups = elementToGroup.size > 0;
26458
- const g = hasGroups ? new import_dagre5.default.graphlib.Graph({ compound: true }) : new import_dagre5.default.graphlib.Graph();
26474
+ const g = hasGroups ? new import_dagre4.default.graphlib.Graph({ compound: true }) : new import_dagre4.default.graphlib.Graph();
26459
26475
  g.setDefaultEdgeLabel(() => ({}));
26460
26476
  if (hasGroups) {
26461
26477
  const seenGroups = /* @__PURE__ */ new Set();
@@ -26539,7 +26555,7 @@ function layoutC4Components(parsed, systemName, containerName, activeTagGroup) {
26539
26555
  g.setEdge(rel.sourceName, rel.targetName, { label: rel.label ?? "" });
26540
26556
  }
26541
26557
  }
26542
- import_dagre5.default.layout(g);
26558
+ import_dagre4.default.layout(g);
26543
26559
  const nodeGroupMap = hasGroups ? new Map([...elementToGroup.entries()].map(([k, v]) => [k, v.name])) : void 0;
26544
26560
  reduceCrossings(
26545
26561
  g,
@@ -26828,7 +26844,7 @@ function layoutC4Deployment(parsed, activeTagGroup) {
26828
26844
  for (const r of refEntries) {
26829
26845
  nameToElement.set(r.element.name, r.element);
26830
26846
  }
26831
- const g = new import_dagre5.default.graphlib.Graph({ compound: true });
26847
+ const g = new import_dagre4.default.graphlib.Graph({ compound: true });
26832
26848
  g.setDefaultEdgeLabel(() => ({}));
26833
26849
  for (const [infraId] of infraIds) {
26834
26850
  g.setNode(infraId, {});
@@ -26872,7 +26888,7 @@ function layoutC4Deployment(parsed, activeTagGroup) {
26872
26888
  g.setEdge(rel.sourceName, rel.targetName, { label: rel.label ?? "" });
26873
26889
  }
26874
26890
  }
26875
- import_dagre5.default.layout(g);
26891
+ import_dagre4.default.layout(g);
26876
26892
  const nodeInfraMap = /* @__PURE__ */ new Map();
26877
26893
  for (const r of refEntries) nodeInfraMap.set(r.element.name, r.infraId);
26878
26894
  reduceCrossings(
@@ -27050,11 +27066,11 @@ function layoutC4Deployment(parsed, activeTagGroup) {
27050
27066
  height: totalHeight
27051
27067
  };
27052
27068
  }
27053
- var import_dagre5, gNode, gEdge, CHAR_WIDTH6, MIN_NODE_WIDTH, MAX_NODE_WIDTH, TYPE_LABEL_HEIGHT, DIVIDER_GAP, NAME_HEIGHT, DESC_LINE_HEIGHT5, DESC_CHAR_WIDTH, CARD_V_PAD3, CARD_H_PAD3, META_LINE_HEIGHT5, META_CHAR_WIDTH, MARGIN5, BOUNDARY_PAD, GROUP_BOUNDARY_PAD, LEGEND_HEIGHT4, LEGEND_PILL_PAD4, LEGEND_DOT_R4, LEGEND_ENTRY_DOT_GAP4, LEGEND_ENTRY_TRAIL4, LEGEND_CAPSULE_PAD4, EDGE_NODE_COLLISION_WEIGHT, META_EXCLUDE_KEYS;
27069
+ var import_dagre4, gNode, gEdge, CHAR_WIDTH6, MIN_NODE_WIDTH, MAX_NODE_WIDTH, TYPE_LABEL_HEIGHT, DIVIDER_GAP, NAME_HEIGHT, DESC_LINE_HEIGHT5, DESC_CHAR_WIDTH, CARD_V_PAD3, CARD_H_PAD3, META_LINE_HEIGHT5, META_CHAR_WIDTH, MARGIN5, BOUNDARY_PAD, GROUP_BOUNDARY_PAD, LEGEND_HEIGHT4, LEGEND_PILL_PAD4, LEGEND_DOT_R4, LEGEND_ENTRY_DOT_GAP4, LEGEND_ENTRY_TRAIL4, LEGEND_CAPSULE_PAD4, EDGE_NODE_COLLISION_WEIGHT, META_EXCLUDE_KEYS;
27054
27070
  var init_layout8 = __esm({
27055
27071
  "src/c4/layout.ts"() {
27056
27072
  "use strict";
27057
- import_dagre5 = __toESM(require("@dagrejs/dagre"), 1);
27073
+ import_dagre4 = __toESM(require("@dagrejs/dagre"), 1);
27058
27074
  init_legend_constants();
27059
27075
  gNode = (g, name) => g.node(name);
27060
27076
  gEdge = (g, v, w) => g.edge(v, w);
@@ -28137,7 +28153,7 @@ function layoutGraph(graph, options) {
28137
28153
  if (allNodes.length === 0) {
28138
28154
  return { nodes: [], edges: [], groups: [], width: 0, height: 0 };
28139
28155
  }
28140
- const g = new import_dagre6.default.graphlib.Graph({ compound: true });
28156
+ const g = new import_dagre5.default.graphlib.Graph({ compound: true });
28141
28157
  g.setGraph({
28142
28158
  rankdir: graph.direction,
28143
28159
  nodesep: 50,
@@ -28173,7 +28189,7 @@ function layoutGraph(graph, options) {
28173
28189
  label: edge.label ?? ""
28174
28190
  });
28175
28191
  }
28176
- import_dagre6.default.layout(g);
28192
+ import_dagre5.default.layout(g);
28177
28193
  const collapsedGroupIds = collapsedChildCounts ? new Set(collapsedChildCounts.keys()) : /* @__PURE__ */ new Set();
28178
28194
  const layoutNodes = allNodes.map((node) => {
28179
28195
  const pos = g.node(node.id);
@@ -28290,11 +28306,11 @@ function layoutGraph(graph, options) {
28290
28306
  height: totalHeight
28291
28307
  };
28292
28308
  }
28293
- var import_dagre6, GROUP_PADDING;
28309
+ var import_dagre5, GROUP_PADDING;
28294
28310
  var init_layout9 = __esm({
28295
28311
  "src/graph/layout.ts"() {
28296
28312
  "use strict";
28297
- import_dagre6 = __toESM(require("@dagrejs/dagre"), 1);
28313
+ import_dagre5 = __toESM(require("@dagrejs/dagre"), 1);
28298
28314
  GROUP_PADDING = 20;
28299
28315
  }
28300
28316
  });
@@ -28606,7 +28622,7 @@ function renderFlowchart(container, graph, layout, palette, isDark, onClickItem,
28606
28622
  endTerminalIds.add(node.id);
28607
28623
  }
28608
28624
  }
28609
- const colorOff = graph.options?.color === "off";
28625
+ const colorOff = graph.options?.["color"] === "off";
28610
28626
  const solid = graph.options?.["solid-fill"] === "on";
28611
28627
  for (const node of layout.nodes) {
28612
28628
  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);
@@ -29839,7 +29855,7 @@ function layoutInfra(computed, expandedNodeIds, collapsedNodes) {
29839
29855
  };
29840
29856
  }
29841
29857
  const isLR = computed.direction !== "TB";
29842
- const g = new import_dagre7.default.graphlib.Graph();
29858
+ const g = new import_dagre6.default.graphlib.Graph();
29843
29859
  g.setGraph({
29844
29860
  rankdir: computed.direction === "TB" ? "TB" : "LR",
29845
29861
  nodesep: isLR ? 70 : 60,
@@ -29890,7 +29906,7 @@ function layoutInfra(computed, expandedNodeIds, collapsedNodes) {
29890
29906
  g.setEdge(edge.sourceId, edge.targetId, { label: edge.label });
29891
29907
  }
29892
29908
  }
29893
- import_dagre7.default.layout(g);
29909
+ import_dagre6.default.layout(g);
29894
29910
  const layoutNodes = computed.nodes.map((node) => {
29895
29911
  const pos = g.node(node.id);
29896
29912
  return {
@@ -30052,11 +30068,11 @@ function layoutInfra(computed, expandedNodeIds, collapsedNodes) {
30052
30068
  height: totalHeight
30053
30069
  };
30054
30070
  }
30055
- var import_dagre7, MIN_NODE_WIDTH2, NODE_HEADER_HEIGHT, META_LINE_HEIGHT7, NODE_SEPARATOR_GAP, NODE_PAD_BOTTOM, ROLE_DOT_ROW, COLLAPSE_BAR_HEIGHT5, CHAR_WIDTH7, META_CHAR_WIDTH3, PADDING_X3, GROUP_PADDING2, GROUP_HEADER_HEIGHT, EDGE_MARGIN, DISPLAY_KEYS, DISPLAY_NAMES, GROUP_GAP;
30071
+ var import_dagre6, MIN_NODE_WIDTH2, NODE_HEADER_HEIGHT, META_LINE_HEIGHT7, NODE_SEPARATOR_GAP, NODE_PAD_BOTTOM, ROLE_DOT_ROW, COLLAPSE_BAR_HEIGHT5, CHAR_WIDTH7, META_CHAR_WIDTH3, PADDING_X3, GROUP_PADDING2, GROUP_HEADER_HEIGHT, EDGE_MARGIN, DISPLAY_KEYS, DISPLAY_NAMES, GROUP_GAP;
30056
30072
  var init_layout10 = __esm({
30057
30073
  "src/infra/layout.ts"() {
30058
30074
  "use strict";
30059
- import_dagre7 = __toESM(require("@dagrejs/dagre"), 1);
30075
+ import_dagre6 = __toESM(require("@dagrejs/dagre"), 1);
30060
30076
  MIN_NODE_WIDTH2 = 140;
30061
30077
  NODE_HEADER_HEIGHT = 28;
30062
30078
  META_LINE_HEIGHT7 = 14;
@@ -30798,7 +30814,7 @@ function renderGroups(svg, groups, palette, _isDark) {
30798
30814
  }
30799
30815
  }
30800
30816
  }
30801
- function renderEdgePaths(svg, edges, nodes, groups, palette, isDark, animate, direction, speedMultiplier = 1) {
30817
+ function renderEdgePaths(svg, edges, nodes, groups, palette, _isDark, animate, direction, speedMultiplier = 1) {
30802
30818
  const nodeMap = new Map(nodes.map((n) => [n.id, n]));
30803
30819
  const maxRps = Math.max(...edges.map((e) => e.computedRps), 1);
30804
30820
  const { srcPts, tgtPts } = computePortPts(edges, nodeMap, direction);
@@ -30839,7 +30855,7 @@ function renderEdgePaths(svg, edges, nodes, groups, palette, isDark, animate, di
30839
30855
  }
30840
30856
  }
30841
30857
  }
30842
- function renderEdgeLabels(svg, edges, nodes, groups, palette, isDark, animate, direction) {
30858
+ function renderEdgeLabels(svg, edges, nodes, groups, palette, _isDark, animate, direction) {
30843
30859
  const nodeMap = new Map(nodes.map((n) => [n.id, n]));
30844
30860
  const { srcPts, tgtPts } = computePortPts(edges, nodeMap, direction);
30845
30861
  for (const edge of edges) {
@@ -31580,7 +31596,7 @@ function sampleBetaPert(o, m, p, rng) {
31580
31596
  const beta = 1 + 4 * (p - m) / range;
31581
31597
  return o + sampleBeta(alpha, beta, rng) * range;
31582
31598
  }
31583
- function simulate(resolved, expanded, predecessors, successors, topo, terminals, poisoned, opts) {
31599
+ function simulate(resolved, expanded, _predecessors, _successors, topo, terminals, poisoned, opts) {
31584
31600
  const rng = mulberry32(opts.seed);
31585
31601
  const expById = /* @__PURE__ */ new Map();
31586
31602
  for (const e of expanded) expById.set(e.id, e);
@@ -32703,7 +32719,7 @@ function relayoutPert(resolved, overrides, collapsedGroupIds = /* @__PURE__ */ n
32703
32719
  }
32704
32720
  }
32705
32721
  const dagreId = (id) => memberToGroup.get(id) ?? id;
32706
- const g = new import_dagre8.default.graphlib.Graph();
32722
+ const g = new import_dagre7.default.graphlib.Graph();
32707
32723
  g.setGraph({
32708
32724
  rankdir: resolved.options.direction,
32709
32725
  nodesep: 50,
@@ -32742,7 +32758,7 @@ function relayoutPert(resolved, overrides, collapsedGroupIds = /* @__PURE__ */ n
32742
32758
  seenEdges.add(k);
32743
32759
  g.setEdge(src, tgt, {});
32744
32760
  }
32745
- import_dagre8.default.layout(g);
32761
+ import_dagre7.default.layout(g);
32746
32762
  const swimApplied = applySwimLanes(
32747
32763
  g,
32748
32764
  resolved,
@@ -32862,7 +32878,7 @@ function relayoutPert(resolved, overrides, collapsedGroupIds = /* @__PURE__ */ n
32862
32878
  height: totalH + DIAGRAM_PADDING10
32863
32879
  };
32864
32880
  }
32865
- function applySwimLanes(g, resolved, memberToGroup, collapsedGroupIds) {
32881
+ function applySwimLanes(g, resolved, _memberToGroup, collapsedGroupIds) {
32866
32882
  const expanded = resolved.groups.filter(
32867
32883
  (rg) => !collapsedGroupIds.has(rg.group.id)
32868
32884
  );
@@ -33088,7 +33104,7 @@ function reduceCrossings2(g, direction) {
33088
33104
  buckets.get(key).push(id);
33089
33105
  }
33090
33106
  const edges = g.edges().map((e) => ({ v: e.v, w: e.w }));
33091
- const countCrossings = () => {
33107
+ const countCrossings2 = () => {
33092
33108
  let total = 0;
33093
33109
  for (let i = 0; i < edges.length; i++) {
33094
33110
  const a = edges[i];
@@ -33101,13 +33117,13 @@ function reduceCrossings2(g, direction) {
33101
33117
  const b1 = g.node(b.v);
33102
33118
  const b2 = g.node(b.w);
33103
33119
  if (!b1 || !b2) continue;
33104
- if (segmentsCross(a1, a2, b1, b2)) total++;
33120
+ if (segmentsCross2(a1, a2, b1, b2)) total++;
33105
33121
  }
33106
33122
  }
33107
33123
  return total;
33108
33124
  };
33109
33125
  const MAX_ITER = 8;
33110
- let baseline = countCrossings();
33126
+ let baseline = countCrossings2();
33111
33127
  if (baseline === 0) return;
33112
33128
  for (let iter = 0; iter < MAX_ITER; iter++) {
33113
33129
  let improved = false;
@@ -33125,7 +33141,7 @@ function reduceCrossings2(g, direction) {
33125
33141
  const bv = bn[slotAxis];
33126
33142
  an[slotAxis] = bv;
33127
33143
  bn[slotAxis] = av;
33128
- const after = countCrossings();
33144
+ const after = countCrossings2();
33129
33145
  if (after < baseline) {
33130
33146
  baseline = after;
33131
33147
  improved = true;
@@ -33146,7 +33162,7 @@ function reduceCrossings2(g, direction) {
33146
33162
  data.points = smoothEdge(src, tgt, direction);
33147
33163
  }
33148
33164
  }
33149
- function segmentsCross(a1, a2, b1, b2) {
33165
+ function segmentsCross2(a1, a2, b1, b2) {
33150
33166
  const ccw = (p, q, r) => (q.x - p.x) * (r.y - p.y) - (q.y - p.y) * (r.x - p.x);
33151
33167
  const d1 = ccw(b1, b2, a1);
33152
33168
  const d2 = ccw(b1, b2, a2);
@@ -33154,11 +33170,11 @@ function segmentsCross(a1, a2, b1, b2) {
33154
33170
  const d4 = ccw(a1, a2, b2);
33155
33171
  return (d1 > 0 && d2 < 0 || d1 < 0 && d2 > 0) && (d32 > 0 && d4 < 0 || d32 < 0 && d4 > 0);
33156
33172
  }
33157
- var import_dagre8, DEFAULT_NODE_HEIGHT, MILESTONE_NODE_HEIGHT, COLLAPSED_GROUP_HEIGHT, DIAGRAM_PADDING10, GROUP_PADDING3, GROUP_TOP_PADDING, SWIMLANE_SLOT_SEP, SWIMLANE_GAP, NODE_CELL_FONT_SIZE, NODE_NAME_FONT_SIZE, CELL_CHAR_WIDTH_RATIO, CELL_PAD_X, NAME_PAD_X, NAME_PIN_WIDTH, MIN_CELL_WIDTH, MIN_NODE_WIDTH3, MAX_NODE_WIDTH2, MIN_MILESTONE_WIDTH, MAX_MILESTONE_WIDTH;
33173
+ var import_dagre7, DEFAULT_NODE_HEIGHT, MILESTONE_NODE_HEIGHT, COLLAPSED_GROUP_HEIGHT, DIAGRAM_PADDING10, GROUP_PADDING3, GROUP_TOP_PADDING, SWIMLANE_SLOT_SEP, SWIMLANE_GAP, NODE_CELL_FONT_SIZE, NODE_NAME_FONT_SIZE, CELL_CHAR_WIDTH_RATIO, CELL_PAD_X, NAME_PAD_X, NAME_PIN_WIDTH, MIN_CELL_WIDTH, MIN_NODE_WIDTH3, MAX_NODE_WIDTH2, MIN_MILESTONE_WIDTH, MAX_MILESTONE_WIDTH;
33158
33174
  var init_layout11 = __esm({
33159
33175
  "src/pert/layout.ts"() {
33160
33176
  "use strict";
33161
- import_dagre8 = __toESM(require("@dagrejs/dagre"), 1);
33177
+ import_dagre7 = __toESM(require("@dagrejs/dagre"), 1);
33162
33178
  init_internal();
33163
33179
  DEFAULT_NODE_HEIGHT = 90;
33164
33180
  MILESTONE_NODE_HEIGHT = DEFAULT_NODE_HEIGHT;
@@ -35155,12 +35171,6 @@ function calculateSchedule(parsed) {
35155
35171
  const warn = (line12, message) => {
35156
35172
  diagnostics.push(makeDgmoError(line12, message, "warning"));
35157
35173
  };
35158
- const _fail = (line12, message) => {
35159
- const diag = makeDgmoError(line12, message);
35160
- diagnostics.push(diag);
35161
- result.error = formatDgmoError(diag);
35162
- return result;
35163
- };
35164
35174
  const holidaySet = buildHolidaySet(parsed.holidays);
35165
35175
  let projectStart;
35166
35176
  if (parsed.options.start) {
@@ -35185,7 +35195,6 @@ function calculateSchedule(parsed) {
35185
35195
  }
35186
35196
  buildImplicitDeps(parsed.nodes, taskMap);
35187
35197
  for (const task of allTasks2) {
35188
- const _node = taskMap.get(task.id);
35189
35198
  for (const dep of task.dependencies) {
35190
35199
  const resolved = resolveTaskName(dep.targetName, allTasks2);
35191
35200
  if (isResolverError(resolved)) {
@@ -36724,7 +36733,7 @@ function buildControlsToggles(hasCriticalPath, criticalPathActive, hasDependenci
36724
36733
  }
36725
36734
  return toggles;
36726
36735
  }
36727
- 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) {
36736
+ 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) {
36728
36737
  let visibleGroups;
36729
36738
  if (activeGroupName) {
36730
36739
  const activeGroup = tagGroups.filter(
@@ -37687,7 +37696,7 @@ function resolveTaskColor(rt, activeTagGroup, resolved, seriesColors2, palette)
37687
37696
  }
37688
37697
  return palette.accent || seriesColors2[0] || "#4a90d9";
37689
37698
  }
37690
- function renderTimeScaleHorizontal(g, scale, innerWidth, innerHeight, textColor) {
37699
+ function renderTimeScaleHorizontal(g, scale, _innerWidth, innerHeight, textColor) {
37691
37700
  const [domainMin, domainMax] = scale.domain();
37692
37701
  const ticks = computeTimeTicks(domainMin, domainMax, scale);
37693
37702
  if (ticks.length < 2) return;
@@ -37934,7 +37943,7 @@ function renderState(container, graph, layout, palette, isDark, onClickItem, exp
37934
37943
  for (const group of layout.groups) {
37935
37944
  if (group.collapsed) collapsedGroupIds.add(group.id);
37936
37945
  }
37937
- const colorOff = graph.options?.color === "off";
37946
+ const colorOff = graph.options?.["color"] === "off";
37938
37947
  const solid = graph.options?.["solid-fill"] === "on";
37939
37948
  for (const node of layout.nodes) {
37940
37949
  const isCollapsedGroup = collapsedGroupIds.has(node.id);
@@ -38334,7 +38343,7 @@ function renderQuadrantFocus(container, parsed, quadrantPosition, palette, isDar
38334
38343
  }
38335
38344
  }
38336
38345
  }
38337
- function renderQuarterCircle(svg, parsed, quadrant, qColor, palette, isDark, width, height, mutedColor, tooltip, rootContainer, onClickItem) {
38346
+ function renderQuarterCircle(svg, parsed, quadrant, qColor, palette, isDark, width, height, mutedColor, _tooltip, rootContainer, onClickItem) {
38338
38347
  const padding = 8;
38339
38348
  const size = Math.min(width - padding, height - padding);
38340
38349
  const maxRadius = size * 0.95;
@@ -39424,7 +39433,7 @@ function estimateListingHeight(parsed) {
39424
39433
  );
39425
39434
  return LISTING_LINE_HEIGHT * (maxBlipsInQuadrant + 1) + LISTING_LINE_HEIGHT + LISTING_TOP_MARGIN;
39426
39435
  }
39427
- function createBlipPopover(container, palette, isDark) {
39436
+ function createBlipPopover(container, _palette, isDark) {
39428
39437
  container.style.position = "relative";
39429
39438
  const existing = container.querySelector(
39430
39439
  "[data-blip-popover]"
@@ -41292,7 +41301,7 @@ function computeEdgeLabelPosition(midAngle, radius, cx, cy, lineCount, maxCharLe
41292
41301
  labelAngle: best.labelAngle
41293
41302
  };
41294
41303
  }
41295
- function fitToCanvas(nodes, edges, parsed, cx, cy, radius, width, height, _isClockwise) {
41304
+ function fitToCanvas(nodes, edges, parsed, _cx, _cy, radius, width, height, _isClockwise) {
41296
41305
  const PADDING3 = 30;
41297
41306
  let contentMinX = Infinity, contentMaxX = -Infinity;
41298
41307
  let contentMinY = Infinity, contentMaxY = -Infinity;
@@ -42801,7 +42810,7 @@ function renderPhaseBar(svg, phase, x, y, width, palette, collapsed, autoColor,
42801
42810
  });
42802
42811
  }
42803
42812
  }
42804
- function renderTaskRow(svg, task, parsed, x, y, labelW, roleX, roleColW, palette, surfaceBg, solid, taskDiagnostics, hasAnyDiagnostic, rowContent, onClickLine, _onMarkerDragStart) {
42813
+ function renderTaskRow(svg, task, parsed, x, y, labelW, roleX, roleColW, palette, surfaceBg, solid, taskDiagnostics, _hasAnyDiagnostic, rowContent, onClickLine, _onMarkerDragStart) {
42805
42814
  const rowG = svg.append("g").attr("class", "raci-task-row").attr("data-task-id", task.id).attr("data-line-number", String(task.lineNumber));
42806
42815
  const labelX = x + 8;
42807
42816
  const labelMaxW = labelW - 16;
@@ -43607,7 +43616,6 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
43607
43616
  const messages = collapsed ? collapsed.messages : parsed.messages;
43608
43617
  const elements = collapsed ? collapsed.elements : parsed.elements;
43609
43618
  const groups = collapsed ? collapsed.groups : parsed.groups;
43610
- const collapsedGroupIds = collapsed?.collapsedGroupIds ?? /* @__PURE__ */ new Map();
43611
43619
  const collapsedSections = options?.collapsedSections;
43612
43620
  const sourceParticipants = collapsed ? collapsed.participants : parsed.participants;
43613
43621
  const participants = applyPositionOverrides(
@@ -43635,7 +43643,7 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
43635
43643
  return Math.min(NOTE_MAX_W, laneMax);
43636
43644
  };
43637
43645
  const charsForWidth = (maxW) => Math.floor((maxW - NOTE_PAD_H * 2 - NOTE_FOLD) / NOTE_CHAR_W);
43638
- const activationsOff = parsedOptions.activations?.toLowerCase() === "off";
43646
+ const activationsOff = parsedOptions["activations"]?.toLowerCase() === "off";
43639
43647
  const activeTagGroup = resolveActiveTagGroup(
43640
43648
  parsed.tagGroups,
43641
43649
  parsedOptions["active-tag"],
@@ -46587,7 +46595,7 @@ function renderTimelineGroupLegend(g, groups, groupColorMap, textColor, palette,
46587
46595
  legendX += pillW + GAP;
46588
46596
  }
46589
46597
  }
46590
- function renderTimeline(container, parsed, palette, isDark, onClickItem, exportDims, activeTagGroup, swimlaneTagGroup, onTagStateChange, viewMode) {
46598
+ function setupTimeline(container, parsed, palette, isDark, exportDims, activeTagGroup, swimlaneTagGroup) {
46591
46599
  d3Selection22.select(container).selectAll(":not([data-d3-tooltip])").remove();
46592
46600
  const solid = parsed.solidFill === true;
46593
46601
  const {
@@ -46596,19 +46604,17 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
46596
46604
  timelineEras,
46597
46605
  timelineMarkers,
46598
46606
  timelineSort,
46599
- timelineScale,
46600
- timelineSwimlanes,
46601
46607
  orientation
46602
46608
  } = parsed;
46603
- const title = parsed.noTitle ? null : parsed.title;
46604
- if (timelineEvents.length === 0) return;
46605
- if (swimlaneTagGroup == null && timelineSort === "tag" && parsed.timelineDefaultSwimlaneTG) {
46606
- swimlaneTagGroup = parsed.timelineDefaultSwimlaneTG;
46609
+ if (timelineEvents.length === 0) return null;
46610
+ let resolvedSwimlaneTG = swimlaneTagGroup ?? null;
46611
+ if (resolvedSwimlaneTG == null && timelineSort === "tag" && parsed.timelineDefaultSwimlaneTG) {
46612
+ resolvedSwimlaneTG = parsed.timelineDefaultSwimlaneTG;
46607
46613
  }
46608
46614
  const tooltip = createTooltip2(container, palette, isDark);
46609
46615
  const width = exportDims?.width ?? container.clientWidth;
46610
46616
  const height = exportDims?.height ?? container.clientHeight;
46611
- if (width <= 0 || height <= 0) return;
46617
+ if (width <= 0 || height <= 0) return null;
46612
46618
  const isVertical = orientation === "vertical";
46613
46619
  const textColor = palette.text;
46614
46620
  const mutedColor = palette.border;
@@ -46620,8 +46626,8 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
46620
46626
  groupColorMap.set(grp.name, grp.color ?? colors[i % colors.length]);
46621
46627
  });
46622
46628
  let tagLanes = null;
46623
- if (swimlaneTagGroup) {
46624
- const tagKey = swimlaneTagGroup.toLowerCase();
46629
+ if (resolvedSwimlaneTG) {
46630
+ const tagKey = resolvedSwimlaneTG.toLowerCase();
46625
46631
  const tagGroup = parsed.timelineTagGroups.find(
46626
46632
  (g) => g.name.toLowerCase() === tagKey
46627
46633
  );
@@ -46652,7 +46658,7 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
46652
46658
  }
46653
46659
  }
46654
46660
  }
46655
- const effectiveColorTG = activeTagGroup ?? swimlaneTagGroup ?? null;
46661
+ const effectiveColorTG = activeTagGroup ?? resolvedSwimlaneTG ?? null;
46656
46662
  function eventColor(ev) {
46657
46663
  if (effectiveColorTG) {
46658
46664
  const tagColor = resolveTagColor(
@@ -46708,6 +46714,30 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
46708
46714
  }
46709
46715
  }
46710
46716
  const datePadding = (maxDate - minDate) * 0.05 || 0.5;
46717
+ const tagLegendReserve = parsed.timelineTagGroups.length > 0 ? 36 : 0;
46718
+ return {
46719
+ width,
46720
+ height,
46721
+ isVertical,
46722
+ tooltip,
46723
+ solid,
46724
+ textColor,
46725
+ mutedColor,
46726
+ bgColor,
46727
+ bg,
46728
+ swimlaneTagGroup: resolvedSwimlaneTG,
46729
+ groupColorMap,
46730
+ tagLanes,
46731
+ eventColor,
46732
+ minDate,
46733
+ maxDate,
46734
+ datePadding,
46735
+ earliestStartDateStr,
46736
+ latestEndDateStr,
46737
+ tagLegendReserve
46738
+ };
46739
+ }
46740
+ function makeTimelineHoverHelpers() {
46711
46741
  const FADE_OPACITY3 = 0.1;
46712
46742
  function fadeToGroup(g, groupName) {
46713
46743
  g.selectAll(".tl-event").each(function() {
@@ -46807,337 +46837,683 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
46807
46837
  evG.attr(`data-tag-${key}`, value.toLowerCase());
46808
46838
  }
46809
46839
  }
46810
- const tagLegendReserve = parsed.timelineTagGroups.length > 0 ? 36 : 0;
46811
- if (isVertical) {
46812
- const useGroupedVertical = tagLanes != null || timelineSort === "group" && timelineGroups.length > 0;
46813
- if (useGroupedVertical) {
46814
- let laneNames;
46815
- let laneEventsByName;
46816
- if (tagLanes) {
46817
- laneNames = tagLanes.map((l) => l.name);
46818
- laneEventsByName = new Map(tagLanes.map((l) => [l.name, l.events]));
46819
- } else {
46820
- const groupNames = timelineGroups.map((gr) => gr.name);
46821
- const ungroupedEvents = timelineEvents.filter(
46822
- (ev) => ev.group === null || !groupNames.includes(ev.group)
46823
- );
46824
- laneNames = ungroupedEvents.length > 0 ? [...groupNames, "(Other)"] : groupNames;
46825
- laneEventsByName = new Map(
46826
- laneNames.map((name) => [
46827
- name,
46828
- timelineEvents.filter(
46829
- (ev) => name === "(Other)" ? ev.group === null || !groupNames.includes(ev.group) : ev.group === name
46830
- )
46831
- ])
46832
- );
46840
+ return {
46841
+ FADE_OPACITY: FADE_OPACITY3,
46842
+ fadeToGroup,
46843
+ fadeToEra,
46844
+ fadeToMarker,
46845
+ fadeReset,
46846
+ fadeToTagValue,
46847
+ setTagAttrs
46848
+ };
46849
+ }
46850
+ function renderTimelineTagLegendOverlay(container, parsed, palette, isDark, setup, hovers, onClickItem, exportDims, swimlaneTagGroup, activeTagGroup, onTagStateChange, viewMode) {
46851
+ if (parsed.timelineTagGroups.length === 0) return;
46852
+ const { width, textColor, groupColorMap, solid } = setup;
46853
+ const { FADE_OPACITY: FADE_OPACITY3, fadeReset, fadeToTagValue } = hovers;
46854
+ const title = parsed.noTitle ? null : parsed.title;
46855
+ const { timelineEvents } = parsed;
46856
+ const LG_HEIGHT = LEGEND_HEIGHT;
46857
+ const LG_PILL_PAD = LEGEND_PILL_PAD;
46858
+ const LG_PILL_FONT_SIZE = LEGEND_PILL_FONT_SIZE;
46859
+ const LG_CAPSULE_PAD = LEGEND_CAPSULE_PAD;
46860
+ const LG_DOT_R = LEGEND_DOT_R;
46861
+ const LG_ENTRY_FONT_SIZE = LEGEND_ENTRY_FONT_SIZE;
46862
+ const LG_ENTRY_DOT_GAP = LEGEND_ENTRY_DOT_GAP;
46863
+ const LG_ENTRY_TRAIL = LEGEND_ENTRY_TRAIL;
46864
+ const LG_ICON_W = 20;
46865
+ const mainSvg = d3Selection22.select(container).select("svg");
46866
+ const mainG = mainSvg.select("g");
46867
+ if (!mainSvg.empty() && !mainG.empty()) {
46868
+ let drawSwimlaneIcon4 = function(parent, x, y, isSwimActive) {
46869
+ const iconG = parent.append("g").attr("class", "tl-swimlane-icon").attr("transform", `translate(${x}, ${y})`).style("cursor", "pointer");
46870
+ const barColor = isSwimActive ? palette.primary : palette.textMuted;
46871
+ const barOpacity = isSwimActive ? 1 : 0.35;
46872
+ const bars = [
46873
+ { y: 0, w: 8 },
46874
+ { y: 4, w: 12 },
46875
+ { y: 8, w: 6 }
46876
+ ];
46877
+ for (const bar of bars) {
46878
+ 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);
46833
46879
  }
46834
- const laneCount = laneNames.length;
46835
- const scaleMargin = timelineScale ? 40 : 0;
46836
- const markerMargin = timelineMarkers.length > 0 ? 30 : 0;
46837
- const margin = {
46838
- top: 104 + markerMargin + tagLegendReserve,
46839
- right: 40 + scaleMargin,
46840
- bottom: 40,
46841
- left: 60 + scaleMargin
46842
- };
46843
- const innerWidth = width - margin.left - margin.right;
46844
- const innerHeight = height - margin.top - margin.bottom;
46845
- const laneWidth = innerWidth / laneCount;
46846
- const yScale = d3Scale2.scaleLinear().domain([minDate - datePadding, maxDate + datePadding]).range([0, innerHeight]);
46847
- 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);
46848
- const g = svg.append("g").attr("transform", `translate(${margin.left},${margin.top})`);
46849
- renderChartTitle(
46850
- svg,
46851
- title,
46852
- parsed.titleLineNumber,
46853
- width,
46854
- textColor,
46855
- onClickItem
46856
- );
46857
- renderEras(
46858
- g,
46859
- timelineEras,
46860
- yScale,
46861
- true,
46862
- innerWidth,
46863
- innerHeight,
46864
- (s, e) => fadeToEra(g, s, e),
46865
- () => fadeReset(g),
46866
- timelineScale,
46867
- tooltip,
46868
- palette
46869
- );
46870
- renderMarkers(
46871
- g,
46872
- timelineMarkers,
46873
- yScale,
46874
- true,
46875
- innerWidth,
46876
- innerHeight,
46877
- (d) => fadeToMarker(g, d),
46878
- () => fadeReset(g),
46879
- timelineScale,
46880
- tooltip,
46881
- palette
46880
+ return iconG;
46881
+ }, relayout2 = function() {
46882
+ renderTimeline(
46883
+ container,
46884
+ parsed,
46885
+ palette,
46886
+ isDark,
46887
+ onClickItem,
46888
+ exportDims,
46889
+ currentActiveGroup,
46890
+ currentSwimlaneGroup,
46891
+ onTagStateChange,
46892
+ viewMode
46882
46893
  );
46883
- if (timelineScale) {
46884
- renderTimeScale(
46885
- g,
46886
- yScale,
46887
- true,
46888
- innerWidth,
46889
- innerHeight,
46890
- textColor,
46891
- minDate,
46892
- maxDate,
46893
- formatBoundaryLabel(earliestStartDateStr, latestEndDateStr),
46894
- formatBoundaryLabel(latestEndDateStr, earliestStartDateStr)
46894
+ }, drawLegend2 = function() {
46895
+ mainSvg.selectAll(".tl-tag-legend-group").remove();
46896
+ mainSvg.selectAll(".tl-tag-legend-container").remove();
46897
+ const effectiveColorKey = (currentActiveGroup ?? currentSwimlaneGroup)?.toLowerCase() ?? null;
46898
+ const visibleGroups = viewMode ? legendGroups.filter(
46899
+ (lg) => effectiveColorKey != null && lg.group.name.toLowerCase() === effectiveColorKey
46900
+ ) : legendGroups;
46901
+ if (visibleGroups.length === 0) return;
46902
+ const legendContainer = mainSvg.append("g").attr("class", "tl-tag-legend-container");
46903
+ if (currentActiveGroup) {
46904
+ legendContainer.attr(
46905
+ "data-legend-active",
46906
+ currentActiveGroup.toLowerCase()
46895
46907
  );
46896
46908
  }
46897
- if (timelineSwimlanes || tagLanes) {
46898
- laneNames.forEach((laneName, laneIdx) => {
46899
- const laneX = laneIdx * laneWidth;
46900
- const fillColor = laneIdx % 2 === 0 ? textColor : "transparent";
46901
- 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);
46902
- });
46903
- }
46904
- laneNames.forEach((laneName, laneIdx) => {
46905
- const laneX = laneIdx * laneWidth;
46906
- const laneColor = groupColorMap.get(laneName) ?? textColor;
46907
- const laneCenter = laneX + laneWidth / 2;
46908
- 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));
46909
- 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);
46910
- 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");
46911
- const laneEvents = laneEventsByName.get(laneName) ?? [];
46912
- for (const ev of laneEvents) {
46913
- const y = yScale(parseTimelineDate(ev.date));
46914
- 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(
46915
- "data-end-date",
46916
- ev.endDate ? String(parseTimelineDate(ev.endDate)) : null
46917
- ).style("cursor", "pointer").on("mouseenter", function(event) {
46918
- fadeToGroup(g, laneName);
46919
- showTooltip(tooltip, buildEventTooltipHtml(ev), event);
46920
- }).on("mouseleave", function() {
46921
- fadeReset(g);
46922
- hideTooltip(tooltip);
46923
- }).on("mousemove", function(event) {
46924
- showTooltip(tooltip, buildEventTooltipHtml(ev), event);
46925
- }).on("click", () => {
46926
- if (onClickItem && ev.lineNumber) onClickItem(ev.lineNumber);
46927
- });
46928
- setTagAttrs(evG, ev);
46929
- const evColor = eventColor(ev);
46930
- if (ev.endDate) {
46931
- const y2 = yScale(parseTimelineDate(ev.endDate));
46932
- const rectH = Math.max(y2 - y, 4);
46933
- let fill2 = shapeFill(palette, evColor, isDark, { solid });
46934
- let stroke2 = evColor;
46935
- if (ev.uncertain) {
46936
- const gradientId = `uncertain-vg-${ev.lineNumber}`;
46937
- const strokeGradientId = `uncertain-vg-s-${ev.lineNumber}`;
46938
- const defs = svg.select("defs").node() || svg.append("defs").node();
46939
- const defsEl = d3Selection22.select(defs);
46940
- defsEl.append("linearGradient").attr("id", gradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "0%").attr("y2", "100%").selectAll("stop").data([
46941
- { offset: "0%", opacity: 1 },
46942
- { offset: "80%", opacity: 1 },
46943
- { offset: "100%", opacity: 0 }
46944
- ]).enter().append("stop").attr("offset", (d) => d.offset).attr("stop-color", mix(laneColor, bg, 30)).attr("stop-opacity", (d) => d.opacity);
46945
- defsEl.append("linearGradient").attr("id", strokeGradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "0%").attr("y2", "100%").selectAll("stop").data([
46946
- { offset: "0%", opacity: 1 },
46947
- { offset: "80%", opacity: 1 },
46948
- { offset: "100%", opacity: 0 }
46949
- ]).enter().append("stop").attr("offset", (d) => d.offset).attr("stop-color", evColor).attr("stop-opacity", (d) => d.opacity);
46950
- fill2 = `url(#${gradientId})`;
46951
- stroke2 = `url(#${strokeGradientId})`;
46952
- }
46953
- 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);
46954
- 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);
46909
+ const iconAddon = viewMode ? 0 : LG_ICON_W;
46910
+ const centralGroups = visibleGroups.map((lg) => ({
46911
+ name: lg.group.name,
46912
+ entries: lg.group.entries.map((e) => ({
46913
+ value: e.value,
46914
+ color: e.color
46915
+ }))
46916
+ }));
46917
+ const centralActive = viewMode ? effectiveColorKey : currentActiveGroup;
46918
+ const centralConfig = {
46919
+ groups: centralGroups,
46920
+ position: { placement: "top-center", titleRelation: "below-title" },
46921
+ mode: "fixed",
46922
+ capsulePillAddonWidth: iconAddon
46923
+ };
46924
+ const centralState = { activeGroup: centralActive };
46925
+ const centralCallbacks = viewMode ? {} : {
46926
+ onGroupToggle: (groupName) => {
46927
+ currentActiveGroup = currentActiveGroup === groupName.toLowerCase() ? null : groupName.toLowerCase();
46928
+ drawLegend2();
46929
+ recolorEvents2();
46930
+ onTagStateChange?.(currentActiveGroup, currentSwimlaneGroup);
46931
+ },
46932
+ onEntryHover: (groupName, entryValue) => {
46933
+ const tagKey = groupName.toLowerCase();
46934
+ if (entryValue) {
46935
+ const tagVal = entryValue.toLowerCase();
46936
+ fadeToTagValue(mainG, tagKey, tagVal);
46937
+ mainSvg.selectAll("[data-legend-entry]").each(function() {
46938
+ const el = d3Selection22.select(this);
46939
+ const ev = el.attr("data-legend-entry");
46940
+ const eg = el.attr("data-tag-group") ?? el.node()?.closest?.("[data-tag-group]")?.getAttribute("data-tag-group");
46941
+ el.attr(
46942
+ "opacity",
46943
+ eg === tagKey && ev === tagVal ? 1 : FADE_OPACITY3
46944
+ );
46945
+ });
46955
46946
  } else {
46956
- 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);
46957
- evG.append("text").attr("x", laneCenter + 10).attr("y", y).attr("dy", "0.35em").attr("fill", textColor).attr("font-size", "10px").text(ev.label);
46947
+ fadeReset(mainG);
46948
+ mainSvg.selectAll("[data-legend-entry]").attr("opacity", 1);
46949
+ }
46950
+ },
46951
+ onGroupRendered: (groupName, groupEl, isActive) => {
46952
+ const groupKey = groupName.toLowerCase();
46953
+ groupEl.attr("data-tag-group", groupKey);
46954
+ if (isActive && !viewMode) {
46955
+ const isSwimActive = currentSwimlaneGroup != null && currentSwimlaneGroup.toLowerCase() === groupKey;
46956
+ const pillWidth3 = measureLegendText(groupName, LG_PILL_FONT_SIZE) + LG_PILL_PAD;
46957
+ const pillXOff = LG_CAPSULE_PAD;
46958
+ const iconX = pillXOff + pillWidth3 + 5;
46959
+ const iconY = (LG_HEIGHT - 10) / 2;
46960
+ const iconEl = drawSwimlaneIcon4(
46961
+ groupEl,
46962
+ iconX,
46963
+ iconY,
46964
+ isSwimActive
46965
+ );
46966
+ iconEl.attr("data-swimlane-toggle", groupKey).on("click", (event) => {
46967
+ event.stopPropagation();
46968
+ currentSwimlaneGroup = currentSwimlaneGroup === groupKey ? null : groupKey;
46969
+ onTagStateChange?.(
46970
+ currentActiveGroup,
46971
+ currentSwimlaneGroup
46972
+ );
46973
+ relayout2();
46974
+ });
46958
46975
  }
46959
46976
  }
46960
- });
46961
- } else {
46962
- const scaleMargin = timelineScale ? 40 : 0;
46963
- const markerMargin = timelineMarkers.length > 0 ? 30 : 0;
46964
- const margin = {
46965
- top: 104 + markerMargin + tagLegendReserve,
46966
- right: 200,
46967
- bottom: 40,
46968
- left: 60 + scaleMargin
46969
46977
  };
46970
- const innerWidth = width - margin.left - margin.right;
46971
- const innerHeight = height - margin.top - margin.bottom;
46972
- const axisX = 20;
46973
- const yScale = d3Scale2.scaleLinear().domain([minDate - datePadding, maxDate + datePadding]).range([0, innerHeight]);
46974
- const sorted = timelineEvents.slice().sort((a, b) => parseTimelineDate(a.date) - parseTimelineDate(b.date));
46975
- 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);
46976
- const g = svg.append("g").attr("transform", `translate(${margin.left},${margin.top})`);
46977
- renderChartTitle(
46978
- svg,
46979
- title,
46980
- parsed.titleLineNumber,
46981
- width,
46982
- textColor,
46983
- onClickItem
46984
- );
46985
- renderEras(
46986
- g,
46987
- timelineEras,
46988
- yScale,
46989
- true,
46990
- innerWidth,
46991
- innerHeight,
46992
- (s, e) => fadeToEra(g, s, e),
46993
- () => fadeReset(g),
46994
- timelineScale,
46995
- tooltip,
46996
- palette
46997
- );
46998
- renderMarkers(
46999
- g,
47000
- timelineMarkers,
47001
- yScale,
47002
- true,
47003
- innerWidth,
47004
- innerHeight,
47005
- (d) => fadeToMarker(g, d),
47006
- () => fadeReset(g),
47007
- timelineScale,
47008
- tooltip,
47009
- palette
46978
+ const legendInnerG = legendContainer.append("g").attr("transform", `translate(0, ${legendY})`);
46979
+ renderLegendD3(
46980
+ legendInnerG,
46981
+ centralConfig,
46982
+ centralState,
46983
+ palette,
46984
+ isDark,
46985
+ centralCallbacks,
46986
+ width
47010
46987
  );
46988
+ }, recolorEvents2 = function() {
46989
+ const colorTG = currentActiveGroup ?? swimlaneTagGroup ?? null;
46990
+ mainG.selectAll(".tl-event").each(function() {
46991
+ const el = d3Selection22.select(this);
46992
+ const lineNum = el.attr("data-line-number");
46993
+ const ev = lineNum ? eventByLine.get(lineNum) : void 0;
46994
+ if (!ev) return;
46995
+ let color;
46996
+ if (colorTG) {
46997
+ const tagColor = resolveTagColor(
46998
+ ev.metadata,
46999
+ parsed.timelineTagGroups,
47000
+ colorTG
47001
+ );
47002
+ color = tagColor ?? (ev.group && groupColorMap.has(ev.group) ? groupColorMap.get(ev.group) : textColor);
47003
+ } else {
47004
+ color = ev.group && groupColorMap.has(ev.group) ? groupColorMap.get(ev.group) : textColor;
47005
+ }
47006
+ el.selectAll("rect").attr("fill", shapeFill(palette, color, isDark, { solid })).attr("stroke", color);
47007
+ el.selectAll("circle:not(.tl-event-point-outline)").attr("fill", shapeFill(palette, color, isDark, { solid })).attr("stroke", color);
47008
+ });
47009
+ };
47010
+ var drawSwimlaneIcon3 = drawSwimlaneIcon4, relayout = relayout2, drawLegend = drawLegend2, recolorEvents = recolorEvents2;
47011
+ const legendY = title ? 50 : 10;
47012
+ const legendGroups = parsed.timelineTagGroups.map((g) => {
47013
+ const pillW = measureLegendText(g.name, LG_PILL_FONT_SIZE) + LG_PILL_PAD;
47014
+ const iconSpace = viewMode ? 8 : LG_ICON_W + 4;
47015
+ let entryX = LG_CAPSULE_PAD + pillW + iconSpace;
47016
+ for (const entry of g.entries) {
47017
+ const textX = entryX + LG_DOT_R * 2 + LG_ENTRY_DOT_GAP;
47018
+ entryX = textX + measureLegendText(entry.value, LG_ENTRY_FONT_SIZE) + LG_ENTRY_TRAIL;
47019
+ }
47020
+ return {
47021
+ group: g,
47022
+ minifiedWidth: pillW,
47023
+ expandedWidth: entryX + LG_CAPSULE_PAD
47024
+ };
47025
+ });
47026
+ let currentActiveGroup = activeTagGroup ?? null;
47027
+ let currentSwimlaneGroup = swimlaneTagGroup ?? null;
47028
+ const eventByLine = /* @__PURE__ */ new Map();
47029
+ for (const ev of timelineEvents) {
47030
+ eventByLine.set(String(ev.lineNumber), ev);
47031
+ }
47032
+ drawLegend2();
47033
+ }
47034
+ }
47035
+ function renderTimelineHorizontalTimeSort(container, parsed, palette, isDark, setup, hovers, onClickItem, _exportDims, _swimlaneTagGroup, _activeTagGroup, _onTagStateChange, _viewMode) {
47036
+ const {
47037
+ width,
47038
+ height,
47039
+ tooltip,
47040
+ solid,
47041
+ textColor,
47042
+ bgColor,
47043
+ bg,
47044
+ groupColorMap,
47045
+ eventColor,
47046
+ minDate,
47047
+ maxDate,
47048
+ datePadding,
47049
+ earliestStartDateStr,
47050
+ latestEndDateStr,
47051
+ tagLegendReserve
47052
+ } = setup;
47053
+ const { fadeToGroup, fadeToEra, fadeToMarker, fadeReset, setTagAttrs } = hovers;
47054
+ const {
47055
+ timelineEvents,
47056
+ timelineGroups,
47057
+ timelineEras,
47058
+ timelineMarkers,
47059
+ timelineScale
47060
+ } = parsed;
47061
+ const title = parsed.noTitle ? null : parsed.title;
47062
+ const BAR_H2 = 22;
47063
+ const sorted = timelineEvents.slice().sort((a, b) => parseTimelineDate(a.date) - parseTimelineDate(b.date));
47064
+ const scaleMargin = timelineScale ? 24 : 0;
47065
+ const ERA_ROW_H = 22;
47066
+ const MARKER_ROW_H = 22;
47067
+ const eraReserve = timelineEras.length > 0 ? ERA_ROW_H : 0;
47068
+ const markerReserve = timelineMarkers.length > 0 ? MARKER_ROW_H : 0;
47069
+ const topScaleH = timelineScale ? 40 : 0;
47070
+ const margin = {
47071
+ top: 104 + topScaleH + eraReserve + markerReserve + tagLegendReserve,
47072
+ right: 40,
47073
+ bottom: 40 + scaleMargin,
47074
+ left: 60
47075
+ };
47076
+ const markerLabelY = markerReserve ? -(topScaleH + MARKER_ROW_H / 2) : 0;
47077
+ const eraLabelY = eraReserve ? -(topScaleH + markerReserve + ERA_ROW_H / 2) : 0;
47078
+ const innerWidth = width - margin.left - margin.right;
47079
+ const innerHeight = height - margin.top - margin.bottom;
47080
+ const rowH = Math.min(28, innerHeight / sorted.length);
47081
+ const xScale = d3Scale2.scaleLinear().domain([minDate - datePadding, maxDate + datePadding]).range([0, innerWidth]);
47082
+ const svg = d3Selection22.select(container).append("svg").attr("width", width).attr("height", height).style("background", bgColor);
47083
+ const g = svg.append("g").attr("transform", `translate(${margin.left},${margin.top})`);
47084
+ renderChartTitle(
47085
+ svg,
47086
+ title,
47087
+ parsed.titleLineNumber,
47088
+ width,
47089
+ textColor,
47090
+ onClickItem
47091
+ );
47092
+ renderEras(
47093
+ g,
47094
+ timelineEras,
47095
+ xScale,
47096
+ false,
47097
+ innerWidth,
47098
+ innerHeight,
47099
+ (s, e) => fadeToEra(g, s, e),
47100
+ () => fadeReset(g),
47101
+ timelineScale,
47102
+ tooltip,
47103
+ palette,
47104
+ eraReserve ? eraLabelY : void 0
47105
+ );
47106
+ renderMarkers(
47107
+ g,
47108
+ timelineMarkers,
47109
+ xScale,
47110
+ false,
47111
+ innerWidth,
47112
+ innerHeight,
47113
+ (d) => fadeToMarker(g, d),
47114
+ () => fadeReset(g),
47115
+ timelineScale,
47116
+ tooltip,
47117
+ palette,
47118
+ markerReserve ? markerLabelY : void 0
47119
+ );
47120
+ if (timelineScale) {
47121
+ renderTimeScale(
47122
+ g,
47123
+ xScale,
47124
+ false,
47125
+ innerWidth,
47126
+ innerHeight,
47127
+ textColor,
47128
+ minDate,
47129
+ maxDate,
47130
+ formatBoundaryLabel(earliestStartDateStr, latestEndDateStr),
47131
+ formatBoundaryLabel(latestEndDateStr, earliestStartDateStr)
47132
+ );
47133
+ }
47134
+ if (timelineGroups.length > 0) {
47135
+ const legendY = timelineScale ? -75 : -55;
47136
+ renderTimelineGroupLegend(
47137
+ g,
47138
+ timelineGroups,
47139
+ groupColorMap,
47140
+ textColor,
47141
+ palette,
47142
+ isDark,
47143
+ legendY,
47144
+ (name) => fadeToGroup(g, name),
47145
+ () => fadeReset(g)
47146
+ );
47147
+ }
47148
+ sorted.forEach((ev, i) => {
47149
+ const y = i * rowH + rowH / 2;
47150
+ const x = xScale(parseTimelineDate(ev.date));
47151
+ const color = eventColor(ev);
47152
+ 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(
47153
+ "data-end-date",
47154
+ ev.endDate ? String(parseTimelineDate(ev.endDate)) : null
47155
+ ).style("cursor", "pointer").on("mouseenter", function(event) {
47156
+ if (ev.group && timelineGroups.length > 0) fadeToGroup(g, ev.group);
47011
47157
  if (timelineScale) {
47012
- renderTimeScale(
47158
+ showEventDatesOnScale(
47013
47159
  g,
47014
- yScale,
47015
- true,
47016
- innerWidth,
47160
+ xScale,
47161
+ ev.date,
47162
+ ev.endDate,
47017
47163
  innerHeight,
47018
- textColor,
47019
- minDate,
47020
- maxDate,
47021
- formatBoundaryLabel(earliestStartDateStr, latestEndDateStr),
47022
- formatBoundaryLabel(latestEndDateStr, earliestStartDateStr)
47164
+ color
47023
47165
  );
47166
+ } else {
47167
+ showTooltip(tooltip, buildEventTooltipHtml(ev), event);
47024
47168
  }
47025
- if (timelineGroups.length > 0) {
47026
- renderTimelineGroupLegend(
47027
- g,
47028
- timelineGroups,
47029
- groupColorMap,
47030
- textColor,
47031
- palette,
47032
- isDark,
47033
- -55,
47034
- (name) => fadeToGroup(g, name),
47035
- () => fadeReset(g)
47036
- );
47169
+ }).on("mouseleave", function() {
47170
+ fadeReset(g);
47171
+ if (timelineScale) {
47172
+ hideEventDatesOnScale(g);
47173
+ } else {
47174
+ hideTooltip(tooltip);
47037
47175
  }
47038
- 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");
47039
- for (const ev of sorted) {
47040
- const y = yScale(parseTimelineDate(ev.date));
47041
- const color = eventColor(ev);
47042
- 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(
47043
- "data-end-date",
47044
- ev.endDate ? String(parseTimelineDate(ev.endDate)) : null
47045
- ).style("cursor", "pointer").on("mouseenter", function(event) {
47046
- if (ev.group && timelineGroups.length > 0) fadeToGroup(g, ev.group);
47176
+ }).on("mousemove", function(event) {
47177
+ if (!timelineScale) {
47178
+ showTooltip(tooltip, buildEventTooltipHtml(ev), event);
47179
+ }
47180
+ }).on("click", () => {
47181
+ if (onClickItem && ev.lineNumber) onClickItem(ev.lineNumber);
47182
+ });
47183
+ setTagAttrs(evG, ev);
47184
+ if (ev.endDate) {
47185
+ const x2 = xScale(parseTimelineDate(ev.endDate));
47186
+ const rectW = Math.max(x2 - x, 4);
47187
+ const estLabelWidth = ev.label.length * 7 + 16;
47188
+ const labelFitsInside = rectW >= estLabelWidth;
47189
+ let fill2 = shapeFill(palette, color, isDark, { solid });
47190
+ let stroke2 = color;
47191
+ if (ev.uncertain) {
47192
+ const gradientId = `uncertain-ts-${ev.lineNumber}`;
47193
+ const strokeGradientId = `uncertain-ts-s-${ev.lineNumber}`;
47194
+ const defs = svg.select("defs").node() || svg.append("defs").node();
47195
+ const defsEl = d3Selection22.select(defs);
47196
+ defsEl.append("linearGradient").attr("id", gradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "100%").attr("y2", "0%").selectAll("stop").data([
47197
+ { offset: "0%", opacity: 1 },
47198
+ { offset: "80%", opacity: 1 },
47199
+ { offset: "100%", opacity: 0 }
47200
+ ]).enter().append("stop").attr("offset", (d) => d.offset).attr("stop-color", mix(color, bg, 30)).attr("stop-opacity", (d) => d.opacity);
47201
+ defsEl.append("linearGradient").attr("id", strokeGradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "100%").attr("y2", "0%").selectAll("stop").data([
47202
+ { offset: "0%", opacity: 1 },
47203
+ { offset: "80%", opacity: 1 },
47204
+ { offset: "100%", opacity: 0 }
47205
+ ]).enter().append("stop").attr("offset", (d) => d.offset).attr("stop-color", color).attr("stop-opacity", (d) => d.opacity);
47206
+ fill2 = `url(#${gradientId})`;
47207
+ stroke2 = `url(#${strokeGradientId})`;
47208
+ }
47209
+ 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);
47210
+ if (labelFitsInside) {
47211
+ 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);
47212
+ } else {
47213
+ const wouldFlipLeft = x + rectW > innerWidth * 0.6;
47214
+ const labelFitsLeft = x - 6 - estLabelWidth > 0;
47215
+ const flipLeft = wouldFlipLeft && labelFitsLeft;
47216
+ 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);
47217
+ }
47218
+ } else {
47219
+ const estLabelWidth = ev.label.length * 7;
47220
+ const wouldFlipLeft = x > innerWidth * 0.6;
47221
+ const labelFitsLeft = x - 10 - estLabelWidth > 0;
47222
+ const flipLeft = wouldFlipLeft && labelFitsLeft;
47223
+ 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);
47224
+ 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);
47225
+ }
47226
+ });
47227
+ }
47228
+ function renderTimelineHorizontalGrouped(container, parsed, palette, isDark, setup, hovers, onClickItem, _exportDims, _swimlaneTagGroup, _activeTagGroup, _onTagStateChange, _viewMode) {
47229
+ const {
47230
+ width,
47231
+ height,
47232
+ tooltip,
47233
+ solid,
47234
+ textColor,
47235
+ bgColor,
47236
+ bg,
47237
+ groupColorMap,
47238
+ tagLanes,
47239
+ eventColor,
47240
+ minDate,
47241
+ maxDate,
47242
+ datePadding,
47243
+ earliestStartDateStr,
47244
+ latestEndDateStr,
47245
+ tagLegendReserve
47246
+ } = setup;
47247
+ const { fadeToGroup, fadeToEra, fadeToMarker, fadeReset, setTagAttrs } = hovers;
47248
+ const {
47249
+ timelineEvents,
47250
+ timelineGroups,
47251
+ timelineEras,
47252
+ timelineMarkers,
47253
+ timelineScale,
47254
+ timelineSwimlanes
47255
+ } = parsed;
47256
+ const title = parsed.noTitle ? null : parsed.title;
47257
+ const BAR_H2 = 22;
47258
+ const GROUP_GAP3 = 12;
47259
+ let lanes;
47260
+ if (tagLanes) {
47261
+ lanes = tagLanes;
47262
+ } else {
47263
+ const groupNames = timelineGroups.map((gr) => gr.name);
47264
+ const ungroupedEvents = timelineEvents.filter(
47265
+ (ev) => ev.group === null || !groupNames.includes(ev.group)
47266
+ );
47267
+ const laneNames = ungroupedEvents.length > 0 ? [...groupNames, "(Other)"] : groupNames;
47268
+ lanes = laneNames.map((name) => ({
47269
+ name,
47270
+ events: timelineEvents.filter(
47271
+ (ev) => name === "(Other)" ? ev.group === null || !groupNames.includes(ev.group) : ev.group === name
47272
+ )
47273
+ }));
47274
+ }
47275
+ const totalEventRows = lanes.reduce((s, l) => s + l.events.length, 0);
47276
+ const scaleMargin = timelineScale ? 24 : 0;
47277
+ const ERA_ROW_H = 22;
47278
+ const MARKER_ROW_H = 22;
47279
+ const eraReserve = timelineEras.length > 0 ? ERA_ROW_H : 0;
47280
+ const markerReserve = timelineMarkers.length > 0 ? MARKER_ROW_H : 0;
47281
+ const topScaleH = timelineScale ? 40 : 0;
47282
+ const maxGroupNameLen = Math.max(...lanes.map((l) => l.name.length));
47283
+ const dynamicLeftMargin = Math.max(120, maxGroupNameLen * 7 + 30);
47284
+ const baseTopMargin = title ? 50 : 20;
47285
+ const margin = {
47286
+ top: baseTopMargin + topScaleH + eraReserve + markerReserve + tagLegendReserve,
47287
+ right: 40,
47288
+ bottom: 40 + scaleMargin,
47289
+ left: dynamicLeftMargin
47290
+ };
47291
+ const markerLabelY = markerReserve ? -(topScaleH + MARKER_ROW_H / 2) : 0;
47292
+ const eraLabelY = eraReserve ? -(topScaleH + markerReserve + ERA_ROW_H / 2) : 0;
47293
+ const innerWidth = width - margin.left - margin.right;
47294
+ const innerHeight = height - margin.top - margin.bottom;
47295
+ const totalGaps = (lanes.length - 1) * GROUP_GAP3;
47296
+ const rowH = Math.min(28, (innerHeight - totalGaps) / totalEventRows);
47297
+ const xScale = d3Scale2.scaleLinear().domain([minDate - datePadding, maxDate + datePadding]).range([0, innerWidth]);
47298
+ const svg = d3Selection22.select(container).append("svg").attr("width", width).attr("height", height).style("background", bgColor);
47299
+ const g = svg.append("g").attr("transform", `translate(${margin.left},${margin.top})`);
47300
+ renderChartTitle(
47301
+ svg,
47302
+ title,
47303
+ parsed.titleLineNumber,
47304
+ width,
47305
+ textColor,
47306
+ onClickItem
47307
+ );
47308
+ renderEras(
47309
+ g,
47310
+ timelineEras,
47311
+ xScale,
47312
+ false,
47313
+ innerWidth,
47314
+ innerHeight,
47315
+ (s, e) => fadeToEra(g, s, e),
47316
+ () => fadeReset(g),
47317
+ timelineScale,
47318
+ tooltip,
47319
+ palette,
47320
+ eraReserve ? eraLabelY : void 0
47321
+ );
47322
+ renderMarkers(
47323
+ g,
47324
+ timelineMarkers,
47325
+ xScale,
47326
+ false,
47327
+ innerWidth,
47328
+ innerHeight,
47329
+ (d) => fadeToMarker(g, d),
47330
+ () => fadeReset(g),
47331
+ timelineScale,
47332
+ tooltip,
47333
+ palette,
47334
+ markerReserve ? markerLabelY : void 0
47335
+ );
47336
+ if (timelineScale) {
47337
+ renderTimeScale(
47338
+ g,
47339
+ xScale,
47340
+ false,
47341
+ innerWidth,
47342
+ innerHeight,
47343
+ textColor,
47344
+ minDate,
47345
+ maxDate,
47346
+ formatBoundaryLabel(earliestStartDateStr, latestEndDateStr),
47347
+ formatBoundaryLabel(latestEndDateStr, earliestStartDateStr)
47348
+ );
47349
+ }
47350
+ let curY = 0;
47351
+ if (timelineSwimlanes || tagLanes) {
47352
+ let swimY = 0;
47353
+ lanes.forEach((lane, idx) => {
47354
+ const laneSpan = lane.events.length * rowH;
47355
+ const fillColor = idx % 2 === 0 ? textColor : "transparent";
47356
+ 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);
47357
+ swimY += laneSpan + GROUP_GAP3;
47358
+ });
47359
+ }
47360
+ for (const lane of lanes) {
47361
+ const laneColor = groupColorMap.get(lane.name) ?? textColor;
47362
+ const laneSpan = lane.events.length * rowH;
47363
+ const group = timelineGroups.find((grp) => grp.name === lane.name);
47364
+ 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", () => {
47365
+ if (onClickItem && group?.lineNumber) onClickItem(group.lineNumber);
47366
+ });
47367
+ 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);
47368
+ lane.events.forEach((ev, i) => {
47369
+ const y = curY + i * rowH + rowH / 2;
47370
+ const x = xScale(parseTimelineDate(ev.date));
47371
+ 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(
47372
+ "data-end-date",
47373
+ ev.endDate ? String(parseTimelineDate(ev.endDate)) : null
47374
+ ).style("cursor", "pointer").on("mouseenter", function(event) {
47375
+ fadeToGroup(g, lane.name);
47376
+ if (timelineScale) {
47377
+ showEventDatesOnScale(
47378
+ g,
47379
+ xScale,
47380
+ ev.date,
47381
+ ev.endDate,
47382
+ innerHeight,
47383
+ laneColor
47384
+ );
47385
+ } else {
47047
47386
  showTooltip(tooltip, buildEventTooltipHtml(ev), event);
47048
- }).on("mouseleave", function() {
47049
- fadeReset(g);
47387
+ }
47388
+ }).on("mouseleave", function() {
47389
+ fadeReset(g);
47390
+ if (timelineScale) {
47391
+ hideEventDatesOnScale(g);
47392
+ } else {
47050
47393
  hideTooltip(tooltip);
47051
- }).on("mousemove", function(event) {
47394
+ }
47395
+ }).on("mousemove", function(event) {
47396
+ if (!timelineScale) {
47052
47397
  showTooltip(tooltip, buildEventTooltipHtml(ev), event);
47053
- }).on("click", () => {
47054
- if (onClickItem && ev.lineNumber) onClickItem(ev.lineNumber);
47055
- });
47056
- setTagAttrs(evG, ev);
47057
- if (ev.endDate) {
47058
- const y2 = yScale(parseTimelineDate(ev.endDate));
47059
- const rectH = Math.max(y2 - y, 4);
47060
- let fill2 = shapeFill(palette, color, isDark, { solid });
47061
- let stroke2 = color;
47062
- if (ev.uncertain) {
47063
- const gradientId = `uncertain-v-${ev.lineNumber}`;
47064
- const strokeGradientId = `uncertain-v-s-${ev.lineNumber}`;
47065
- const defs = svg.select("defs").node() || svg.append("defs").node();
47066
- const defsEl = d3Selection22.select(defs);
47067
- defsEl.append("linearGradient").attr("id", gradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "0%").attr("y2", "100%").selectAll("stop").data([
47068
- { offset: "0%", opacity: 1 },
47069
- { offset: "80%", opacity: 1 },
47070
- { offset: "100%", opacity: 0 }
47071
- ]).enter().append("stop").attr("offset", (d) => d.offset).attr("stop-color", mix(color, bg, 30)).attr("stop-opacity", (d) => d.opacity);
47072
- defsEl.append("linearGradient").attr("id", strokeGradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "0%").attr("y2", "100%").selectAll("stop").data([
47073
- { offset: "0%", opacity: 1 },
47074
- { offset: "80%", opacity: 1 },
47075
- { offset: "100%", opacity: 0 }
47076
- ]).enter().append("stop").attr("offset", (d) => d.offset).attr("stop-color", color).attr("stop-opacity", (d) => d.opacity);
47077
- fill2 = `url(#${gradientId})`;
47078
- stroke2 = `url(#${strokeGradientId})`;
47079
- }
47080
- 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);
47081
- 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);
47398
+ }
47399
+ }).on("click", () => {
47400
+ if (onClickItem && ev.lineNumber) onClickItem(ev.lineNumber);
47401
+ });
47402
+ setTagAttrs(evG, ev);
47403
+ const evColor = eventColor(ev);
47404
+ if (ev.endDate) {
47405
+ const x2 = xScale(parseTimelineDate(ev.endDate));
47406
+ const rectW = Math.max(x2 - x, 4);
47407
+ const estLabelWidth = ev.label.length * 7 + 16;
47408
+ const labelFitsInside = rectW >= estLabelWidth;
47409
+ let fill2 = shapeFill(palette, evColor, isDark, { solid });
47410
+ let stroke2 = evColor;
47411
+ if (ev.uncertain) {
47412
+ const gradientId = `uncertain-${ev.lineNumber}`;
47413
+ const strokeGradientId = `uncertain-s-${ev.lineNumber}`;
47414
+ const defs = svg.select("defs").node() || svg.append("defs").node();
47415
+ const defsEl = d3Selection22.select(defs);
47416
+ defsEl.append("linearGradient").attr("id", gradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "100%").attr("y2", "0%").selectAll("stop").data([
47417
+ { offset: "0%", opacity: 1 },
47418
+ { offset: "80%", opacity: 1 },
47419
+ { offset: "100%", opacity: 0 }
47420
+ ]).enter().append("stop").attr("offset", (d) => d.offset).attr("stop-color", mix(evColor, bg, 30)).attr("stop-opacity", (d) => d.opacity);
47421
+ defsEl.append("linearGradient").attr("id", strokeGradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "100%").attr("y2", "0%").selectAll("stop").data([
47422
+ { offset: "0%", opacity: 1 },
47423
+ { offset: "80%", opacity: 1 },
47424
+ { offset: "100%", opacity: 0 }
47425
+ ]).enter().append("stop").attr("offset", (d) => d.offset).attr("stop-color", evColor).attr("stop-opacity", (d) => d.opacity);
47426
+ fill2 = `url(#${gradientId})`;
47427
+ stroke2 = `url(#${strokeGradientId})`;
47428
+ }
47429
+ 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);
47430
+ if (labelFitsInside) {
47431
+ 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);
47082
47432
  } else {
47083
- 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);
47084
- evG.append("text").attr("x", axisX + 16).attr("y", y).attr("dy", "0.35em").attr("fill", textColor).attr("font-size", "11px").text(ev.label);
47433
+ const wouldFlipLeft = x + rectW > innerWidth * 0.6;
47434
+ const labelFitsLeft = x - 6 - estLabelWidth > 0;
47435
+ const flipLeft = wouldFlipLeft && labelFitsLeft;
47436
+ 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);
47085
47437
  }
47086
- evG.append("text").attr("x", axisX - 14).attr(
47087
- "y",
47088
- ev.endDate ? yScale(parseTimelineDate(ev.date)) + Math.max(
47089
- yScale(parseTimelineDate(ev.endDate)) - yScale(parseTimelineDate(ev.date)),
47090
- 4
47091
- ) / 2 : y
47092
- ).attr("dy", "0.35em").attr("text-anchor", "end").attr("fill", mutedColor).attr("font-size", "10px").text(ev.date + (ev.endDate ? `\u2192${ev.endDate}` : ""));
47438
+ } else {
47439
+ const estLabelWidth = ev.label.length * 7;
47440
+ const wouldFlipLeft = x > innerWidth * 0.6;
47441
+ const labelFitsLeft = x - 10 - estLabelWidth > 0;
47442
+ const flipLeft = wouldFlipLeft && labelFitsLeft;
47443
+ 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);
47444
+ 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);
47093
47445
  }
47094
- }
47095
- return;
47446
+ });
47447
+ curY += laneSpan + GROUP_GAP3;
47096
47448
  }
47097
- const BAR_H2 = 22;
47098
- const GROUP_GAP3 = 12;
47099
- const useGroupedHorizontal = tagLanes != null || timelineSort === "group" && timelineGroups.length > 0;
47100
- if (useGroupedHorizontal) {
47101
- let lanes;
47449
+ }
47450
+ function renderTimelineVertical(container, parsed, palette, isDark, setup, hovers, onClickItem, exportDims, _swimlaneTagGroup, _activeTagGroup, _onTagStateChange, _viewMode) {
47451
+ const {
47452
+ width,
47453
+ height,
47454
+ tooltip,
47455
+ solid,
47456
+ textColor,
47457
+ mutedColor,
47458
+ bgColor,
47459
+ bg,
47460
+ groupColorMap,
47461
+ tagLanes,
47462
+ eventColor,
47463
+ minDate,
47464
+ maxDate,
47465
+ datePadding,
47466
+ earliestStartDateStr,
47467
+ latestEndDateStr,
47468
+ tagLegendReserve
47469
+ } = setup;
47470
+ const { fadeToGroup, fadeToEra, fadeToMarker, fadeReset, setTagAttrs } = hovers;
47471
+ const {
47472
+ timelineEvents,
47473
+ timelineGroups,
47474
+ timelineEras,
47475
+ timelineMarkers,
47476
+ timelineSort,
47477
+ timelineScale,
47478
+ timelineSwimlanes
47479
+ } = parsed;
47480
+ const title = parsed.noTitle ? null : parsed.title;
47481
+ const useGroupedVertical = tagLanes != null || timelineSort === "group" && timelineGroups.length > 0;
47482
+ if (useGroupedVertical) {
47483
+ let laneNames;
47484
+ let laneEventsByName;
47102
47485
  if (tagLanes) {
47103
- lanes = tagLanes;
47486
+ laneNames = tagLanes.map((l) => l.name);
47487
+ laneEventsByName = new Map(tagLanes.map((l) => [l.name, l.events]));
47104
47488
  } else {
47105
47489
  const groupNames = timelineGroups.map((gr) => gr.name);
47106
47490
  const ungroupedEvents = timelineEvents.filter(
47107
47491
  (ev) => ev.group === null || !groupNames.includes(ev.group)
47108
47492
  );
47109
- const laneNames = ungroupedEvents.length > 0 ? [...groupNames, "(Other)"] : groupNames;
47110
- lanes = laneNames.map((name) => ({
47111
- name,
47112
- events: timelineEvents.filter(
47113
- (ev) => name === "(Other)" ? ev.group === null || !groupNames.includes(ev.group) : ev.group === name
47114
- )
47115
- }));
47493
+ laneNames = ungroupedEvents.length > 0 ? [...groupNames, "(Other)"] : groupNames;
47494
+ laneEventsByName = new Map(
47495
+ laneNames.map((name) => [
47496
+ name,
47497
+ timelineEvents.filter(
47498
+ (ev) => name === "(Other)" ? ev.group === null || !groupNames.includes(ev.group) : ev.group === name
47499
+ )
47500
+ ])
47501
+ );
47116
47502
  }
47117
- const totalEventRows = lanes.reduce((s, l) => s + l.events.length, 0);
47118
- const scaleMargin = timelineScale ? 24 : 0;
47119
- const ERA_ROW_H = 22;
47120
- const MARKER_ROW_H = 22;
47121
- const eraReserve = timelineEras.length > 0 ? ERA_ROW_H : 0;
47122
- const markerReserve = timelineMarkers.length > 0 ? MARKER_ROW_H : 0;
47123
- const topScaleH = timelineScale ? 40 : 0;
47124
- const maxGroupNameLen = Math.max(...lanes.map((l) => l.name.length));
47125
- const dynamicLeftMargin = Math.max(120, maxGroupNameLen * 7 + 30);
47126
- const baseTopMargin = title ? 50 : 20;
47503
+ const laneCount = laneNames.length;
47504
+ const scaleMargin = timelineScale ? 40 : 0;
47505
+ const markerMargin = timelineMarkers.length > 0 ? 30 : 0;
47127
47506
  const margin = {
47128
- top: baseTopMargin + topScaleH + eraReserve + markerReserve + tagLegendReserve,
47129
- right: 40,
47130
- bottom: 40 + scaleMargin,
47131
- left: dynamicLeftMargin
47507
+ top: 104 + markerMargin + tagLegendReserve,
47508
+ right: 40 + scaleMargin,
47509
+ bottom: 40,
47510
+ left: 60 + scaleMargin
47132
47511
  };
47133
- const markerLabelY = markerReserve ? -(topScaleH + MARKER_ROW_H / 2) : 0;
47134
- const eraLabelY = eraReserve ? -(topScaleH + markerReserve + ERA_ROW_H / 2) : 0;
47135
47512
  const innerWidth = width - margin.left - margin.right;
47136
47513
  const innerHeight = height - margin.top - margin.bottom;
47137
- const totalGaps = (lanes.length - 1) * GROUP_GAP3;
47138
- const rowH = Math.min(28, (innerHeight - totalGaps) / totalEventRows);
47139
- const xScale = d3Scale2.scaleLinear().domain([minDate - datePadding, maxDate + datePadding]).range([0, innerWidth]);
47140
- const svg = d3Selection22.select(container).append("svg").attr("width", width).attr("height", height).style("background", bgColor);
47514
+ const laneWidth = innerWidth / laneCount;
47515
+ const yScale = d3Scale2.scaleLinear().domain([minDate - datePadding, maxDate + datePadding]).range([0, innerHeight]);
47516
+ 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);
47141
47517
  const g = svg.append("g").attr("transform", `translate(${margin.left},${margin.top})`);
47142
47518
  renderChartTitle(
47143
47519
  svg,
@@ -47150,36 +47526,34 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
47150
47526
  renderEras(
47151
47527
  g,
47152
47528
  timelineEras,
47153
- xScale,
47154
- false,
47529
+ yScale,
47530
+ true,
47155
47531
  innerWidth,
47156
47532
  innerHeight,
47157
47533
  (s, e) => fadeToEra(g, s, e),
47158
47534
  () => fadeReset(g),
47159
47535
  timelineScale,
47160
47536
  tooltip,
47161
- palette,
47162
- eraReserve ? eraLabelY : void 0
47537
+ palette
47163
47538
  );
47164
47539
  renderMarkers(
47165
47540
  g,
47166
47541
  timelineMarkers,
47167
- xScale,
47168
- false,
47542
+ yScale,
47543
+ true,
47169
47544
  innerWidth,
47170
47545
  innerHeight,
47171
47546
  (d) => fadeToMarker(g, d),
47172
47547
  () => fadeReset(g),
47173
47548
  timelineScale,
47174
47549
  tooltip,
47175
- palette,
47176
- markerReserve ? markerLabelY : void 0
47550
+ palette
47177
47551
  );
47178
47552
  if (timelineScale) {
47179
47553
  renderTimeScale(
47180
47554
  g,
47181
- xScale,
47182
- false,
47555
+ yScale,
47556
+ true,
47183
47557
  innerWidth,
47184
47558
  innerHeight,
47185
47559
  textColor,
@@ -47189,78 +47563,55 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
47189
47563
  formatBoundaryLabel(latestEndDateStr, earliestStartDateStr)
47190
47564
  );
47191
47565
  }
47192
- let curY = 0;
47193
47566
  if (timelineSwimlanes || tagLanes) {
47194
- let swimY = 0;
47195
- lanes.forEach((lane, idx) => {
47196
- const laneSpan = lane.events.length * rowH;
47197
- const fillColor = idx % 2 === 0 ? textColor : "transparent";
47198
- 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);
47199
- swimY += laneSpan + GROUP_GAP3;
47567
+ laneNames.forEach((laneName, laneIdx) => {
47568
+ const laneX = laneIdx * laneWidth;
47569
+ const fillColor = laneIdx % 2 === 0 ? textColor : "transparent";
47570
+ 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);
47200
47571
  });
47201
47572
  }
47202
- for (const lane of lanes) {
47203
- const laneColor = groupColorMap.get(lane.name) ?? textColor;
47204
- const laneSpan = lane.events.length * rowH;
47205
- const group = timelineGroups.find((grp) => grp.name === lane.name);
47206
- 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", () => {
47207
- if (onClickItem && group?.lineNumber) onClickItem(group.lineNumber);
47208
- });
47209
- 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);
47210
- lane.events.forEach((ev, i) => {
47211
- const y = curY + i * rowH + rowH / 2;
47212
- const x = xScale(parseTimelineDate(ev.date));
47213
- 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(
47573
+ laneNames.forEach((laneName, laneIdx) => {
47574
+ const laneX = laneIdx * laneWidth;
47575
+ const laneColor = groupColorMap.get(laneName) ?? textColor;
47576
+ const laneCenter = laneX + laneWidth / 2;
47577
+ 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));
47578
+ 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);
47579
+ 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");
47580
+ const laneEvents = laneEventsByName.get(laneName) ?? [];
47581
+ for (const ev of laneEvents) {
47582
+ const y = yScale(parseTimelineDate(ev.date));
47583
+ 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(
47214
47584
  "data-end-date",
47215
47585
  ev.endDate ? String(parseTimelineDate(ev.endDate)) : null
47216
47586
  ).style("cursor", "pointer").on("mouseenter", function(event) {
47217
- fadeToGroup(g, lane.name);
47218
- if (timelineScale) {
47219
- showEventDatesOnScale(
47220
- g,
47221
- xScale,
47222
- ev.date,
47223
- ev.endDate,
47224
- innerHeight,
47225
- laneColor
47226
- );
47227
- } else {
47228
- showTooltip(tooltip, buildEventTooltipHtml(ev), event);
47229
- }
47587
+ fadeToGroup(g, laneName);
47588
+ showTooltip(tooltip, buildEventTooltipHtml(ev), event);
47230
47589
  }).on("mouseleave", function() {
47231
47590
  fadeReset(g);
47232
- if (timelineScale) {
47233
- hideEventDatesOnScale(g);
47234
- } else {
47235
- hideTooltip(tooltip);
47236
- }
47591
+ hideTooltip(tooltip);
47237
47592
  }).on("mousemove", function(event) {
47238
- if (!timelineScale) {
47239
- showTooltip(tooltip, buildEventTooltipHtml(ev), event);
47240
- }
47593
+ showTooltip(tooltip, buildEventTooltipHtml(ev), event);
47241
47594
  }).on("click", () => {
47242
47595
  if (onClickItem && ev.lineNumber) onClickItem(ev.lineNumber);
47243
47596
  });
47244
47597
  setTagAttrs(evG, ev);
47245
47598
  const evColor = eventColor(ev);
47246
47599
  if (ev.endDate) {
47247
- const x2 = xScale(parseTimelineDate(ev.endDate));
47248
- const rectW = Math.max(x2 - x, 4);
47249
- const estLabelWidth = ev.label.length * 7 + 16;
47250
- const labelFitsInside = rectW >= estLabelWidth;
47600
+ const y2 = yScale(parseTimelineDate(ev.endDate));
47601
+ const rectH = Math.max(y2 - y, 4);
47251
47602
  let fill2 = shapeFill(palette, evColor, isDark, { solid });
47252
47603
  let stroke2 = evColor;
47253
47604
  if (ev.uncertain) {
47254
- const gradientId = `uncertain-${ev.lineNumber}`;
47255
- const strokeGradientId = `uncertain-s-${ev.lineNumber}`;
47605
+ const gradientId = `uncertain-vg-${ev.lineNumber}`;
47606
+ const strokeGradientId = `uncertain-vg-s-${ev.lineNumber}`;
47256
47607
  const defs = svg.select("defs").node() || svg.append("defs").node();
47257
47608
  const defsEl = d3Selection22.select(defs);
47258
- defsEl.append("linearGradient").attr("id", gradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "100%").attr("y2", "0%").selectAll("stop").data([
47609
+ defsEl.append("linearGradient").attr("id", gradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "0%").attr("y2", "100%").selectAll("stop").data([
47259
47610
  { offset: "0%", opacity: 1 },
47260
47611
  { offset: "80%", opacity: 1 },
47261
47612
  { offset: "100%", opacity: 0 }
47262
- ]).enter().append("stop").attr("offset", (d) => d.offset).attr("stop-color", mix(evColor, bg, 30)).attr("stop-opacity", (d) => d.opacity);
47263
- defsEl.append("linearGradient").attr("id", strokeGradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "100%").attr("y2", "0%").selectAll("stop").data([
47613
+ ]).enter().append("stop").attr("offset", (d) => d.offset).attr("stop-color", mix(laneColor, bg, 30)).attr("stop-opacity", (d) => d.opacity);
47614
+ defsEl.append("linearGradient").attr("id", strokeGradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "0%").attr("y2", "100%").selectAll("stop").data([
47264
47615
  { offset: "0%", opacity: 1 },
47265
47616
  { offset: "80%", opacity: 1 },
47266
47617
  { offset: "100%", opacity: 0 }
@@ -47268,47 +47619,29 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
47268
47619
  fill2 = `url(#${gradientId})`;
47269
47620
  stroke2 = `url(#${strokeGradientId})`;
47270
47621
  }
47271
- 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);
47272
- if (labelFitsInside) {
47273
- 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);
47274
- } else {
47275
- const wouldFlipLeft = x + rectW > innerWidth * 0.6;
47276
- const labelFitsLeft = x - 6 - estLabelWidth > 0;
47277
- const flipLeft = wouldFlipLeft && labelFitsLeft;
47278
- 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);
47279
- }
47622
+ 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);
47623
+ 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);
47280
47624
  } else {
47281
- const estLabelWidth = ev.label.length * 7;
47282
- const wouldFlipLeft = x > innerWidth * 0.6;
47283
- const labelFitsLeft = x - 10 - estLabelWidth > 0;
47284
- const flipLeft = wouldFlipLeft && labelFitsLeft;
47285
- 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);
47286
- 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);
47625
+ 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);
47626
+ evG.append("text").attr("x", laneCenter + 10).attr("y", y).attr("dy", "0.35em").attr("fill", textColor).attr("font-size", "10px").text(ev.label);
47287
47627
  }
47288
- });
47289
- curY += laneSpan + GROUP_GAP3;
47290
- }
47628
+ }
47629
+ });
47291
47630
  } else {
47292
- const sorted = timelineEvents.slice().sort((a, b) => parseTimelineDate(a.date) - parseTimelineDate(b.date));
47293
- const scaleMargin = timelineScale ? 24 : 0;
47294
- const ERA_ROW_H = 22;
47295
- const MARKER_ROW_H = 22;
47296
- const eraReserve = timelineEras.length > 0 ? ERA_ROW_H : 0;
47297
- const markerReserve = timelineMarkers.length > 0 ? MARKER_ROW_H : 0;
47298
- const topScaleH = timelineScale ? 40 : 0;
47631
+ const scaleMargin = timelineScale ? 40 : 0;
47632
+ const markerMargin = timelineMarkers.length > 0 ? 30 : 0;
47299
47633
  const margin = {
47300
- top: 104 + topScaleH + eraReserve + markerReserve + tagLegendReserve,
47301
- right: 40,
47302
- bottom: 40 + scaleMargin,
47303
- left: 60
47634
+ top: 104 + markerMargin + tagLegendReserve,
47635
+ right: 200,
47636
+ bottom: 40,
47637
+ left: 60 + scaleMargin
47304
47638
  };
47305
- const markerLabelY = markerReserve ? -(topScaleH + MARKER_ROW_H / 2) : 0;
47306
- const eraLabelY = eraReserve ? -(topScaleH + markerReserve + ERA_ROW_H / 2) : 0;
47307
47639
  const innerWidth = width - margin.left - margin.right;
47308
47640
  const innerHeight = height - margin.top - margin.bottom;
47309
- const rowH = Math.min(28, innerHeight / sorted.length);
47310
- const xScale = d3Scale2.scaleLinear().domain([minDate - datePadding, maxDate + datePadding]).range([0, innerWidth]);
47311
- const svg = d3Selection22.select(container).append("svg").attr("width", width).attr("height", height).style("background", bgColor);
47641
+ const axisX = 20;
47642
+ const yScale = d3Scale2.scaleLinear().domain([minDate - datePadding, maxDate + datePadding]).range([0, innerHeight]);
47643
+ const sorted = timelineEvents.slice().sort((a, b) => parseTimelineDate(a.date) - parseTimelineDate(b.date));
47644
+ 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);
47312
47645
  const g = svg.append("g").attr("transform", `translate(${margin.left},${margin.top})`);
47313
47646
  renderChartTitle(
47314
47647
  svg,
@@ -47321,36 +47654,34 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
47321
47654
  renderEras(
47322
47655
  g,
47323
47656
  timelineEras,
47324
- xScale,
47325
- false,
47657
+ yScale,
47658
+ true,
47326
47659
  innerWidth,
47327
47660
  innerHeight,
47328
47661
  (s, e) => fadeToEra(g, s, e),
47329
47662
  () => fadeReset(g),
47330
47663
  timelineScale,
47331
47664
  tooltip,
47332
- palette,
47333
- eraReserve ? eraLabelY : void 0
47665
+ palette
47334
47666
  );
47335
47667
  renderMarkers(
47336
47668
  g,
47337
47669
  timelineMarkers,
47338
- xScale,
47339
- false,
47670
+ yScale,
47671
+ true,
47340
47672
  innerWidth,
47341
47673
  innerHeight,
47342
47674
  (d) => fadeToMarker(g, d),
47343
47675
  () => fadeReset(g),
47344
47676
  timelineScale,
47345
47677
  tooltip,
47346
- palette,
47347
- markerReserve ? markerLabelY : void 0
47678
+ palette
47348
47679
  );
47349
47680
  if (timelineScale) {
47350
47681
  renderTimeScale(
47351
47682
  g,
47352
- xScale,
47353
- false,
47683
+ yScale,
47684
+ true,
47354
47685
  innerWidth,
47355
47686
  innerHeight,
47356
47687
  textColor,
@@ -47361,7 +47692,6 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
47361
47692
  );
47362
47693
  }
47363
47694
  if (timelineGroups.length > 0) {
47364
- const legendY = timelineScale ? -75 : -55;
47365
47695
  renderTimelineGroupLegend(
47366
47696
  g,
47367
47697
  timelineGroups,
@@ -47369,65 +47699,46 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
47369
47699
  textColor,
47370
47700
  palette,
47371
47701
  isDark,
47372
- legendY,
47702
+ -55,
47373
47703
  (name) => fadeToGroup(g, name),
47374
47704
  () => fadeReset(g)
47375
47705
  );
47376
47706
  }
47377
- sorted.forEach((ev, i) => {
47378
- const y = i * rowH + rowH / 2;
47379
- const x = xScale(parseTimelineDate(ev.date));
47707
+ 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");
47708
+ for (const ev of sorted) {
47709
+ const y = yScale(parseTimelineDate(ev.date));
47380
47710
  const color = eventColor(ev);
47381
47711
  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(
47382
47712
  "data-end-date",
47383
47713
  ev.endDate ? String(parseTimelineDate(ev.endDate)) : null
47384
47714
  ).style("cursor", "pointer").on("mouseenter", function(event) {
47385
47715
  if (ev.group && timelineGroups.length > 0) fadeToGroup(g, ev.group);
47386
- if (timelineScale) {
47387
- showEventDatesOnScale(
47388
- g,
47389
- xScale,
47390
- ev.date,
47391
- ev.endDate,
47392
- innerHeight,
47393
- color
47394
- );
47395
- } else {
47396
- showTooltip(tooltip, buildEventTooltipHtml(ev), event);
47397
- }
47716
+ showTooltip(tooltip, buildEventTooltipHtml(ev), event);
47398
47717
  }).on("mouseleave", function() {
47399
47718
  fadeReset(g);
47400
- if (timelineScale) {
47401
- hideEventDatesOnScale(g);
47402
- } else {
47403
- hideTooltip(tooltip);
47404
- }
47719
+ hideTooltip(tooltip);
47405
47720
  }).on("mousemove", function(event) {
47406
- if (!timelineScale) {
47407
- showTooltip(tooltip, buildEventTooltipHtml(ev), event);
47408
- }
47721
+ showTooltip(tooltip, buildEventTooltipHtml(ev), event);
47409
47722
  }).on("click", () => {
47410
47723
  if (onClickItem && ev.lineNumber) onClickItem(ev.lineNumber);
47411
47724
  });
47412
47725
  setTagAttrs(evG, ev);
47413
47726
  if (ev.endDate) {
47414
- const x2 = xScale(parseTimelineDate(ev.endDate));
47415
- const rectW = Math.max(x2 - x, 4);
47416
- const estLabelWidth = ev.label.length * 7 + 16;
47417
- const labelFitsInside = rectW >= estLabelWidth;
47727
+ const y2 = yScale(parseTimelineDate(ev.endDate));
47728
+ const rectH = Math.max(y2 - y, 4);
47418
47729
  let fill2 = shapeFill(palette, color, isDark, { solid });
47419
47730
  let stroke2 = color;
47420
47731
  if (ev.uncertain) {
47421
- const gradientId = `uncertain-ts-${ev.lineNumber}`;
47422
- const strokeGradientId = `uncertain-ts-s-${ev.lineNumber}`;
47732
+ const gradientId = `uncertain-v-${ev.lineNumber}`;
47733
+ const strokeGradientId = `uncertain-v-s-${ev.lineNumber}`;
47423
47734
  const defs = svg.select("defs").node() || svg.append("defs").node();
47424
47735
  const defsEl = d3Selection22.select(defs);
47425
- defsEl.append("linearGradient").attr("id", gradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "100%").attr("y2", "0%").selectAll("stop").data([
47736
+ defsEl.append("linearGradient").attr("id", gradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "0%").attr("y2", "100%").selectAll("stop").data([
47426
47737
  { offset: "0%", opacity: 1 },
47427
47738
  { offset: "80%", opacity: 1 },
47428
47739
  { offset: "100%", opacity: 0 }
47429
47740
  ]).enter().append("stop").attr("offset", (d) => d.offset).attr("stop-color", mix(color, bg, 30)).attr("stop-opacity", (d) => d.opacity);
47430
- defsEl.append("linearGradient").attr("id", strokeGradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "100%").attr("y2", "0%").selectAll("stop").data([
47741
+ defsEl.append("linearGradient").attr("id", strokeGradientId).attr("x1", "0%").attr("y1", "0%").attr("x2", "0%").attr("y2", "100%").selectAll("stop").data([
47431
47742
  { offset: "0%", opacity: 1 },
47432
47743
  { offset: "80%", opacity: 1 },
47433
47744
  { offset: "100%", opacity: 0 }
@@ -47435,206 +47746,100 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
47435
47746
  fill2 = `url(#${gradientId})`;
47436
47747
  stroke2 = `url(#${strokeGradientId})`;
47437
47748
  }
47438
- 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);
47439
- if (labelFitsInside) {
47440
- 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);
47441
- } else {
47442
- const wouldFlipLeft = x + rectW > innerWidth * 0.6;
47443
- const labelFitsLeft = x - 6 - estLabelWidth > 0;
47444
- const flipLeft = wouldFlipLeft && labelFitsLeft;
47445
- 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);
47446
- }
47749
+ 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);
47750
+ 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);
47447
47751
  } else {
47448
- const estLabelWidth = ev.label.length * 7;
47449
- const wouldFlipLeft = x > innerWidth * 0.6;
47450
- const labelFitsLeft = x - 10 - estLabelWidth > 0;
47451
- const flipLeft = wouldFlipLeft && labelFitsLeft;
47452
- 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);
47453
- 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);
47454
- }
47455
- });
47456
- }
47457
- if (parsed.timelineTagGroups.length > 0) {
47458
- const LG_HEIGHT = LEGEND_HEIGHT;
47459
- const LG_PILL_PAD = LEGEND_PILL_PAD;
47460
- const LG_PILL_FONT_SIZE = LEGEND_PILL_FONT_SIZE;
47461
- const LG_CAPSULE_PAD = LEGEND_CAPSULE_PAD;
47462
- const LG_DOT_R = LEGEND_DOT_R;
47463
- const LG_ENTRY_FONT_SIZE = LEGEND_ENTRY_FONT_SIZE;
47464
- const LG_ENTRY_DOT_GAP = LEGEND_ENTRY_DOT_GAP;
47465
- const LG_ENTRY_TRAIL = LEGEND_ENTRY_TRAIL;
47466
- const LG_ICON_W = 20;
47467
- const mainSvg = d3Selection22.select(container).select("svg");
47468
- const mainG = mainSvg.select("g");
47469
- if (!mainSvg.empty() && !mainG.empty()) {
47470
- let drawSwimlaneIcon4 = function(parent, x, y, isSwimActive) {
47471
- const iconG = parent.append("g").attr("class", "tl-swimlane-icon").attr("transform", `translate(${x}, ${y})`).style("cursor", "pointer");
47472
- const barColor = isSwimActive ? palette.primary : palette.textMuted;
47473
- const barOpacity = isSwimActive ? 1 : 0.35;
47474
- const bars = [
47475
- { y: 0, w: 8 },
47476
- { y: 4, w: 12 },
47477
- { y: 8, w: 6 }
47478
- ];
47479
- for (const bar of bars) {
47480
- 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);
47481
- }
47482
- return iconG;
47483
- }, relayout2 = function() {
47484
- renderTimeline(
47485
- container,
47486
- parsed,
47487
- palette,
47488
- isDark,
47489
- onClickItem,
47490
- exportDims,
47491
- currentActiveGroup,
47492
- currentSwimlaneGroup,
47493
- onTagStateChange,
47494
- viewMode
47495
- );
47496
- }, drawLegend2 = function() {
47497
- mainSvg.selectAll(".tl-tag-legend-group").remove();
47498
- mainSvg.selectAll(".tl-tag-legend-container").remove();
47499
- const effectiveColorKey = (currentActiveGroup ?? currentSwimlaneGroup)?.toLowerCase() ?? null;
47500
- const visibleGroups = viewMode ? legendGroups.filter(
47501
- (lg) => effectiveColorKey != null && lg.group.name.toLowerCase() === effectiveColorKey
47502
- ) : legendGroups;
47503
- if (visibleGroups.length === 0) return;
47504
- const legendContainer = mainSvg.append("g").attr("class", "tl-tag-legend-container");
47505
- if (currentActiveGroup) {
47506
- legendContainer.attr(
47507
- "data-legend-active",
47508
- currentActiveGroup.toLowerCase()
47509
- );
47510
- }
47511
- const iconAddon = viewMode ? 0 : LG_ICON_W;
47512
- const centralGroups = visibleGroups.map((lg) => ({
47513
- name: lg.group.name,
47514
- entries: lg.group.entries.map((e) => ({
47515
- value: e.value,
47516
- color: e.color
47517
- }))
47518
- }));
47519
- const centralActive = viewMode ? effectiveColorKey : currentActiveGroup;
47520
- const centralConfig = {
47521
- groups: centralGroups,
47522
- position: { placement: "top-center", titleRelation: "below-title" },
47523
- mode: "fixed",
47524
- capsulePillAddonWidth: iconAddon
47525
- };
47526
- const centralState = { activeGroup: centralActive };
47527
- const centralCallbacks = viewMode ? {} : {
47528
- onGroupToggle: (groupName) => {
47529
- currentActiveGroup = currentActiveGroup === groupName.toLowerCase() ? null : groupName.toLowerCase();
47530
- drawLegend2();
47531
- recolorEvents2();
47532
- onTagStateChange?.(currentActiveGroup, currentSwimlaneGroup);
47533
- },
47534
- onEntryHover: (groupName, entryValue) => {
47535
- const tagKey = groupName.toLowerCase();
47536
- if (entryValue) {
47537
- const tagVal = entryValue.toLowerCase();
47538
- fadeToTagValue(mainG, tagKey, tagVal);
47539
- mainSvg.selectAll("[data-legend-entry]").each(function() {
47540
- const el = d3Selection22.select(this);
47541
- const ev = el.attr("data-legend-entry");
47542
- const eg = el.attr("data-tag-group") ?? el.node()?.closest?.("[data-tag-group]")?.getAttribute("data-tag-group");
47543
- el.attr(
47544
- "opacity",
47545
- eg === tagKey && ev === tagVal ? 1 : FADE_OPACITY3
47546
- );
47547
- });
47548
- } else {
47549
- fadeReset(mainG);
47550
- mainSvg.selectAll("[data-legend-entry]").attr("opacity", 1);
47551
- }
47552
- },
47553
- onGroupRendered: (groupName, groupEl, isActive) => {
47554
- const groupKey = groupName.toLowerCase();
47555
- groupEl.attr("data-tag-group", groupKey);
47556
- if (isActive && !viewMode) {
47557
- const isSwimActive = currentSwimlaneGroup != null && currentSwimlaneGroup.toLowerCase() === groupKey;
47558
- const pillWidth3 = measureLegendText(groupName, LG_PILL_FONT_SIZE) + LG_PILL_PAD;
47559
- const pillXOff = LG_CAPSULE_PAD;
47560
- const iconX = pillXOff + pillWidth3 + 5;
47561
- const iconY = (LG_HEIGHT - 10) / 2;
47562
- const iconEl = drawSwimlaneIcon4(
47563
- groupEl,
47564
- iconX,
47565
- iconY,
47566
- isSwimActive
47567
- );
47568
- iconEl.attr("data-swimlane-toggle", groupKey).on("click", (event) => {
47569
- event.stopPropagation();
47570
- currentSwimlaneGroup = currentSwimlaneGroup === groupKey ? null : groupKey;
47571
- onTagStateChange?.(
47572
- currentActiveGroup,
47573
- currentSwimlaneGroup
47574
- );
47575
- relayout2();
47576
- });
47577
- }
47578
- }
47579
- };
47580
- const legendInnerG = legendContainer.append("g").attr("transform", `translate(0, ${legendY})`);
47581
- renderLegendD3(
47582
- legendInnerG,
47583
- centralConfig,
47584
- centralState,
47585
- palette,
47586
- isDark,
47587
- centralCallbacks,
47588
- width
47589
- );
47590
- }, recolorEvents2 = function() {
47591
- const colorTG = currentActiveGroup ?? swimlaneTagGroup ?? null;
47592
- mainG.selectAll(".tl-event").each(function() {
47593
- const el = d3Selection22.select(this);
47594
- const lineNum = el.attr("data-line-number");
47595
- const ev = lineNum ? eventByLine.get(lineNum) : void 0;
47596
- if (!ev) return;
47597
- let color;
47598
- if (colorTG) {
47599
- const tagColor = resolveTagColor(
47600
- ev.metadata,
47601
- parsed.timelineTagGroups,
47602
- colorTG
47603
- );
47604
- color = tagColor ?? (ev.group && groupColorMap.has(ev.group) ? groupColorMap.get(ev.group) : textColor);
47605
- } else {
47606
- color = ev.group && groupColorMap.has(ev.group) ? groupColorMap.get(ev.group) : textColor;
47607
- }
47608
- el.selectAll("rect").attr("fill", shapeFill(palette, color, isDark, { solid })).attr("stroke", color);
47609
- el.selectAll("circle:not(.tl-event-point-outline)").attr("fill", shapeFill(palette, color, isDark, { solid })).attr("stroke", color);
47610
- });
47611
- };
47612
- var drawSwimlaneIcon3 = drawSwimlaneIcon4, relayout = relayout2, drawLegend = drawLegend2, recolorEvents = recolorEvents2;
47613
- const legendY = title ? 50 : 10;
47614
- const legendGroups = parsed.timelineTagGroups.map((g) => {
47615
- const pillW = measureLegendText(g.name, LG_PILL_FONT_SIZE) + LG_PILL_PAD;
47616
- const iconSpace = viewMode ? 8 : LG_ICON_W + 4;
47617
- let entryX = LG_CAPSULE_PAD + pillW + iconSpace;
47618
- for (const entry of g.entries) {
47619
- const textX = entryX + LG_DOT_R * 2 + LG_ENTRY_DOT_GAP;
47620
- entryX = textX + measureLegendText(entry.value, LG_ENTRY_FONT_SIZE) + LG_ENTRY_TRAIL;
47621
- }
47622
- return {
47623
- group: g,
47624
- minifiedWidth: pillW,
47625
- expandedWidth: entryX + LG_CAPSULE_PAD
47626
- };
47627
- });
47628
- let currentActiveGroup = activeTagGroup ?? null;
47629
- let currentSwimlaneGroup = swimlaneTagGroup ?? null;
47630
- const eventByLine = /* @__PURE__ */ new Map();
47631
- for (const ev of timelineEvents) {
47632
- eventByLine.set(String(ev.lineNumber), ev);
47752
+ 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);
47753
+ evG.append("text").attr("x", axisX + 16).attr("y", y).attr("dy", "0.35em").attr("fill", textColor).attr("font-size", "11px").text(ev.label);
47633
47754
  }
47634
- drawLegend2();
47755
+ evG.append("text").attr("x", axisX - 14).attr(
47756
+ "y",
47757
+ ev.endDate ? yScale(parseTimelineDate(ev.date)) + Math.max(
47758
+ yScale(parseTimelineDate(ev.endDate)) - yScale(parseTimelineDate(ev.date)),
47759
+ 4
47760
+ ) / 2 : y
47761
+ ).attr("dy", "0.35em").attr("text-anchor", "end").attr("fill", mutedColor).attr("font-size", "10px").text(ev.date + (ev.endDate ? `\u2192${ev.endDate}` : ""));
47635
47762
  }
47636
47763
  }
47637
47764
  }
47765
+ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportDims, activeTagGroup, swimlaneTagGroup, onTagStateChange, viewMode) {
47766
+ const setup = setupTimeline(
47767
+ container,
47768
+ parsed,
47769
+ palette,
47770
+ isDark,
47771
+ exportDims,
47772
+ activeTagGroup,
47773
+ swimlaneTagGroup
47774
+ );
47775
+ if (!setup) return;
47776
+ swimlaneTagGroup = setup.swimlaneTagGroup;
47777
+ const { isVertical, tagLanes } = setup;
47778
+ const hovers = makeTimelineHoverHelpers();
47779
+ if (isVertical) {
47780
+ renderTimelineVertical(
47781
+ container,
47782
+ parsed,
47783
+ palette,
47784
+ isDark,
47785
+ setup,
47786
+ hovers,
47787
+ onClickItem,
47788
+ exportDims,
47789
+ swimlaneTagGroup,
47790
+ activeTagGroup,
47791
+ onTagStateChange,
47792
+ viewMode
47793
+ );
47794
+ return;
47795
+ }
47796
+ const useGroupedHorizontal = tagLanes != null || parsed.timelineSort === "group" && parsed.timelineGroups.length > 0;
47797
+ if (useGroupedHorizontal) {
47798
+ renderTimelineHorizontalGrouped(
47799
+ container,
47800
+ parsed,
47801
+ palette,
47802
+ isDark,
47803
+ setup,
47804
+ hovers,
47805
+ onClickItem,
47806
+ exportDims,
47807
+ swimlaneTagGroup,
47808
+ activeTagGroup,
47809
+ onTagStateChange,
47810
+ viewMode
47811
+ );
47812
+ } else {
47813
+ renderTimelineHorizontalTimeSort(
47814
+ container,
47815
+ parsed,
47816
+ palette,
47817
+ isDark,
47818
+ setup,
47819
+ hovers,
47820
+ onClickItem,
47821
+ exportDims,
47822
+ swimlaneTagGroup,
47823
+ activeTagGroup,
47824
+ onTagStateChange,
47825
+ viewMode
47826
+ );
47827
+ }
47828
+ renderTimelineTagLegendOverlay(
47829
+ container,
47830
+ parsed,
47831
+ palette,
47832
+ isDark,
47833
+ setup,
47834
+ hovers,
47835
+ onClickItem,
47836
+ exportDims,
47837
+ swimlaneTagGroup,
47838
+ activeTagGroup,
47839
+ onTagStateChange,
47840
+ viewMode
47841
+ );
47842
+ }
47638
47843
  function getRotateFn(mode) {
47639
47844
  if (mode === "mixed") return () => Math.random() > 0.5 ? 0 : 90;
47640
47845
  if (mode === "angled") return () => Math.round(Math.random() * 30 - 15);
@@ -47805,7 +48010,7 @@ function regionCentroid(circles, inside) {
47805
48010
  }
47806
48011
  return { x: sx / count, y: sy / count };
47807
48012
  }
47808
- function renderVenn(container, parsed, palette, isDark, onClickItem, exportDims) {
48013
+ function renderVenn(container, parsed, palette, _isDark, onClickItem, exportDims) {
47809
48014
  const { vennSets, vennOverlaps } = parsed;
47810
48015
  const title = parsed.noTitle ? null : parsed.title;
47811
48016
  if (vennSets.length < 2 || vennSets.length > 3) return;
@@ -48039,7 +48244,7 @@ function renderVenn(container, parsed, palette, isDark, onClickItem, exportDims)
48039
48244
  };
48040
48245
  const gcx = circles.reduce((s, c) => s + c.x, 0) / n;
48041
48246
  const gcy = circles.reduce((s, c) => s + c.y, 0) / n;
48042
- function exclusiveHSpan(px, py, ci) {
48247
+ function exclusiveHSpan(_px, py, ci) {
48043
48248
  const dy = py - circles[ci].y;
48044
48249
  const halfChord = Math.sqrt(
48045
48250
  Math.max(0, circles[ci].r * circles[ci].r - dy * dy)
@@ -48952,9 +49157,9 @@ async function renderForExport(content, theme, palette, viewState, options) {
48952
49157
  blHiddenTagValues.set(k, new Set(v));
48953
49158
  }
48954
49159
  }
48955
- const { layoutBoxesAndLines: layoutBoxesAndLines2 } = await Promise.resolve().then(() => (init_layout5(), layout_exports5));
48956
49160
  const { renderBoxesAndLinesForExport: renderBoxesAndLinesForExport2 } = await Promise.resolve().then(() => (init_renderer6(), renderer_exports6));
48957
- const blLayout = layoutBoxesAndLines2(blParsed);
49161
+ const { layoutBoxesAndLines: layoutBoxesAndLines2 } = await Promise.resolve().then(() => (init_layout5(), layout_exports5));
49162
+ const blLayout = await layoutBoxesAndLines2(blParsed);
48958
49163
  const PADDING3 = 20;
48959
49164
  const titleOffset = blParsed.title ? 40 : 0;
48960
49165
  const exportWidth = blLayout.width + PADDING3 * 2;
@@ -50046,7 +50251,6 @@ __export(internal_exports, {
50046
50251
  ALL_CHART_TYPES: () => ALL_CHART_TYPES,
50047
50252
  AMBIGUITY_THRESHOLD: () => AMBIGUITY_THRESHOLD,
50048
50253
  ARROW_DIAGNOSTIC_CODES: () => ARROW_DIAGNOSTIC_CODES,
50049
- BETA_CHART_IDS: () => BETA_CHART_IDS,
50050
50254
  CHART_TYPES: () => CHART_TYPES,
50051
50255
  CHART_TYPE_DESCRIPTIONS: () => CHART_TYPE_DESCRIPTIONS,
50052
50256
  COMPLETION_REGISTRY: () => COMPLETION_REGISTRY,
@@ -50303,6 +50507,8 @@ __export(internal_exports, {
50303
50507
  validateLabelCharacters: () => validateLabelCharacters
50304
50508
  });
50305
50509
  module.exports = __toCommonJS(internal_exports);
50510
+
50511
+ // src/advanced.ts
50306
50512
  init_diagnostics();
50307
50513
  init_arrows();
50308
50514
 
@@ -50373,7 +50579,7 @@ async function render(content, options) {
50373
50579
  return { svg, diagnostics };
50374
50580
  }
50375
50581
 
50376
- // src/internal.ts
50582
+ // src/advanced.ts
50377
50583
  init_chart_types();
50378
50584
 
50379
50585
  // src/chart-type-scoring.ts
@@ -50450,7 +50656,7 @@ function suggestChartTypes(prompt) {
50450
50656
  };
50451
50657
  }
50452
50658
 
50453
- // src/internal.ts
50659
+ // src/advanced.ts
50454
50660
  init_dgmo_router();
50455
50661
  init_chart();
50456
50662
  init_echarts();
@@ -50502,7 +50708,7 @@ function collapseStateGroups(parsed, collapsedGroups) {
50502
50708
  };
50503
50709
  }
50504
50710
 
50505
- // src/internal.ts
50711
+ // src/advanced.ts
50506
50712
  init_parser2();
50507
50713
  init_layout3();
50508
50714
  init_renderer4();
@@ -50580,7 +50786,7 @@ function collapseBoxesAndLines(parsed, collapsedGroups) {
50580
50786
  };
50581
50787
  }
50582
50788
 
50583
- // src/internal.ts
50789
+ // src/advanced.ts
50584
50790
  init_parser7();
50585
50791
  init_layout2();
50586
50792
  init_renderer2();
@@ -50722,7 +50928,7 @@ function validateComputed(computed) {
50722
50928
  return diagnostics;
50723
50929
  }
50724
50930
 
50725
- // src/internal.ts
50931
+ // src/advanced.ts
50726
50932
  init_roles();
50727
50933
  init_layout10();
50728
50934
  init_renderer10();
@@ -50758,7 +50964,7 @@ function normalizePertSourceForShare(dsl) {
50758
50964
  return out.join("\n");
50759
50965
  }
50760
50966
 
50761
- // src/internal.ts
50967
+ // src/advanced.ts
50762
50968
  init_monte_carlo();
50763
50969
  init_renderer11();
50764
50970
  init_collapse();
@@ -51286,7 +51492,7 @@ function mergeTagGroups(inline, tagsFile, imported) {
51286
51492
  return Array.from(seen.values());
51287
51493
  }
51288
51494
 
51289
- // src/internal.ts
51495
+ // src/advanced.ts
51290
51496
  init_layout9();
51291
51497
  init_flowchart_renderer();
51292
51498
  init_echarts();
@@ -51399,7 +51605,7 @@ init_parser8();
51399
51605
  init_parser2();
51400
51606
  init_parser10();
51401
51607
  init_parsing();
51402
- init_dgmo_router();
51608
+ init_chart_types();
51403
51609
  var extractorRegistry = /* @__PURE__ */ new Map();
51404
51610
  function registerExtractor(kind, fn) {
51405
51611
  extractorRegistry.set(kind, fn);
@@ -51878,9 +52084,12 @@ for (const [type, spec] of COMPLETION_REGISTRY) {
51878
52084
  };
51879
52085
  }
51880
52086
  }
52087
+ var CHART_TYPE_DESCRIPTIONS2 = Object.fromEntries(
52088
+ chartTypes.map((c) => [c.id, c.description])
52089
+ );
51881
52090
  var CHART_TYPES = [...ALL_CHART_TYPES].filter((t) => t !== "multi-line").map((name) => ({
51882
52091
  name,
51883
- description: CHART_TYPE_DESCRIPTIONS[name] ?? name
52092
+ description: CHART_TYPE_DESCRIPTIONS2[name] ?? name
51884
52093
  }));
51885
52094
  var ENTITY_TYPES = /* @__PURE__ */ new Map([
51886
52095
  [
@@ -52586,7 +52795,7 @@ function extractJourneyMapSymbols(docText) {
52586
52795
  };
52587
52796
  }
52588
52797
 
52589
- // src/internal.ts
52798
+ // src/advanced.ts
52590
52799
  init_parsing();
52591
52800
  init_palettes();
52592
52801
 
@@ -52597,14 +52806,13 @@ var themes = {
52597
52806
  transparent: "transparent"
52598
52807
  };
52599
52808
 
52600
- // src/internal.ts
52809
+ // src/advanced.ts
52601
52810
  init_dgmo_router();
52602
52811
  // Annotate the CommonJS export names for ESM import in node:
52603
52812
  0 && (module.exports = {
52604
52813
  ALL_CHART_TYPES,
52605
52814
  AMBIGUITY_THRESHOLD,
52606
52815
  ARROW_DIAGNOSTIC_CODES,
52607
- BETA_CHART_IDS,
52608
52816
  CHART_TYPES,
52609
52817
  CHART_TYPE_DESCRIPTIONS,
52610
52818
  COMPLETION_REGISTRY,