@diagrammo/dgmo 0.36.0 → 0.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/.cursorrules +3 -0
  2. package/.github/copilot-instructions.md +3 -0
  3. package/.windsurfrules +3 -0
  4. package/SKILL.md +3 -0
  5. package/dist/advanced.cjs +1058 -135
  6. package/dist/advanced.d.cts +122 -8
  7. package/dist/advanced.d.ts +122 -8
  8. package/dist/advanced.js +1055 -133
  9. package/dist/auto.cjs +1047 -132
  10. package/dist/auto.js +96 -95
  11. package/dist/auto.mjs +1048 -130
  12. package/dist/cli.cjs +117 -116
  13. package/dist/editor.cjs +4 -1
  14. package/dist/editor.js +4 -1
  15. package/dist/highlight.cjs +3 -0
  16. package/dist/highlight.js +3 -0
  17. package/dist/index.cjs +1043 -131
  18. package/dist/index.js +1044 -129
  19. package/docs/ai-integration.md +3 -0
  20. package/docs/language-reference.md +106 -7
  21. package/gallery/fixtures/map-coastline.dgmo +2 -2
  22. package/gallery/fixtures/map-route.dgmo +5 -5
  23. package/gallery/fixtures/treemap-branch.dgmo +15 -0
  24. package/gallery/fixtures/treemap-heat.dgmo +12 -0
  25. package/gallery/fixtures/treemap-tag-heat.dgmo +21 -0
  26. package/gallery/fixtures/treemap-tags.dgmo +18 -0
  27. package/package.json +1 -1
  28. package/src/advanced.ts +11 -0
  29. package/src/boxes-and-lines/layout-search.ts +19 -1
  30. package/src/chart-type-registry.ts +4 -0
  31. package/src/chart-types.ts +5 -0
  32. package/src/completion.ts +64 -0
  33. package/src/d3.ts +30 -18
  34. package/src/editor/highlight-api.ts +2 -0
  35. package/src/editor/keywords.ts +3 -0
  36. package/src/infra/parser.ts +95 -38
  37. package/src/map/dimensions.ts +19 -2
  38. package/src/map/layout.ts +91 -7
  39. package/src/map/parser.ts +51 -29
  40. package/src/map/renderer.ts +10 -0
  41. package/src/map/types.ts +9 -8
  42. package/src/treemap/layout.ts +189 -0
  43. package/src/treemap/parser.ts +475 -0
  44. package/src/treemap/renderer.ts +698 -0
  45. package/src/treemap/types.ts +57 -0
  46. package/src/utils/parsing.ts +1 -0
  47. package/src/utils/reserved-key-registry.ts +5 -0
package/dist/index.cjs CHANGED
@@ -602,7 +602,7 @@ function withTagAliases(base, aliases) {
602
602
  function isReservedKey(registry, key) {
603
603
  return registry.keys.has(key) || registry.tagAliases.has(key);
604
604
  }
605
- var SEQUENCE_REGISTRY, INFRA_REGISTRY, MAP_REGISTRY, ORG_REGISTRY, C4_REGISTRY, ER_REGISTRY, KANBAN_REGISTRY, SITEMAP_REGISTRY, GANTT_REGISTRY, PERT_REGISTRY, BOXES_AND_LINES_REGISTRY, TIMELINE_REGISTRY, MINDMAP_REGISTRY, TECH_RADAR_REGISTRY, CYCLE_REGISTRY, JOURNEY_MAP_REGISTRY, PYRAMID_REGISTRY, RING_REGISTRY, RACI_REGISTRY;
605
+ var SEQUENCE_REGISTRY, INFRA_REGISTRY, MAP_REGISTRY, ORG_REGISTRY, C4_REGISTRY, ER_REGISTRY, KANBAN_REGISTRY, SITEMAP_REGISTRY, GANTT_REGISTRY, PERT_REGISTRY, BOXES_AND_LINES_REGISTRY, TIMELINE_REGISTRY, MINDMAP_REGISTRY, TECH_RADAR_REGISTRY, CYCLE_REGISTRY, JOURNEY_MAP_REGISTRY, PYRAMID_REGISTRY, RING_REGISTRY, TREEMAP_REGISTRY, RACI_REGISTRY;
606
606
  var init_reserved_key_registry = __esm({
607
607
  "src/utils/reserved-key-registry.ts"() {
608
608
  "use strict";
@@ -721,6 +721,7 @@ var init_reserved_key_registry = __esm({
721
721
  "color",
722
722
  "description"
723
723
  ]);
724
+ TREEMAP_REGISTRY = staticRegistry(["heat"]);
724
725
  RACI_REGISTRY = staticRegistry([
725
726
  "color",
726
727
  "description"
@@ -1150,6 +1151,7 @@ var init_parsing = __esm({
1150
1151
  "journey-map",
1151
1152
  "pyramid",
1152
1153
  "ring",
1154
+ "treemap",
1153
1155
  "raci",
1154
1156
  "rasci",
1155
1157
  "daci",
@@ -11809,6 +11811,10 @@ var init_chart_types = __esm({
11809
11811
  id: "ring",
11810
11812
  description: "Concentric rings showing nested or hierarchical categories (read core-out)"
11811
11813
  },
11814
+ {
11815
+ id: "treemap",
11816
+ description: "Nested rectangles sized by value \u2014 show a hierarchy\u2019s proportions (budgets, disk usage, portfolios) with color by category, value heatmap, or branch"
11817
+ },
11812
11818
  {
11813
11819
  id: "map",
11814
11820
  description: "Geographic concept map: highlight/score regions, drop points of interest, connect with routes or edges"
@@ -16665,6 +16671,7 @@ function parseInfra(content) {
16665
16671
  let currentGroup = null;
16666
16672
  let currentTagGroup = null;
16667
16673
  let baseIndent = 0;
16674
+ let firstLineConsumed = false;
16668
16675
  function finishCurrentNode() {
16669
16676
  if (!currentNode) return;
16670
16677
  const key = currentNode.id;
@@ -16672,7 +16679,8 @@ function parseInfra(content) {
16672
16679
  if (existing) {
16673
16680
  const incomingDisplay = displayName(currentNode.label);
16674
16681
  const existingDisplay = displayName(existing.label);
16675
- if (incomingDisplay !== existingDisplay) {
16682
+ const isAliasRef = nameAliasMap.get(currentNode.label) === key;
16683
+ if (incomingDisplay !== existingDisplay && !isAliasRef) {
16676
16684
  result.diagnostics.push(
16677
16685
  makeDgmoError(
16678
16686
  currentNode.lineNumber,
@@ -16738,19 +16746,22 @@ function parseInfra(content) {
16738
16746
  if (indent === 0 && currentNode && !trimmed.startsWith("-")) {
16739
16747
  finishCurrentNode();
16740
16748
  }
16741
- const firstLineResult = parseFirstLine(trimmed);
16742
- if (firstLineResult) {
16743
- if (firstLineResult.chartType !== "infra") {
16744
- setError(
16745
- lineNumber,
16746
- `Expected chart type 'infra', got '${firstLineResult.chartType}'`
16747
- );
16748
- }
16749
- if (firstLineResult.title) {
16750
- result.title = firstLineResult.title;
16751
- result.titleLineNumber = lineNumber;
16749
+ if (!firstLineConsumed) {
16750
+ firstLineConsumed = true;
16751
+ const firstLineResult = parseFirstLine(trimmed);
16752
+ if (firstLineResult) {
16753
+ if (firstLineResult.chartType !== "infra") {
16754
+ setError(
16755
+ lineNumber,
16756
+ `Expected chart type 'infra', got '${firstLineResult.chartType}'`
16757
+ );
16758
+ }
16759
+ if (firstLineResult.title) {
16760
+ result.title = firstLineResult.title;
16761
+ result.titleLineNumber = lineNumber;
16762
+ }
16763
+ continue;
16752
16764
  }
16753
- continue;
16754
16765
  }
16755
16766
  if (/^direction-tb$/i.test(trimmed)) {
16756
16767
  result.direction = "TB";
@@ -16816,18 +16827,20 @@ function parseInfra(content) {
16816
16827
  if (compMatch) {
16817
16828
  finishCurrentNode();
16818
16829
  finishCurrentTagGroup();
16819
- const rawName = (compMatch[1] ?? compMatch[2] ?? "").trim();
16830
+ const { qname, uname, alias: asAlias, meta } = compMatch.groups;
16831
+ const rawName = (qname ?? uname ?? "").trim();
16820
16832
  const peeled = peelInfraDecorations(rawName, lineNumber);
16821
16833
  const name = peeled.label;
16822
- const rest = compMatch[3] || "";
16834
+ const alias = asAlias ?? peeled.alias;
16835
+ const rest = meta ?? "";
16823
16836
  const { tags } = extractPipeMetadata(rest);
16824
16837
  warnUnknownMetaKeys(
16825
16838
  tags,
16826
16839
  withTagAliases(INFRA_REGISTRY, tagAliasSet),
16827
16840
  (msg) => warn(lineNumber, msg)
16828
16841
  );
16829
- const id = nodeId2(name);
16830
- if (peeled.alias) nameAliasMap.set(peeled.alias, id);
16842
+ const id = nameAliasMap.get(name) ?? nodeId2(name);
16843
+ if (alias) nameAliasMap.set(alias, id);
16831
16844
  const isEdge = EDGE_NODE_NAMES.has(id.toLowerCase());
16832
16845
  currentNode = {
16833
16846
  id,
@@ -16911,18 +16924,20 @@ function parseInfra(content) {
16911
16924
  const compMatch = trimmed.match(COMPONENT_RE);
16912
16925
  if (compMatch) {
16913
16926
  finishCurrentTagGroup();
16914
- const rawName = (compMatch[1] ?? compMatch[2] ?? "").trim();
16927
+ const { qname, uname, alias: asAlias, meta } = compMatch.groups;
16928
+ const rawName = (qname ?? uname ?? "").trim();
16915
16929
  const peeled = peelInfraDecorations(rawName, lineNumber);
16916
16930
  const name = peeled.label;
16917
- const rest = compMatch[3] || "";
16931
+ const alias = asAlias ?? peeled.alias;
16932
+ const rest = meta ?? "";
16918
16933
  const { tags: nodeTags } = extractPipeMetadata(rest);
16919
16934
  warnUnknownMetaKeys(
16920
16935
  nodeTags,
16921
16936
  withTagAliases(INFRA_REGISTRY, tagAliasSet),
16922
16937
  (msg) => warn(lineNumber, msg)
16923
16938
  );
16924
- const id = nodeId2(name);
16925
- if (peeled.alias) nameAliasMap.set(peeled.alias, id);
16939
+ const id = nameAliasMap.get(name) ?? nodeId2(name);
16940
+ if (alias) nameAliasMap.set(alias, id);
16926
16941
  const tags = currentGroup.metadata ? { ...currentGroup.metadata, ...nodeTags } : nodeTags;
16927
16942
  currentNode = {
16928
16943
  id,
@@ -17113,6 +17128,11 @@ function parseInfra(content) {
17113
17128
  }
17114
17129
  continue;
17115
17130
  }
17131
+ if (currentNode && tagAliasSet.has(normalizeName(key))) {
17132
+ const mut = nodeMutableTags.get(currentNode.id);
17133
+ if (mut) mut[tagAttrKey(key)] = rawVal;
17134
+ continue;
17135
+ }
17116
17136
  if (!INFRA_BEHAVIOR_KEYS.has(key) && !EDGE_ONLY_KEYS.has(key)) {
17117
17137
  const allKeys = [...INFRA_BEHAVIOR_KEYS, ...EDGE_ONLY_KEYS];
17118
17138
  const hint = suggest(key, allKeys);
@@ -17178,18 +17198,20 @@ function parseInfra(content) {
17178
17198
  finishCurrentNode();
17179
17199
  const compMatch = trimmed.match(COMPONENT_RE);
17180
17200
  if (compMatch) {
17181
- const rawName = (compMatch[1] ?? compMatch[2] ?? "").trim();
17201
+ const { qname, uname, alias: asAlias, meta } = compMatch.groups;
17202
+ const rawName = (qname ?? uname ?? "").trim();
17182
17203
  const peeled = peelInfraDecorations(rawName, lineNumber);
17183
17204
  const name = peeled.label;
17184
- const rest = compMatch[3] || "";
17205
+ const alias = asAlias ?? peeled.alias;
17206
+ const rest = meta ?? "";
17185
17207
  const { tags: nodeTags } = extractPipeMetadata(rest);
17186
17208
  warnUnknownMetaKeys(
17187
17209
  nodeTags,
17188
17210
  withTagAliases(INFRA_REGISTRY, tagAliasSet),
17189
17211
  (msg) => warn(lineNumber, msg)
17190
17212
  );
17191
- const id = nodeId2(name);
17192
- if (peeled.alias) nameAliasMap.set(peeled.alias, id);
17213
+ const id = nameAliasMap.get(name) ?? nodeId2(name);
17214
+ if (alias) nameAliasMap.set(alias, id);
17193
17215
  const tags = currentGroup.metadata ? { ...currentGroup.metadata, ...nodeTags } : nodeTags;
17194
17216
  currentNode = {
17195
17217
  id,
@@ -17211,18 +17233,20 @@ function parseInfra(content) {
17211
17233
  finishCurrentNode();
17212
17234
  finishCurrentTagGroup();
17213
17235
  currentGroup = null;
17214
- const rawName = (compMatch[1] ?? compMatch[2] ?? "").trim();
17236
+ const { qname, uname, alias: asAlias, meta } = compMatch.groups;
17237
+ const rawName = (qname ?? uname ?? "").trim();
17215
17238
  const peeled = peelInfraDecorations(rawName, lineNumber);
17216
17239
  const name = peeled.label;
17217
- const rest = compMatch[3] || "";
17240
+ const alias = asAlias ?? peeled.alias;
17241
+ const rest = meta ?? "";
17218
17242
  const { tags } = extractPipeMetadata(rest);
17219
17243
  warnUnknownMetaKeys(
17220
17244
  tags,
17221
17245
  withTagAliases(INFRA_REGISTRY, tagAliasSet),
17222
17246
  (msg) => warn(lineNumber, msg)
17223
17247
  );
17224
- const id = nodeId2(name);
17225
- if (peeled.alias) nameAliasMap.set(peeled.alias, id);
17248
+ const id = nameAliasMap.get(name) ?? nodeId2(name);
17249
+ if (alias) nameAliasMap.set(alias, id);
17226
17250
  currentNode = {
17227
17251
  id,
17228
17252
  label: name,
@@ -17422,7 +17446,7 @@ var init_parser15 = __esm({
17422
17446
  DEPRECATED_FANOUT_RE = /\bx(\d+)\s*$/;
17423
17447
  GROUP_RE = /^\[([^\]]+)\]\s*(?:as\s+([A-Za-z][A-Za-z0-9_]{0,11})\s*)?((?:\|.*)|(?:[a-zA-Z_]\w*\s*:.*))?$/;
17424
17448
  TAG_VALUE_RE = /^(\w[\w\s]+?)\s*$/;
17425
- COMPONENT_RE = /^(?:"([^"]+)"|([a-zA-Z_][\w -]*?))\s*((?:\|.*)|(?:[a-zA-Z_]\w*\s*:.*))?$/;
17449
+ COMPONENT_RE = /^(?:"(?<qname>[^"]+)"|(?<uname>[a-zA-Z_][\w -]*?))(?:\s+as\s+(?<alias>[A-Za-z][A-Za-z0-9_]{0,11}))?\s*(?<meta>(?:\|.*)|(?:[a-zA-Z_]\w*\s*:.*))?$/;
17426
17450
  PIPE_META_RE = /[|,]\s*(\w+)\s*:\s*([^|,]+)/g;
17427
17451
  SAMELINE_META_RE = /(?:^|[\s,])(\w+)\s*:\s*([^,]+?)(?=\s*,|\s*$)/g;
17428
17452
  PROPERTY_RE = /^([\w-]+):\s*(.+)$/;
@@ -18906,8 +18930,8 @@ function parseMap(content, palette) {
18906
18930
  continue;
18907
18931
  }
18908
18932
  if (open.route && indent > open.route.indent) {
18909
- const leg = parseLeg(trimmed, lineNumber, open.route.route.style);
18910
- open.route.route.legs.push(leg);
18933
+ const leg = parseLeg(trimmed, lineNumber);
18934
+ if (leg) open.route.route.legs.push(leg);
18911
18935
  continue;
18912
18936
  }
18913
18937
  if (open.poi && indent > open.poi.indent) {
@@ -18936,6 +18960,14 @@ function parseMap(content, palette) {
18936
18960
  Object.assign(open.poi.poi.meta, split.meta);
18937
18961
  continue;
18938
18962
  }
18963
+ if (split.name) {
18964
+ const src = open.poi.poi.alias ?? poiName(open.poi.poi.pos) ?? "the poi";
18965
+ pushError(
18966
+ lineNumber,
18967
+ `Malformed hub edge: "${trimmed}" \u2014 an indented line under a poi is an edge from "${src}" and needs an arrow glyph (\`-> dest\`, \`~> dest\`, or labeled \`-label-> dest\`). For a standalone place, declare it at the top level. (\xA724B.5)`
18968
+ );
18969
+ continue;
18970
+ }
18939
18971
  }
18940
18972
  closeBlocks();
18941
18973
  const firstWord = trimmed.split(/\s+/)[0];
@@ -18944,7 +18976,7 @@ function parseMap(content, palette) {
18944
18976
  continue;
18945
18977
  }
18946
18978
  if (DIRECTIVE_SET.has(firstWord) && !trimmed.slice(firstWord.length).trimStart().startsWith(":")) {
18947
- handleDirective(
18979
+ handleDirective2(
18948
18980
  firstWord,
18949
18981
  trimmed.slice(firstWord.length).trim(),
18950
18982
  lineNumber
@@ -18983,7 +19015,7 @@ function parseMap(content, palette) {
18983
19015
  }
18984
19016
  }
18985
19017
  return result;
18986
- function handleDirective(key, value, line11) {
19018
+ function handleDirective2(key, value, line11) {
18987
19019
  const d = result.directives;
18988
19020
  const dup = (have) => {
18989
19021
  if (have !== void 0)
@@ -19184,31 +19216,44 @@ function parseMap(content, palette) {
19184
19216
  const { tags, meta } = partitionMeta(split.meta, tagGroupNames());
19185
19217
  const originLabel = meta["label"];
19186
19218
  const originValue = meta["value"];
19187
- const style = meta["style"] === "arc" ? "arc" : "straight";
19219
+ if (meta["style"] !== void 0) {
19220
+ pushError(
19221
+ line11,
19222
+ "route header no longer takes `style:` \u2014 set leg shape with the arrow glyph instead (`~\u2026~>` for an arc leg, `-\u2026->` for a straight one). (\xA724B.6)"
19223
+ );
19224
+ }
19188
19225
  const route = {
19189
19226
  origin: pos,
19190
19227
  ...split.alias !== void 0 && { originAlias: split.alias },
19191
19228
  ...originLabel !== void 0 && { originLabel },
19192
19229
  ...originValue !== void 0 && { originValue },
19193
19230
  originTags: tags,
19194
- style,
19195
19231
  legs: [],
19196
19232
  lineNumber: line11
19197
19233
  };
19198
19234
  routes.push(route);
19199
19235
  open.route = { route, indent };
19200
19236
  }
19201
- function parseLeg(trimmed, line11, headerStyle) {
19202
- let arrowStyle = "straight";
19203
- let label;
19204
- let rest = trimmed;
19237
+ function parseLeg(trimmed, line11) {
19205
19238
  const m = trimmed.match(LEG_ARROW_RE);
19206
- if (m) {
19207
- const arr = classifyArrow(m[1], line11);
19208
- arrowStyle = arr.style;
19209
- label = arr.label;
19210
- rest = m[2];
19239
+ if (!m) {
19240
+ pushError(
19241
+ line11,
19242
+ `Malformed route leg: "${trimmed}" \u2014 a leg needs an arrow glyph (\`-> dest\`, \`~> dest\`, or labeled \`-label-> dest\` / \`~label~> dest\`). (\xA724B.6)`
19243
+ );
19244
+ return null;
19211
19245
  }
19246
+ const arr = classifyArrow(m[1], line11);
19247
+ if (!arr.directed) {
19248
+ pushError(
19249
+ line11,
19250
+ `A route leg is directional \u2014 "${trimmed}" uses an undirected glyph; use \`-> \` (straight) or \`~> \` (arc). (\xA724B.6)`
19251
+ );
19252
+ return null;
19253
+ }
19254
+ const arrowStyle = arr.style;
19255
+ const label = arr.label;
19256
+ const rest = m[2];
19212
19257
  const split = splitNameAndMeta(
19213
19258
  rest,
19214
19259
  registry(),
@@ -19224,10 +19269,9 @@ function parseMap(content, palette) {
19224
19269
  const { tags, meta } = partitionMeta(split.meta, tagGroupNames());
19225
19270
  const value = meta["value"];
19226
19271
  const destLabel = meta["label"];
19227
- const style = arrowStyle === "arc" || headerStyle === "arc" ? "arc" : "straight";
19228
19272
  return {
19229
19273
  ...label !== void 0 && { label },
19230
- style,
19274
+ style: arrowStyle,
19231
19275
  ...value !== void 0 && { value },
19232
19276
  dest: pos,
19233
19277
  ...split.alias !== void 0 && { destAlias: split.alias },
@@ -22841,6 +22885,344 @@ var init_parser25 = __esm({
22841
22885
  }
22842
22886
  });
22843
22887
 
22888
+ // src/treemap/parser.ts
22889
+ var parser_exports20 = {};
22890
+ __export(parser_exports20, {
22891
+ TREEMAP_DIAGNOSTIC_CODES: () => TREEMAP_DIAGNOSTIC_CODES,
22892
+ parseTreemap: () => parseTreemap
22893
+ });
22894
+ function isFullyQuoted(s) {
22895
+ return s.length >= 2 && (s.startsWith('"') && s.endsWith('"') || s.startsWith("'") && s.endsWith("'"));
22896
+ }
22897
+ function parseTreemap(content, palette) {
22898
+ const options = {
22899
+ heatColors: [],
22900
+ noValues: false,
22901
+ noPercent: false,
22902
+ noHeaders: false,
22903
+ noLegend: false
22904
+ };
22905
+ const result = {
22906
+ type: "treemap",
22907
+ title: null,
22908
+ titleLineNumber: null,
22909
+ roots: [],
22910
+ tagGroups: [],
22911
+ hasHeat: false,
22912
+ defaultColorMode: "branch",
22913
+ options,
22914
+ diagnostics: [],
22915
+ error: null
22916
+ };
22917
+ const fail = makeFail(result);
22918
+ const pushError = (line11, message, code) => {
22919
+ const diag = makeDgmoError(line11, message, "error", code);
22920
+ result.diagnostics.push(diag);
22921
+ if (!result.error) result.error = formatDgmoError(diag);
22922
+ };
22923
+ const pushWarning = (line11, message, code) => {
22924
+ result.diagnostics.push(makeDgmoError(line11, message, "warning", code));
22925
+ };
22926
+ if (!content?.trim()) {
22927
+ return fail(0, "No content provided");
22928
+ }
22929
+ const lines = content.split("\n");
22930
+ let contentStarted = false;
22931
+ let nodeCounter = 0;
22932
+ let currentTagGroup = null;
22933
+ const aliasMap = /* @__PURE__ */ new Map();
22934
+ const indentStack = [];
22935
+ for (let i = 0; i < lines.length; i++) {
22936
+ const line11 = lines[i];
22937
+ const lineNumber = i + 1;
22938
+ const trimmed = line11.trim();
22939
+ if (!trimmed) {
22940
+ currentTagGroup = null;
22941
+ continue;
22942
+ }
22943
+ if (trimmed.startsWith("//")) continue;
22944
+ if (!contentStarted) {
22945
+ const firstLine = parseFirstLine(trimmed);
22946
+ if (firstLine && result.titleLineNumber === null && i === 0) {
22947
+ if (firstLine.chartType !== "treemap") {
22948
+ let msg = `Expected chart type "treemap", got "${firstLine.chartType}"`;
22949
+ const hint = suggest(firstLine.chartType, ["treemap"]);
22950
+ if (hint) msg += `. ${hint}`;
22951
+ return fail(lineNumber, msg);
22952
+ }
22953
+ result.title = firstLine.title ?? null;
22954
+ result.titleLineNumber = lineNumber;
22955
+ continue;
22956
+ }
22957
+ }
22958
+ const tagBlockMatch = matchTagBlockHeading(trimmed);
22959
+ if (tagBlockMatch) {
22960
+ emitTagLegacyDiagnostic(tagBlockMatch, lineNumber, result.diagnostics);
22961
+ if (contentStarted) {
22962
+ pushError(
22963
+ lineNumber,
22964
+ "Tag groups must appear before treemap content",
22965
+ "E_TAG_DECLARED_AFTER_CONTENT"
22966
+ );
22967
+ continue;
22968
+ }
22969
+ currentTagGroup = {
22970
+ name: tagBlockMatch.name,
22971
+ ...tagBlockMatch.alias !== void 0 && {
22972
+ alias: tagBlockMatch.alias
22973
+ },
22974
+ entries: [],
22975
+ lineNumber
22976
+ };
22977
+ if (tagBlockMatch.alias) {
22978
+ aliasMap.set(
22979
+ tagBlockMatch.alias.toLowerCase(),
22980
+ tagAttrKey(tagBlockMatch.name)
22981
+ );
22982
+ }
22983
+ aliasMap.set(
22984
+ tagAttrKey(tagBlockMatch.name),
22985
+ tagAttrKey(tagBlockMatch.name)
22986
+ );
22987
+ result.tagGroups.push(currentTagGroup);
22988
+ continue;
22989
+ }
22990
+ if (currentTagGroup && !contentStarted) {
22991
+ const indent2 = measureIndent(line11);
22992
+ if (indent2 > 0) {
22993
+ const { text: cleanEntry, isDefault } = stripDefaultModifier(trimmed);
22994
+ const { label, color } = extractColor(
22995
+ cleanEntry,
22996
+ palette,
22997
+ result.diagnostics,
22998
+ lineNumber
22999
+ );
23000
+ if (isDefault) {
23001
+ currentTagGroup.defaultValue = label;
23002
+ } else if (currentTagGroup.entries.length === 0) {
23003
+ currentTagGroup.defaultValue = label;
23004
+ }
23005
+ currentTagGroup.entries.push({
23006
+ value: label,
23007
+ color: color ?? AUTO_TAG_COLOR_SENTINEL,
23008
+ lineNumber
23009
+ });
23010
+ continue;
23011
+ }
23012
+ currentTagGroup = null;
23013
+ }
23014
+ if (!contentStarted && measureIndent(line11) === 0) {
23015
+ if (handleDirective(trimmed, options, result, pushWarning, lineNumber)) {
23016
+ continue;
23017
+ }
23018
+ }
23019
+ contentStarted = true;
23020
+ currentTagGroup = null;
23021
+ const indent = measureIndent(line11);
23022
+ const node = parseNodeLine3(
23023
+ trimmed,
23024
+ lineNumber,
23025
+ ++nodeCounter,
23026
+ aliasMap,
23027
+ result.diagnostics,
23028
+ pushWarning
23029
+ );
23030
+ if (node.heat !== void 0) result.hasHeat = true;
23031
+ attachNode4(node, indent, indentStack, result);
23032
+ }
23033
+ finalizeAutoTagColors(result.tagGroups, palette);
23034
+ const allNodes = [];
23035
+ const collectAll = (nodes) => {
23036
+ for (const n of nodes) {
23037
+ allNodes.push(n);
23038
+ collectAll(n.children);
23039
+ }
23040
+ };
23041
+ collectAll(result.roots);
23042
+ for (const n of allNodes) {
23043
+ const node = n;
23044
+ const isBranch = node.children.length > 0;
23045
+ if (isBranch) {
23046
+ if (node.value !== void 0) {
23047
+ pushWarning(
23048
+ node.lineNumber,
23049
+ `"${node.label}" is a branch \u2014 its trailing number is ignored; the area is the auto-sum of its children`,
23050
+ TREEMAP_DIAGNOSTIC_CODES.BRANCH_VALUE_IGNORED
23051
+ );
23052
+ delete node.value;
23053
+ }
23054
+ } else if (node.value === void 0) {
23055
+ pushWarning(
23056
+ node.lineNumber,
23057
+ `Leaf "${node.label}" has no value \u2014 it renders with zero area`,
23058
+ TREEMAP_DIAGNOSTIC_CODES.LEAF_NO_VALUE
23059
+ );
23060
+ node.value = 0;
23061
+ } else if (node.value < 0) {
23062
+ pushError(
23063
+ node.lineNumber,
23064
+ `Leaf "${node.label}" has a negative value (${node.value}) \u2014 treemap sizes must be \u2265 0`,
23065
+ TREEMAP_DIAGNOSTIC_CODES.NEGATIVE_VALUE
23066
+ );
23067
+ }
23068
+ }
23069
+ if (result.hasHeat || options.heatLabel !== void 0) {
23070
+ result.hasHeat = true;
23071
+ }
23072
+ if (result.tagGroups.length > 0) {
23073
+ validateTagValues(allNodes, result.tagGroups, pushWarning, suggest);
23074
+ validateTagGroupNames(result.tagGroups, pushWarning);
23075
+ cascadeTagMetadata(result.roots, result.tagGroups);
23076
+ }
23077
+ result.defaultColorMode = resolveDefaultColorMode(result);
23078
+ if (result.roots.length === 0 && !result.error) {
23079
+ const diag = makeDgmoError(1, "No nodes found in treemap");
23080
+ result.diagnostics.push(diag);
23081
+ result.error = formatDgmoError(diag);
23082
+ }
23083
+ return result;
23084
+ }
23085
+ function handleDirective(trimmed, options, result, pushWarning, lineNumber) {
23086
+ const depthMatch = trimmed.match(/^depth\s+(-?\d+)\s*$/i);
23087
+ if (depthMatch) {
23088
+ const n = parseInt(depthMatch[1], 10);
23089
+ if (n >= 1) options.maxDepth = n;
23090
+ else pushWarning(lineNumber, '"depth" must be \u2265 1 \u2014 ignored');
23091
+ return true;
23092
+ }
23093
+ if (/^other-below\b/i.test(trimmed)) {
23094
+ pushWarning(
23095
+ lineNumber,
23096
+ '"other-below" is no longer supported \u2014 remove this line'
23097
+ );
23098
+ return true;
23099
+ }
23100
+ const heatMatch = trimmed.match(/^heat\s+(.+)$/i);
23101
+ if (heatMatch) {
23102
+ const { label, low, high } = peelRampColors(heatMatch[1].trim());
23103
+ options.heatLabel = label || "Value";
23104
+ const colors = [];
23105
+ if (low !== void 0) colors.push(low);
23106
+ if (high !== void 0) colors.push(high);
23107
+ options.heatColors = colors;
23108
+ result.hasHeat = true;
23109
+ return true;
23110
+ }
23111
+ const noMatch = trimmed.match(/^no-(values|percent|headers|legend)\s*$/i);
23112
+ if (noMatch) {
23113
+ const key = noMatch[1].toLowerCase();
23114
+ if (key === "values") options.noValues = true;
23115
+ else if (key === "percent") options.noPercent = true;
23116
+ else if (key === "headers") options.noHeaders = true;
23117
+ else if (key === "legend") options.noLegend = true;
23118
+ return true;
23119
+ }
23120
+ return false;
23121
+ }
23122
+ function resolveDefaultColorMode(result) {
23123
+ if (result.tagGroups.length > 0) return "tag";
23124
+ if (result.hasHeat) return "heat";
23125
+ return "branch";
23126
+ }
23127
+ function parseNodeLine3(trimmed, lineNumber, counter, aliasMap, diagnostics, pushWarning) {
23128
+ if (trimmed.includes("|")) {
23129
+ diagnostics.push(
23130
+ makeDgmoError(
23131
+ lineNumber,
23132
+ pipeOperatorRemovedMessage(),
23133
+ "error",
23134
+ METADATA_DIAGNOSTIC_CODES.PIPE_OPERATOR_REMOVED
23135
+ )
23136
+ );
23137
+ }
23138
+ const registry = withTagAliases(TREEMAP_REGISTRY, new Set(aliasMap.keys()));
23139
+ const split = splitNameAndMeta(
23140
+ trimmed,
23141
+ registry,
23142
+ aliasMap,
23143
+ void 0,
23144
+ diagnostics,
23145
+ lineNumber
23146
+ );
23147
+ warnUnknownMetaKeys(
23148
+ split.meta,
23149
+ registry,
23150
+ (msg) => diagnostics.push(makeDgmoError(lineNumber, msg, "warning")),
23151
+ split.name
23152
+ );
23153
+ const metadata = { ...split.meta };
23154
+ let heat;
23155
+ if ("heat" in metadata) {
23156
+ const h = parseFloat(metadata["heat"].replace(/_/g, ""));
23157
+ if (Number.isFinite(h)) heat = h;
23158
+ delete metadata["heat"];
23159
+ }
23160
+ const rawName = split.name;
23161
+ let label;
23162
+ let value;
23163
+ if (isFullyQuoted(rawName)) {
23164
+ label = stripQuotes(rawName);
23165
+ } else {
23166
+ const vm = rawName.match(VALUE_TOKEN_RE);
23167
+ if (vm) {
23168
+ const labelPart = vm[1].trim();
23169
+ const token = vm[2];
23170
+ if (token.includes(",")) {
23171
+ pushWarning(lineNumber, dataCommaRemovedMessage(labelPart));
23172
+ }
23173
+ const cleaned = token.replace(/[_,]/g, "");
23174
+ const parsed = parseFloat(cleaned);
23175
+ if (Number.isFinite(parsed)) {
23176
+ value = parsed;
23177
+ label = isFullyQuoted(labelPart) ? stripQuotes(labelPart) : labelPart;
23178
+ } else {
23179
+ label = rawName;
23180
+ }
23181
+ } else {
23182
+ label = rawName;
23183
+ }
23184
+ }
23185
+ return {
23186
+ id: `treemap-node-${counter}`,
23187
+ label,
23188
+ ...value !== void 0 && { value },
23189
+ ...heat !== void 0 && { heat },
23190
+ metadata,
23191
+ children: [],
23192
+ lineNumber
23193
+ };
23194
+ }
23195
+ function attachNode4(node, indent, indentStack, result) {
23196
+ while (indentStack.length > 0) {
23197
+ const top = indentStack[indentStack.length - 1];
23198
+ if (top.indent < indent) break;
23199
+ indentStack.pop();
23200
+ }
23201
+ if (indentStack.length > 0) {
23202
+ const parent = indentStack[indentStack.length - 1].node;
23203
+ parent.children.push(node);
23204
+ } else {
23205
+ result.roots.push(node);
23206
+ }
23207
+ indentStack.push({ node, indent });
23208
+ }
23209
+ var TREEMAP_DIAGNOSTIC_CODES, VALUE_TOKEN_RE;
23210
+ var init_parser26 = __esm({
23211
+ "src/treemap/parser.ts"() {
23212
+ "use strict";
23213
+ init_diagnostics();
23214
+ init_tag_groups();
23215
+ init_parsing();
23216
+ init_reserved_key_registry();
23217
+ TREEMAP_DIAGNOSTIC_CODES = {
23218
+ NEGATIVE_VALUE: "E_TREEMAP_NEGATIVE_VALUE",
23219
+ LEAF_NO_VALUE: "W_TREEMAP_LEAF_NO_VALUE",
23220
+ BRANCH_VALUE_IGNORED: "W_TREEMAP_BRANCH_VALUE_IGNORED"
23221
+ };
23222
+ VALUE_TOKEN_RE = /^(.+?)\s+(-?\d[\d_,.]*)$/;
23223
+ }
23224
+ });
23225
+
22844
23226
  // src/raci/variants.ts
22845
23227
  function inferVariant(markers) {
22846
23228
  let hasD = false;
@@ -23095,8 +23477,8 @@ var init_variants = __esm({
23095
23477
  });
23096
23478
 
23097
23479
  // src/raci/parser.ts
23098
- var parser_exports20 = {};
23099
- __export(parser_exports20, {
23480
+ var parser_exports21 = {};
23481
+ __export(parser_exports21, {
23100
23482
  allTasks: () => allTasks,
23101
23483
  parseRaci: () => parseRaci
23102
23484
  });
@@ -23617,7 +23999,7 @@ function* allTasks(parsed) {
23617
23999
  }
23618
24000
  }
23619
24001
  var RACI_CHART_TYPE_IDS, CHART_TYPE_VARIANT_LOCK, VARIANT_LOCK_DIRECTIVES, KNOWN_OPTIONS10, KNOWN_BOOLEANS7, REMOVED_BOOLEANS3, PHASE_RE2, PHASE_PALETTE_COLOR_RE, ROLE_ASSIGNMENT_RE;
23620
- var init_parser26 = __esm({
24002
+ var init_parser27 = __esm({
23621
24003
  "src/raci/parser.ts"() {
23622
24004
  "use strict";
23623
24005
  init_diagnostics();
@@ -23863,6 +24245,7 @@ var init_chart_type_registry = __esm({
23863
24245
  init_parser24();
23864
24246
  init_parser25();
23865
24247
  init_parser26();
24248
+ init_parser27();
23866
24249
  CHART_TYPE_REGISTRY = [
23867
24250
  // ── Structured diagrams ───────────────────────────────────
23868
24251
  {
@@ -24003,6 +24386,9 @@ var init_chart_type_registry = __esm({
24003
24386
  { id: "cycle", category: "visualization", parse: parseCycle },
24004
24387
  { id: "pyramid", category: "visualization", parse: parsePyramid },
24005
24388
  { id: "ring", category: "visualization", parse: parseRing },
24389
+ // Treemap: squarified hierarchy. No measure/minDims — a treemap fills whatever
24390
+ // rectangle it's given and has no intrinsic aspect/size (F11).
24391
+ { id: "treemap", category: "visualization", parse: parseTreemap },
24006
24392
  // ── Geographic map (own parser → resolver → layout → renderer) ──
24007
24393
  { id: "map", category: "visualization", parse: parseMap }
24008
24394
  ];
@@ -26735,10 +27121,10 @@ async function renderSitemapForExport(content, theme, palette) {
26735
27121
  const parsed = parseSitemap2(content, effectivePalette);
26736
27122
  if (parsed.error || parsed.roots.length === 0) return "";
26737
27123
  const sitemapLayout = layoutSitemap2(parsed, void 0, null, void 0, true);
26738
- const PADDING3 = 20;
27124
+ const PADDING4 = 20;
26739
27125
  const titleOffset = parsed.title ? 30 : 0;
26740
- const exportWidth = sitemapLayout.width + PADDING3 * 2;
26741
- const exportHeight = sitemapLayout.height + PADDING3 * 2 + titleOffset;
27126
+ const exportWidth = sitemapLayout.width + PADDING4 * 2;
27127
+ const exportHeight = sitemapLayout.height + PADDING4 * 2 + titleOffset;
26742
27128
  const container = document.createElement("div");
26743
27129
  container.style.width = `${exportWidth}px`;
26744
27130
  container.style.height = `${exportHeight}px`;
@@ -31766,6 +32152,10 @@ async function layoutBoxesAndLinesSearch(parsed, collapseInfo, opts) {
31766
32152
  const reserveEdgeLabels = opts?.reserveEdgeLabels ?? false;
31767
32153
  const onProgress = opts?.onProgress;
31768
32154
  const tick = onProgress ? () => new Promise((r) => setTimeout(r)) : () => void 0;
32155
+ const YIELD_AFTER_MS = 150;
32156
+ const YIELD_EVERY_MS = 30;
32157
+ const searchStart = performance.now();
32158
+ let lastYield = searchStart;
31769
32159
  const collapsedGroupLabels = /* @__PURE__ */ new Set();
31770
32160
  if (collapseInfo) {
31771
32161
  const missing = /* @__PURE__ */ new Set();
@@ -32195,7 +32585,11 @@ async function layoutBoxesAndLinesSearch(parsed, collapseInfo, opts) {
32195
32585
  const step = async (phase) => {
32196
32586
  if (!onProgress) return;
32197
32587
  onProgress(++progressDone, progressTotal, phase);
32198
- await tick();
32588
+ const now = performance.now();
32589
+ if (now - searchStart > YIELD_AFTER_MS && now - lastYield > YIELD_EVERY_MS) {
32590
+ lastYield = now;
32591
+ await tick();
32592
+ }
32199
32593
  };
32200
32594
  const pool = [];
32201
32595
  for (const cfg of configs) {
@@ -50585,7 +50979,7 @@ function computeEdgeLabelPosition(midAngle, radius, cx, cy, lineCount, labelPxW,
50585
50979
  };
50586
50980
  }
50587
50981
  function fitToCanvas(nodes, edges, parsed, _cx, _cy, radius, width, height, _isClockwise) {
50588
- const PADDING3 = 30;
50982
+ const PADDING4 = 30;
50589
50983
  let contentMinX = Infinity, contentMaxX = -Infinity;
50590
50984
  let contentMinY = Infinity, contentMaxY = -Infinity;
50591
50985
  for (const n of nodes) {
@@ -50627,13 +51021,13 @@ function fitToCanvas(nodes, edges, parsed, _cx, _cy, radius, width, height, _isC
50627
51021
  contentMinY = Math.min(contentMinY, le.labelY - 12);
50628
51022
  contentMaxY = Math.max(contentMaxY, le.labelY + (lineCount - 1) * 15);
50629
51023
  }
50630
- const overflowX = Math.max(0, PADDING3 - contentMinX) + Math.max(0, contentMaxX - (width - PADDING3));
50631
- const overflowY = Math.max(0, PADDING3 - contentMinY) + Math.max(0, contentMaxY - (height - PADDING3));
51024
+ const overflowX = Math.max(0, PADDING4 - contentMinX) + Math.max(0, contentMaxX - (width - PADDING4));
51025
+ const overflowY = Math.max(0, PADDING4 - contentMinY) + Math.max(0, contentMaxY - (height - PADDING4));
50632
51026
  if (overflowX <= 0 && overflowY <= 0) return null;
50633
51027
  const contentW = contentMaxX - contentMinX;
50634
51028
  const contentH = contentMaxY - contentMinY;
50635
- const availW = width - 2 * PADDING3;
50636
- const availH = height - 2 * PADDING3;
51029
+ const availW = width - 2 * PADDING4;
51030
+ const availH = height - 2 * PADDING4;
50637
51031
  const shrink = Math.min(availW / contentW, availH / contentH);
50638
51032
  const newRadius = Math.max(80, radius * shrink);
50639
51033
  return { radius: newRadius };
@@ -50831,7 +51225,7 @@ function renderCycle(container, parsed, palette, isDark, onClickItem, exportDims
50831
51225
  }
50832
51226
  edgeLabelInfo.push({ le, edge });
50833
51227
  }
50834
- const HEADER_H = 36 * layout.scale;
51228
+ const HEADER_H2 = 36 * layout.scale;
50835
51229
  const scaledNodeFont = Math.max(6, Math.round(NODE_FONT_SIZE7 * layout.scale));
50836
51230
  const scaledEdgeLabelFont = Math.max(
50837
51231
  6,
@@ -50895,10 +51289,10 @@ function renderCycle(container, parsed, palette, isDark, onClickItem, exportDims
50895
51289
  const rx = 6;
50896
51290
  nodeG.append("rect").attr("x", ln.x - nodeW / 2).attr("y", ln.y - nodeH / 2).attr("width", nodeW).attr("height", nodeH).attr("rx", rx).attr("ry", rx).attr("fill", fillColor).attr("stroke", solidColor).attr("stroke-width", 2);
50897
51291
  if (hasDesc) {
50898
- const headerCenterY = ln.y - nodeH / 2 + HEADER_H / 2;
51292
+ const headerCenterY = ln.y - nodeH / 2 + HEADER_H2 / 2;
50899
51293
  const labelText = nodeG.append("text").attr("x", ln.x).attr("y", headerCenterY + scaledNodeFont / 3).attr("text-anchor", "middle").attr("fill", textColor).attr("font-family", FONT_FAMILY).attr("font-size", scaledNodeFont).attr("font-weight", "600");
50900
51294
  renderInlineText(labelText, node.label, palette, scaledNodeFont);
50901
- const sepY = ln.y - nodeH / 2 + HEADER_H;
51295
+ const sepY = ln.y - nodeH / 2 + HEADER_H2;
50902
51296
  nodeG.append("line").attr("x1", ln.x - nodeW / 2).attr("y1", sepY).attr("x2", ln.x + nodeW / 2).attr("y2", sepY).attr("stroke", solid ? descColor : solidColor).attr("stroke-opacity", 0.3).attr("stroke-width", 1);
50903
51297
  const descStartY = sepY + 4 + scaledDescFont;
50904
51298
  const descPadX = Math.max(8, 12 * layout.scale);
@@ -53718,13 +54112,15 @@ function layoutMap(resolvedIn, data, size, opts) {
53718
54112
  labelY: lp.y
53719
54113
  };
53720
54114
  const routeLabelStyle = leg.label !== void 0 ? labelOnFill(fillAt(bow.labelX, bow.labelY)) : void 0;
54115
+ const routeVal = Number(leg.value);
53721
54116
  legs.push({
53722
54117
  d: legPath(a, b, bow.curved, bow.offset),
53723
- width: routeWidthFor(Number(leg.value)),
54118
+ width: routeWidthFor(routeVal),
53724
54119
  color: lineColor(leg.tags) ?? mix(palette.text, palette.bg, 72),
53725
54120
  arrow: true,
53726
54121
  fromId: leg.fromId,
53727
54122
  toId: leg.toId,
54123
+ ...Number.isFinite(routeVal) && routeVal > 0 && { value: routeVal },
53728
54124
  ...Object.keys(leg.tags).length > 0 && { tags: leg.tags },
53729
54125
  lineNumber: leg.lineNumber,
53730
54126
  ...leg.label !== void 0 && {
@@ -53771,6 +54167,7 @@ function layoutMap(resolvedIn, data, size, opts) {
53771
54167
  labelY: lp.y
53772
54168
  };
53773
54169
  const edgeLabelStyle = e.label !== void 0 ? labelOnFill(fillAt(bow.labelX, bow.labelY)) : void 0;
54170
+ const edgeVal = Number(e.meta["value"]);
53774
54171
  legs.push({
53775
54172
  d: legPath(a, b, bow.curved, bow.offset),
53776
54173
  width: widthFor(e),
@@ -53778,6 +54175,7 @@ function layoutMap(resolvedIn, data, size, opts) {
53778
54175
  arrow: e.directed,
53779
54176
  fromId: e.fromId,
53780
54177
  toId: e.toId,
54178
+ ...Number.isFinite(edgeVal) && edgeVal > 0 && { value: edgeVal },
53781
54179
  ...Object.keys(e.tags).length > 0 && { tags: e.tags },
53782
54180
  lineNumber: e.lineNumber,
53783
54181
  ...e.label !== void 0 && {
@@ -53935,18 +54333,49 @@ function layoutMap(resolvedIn, data, size, opts) {
53935
54333
  const SHORT_HOP_MAX = Math.max(46, Math.min(width, height) * 0.11);
53936
54334
  const STEP = 4;
53937
54335
  const HOP_GAP = 9;
54336
+ const CLEAR_STEP = 6;
54337
+ const CLEAR_MAX = SHORT_HOP_MAX * 3;
54338
+ const CLEAR_TOL = CLEAR_STEP;
54339
+ const clearanceAt = (px, py, ox, oy) => {
54340
+ const baseAng = Math.atan2(oy, ox);
54341
+ let minClear = CLEAR_MAX;
54342
+ for (let k = -2; k <= 2; k++) {
54343
+ const a = baseAng + k * Math.PI / 4;
54344
+ const rx = Math.cos(a);
54345
+ const ry = Math.sin(a);
54346
+ let d = CLEAR_STEP;
54347
+ for (; d <= CLEAR_MAX; d += CLEAR_STEP) {
54348
+ const qx = px + rx * d;
54349
+ const qy = py + ry * d;
54350
+ if (qx < FIT_PAD || qy < topPad || qx > width - FIT_PAD || qy > height - FIT_PAD)
54351
+ break;
54352
+ if (fillAt(qx, qy) !== water) break;
54353
+ }
54354
+ if (d < minClear) minClear = d;
54355
+ }
54356
+ return minClear;
54357
+ };
53938
54358
  const tryShortHopCallout = (cx, cy, fill2, name, value, font = FONT2, gap = HOP_GAP, maxLen = SHORT_HOP_MAX) => {
53939
54359
  const chipW = stackW(name, value, font);
53940
54360
  const chipH = stackH(value !== void 0, font);
54361
+ const D = Math.SQRT1_2;
53941
54362
  const dirs = [
53942
54363
  [0, -1],
53943
- // north (over Canada)
54364
+ // north
53944
54365
  [0, 1],
53945
- // south (over Mexico / Gulf)
54366
+ // south
53946
54367
  [1, 0],
53947
- // east (Atlantic)
53948
- [-1, 0]
53949
- // west (Pacific)
54368
+ // east
54369
+ [-1, 0],
54370
+ // west
54371
+ [D, -D],
54372
+ // NE
54373
+ [D, D],
54374
+ // SE
54375
+ [-D, -D],
54376
+ // NW
54377
+ [-D, D]
54378
+ // SW
53950
54379
  ];
53951
54380
  let best = null;
53952
54381
  for (const [dx, dy] of dirs) {
@@ -53996,13 +54425,16 @@ function layoutMap(resolvedIn, data, size, opts) {
53996
54425
  (p) => segmentRectOverlap(cx, cy, innerX, innerY, p)
53997
54426
  ))
53998
54427
  continue;
53999
- if (best === null || len < best.len)
54428
+ const clear = clearanceAt(ccx, ccy, dx, dy);
54429
+ const better = best === null || clear > best.clear + CLEAR_TOL || clear >= best.clear - CLEAR_TOL && len < best.len;
54430
+ if (better)
54000
54431
  best = {
54001
54432
  x: ccx,
54002
54433
  y: ccy,
54003
54434
  rect,
54004
54435
  leader: [cx, cy, innerX, innerY],
54005
- len
54436
+ len,
54437
+ clear
54006
54438
  };
54007
54439
  }
54008
54440
  return best ? { x: best.x, y: best.y, rect: best.rect, leader: best.leader } : null;
@@ -54663,6 +55095,9 @@ function layoutMap(resolvedIn, data, size, opts) {
54663
55095
  const nx = -dy / len;
54664
55096
  const ny = dx / len;
54665
55097
  const perp = labelH + 2;
55098
+ const stroke2 = lg.width ?? W_MIN;
55099
+ const clearW = stroke2 / 2 + labelH / 2 + 3;
55100
+ const offList = stroke2 >= 4 ? [clearW, -clearW, clearW + perp, -(clearW + perp), 0] : [0, perp, -perp, 2 * perp, -2 * perp];
54666
55101
  const pm = /^M(-?[\d.]+),(-?[\d.]+)(?:L(-?[\d.]+),(-?[\d.]+)|Q(-?[\d.]+),(-?[\d.]+) (-?[\d.]+),(-?[\d.]+))$/.exec(
54667
55102
  lg.d
54668
55103
  );
@@ -54682,7 +55117,7 @@ function layoutMap(resolvedIn, data, size, opts) {
54682
55117
  return [a.cx + dx * t, a.cy + dy * t];
54683
55118
  };
54684
55119
  const candidates = [];
54685
- for (const off of [0, perp, -perp, 2 * perp, -2 * perp])
55120
+ for (const off of offList)
54686
55121
  for (const t of T_LIST) {
54687
55122
  const [bx, by] = pointAt(t);
54688
55123
  candidates.push([bx + nx * off, by + ny * off - 4]);
@@ -55434,6 +55869,12 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
55434
55869
  }
55435
55870
  }
55436
55871
  wireSync(p, leg.lineNumber);
55872
+ if (leg.value !== void 0) {
55873
+ p.attr("data-value", leg.value);
55874
+ p.append("title").text(
55875
+ leg.label !== void 0 ? `${leg.label}: ${leg.value}` : `${leg.value}`
55876
+ );
55877
+ }
55437
55878
  if (arrowTri) {
55438
55879
  gLegs.append("path").attr("d", arrowTri).attr("fill", leg.color).attr("stroke", leg.color).attr("stroke-width", 1).attr("stroke-linejoin", "round").attr("data-from-id", leg.fromId).attr("data-to-id", leg.toId);
55439
55880
  }
@@ -55663,7 +56104,9 @@ function mapContentAspect(resolved, data, ref = REF) {
55663
56104
  function mapExportDimensions(resolved, data, baseWidth = 1200, aspectOverride) {
55664
56105
  const useOverride = aspectOverride !== void 0 && Number.isFinite(aspectOverride) && aspectOverride > 0;
55665
56106
  const raw = useOverride ? aspectOverride : mapContentAspect(resolved, data);
55666
- const clamped = useOverride ? raw : Math.max(ASPECT_MIN, Math.min(ASPECT_MAX, raw));
56107
+ const isGlobal = !useOverride && buildMapProjection(resolved, data).fitIsGlobal;
56108
+ const target = isGlobal ? raw / GLOBAL_HEIGHT_BOOST : raw;
56109
+ const clamped = useOverride ? raw : Math.max(ASPECT_MIN, Math.min(ASPECT_MAX, target));
55667
56110
  const width = baseWidth;
55668
56111
  let height = Math.round(width / clamped);
55669
56112
  let chromeReserve = 0;
@@ -55676,10 +56119,10 @@ function mapExportDimensions(resolved, data, baseWidth = 1200, aspectOverride) {
55676
56119
  height = Math.round(chromeReserve + MIN_MAP_BAND);
55677
56120
  floored = true;
55678
56121
  }
55679
- const preferContain = useOverride ? floored : clamped !== raw || floored;
56122
+ const preferContain = useOverride ? floored : clamped !== target || floored;
55680
56123
  return { width, height, preferContain };
55681
56124
  }
55682
- var import_d3_geo3, FIT_PAD2, TITLE_GAP, ASPECT_MAX, ASPECT_MIN, MIN_MAP_BAND, FALLBACK_ASPECT, REF;
56125
+ var import_d3_geo3, FIT_PAD2, TITLE_GAP, ASPECT_MAX, ASPECT_MIN, GLOBAL_HEIGHT_BOOST, MIN_MAP_BAND, FALLBACK_ASPECT, REF;
55683
56126
  var init_dimensions = __esm({
55684
56127
  "src/map/dimensions.ts"() {
55685
56128
  "use strict";
@@ -55690,6 +56133,7 @@ var init_dimensions = __esm({
55690
56133
  TITLE_GAP = 16;
55691
56134
  ASPECT_MAX = 3;
55692
56135
  ASPECT_MIN = 0.9;
56136
+ GLOBAL_HEIGHT_BOOST = 1.12;
55693
56137
  MIN_MAP_BAND = 200;
55694
56138
  FALLBACK_ASPECT = 1.5;
55695
56139
  REF = 1e3;
@@ -56479,9 +56923,469 @@ var init_renderer18 = __esm({
56479
56923
  }
56480
56924
  });
56481
56925
 
56482
- // src/raci/renderer.ts
56926
+ // src/treemap/layout.ts
56927
+ function toDatum(node) {
56928
+ if (node.children.length === 0) {
56929
+ return {
56930
+ ref: node,
56931
+ label: node.label,
56932
+ value: node.value ?? 0,
56933
+ ...node.heat !== void 0 && { heat: node.heat },
56934
+ lineNumber: node.lineNumber
56935
+ };
56936
+ }
56937
+ return {
56938
+ ref: node,
56939
+ label: node.label,
56940
+ ...node.heat !== void 0 && { heat: node.heat },
56941
+ lineNumber: node.lineNumber,
56942
+ children: node.children.map((c) => toDatum(c))
56943
+ };
56944
+ }
56945
+ function datumHeat(node) {
56946
+ if (node.data.heat !== void 0) return node.data.heat;
56947
+ const xs = [];
56948
+ for (const l of node.leaves()) {
56949
+ if (l.data.heat !== void 0) xs.push(l.data.heat);
56950
+ }
56951
+ if (xs.length === 0) return void 0;
56952
+ return xs.reduce((a, b) => a + b, 0) / xs.length;
56953
+ }
56954
+ function layoutTreemap(roots, opts) {
56955
+ const maxDepth = opts.maxDepth ?? Infinity;
56956
+ const rootDatum = {
56957
+ label: "__root",
56958
+ children: roots.map((r) => toDatum(r))
56959
+ };
56960
+ const h = (0, import_d3_hierarchy2.hierarchy)(rootDatum).sum((d) => d.children?.length ? 0 : d.value ?? 0).sort((a, b) => (b.value ?? 0) - (a.value ?? 0));
56961
+ const hroot = (0, import_d3_hierarchy2.treemap)().tile(import_d3_hierarchy2.treemapSquarify).size([opts.width, opts.height]).paddingOuter(opts.paddingOuter ?? 3).paddingTop(opts.headerH > 0 ? opts.headerH : opts.paddingInner ?? 2).paddingInner(opts.paddingInner ?? 2).round(true)(h);
56962
+ const total = hroot.value ?? 0;
56963
+ (hroot.children ?? []).forEach((top, i) => {
56964
+ top.each((d) => {
56965
+ d._topIndex = i;
56966
+ });
56967
+ });
56968
+ const cells = [];
56969
+ for (const d of hroot.descendants()) {
56970
+ if (d.depth === 0) continue;
56971
+ if (d.depth > maxDepth) continue;
56972
+ const hasChildren = !!d.children && d.children.length > 0;
56973
+ const isCollapsed = hasChildren && d.depth >= maxDepth;
56974
+ const isContainer = hasChildren && !isCollapsed;
56975
+ const path = [];
56976
+ let p = d;
56977
+ while (p && p.depth > 0) {
56978
+ path.unshift(p.data.label);
56979
+ p = p.parent;
56980
+ }
56981
+ const heatVal = datumHeat(d);
56982
+ cells.push({
56983
+ node: d.data.ref ?? null,
56984
+ label: d.data.label,
56985
+ x0: d.x0,
56986
+ y0: d.y0,
56987
+ x1: d.x1,
56988
+ y1: d.y1,
56989
+ depth: d.depth,
56990
+ value: d.value ?? 0,
56991
+ isContainer,
56992
+ isCollapsed,
56993
+ topIndex: d._topIndex ?? 0,
56994
+ pctOfRoot: total > 0 ? (d.value ?? 0) / total : 0,
56995
+ pctOfParent: d.parent && (d.parent.value ?? 0) > 0 ? (d.value ?? 0) / (d.parent.value ?? 1) : 1,
56996
+ ...heatVal !== void 0 && { heat: heatVal },
56997
+ path,
56998
+ ...d.data.lineNumber !== void 0 && { lineNumber: d.data.lineNumber }
56999
+ });
57000
+ }
57001
+ return { cells, total };
57002
+ }
57003
+ var import_d3_hierarchy2;
57004
+ var init_layout16 = __esm({
57005
+ "src/treemap/layout.ts"() {
57006
+ "use strict";
57007
+ import_d3_hierarchy2 = require("d3-hierarchy");
57008
+ }
57009
+ });
57010
+
57011
+ // src/treemap/renderer.ts
56483
57012
  var renderer_exports19 = {};
56484
57013
  __export(renderer_exports19, {
57014
+ compactNumber: () => compactNumber2,
57015
+ renderTreemap: () => renderTreemap,
57016
+ renderTreemapForExport: () => renderTreemapForExport
57017
+ });
57018
+ function renderTreemapForExport(container, parsed, palette, isDark, exportDims, options) {
57019
+ renderTreemap(container, parsed, palette, isDark, exportDims, {
57020
+ exportMode: true,
57021
+ ...options
57022
+ });
57023
+ }
57024
+ function renderTreemap(container, parsed, palette, isDark, exportDims, options = {}) {
57025
+ if (parsed.error || parsed.roots.length === 0) return;
57026
+ void isDark;
57027
+ d3Selection26.select(container).selectAll(":not([data-d3-tooltip])").remove();
57028
+ const width = exportDims?.width ?? container.clientWidth;
57029
+ const height = exportDims?.height ?? container.clientHeight;
57030
+ if (width <= 0 || height <= 0) return;
57031
+ const mode = resolveColorMode(parsed, options.colorMode);
57032
+ const opts = parsed.options;
57033
+ const exportMode = options.exportMode ?? false;
57034
+ const seriesColorsTop = getSeriesColors(palette);
57035
+ const showTitle = !!parsed.title;
57036
+ const titleH = showTitle ? TITLE_BAND : 0;
57037
+ const heat = buildHeatScale(parsed, palette);
57038
+ const legend = !opts.noLegend ? buildLegend(mode, parsed, heat, seriesColorsTop, options.colorOffset ?? 0) : null;
57039
+ const legendReserve = legend ? getMaxLegendReservedHeight(
57040
+ { groups: legend.groups, position: LEGEND_POSITION, mode: "preview" },
57041
+ width
57042
+ ) + LEGEND_GROUP_GAP : 0;
57043
+ const headerH = opts.noHeaders ? 0 : HEADER_H;
57044
+ const areaX = PADDING3;
57045
+ const areaY = titleH + legendReserve + PADDING3;
57046
+ const areaW = Math.max(1, width - PADDING3 * 2);
57047
+ const areaH = Math.max(1, height - areaY - PADDING3);
57048
+ const layout = layoutTreemap(parsed.roots, {
57049
+ width: areaW,
57050
+ height: areaH,
57051
+ headerH,
57052
+ ...options.maxDepth !== void 0 && { maxDepth: options.maxDepth }
57053
+ });
57054
+ const svg = d3Selection26.select(container).append("svg").attr("width", width).attr("height", height).attr("viewBox", `0 0 ${width} ${height}`).attr("preserveAspectRatio", "xMidYMin meet").attr("xmlns", "http://www.w3.org/2000/svg").attr("class", "dgmo-treemap").style("font-family", FONT_FAMILY);
57055
+ svg.append("style").text(
57056
+ ".dgmo-treemap-focus{opacity:.3;transition:opacity .12s}.dgmo-treemap-cell:hover .dgmo-treemap-focus{opacity:.7}"
57057
+ );
57058
+ svg.append("rect").attr("width", width).attr("height", height).attr("fill", palette.bg);
57059
+ if (showTitle) {
57060
+ const title = svg.append("text").attr("class", "chart-title").attr("x", width / 2).attr("y", TITLE_Y).attr("text-anchor", "middle").attr("fill", palette.text).attr("font-family", FONT_FAMILY).attr("font-size", TITLE_FONT_SIZE).attr("font-weight", TITLE_FONT_WEIGHT).text(parsed.title);
57061
+ if (parsed.titleLineNumber !== null) {
57062
+ title.attr("data-line-number", parsed.titleLineNumber);
57063
+ }
57064
+ }
57065
+ const root = svg.append("g").attr("class", "dgmo-treemap-cells").attr("transform", `translate(${areaX},${areaY})`);
57066
+ const seriesColors2 = seriesColorsTop;
57067
+ const colorOffset = options.colorOffset ?? 0;
57068
+ const activeGroup = parsed.tagGroups.length > 0 ? parsed.tagGroups[0].name : null;
57069
+ const rootIndexByLabel = new Map(parsed.roots.map((r, i) => [r.label, i]));
57070
+ const colorOf = (cell) => {
57071
+ if (mode === "heat") {
57072
+ return cell.heat !== void 0 && heat ? heat.scale(cell.heat) : MUTED_FILL;
57073
+ }
57074
+ if (mode === "tag") {
57075
+ if (!cell.node) return MUTED_FILL;
57076
+ return resolveTagColor(cell.node.metadata, parsed.tagGroups, activeGroup) ?? MUTED_FILL;
57077
+ }
57078
+ const topLabel = cell.path[0] ?? cell.label;
57079
+ const idx = (rootIndexByLabel.get(topLabel) ?? cell.topIndex) + colorOffset;
57080
+ const hue = seriesColors2[idx % seriesColors2.length];
57081
+ if (cell.depth <= 1) return hue;
57082
+ const keepPct = Math.max(55, 100 - (cell.depth - 1) * 18);
57083
+ return mix(hue, palette.bg, keepPct);
57084
+ };
57085
+ for (const cell of layout.cells) {
57086
+ const w = Math.max(0, cell.x1 - cell.x0);
57087
+ const h = Math.max(0, cell.y1 - cell.y0);
57088
+ if (w <= 0 || h <= 0) continue;
57089
+ const baseColor = colorOf(cell);
57090
+ const fill2 = cell.isContainer ? baseColor : mix(baseColor, palette.bg, LEAF_MUTE_PCT);
57091
+ const drillable = cell.isContainer || cell.isCollapsed;
57092
+ const g = root.append("g").attr("class", "dgmo-treemap-cell").attr("transform", `translate(${cell.x0},${cell.y0})`).attr("data-node-path", cell.path.join(" / "));
57093
+ if (cell.lineNumber !== void 0) {
57094
+ g.attr("data-line-number", cell.lineNumber);
57095
+ }
57096
+ if (cell.heat !== void 0) g.attr("data-heat", cell.heat);
57097
+ if (cell.node && activeGroup) {
57098
+ const key = tagAttrKey(activeGroup);
57099
+ const tagVal = cell.node.metadata[key];
57100
+ if (tagVal) g.attr(`data-tag-${key}`, tagVal);
57101
+ }
57102
+ const rect = g.append("rect").attr(
57103
+ "class",
57104
+ cell.isContainer ? "dgmo-treemap-rect branch" : "dgmo-treemap-rect"
57105
+ ).attr("width", w).attr("height", h).attr("rx", 2).attr("fill", fill2).attr("fill-opacity", 1).attr("stroke", palette.bg).attr("stroke-width", cell.isContainer ? 1 : 0);
57106
+ if (drillable && options.onClickItem && cell.lineNumber !== void 0) {
57107
+ const ln = cell.lineNumber;
57108
+ rect.style("cursor", "pointer").on("click", () => options.onClickItem(ln));
57109
+ }
57110
+ const ink = contrastText(
57111
+ fill2,
57112
+ palette.textOnFillLight,
57113
+ palette.textOnFillDark
57114
+ );
57115
+ if (cell.isContainer && headerH > 0 && w > 34 && h > headerH) {
57116
+ const valParts = [];
57117
+ if (!opts.noValues) valParts.push(compactNumber2(cell.value));
57118
+ if (!opts.noPercent) valParts.push(formatPct(cell.pctOfRoot));
57119
+ const valStr = valParts.join(" \xB7 ");
57120
+ const ICON_RESERVE = drillable ? 16 : 4;
57121
+ const showVal = valStr.length > 0 && w > 110;
57122
+ const valW = showVal ? measureText(valStr, 10.5) : 0;
57123
+ const labelMax = w - 8 - ICON_RESERVE - (showVal ? valW + 10 : 0);
57124
+ g.append("text").attr("class", "dgmo-treemap-header").attr("x", 6).attr("y", 13).attr("font-size", 11).attr("font-weight", 700).attr("fill", ink).text(clipLabel(cell.label, Math.max(0, labelMax), 11));
57125
+ if (showVal) {
57126
+ g.append("text").attr("class", "dgmo-treemap-header-value").attr("x", w - ICON_RESERVE - 4).attr("y", 13).attr("text-anchor", "end").attr("font-size", 10.5).attr("fill", ink).attr("opacity", 0.75).text(valStr);
57127
+ }
57128
+ }
57129
+ const PAD = Math.max(4, Math.min(14, Math.floor(Math.min(w, h) / 5)));
57130
+ const MIN_FS = 7;
57131
+ if (!cell.isContainer && w >= 2 * PAD + 8 && h >= 2 * PAD + 8) {
57132
+ const maxW = w - 2 * PAD;
57133
+ let fs = clamp3(Math.round(Math.min(w / 3.6, h / 3.4)), MIN_FS, 72);
57134
+ const nameW = measureText(cell.label, fs) * 1.06;
57135
+ if (nameW > maxW) fs = Math.max(MIN_FS, Math.floor(fs * maxW / nameW));
57136
+ const tg = clamp3((fs - MIN_FS) / (72 - MIN_FS), 0, 1);
57137
+ const nameOpacity = 0.95 - tg * 0.5;
57138
+ const vfs = clamp3(Math.round(fs * 0.42), 11, 28);
57139
+ const valOpacity = Math.max(0.45, nameOpacity - 0.1);
57140
+ let y = PAD + Math.round(fs * 0.78);
57141
+ g.append("text").attr("class", "dgmo-treemap-label").attr("x", PAD).attr("y", y).attr("font-size", fs).attr("font-weight", 600).attr("fill", ink).attr("opacity", nameOpacity).text(clipLabel(cell.label, maxW, fs));
57142
+ const valParts = [
57143
+ opts.noValues ? "" : compactNumber2(cell.value),
57144
+ opts.noPercent ? "" : formatPct(cell.pctOfRoot)
57145
+ ].filter(Boolean);
57146
+ const combined = valParts.join(" \xB7 ");
57147
+ const nameBaseY = y;
57148
+ const addLineAt = (text, yy, size, opacity) => {
57149
+ g.append("text").attr("class", "dgmo-treemap-value").attr("x", PAD).attr("y", yy).attr("font-size", size).attr("fill", ink).attr("opacity", opacity).text(text);
57150
+ };
57151
+ if (combined) {
57152
+ const fitsW = measureText(combined, vfs) <= maxW;
57153
+ const roomBelow = h - PAD > y + vfs + 6;
57154
+ if (fitsW && roomBelow) {
57155
+ addLineAt(combined, y + vfs + 6, vfs, valOpacity);
57156
+ } else if (fitsW) {
57157
+ const ivfs = clamp3(Math.round(fs * 0.5), 11, Math.max(11, vfs));
57158
+ const rendered = clipLabel(cell.label, maxW, fs);
57159
+ const nW = measureText(rendered, fs) * 1.12;
57160
+ const gap = Math.max(12, Math.round(fs * 0.25));
57161
+ if (PAD + nW + gap + measureText(combined, ivfs) <= w - PAD) {
57162
+ g.append("text").attr("class", "dgmo-treemap-value").attr("x", PAD + nW + gap).attr("y", nameBaseY).attr("font-size", ivfs).attr("fill", ink).attr("opacity", valOpacity).text(combined);
57163
+ }
57164
+ } else if (valParts.length === 2) {
57165
+ if (h - PAD > y + vfs + 6) {
57166
+ y += vfs + 6;
57167
+ addLineAt(valParts[0], y, vfs, valOpacity);
57168
+ }
57169
+ const pfs = Math.max(10, Math.round(vfs * 0.9));
57170
+ if (h - PAD > y + pfs + 4) {
57171
+ y += pfs + 4;
57172
+ addLineAt(valParts[1], y, pfs, valOpacity);
57173
+ }
57174
+ } else if (h - PAD > y + vfs + 6) {
57175
+ addLineAt(combined, y + vfs + 6, vfs, valOpacity);
57176
+ }
57177
+ }
57178
+ }
57179
+ if (drillable && w > 30 && h > 22) {
57180
+ drawFocusIcon(g, w, ink, 9);
57181
+ }
57182
+ }
57183
+ if (legend) {
57184
+ const legendG = svg.append("g").attr("class", "dgmo-treemap-legend").attr("transform", `translate(0, ${titleH})`);
57185
+ renderIntegratedLegend(legendG, {
57186
+ groups: legend.groups,
57187
+ palette: {
57188
+ bg: palette.bg,
57189
+ surface: palette.surface,
57190
+ text: palette.text,
57191
+ textMuted: palette.textMuted,
57192
+ primary: palette.primary
57193
+ },
57194
+ isDark,
57195
+ width,
57196
+ mode: exportMode ? "export" : "preview",
57197
+ position: LEGEND_POSITION,
57198
+ activeGroup: legend.activeGroup,
57199
+ // The color-mode switcher is the legend itself: each applicable mode is a
57200
+ // group pill; the active one is the open capsule, the rest are clickable
57201
+ // pills that switch mode. Export shows only the active group.
57202
+ showInactivePills: !exportMode,
57203
+ showEmptyGroups: !exportMode,
57204
+ ...options.onSelectMode !== void 0 && {
57205
+ callbacks: {
57206
+ onGroupToggle: (name) => {
57207
+ const m = legend.modeByName.get(name);
57208
+ if (m) options.onSelectMode(m);
57209
+ }
57210
+ }
57211
+ }
57212
+ });
57213
+ }
57214
+ }
57215
+ function buildLegend(activeMode, parsed, heat, seriesColors2, colorOffset) {
57216
+ const groups = [];
57217
+ const modeByName = /* @__PURE__ */ new Map();
57218
+ let activeGroup = null;
57219
+ if (parsed.tagGroups.length > 0) {
57220
+ const tg = parsed.tagGroups[0];
57221
+ const used = /* @__PURE__ */ new Set();
57222
+ const collect = (nodes) => {
57223
+ for (const n of nodes) {
57224
+ const v = n.metadata[tagAttrKey(tg.name)];
57225
+ if (v) used.add(v.toLowerCase());
57226
+ collect(n.children);
57227
+ }
57228
+ };
57229
+ collect(parsed.roots);
57230
+ groups.push({
57231
+ name: tg.name,
57232
+ entries: tg.entries.filter((e) => used.has(e.value.toLowerCase())).map((e) => ({ value: e.value, color: e.color }))
57233
+ });
57234
+ modeByName.set(tg.name, "tag");
57235
+ if (activeMode === "tag") activeGroup = tg.name;
57236
+ }
57237
+ if (heat) {
57238
+ const name = parsed.options.heatLabel ?? "Value";
57239
+ groups.push({
57240
+ name,
57241
+ entries: [],
57242
+ gradient: {
57243
+ min: heat.min,
57244
+ max: heat.max,
57245
+ low: heat.stops[0],
57246
+ high: heat.stops[heat.stops.length - 1]
57247
+ }
57248
+ });
57249
+ modeByName.set(name, "heat");
57250
+ if (activeMode === "heat") activeGroup = name;
57251
+ }
57252
+ groups.push({
57253
+ name: "Branch",
57254
+ entries: parsed.roots.map((r, i) => ({
57255
+ value: r.label,
57256
+ color: seriesColors2[(i + colorOffset) % seriesColors2.length]
57257
+ }))
57258
+ });
57259
+ modeByName.set("Branch", "branch");
57260
+ if (activeMode === "branch" || activeGroup === null) activeGroup = "Branch";
57261
+ return { groups, activeGroup, modeByName };
57262
+ }
57263
+ function buildHeatScale(parsed, palette) {
57264
+ if (!parsed.hasHeat) return null;
57265
+ const values = [];
57266
+ const collect = (nodes) => {
57267
+ for (const n of nodes) {
57268
+ if (typeof n.heat === "number") values.push(n.heat);
57269
+ collect(n.children);
57270
+ }
57271
+ };
57272
+ collect(parsed.roots);
57273
+ if (values.length === 0) return null;
57274
+ const min = Math.min(...values);
57275
+ const max = Math.max(...values);
57276
+ const signed = min < 0 && max > 0;
57277
+ const neutral = palette.surface;
57278
+ const explicit = parsed.options.heatColors.map((c) => resolveColor(c, palette) ?? c).filter((c) => !!c);
57279
+ let stops;
57280
+ let domain;
57281
+ if (explicit.length >= 2) {
57282
+ stops = [explicit[0], neutral, explicit[1]];
57283
+ const mid = signed ? 0 : (min + max) / 2;
57284
+ domain = [min, mid, max];
57285
+ } else if (explicit.length === 1) {
57286
+ stops = [neutral, explicit[0]];
57287
+ domain = [min, max];
57288
+ } else if (signed) {
57289
+ stops = [palette.colors.red, neutral, palette.colors.green];
57290
+ domain = [min, 0, max];
57291
+ } else {
57292
+ stops = [neutral, palette.primary];
57293
+ domain = [min, max];
57294
+ }
57295
+ if (domain[0] === domain[domain.length - 1]) {
57296
+ const last = stops[stops.length - 1];
57297
+ return { scale: () => last, min, max, stops, signed };
57298
+ }
57299
+ const linear = (0, import_d3_scale.scaleLinear)().domain(domain).range(stops).clamp(true);
57300
+ return { scale: (v) => toHex(linear(v)), min, max, stops, signed };
57301
+ }
57302
+ function toHex(c) {
57303
+ if (c.startsWith("#")) return c;
57304
+ const m = c.match(/rgba?\(([^)]+)\)/);
57305
+ if (!m) return c;
57306
+ const parts = m[1].split(",").map((s) => Math.round(parseFloat(s)));
57307
+ const h = (n) => Math.max(0, Math.min(255, n || 0)).toString(16).padStart(2, "0");
57308
+ return `#${h(parts[0] ?? 0)}${h(parts[1] ?? 0)}${h(parts[2] ?? 0)}`;
57309
+ }
57310
+ function resolveColorMode(parsed, override) {
57311
+ let mode = override ?? parsed.defaultColorMode;
57312
+ if (mode === "tag" && parsed.tagGroups.length === 0) {
57313
+ mode = parsed.hasHeat ? "heat" : "branch";
57314
+ }
57315
+ if (mode === "heat" && !parsed.hasHeat) mode = "branch";
57316
+ return mode;
57317
+ }
57318
+ function drawFocusIcon(g, w, ink, cy) {
57319
+ const r = 4.5;
57320
+ const cx = w - r - 5;
57321
+ const fi = g.append("g").attr("class", "dgmo-treemap-focus").attr("data-export-ignore", "true");
57322
+ fi.append("rect").attr("x", cx - 9).attr("y", cy - 9).attr("width", 18).attr("height", 18).attr("fill", "transparent");
57323
+ fi.append("circle").attr("cx", cx).attr("cy", cy).attr("r", r).attr("fill", "none").attr("stroke", ink).attr("stroke-width", 1.25);
57324
+ fi.append("circle").attr("cx", cx).attr("cy", cy).attr("r", 1.4).attr("fill", ink);
57325
+ }
57326
+ function clamp3(x, lo, hi) {
57327
+ return Math.max(lo, Math.min(hi, x));
57328
+ }
57329
+ function clipLabel(s, maxWidth, fs) {
57330
+ if (measureText(s, fs) <= maxWidth) return s;
57331
+ let lo = 0;
57332
+ let hi = s.length;
57333
+ while (lo < hi) {
57334
+ const mid = Math.ceil((lo + hi) / 2);
57335
+ if (measureText(s.slice(0, mid) + "\u2026", fs) <= maxWidth) lo = mid;
57336
+ else hi = mid - 1;
57337
+ }
57338
+ return lo <= 0 ? "" : s.slice(0, lo) + "\u2026";
57339
+ }
57340
+ function compactNumber2(v) {
57341
+ const abs = Math.abs(v);
57342
+ if (abs >= 1e9) return strip(v / 1e9) + "B";
57343
+ if (abs >= 1e6) return strip(v / 1e6) + "M";
57344
+ if (abs >= 1e3) return strip(v / 1e3) + "k";
57345
+ return strip(Math.round(v * 100) / 100);
57346
+ }
57347
+ function strip(n) {
57348
+ return parseFloat(
57349
+ n.toFixed(n < 10 && !Number.isInteger(n) ? 1 : 0)
57350
+ ).toString();
57351
+ }
57352
+ function formatPct(frac) {
57353
+ const pct = frac * 100;
57354
+ if (pct >= 10) return `${Math.round(pct)}%`;
57355
+ if (pct >= 1) return `${pct.toFixed(0)}%`;
57356
+ return `${pct.toFixed(1)}%`;
57357
+ }
57358
+ var d3Selection26, import_d3_scale, PADDING3, HEADER_H, TITLE_BAND, MUTED_FILL, LEAF_MUTE_PCT, LEGEND_POSITION;
57359
+ var init_renderer19 = __esm({
57360
+ "src/treemap/renderer.ts"() {
57361
+ "use strict";
57362
+ d3Selection26 = __toESM(require("d3-selection"), 1);
57363
+ import_d3_scale = require("d3-scale");
57364
+ init_fonts();
57365
+ init_colors();
57366
+ init_color_utils();
57367
+ init_tag_groups();
57368
+ init_text_measure();
57369
+ init_legend_integration();
57370
+ init_legend_layout();
57371
+ init_legend_constants();
57372
+ init_title_constants();
57373
+ init_layout16();
57374
+ PADDING3 = 12;
57375
+ HEADER_H = 18;
57376
+ TITLE_BAND = 36;
57377
+ MUTED_FILL = "#cbd5e1";
57378
+ LEAF_MUTE_PCT = 50;
57379
+ LEGEND_POSITION = {
57380
+ placement: "top-center",
57381
+ titleRelation: "below-title"
57382
+ };
57383
+ }
57384
+ });
57385
+
57386
+ // src/raci/renderer.ts
57387
+ var renderer_exports20 = {};
57388
+ __export(renderer_exports20, {
56485
57389
  MARKER_LABELS: () => MARKER_LABELS,
56486
57390
  renderRaci: () => renderRaci,
56487
57391
  renderRaciForExport: () => renderRaciForExport
@@ -56557,7 +57461,7 @@ function renderRaci(container, parsed, palette, isDark, handlers, exportDims) {
56557
57461
  const hideLegend = opts.hideLegend ?? false;
56558
57462
  const collapsedPhases = opts.collapsedPhases ?? /* @__PURE__ */ new Set();
56559
57463
  const hideTitle = (opts.hideTitle ?? false) || parsed.options["no-title"] === "on";
56560
- d3Selection26.select(container).selectAll(":not([data-d3-tooltip])").remove();
57464
+ d3Selection27.select(container).selectAll(":not([data-d3-tooltip])").remove();
56561
57465
  const width = exportDims?.width ?? container.clientWidth;
56562
57466
  const height = exportDims?.height ?? container.clientHeight;
56563
57467
  if (width <= 0 || height <= 0) return;
@@ -56664,7 +57568,7 @@ function renderRaci(container, parsed, palette, isDark, handlers, exportDims) {
56664
57568
  const colBottomY = cursorY + sColumnBottomPad;
56665
57569
  const totalHeight = colBottomY + sVMargin;
56666
57570
  const svgHeight = exportDims ? totalHeight : Math.max(height, totalHeight);
56667
- const svg = d3Selection26.select(container).append("svg").attr("xmlns", "http://www.w3.org/2000/svg").attr("width", width).attr("height", svgHeight).attr("viewBox", `0 0 ${width} ${svgHeight}`).attr("preserveAspectRatio", "xMidYMin meet").attr("font-family", FONT_FAMILY).style("background", "transparent");
57571
+ const svg = d3Selection27.select(container).append("svg").attr("xmlns", "http://www.w3.org/2000/svg").attr("width", width).attr("height", svgHeight).attr("viewBox", `0 0 ${width} ${svgHeight}`).attr("preserveAspectRatio", "xMidYMin meet").attr("font-family", FONT_FAMILY).style("background", "transparent");
56668
57572
  if (ctx.isBelowFloor) {
56669
57573
  svg.attr("width", "100%");
56670
57574
  }
@@ -57144,15 +58048,15 @@ function parseQuotedSegments(message) {
57144
58048
  out.push({ text: message.slice(last), bold: false });
57145
58049
  return out;
57146
58050
  }
57147
- var d3Selection26, MARKER_LABELS, TITLE_AREA_HEIGHT4, H_MARGIN, V_MARGIN3, LEGEND_HEIGHT2, LEGEND_CHIP_GAP, LEGEND_CHIP_LABEL_MIN, LEGEND_LETTER_CHIP_W, TITLE_LEGEND_GAP, LEGEND_LABEL_FONT, LEGEND_LETTER_FONT, HEADER_HEIGHT5, ROW_HEIGHT, PHASE_HEIGHT, TASK_LABEL_MIN, TASK_LABEL_MAX, ROLE_COL_MIN, ROLE_COL_MAX, CELL_PAD, VIOLATION_LINE_HEIGHT, STACK_TOP_GAP, DESC_FONT, COLUMN_RADIUS3, COLUMN_INSET, COLUMN_BOTTOM_PAD, MARKER_FONT, MARKER_FONT_WEIGHT, LABEL_FONT2, ROLE_HEADER_FONT, PHASE_FONT, TINT_PCT, NODE_RADIUS3, AUTO_ACCENTS, SLICE_GAP, NAME_LINE_HEIGHT, DESC_LINE_HEIGHT9;
57148
- var init_renderer19 = __esm({
58051
+ var d3Selection27, MARKER_LABELS, TITLE_AREA_HEIGHT4, H_MARGIN, V_MARGIN3, LEGEND_HEIGHT2, LEGEND_CHIP_GAP, LEGEND_CHIP_LABEL_MIN, LEGEND_LETTER_CHIP_W, TITLE_LEGEND_GAP, LEGEND_LABEL_FONT, LEGEND_LETTER_FONT, HEADER_HEIGHT5, ROW_HEIGHT, PHASE_HEIGHT, TASK_LABEL_MIN, TASK_LABEL_MAX, ROLE_COL_MIN, ROLE_COL_MAX, CELL_PAD, VIOLATION_LINE_HEIGHT, STACK_TOP_GAP, DESC_FONT, COLUMN_RADIUS3, COLUMN_INSET, COLUMN_BOTTOM_PAD, MARKER_FONT, MARKER_FONT_WEIGHT, LABEL_FONT2, ROLE_HEADER_FONT, PHASE_FONT, TINT_PCT, NODE_RADIUS3, AUTO_ACCENTS, SLICE_GAP, NAME_LINE_HEIGHT, DESC_LINE_HEIGHT9;
58052
+ var init_renderer20 = __esm({
57149
58053
  "src/raci/renderer.ts"() {
57150
58054
  "use strict";
57151
- d3Selection26 = __toESM(require("d3-selection"), 1);
58055
+ d3Selection27 = __toESM(require("d3-selection"), 1);
57152
58056
  init_fonts();
57153
58057
  init_title_constants();
57154
58058
  init_color_utils();
57155
- init_parser26();
58059
+ init_parser27();
57156
58060
  init_variants();
57157
58061
  init_scaling();
57158
58062
  init_text_measure();
@@ -57409,8 +58313,8 @@ var init_tag_resolution = __esm({
57409
58313
  });
57410
58314
 
57411
58315
  // src/sequence/renderer.ts
57412
- var renderer_exports20 = {};
57413
- __export(renderer_exports20, {
58316
+ var renderer_exports21 = {};
58317
+ __export(renderer_exports21, {
57414
58318
  applyGroupOrdering: () => applyGroupOrdering,
57415
58319
  applyPositionOverrides: () => applyPositionOverrides,
57416
58320
  buildNoteMessageMap: () => buildNoteMessageMap,
@@ -57750,7 +58654,7 @@ function applyGroupOrdering(participants, groups, messages = []) {
57750
58654
  return result;
57751
58655
  }
57752
58656
  function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateToLine, options) {
57753
- d3Selection27.select(container).selectAll("*").remove();
58657
+ d3Selection28.select(container).selectAll("*").remove();
57754
58658
  const { title, options: parsedOptions } = parsed;
57755
58659
  const solid = parsedOptions["solid-fill"] === "on";
57756
58660
  const effectiveCollapsedGroups = /* @__PURE__ */ new Set();
@@ -58401,7 +59305,7 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
58401
59305
  offsetX = leftMargin + Math.max(0, (svgWidth - totalWidth) / 2);
58402
59306
  buildParticipantX();
58403
59307
  }
58404
- const svg = d3Selection27.select(container).append("svg").attr("width", "100%").attr("height", totalHeight).attr("viewBox", `0 0 ${svgWidth} ${totalHeight}`).attr("preserveAspectRatio", "xMidYMin meet").attr("class", "sequence-diagram").style("font-family", FONT_FAMILY);
59308
+ const svg = d3Selection28.select(container).append("svg").attr("width", "100%").attr("height", totalHeight).attr("viewBox", `0 0 ${svgWidth} ${totalHeight}`).attr("preserveAspectRatio", "xMidYMin meet").attr("class", "sequence-diagram").style("font-family", FONT_FAMILY);
58405
59309
  const defs = svg.append("defs");
58406
59310
  defs.append("marker").attr("id", "seq-arrowhead").attr("viewBox", `0 0 ${sArrowheadSize} ${sArrowheadSize}`).attr("refX", sArrowheadSize).attr("refY", sArrowheadSize / 2).attr("markerWidth", sArrowheadSize).attr("markerHeight", sArrowheadSize).attr("orient", "auto").append("polygon").attr(
58407
59311
  "points",
@@ -59013,12 +59917,12 @@ function renderParticipant(svg, participant, cx, cy, palette, isDark, color, tag
59013
59917
  });
59014
59918
  }
59015
59919
  }
59016
- var d3Selection27, PARTICIPANT_GAP, PARTICIPANT_BOX_WIDTH, PARTICIPANT_BOX_HEIGHT, LABEL_FONT_SIZE5, TOP_MARGIN, TITLE_HEIGHT8, PARTICIPANT_Y_OFFSET, MESSAGE_START_OFFSET, LIFELINE_TAIL, ARROWHEAD_SIZE, NOTE_MAX_W2, NOTE_FOLD2, NOTE_PAD_H2, NOTE_PAD_V2, NOTE_FONT_SIZE2, NOTE_LINE_H2, NOTE_GAP2, ACTIVATION_WIDTH, SELF_CALL_HEIGHT, SELF_CALL_WIDTH, ACTOR_LABEL_CLEARANCE, labelTextWidth, fill, stroke, SW, W, H;
59017
- var init_renderer20 = __esm({
59920
+ var d3Selection28, PARTICIPANT_GAP, PARTICIPANT_BOX_WIDTH, PARTICIPANT_BOX_HEIGHT, LABEL_FONT_SIZE5, TOP_MARGIN, TITLE_HEIGHT8, PARTICIPANT_Y_OFFSET, MESSAGE_START_OFFSET, LIFELINE_TAIL, ARROWHEAD_SIZE, NOTE_MAX_W2, NOTE_FOLD2, NOTE_PAD_H2, NOTE_PAD_V2, NOTE_FONT_SIZE2, NOTE_LINE_H2, NOTE_GAP2, ACTIVATION_WIDTH, SELF_CALL_HEIGHT, SELF_CALL_WIDTH, ACTOR_LABEL_CLEARANCE, labelTextWidth, fill, stroke, SW, W, H;
59921
+ var init_renderer21 = __esm({
59018
59922
  "src/sequence/renderer.ts"() {
59019
59923
  "use strict";
59020
59924
  init_tag_groups();
59021
- d3Selection27 = __toESM(require("d3-selection"), 1);
59925
+ d3Selection28 = __toESM(require("d3-selection"), 1);
59022
59926
  init_color_utils();
59023
59927
  init_inline_markdown();
59024
59928
  init_fonts();
@@ -62915,6 +63819,7 @@ var DIAGRAM_EXPORT_HANDLERS = {
62915
63819
  map: exportMap,
62916
63820
  pyramid: exportPyramid,
62917
63821
  ring: exportRing,
63822
+ treemap: exportTreemap,
62918
63823
  raci: exportRaci,
62919
63824
  rasci: exportRaci,
62920
63825
  daci: exportRaci,
@@ -62972,10 +63877,10 @@ async function exportOrg(ctx) {
62972
63877
  false
62973
63878
  // expandAllLegend off — collapsed-by-default per §1.3
62974
63879
  );
62975
- const PADDING3 = 20;
63880
+ const PADDING4 = 20;
62976
63881
  const titleOffset = effectiveParsed.title ? 30 : 0;
62977
- const exportWidth = orgLayout.width + PADDING3 * 2;
62978
- const exportHeight = orgLayout.height + PADDING3 * 2 + titleOffset;
63882
+ const exportWidth = orgLayout.width + PADDING4 * 2;
63883
+ const exportHeight = orgLayout.height + PADDING4 * 2 + titleOffset;
62979
63884
  const container = createExportContainer(exportWidth, exportHeight);
62980
63885
  renderOrg2(
62981
63886
  container,
@@ -63017,10 +63922,10 @@ async function exportSitemap(ctx) {
63017
63922
  hiddenAttributes,
63018
63923
  true
63019
63924
  );
63020
- const PADDING3 = 20;
63925
+ const PADDING4 = 20;
63021
63926
  const titleOffset = effectiveParsed.title ? 30 : 0;
63022
- const exportWidth = sitemapLayout.width + PADDING3 * 2;
63023
- const exportHeight = sitemapLayout.height + PADDING3 * 2 + titleOffset;
63927
+ const exportWidth = sitemapLayout.width + PADDING4 * 2;
63928
+ const exportHeight = sitemapLayout.height + PADDING4 * 2 + titleOffset;
63024
63929
  const container = createExportContainer(exportWidth, exportHeight);
63025
63930
  renderSitemap2(
63026
63931
  container,
@@ -63076,10 +63981,10 @@ async function exportClass(ctx) {
63076
63981
  const classParsed = parseClassDiagram2(content, effectivePalette);
63077
63982
  if (classParsed.error || classParsed.classes.length === 0) return "";
63078
63983
  const classLayout = layoutClassDiagram2(classParsed);
63079
- const PADDING3 = 20;
63984
+ const PADDING4 = 20;
63080
63985
  const titleOffset = classParsed.title ? 40 : 0;
63081
- const exportWidth = classLayout.width + PADDING3 * 2;
63082
- const exportHeight = classLayout.height + PADDING3 * 2 + titleOffset;
63986
+ const exportWidth = classLayout.width + PADDING4 * 2;
63987
+ const exportHeight = classLayout.height + PADDING4 * 2 + titleOffset;
63083
63988
  const container = createExportContainer(exportWidth, exportHeight);
63084
63989
  renderClassDiagram2(
63085
63990
  container,
@@ -63103,10 +64008,10 @@ async function exportEr(ctx) {
63103
64008
  const erParsed = parseERDiagram2(content, effectivePalette);
63104
64009
  if (erParsed.error || erParsed.tables.length === 0) return "";
63105
64010
  const erLayout = layoutERDiagram2(erParsed);
63106
- const PADDING3 = 20;
64011
+ const PADDING4 = 20;
63107
64012
  const titleOffset = erParsed.title ? 40 : 0;
63108
- const exportWidth = erLayout.width + PADDING3 * 2;
63109
- const exportHeight = erLayout.height + PADDING3 * 2 + titleOffset;
64013
+ const exportWidth = erLayout.width + PADDING4 * 2;
64014
+ const exportHeight = erLayout.height + PADDING4 * 2 + titleOffset;
63110
64015
  const container = createExportContainer(exportWidth, exportHeight);
63111
64016
  renderERDiagram2(
63112
64017
  container,
@@ -63142,10 +64047,10 @@ async function exportBoxesAndLines(ctx) {
63142
64047
  const { renderBoxesAndLinesForExport: renderBoxesAndLinesForExport2 } = await Promise.resolve().then(() => (init_renderer6(), renderer_exports6));
63143
64048
  const { layoutBoxesAndLines: layoutBoxesAndLines2 } = await Promise.resolve().then(() => (init_layout5(), layout_exports5));
63144
64049
  const blLayout = await layoutBoxesAndLines2(blParsed);
63145
- const PADDING3 = 20;
64050
+ const PADDING4 = 20;
63146
64051
  const titleOffset = blParsed.title ? 40 : 0;
63147
- const exportWidth = blLayout.width + PADDING3 * 2;
63148
- const exportHeight = blLayout.height + PADDING3 * 2 + titleOffset;
64052
+ const exportWidth = blLayout.width + PADDING4 * 2;
64053
+ const exportHeight = blLayout.height + PADDING4 * 2 + titleOffset;
63149
64054
  const container = createExportContainer(exportWidth, exportHeight);
63150
64055
  const blActiveTagGroup = ctxTagOverride(ctx);
63151
64056
  renderBoxesAndLinesForExport2(
@@ -63192,10 +64097,10 @@ async function exportMindmap(ctx) {
63192
64097
  activeTagGroup,
63193
64098
  hideDescriptions
63194
64099
  });
63195
- const PADDING3 = 20;
64100
+ const PADDING4 = 20;
63196
64101
  const titleOffset = effectiveParsed.title ? 30 : 0;
63197
- const exportWidth = mmLayout.width + PADDING3 * 2;
63198
- const exportHeight = mmLayout.height + PADDING3 * 2 + titleOffset;
64102
+ const exportWidth = mmLayout.width + PADDING4 * 2;
64103
+ const exportHeight = mmLayout.height + PADDING4 * 2 + titleOffset;
63199
64104
  const container = createExportContainer(exportWidth, exportHeight);
63200
64105
  const colorByDepth = viewState?.cbd === true;
63201
64106
  renderMindmap2(
@@ -63256,10 +64161,10 @@ async function exportC4(ctx) {
63256
64161
  const c4Container = ctx.options?.c4Container ?? viewState?.c4c;
63257
64162
  const c4Layout = c4Level === "deployment" ? layoutC4Deployment2(c4Parsed) : c4Level === "components" && c4System && c4Container ? layoutC4Components2(c4Parsed, c4System, c4Container) : c4Level === "containers" && c4System ? layoutC4Containers2(c4Parsed, c4System) : layoutC4Context2(c4Parsed);
63258
64163
  if (c4Layout.nodes.length === 0) return "";
63259
- const PADDING3 = 20;
64164
+ const PADDING4 = 20;
63260
64165
  const titleOffset = c4Parsed.title ? 40 : 0;
63261
- const exportWidth = c4Layout.width + PADDING3 * 2;
63262
- const exportHeight = c4Layout.height + PADDING3 * 2 + titleOffset;
64166
+ const exportWidth = c4Layout.width + PADDING4 * 2;
64167
+ const exportHeight = c4Layout.height + PADDING4 * 2 + titleOffset;
63263
64168
  const container = createExportContainer(exportWidth, exportHeight);
63264
64169
  const renderFn = c4Level === "deployment" || c4Level === "components" && c4System && c4Container || c4Level === "containers" && c4System ? renderC4Containers2 : renderC4Context2;
63265
64170
  renderFn(
@@ -63575,30 +64480,44 @@ async function exportRing(ctx) {
63575
64480
  const ringParsed = parseRing2(content);
63576
64481
  if (ringParsed.error || ringParsed.layers.length === 0) return "";
63577
64482
  const container = createExportContainer(EXPORT_WIDTH, EXPORT_HEIGHT);
63578
- renderRingForExport2(
64483
+ renderRingForExport2(container, ringParsed, effectivePalette, ctx.isDark, {
64484
+ width: EXPORT_WIDTH,
64485
+ height: EXPORT_HEIGHT
64486
+ });
64487
+ return finalizeSvgExport(container, theme, effectivePalette);
64488
+ }
64489
+ async function exportTreemap(ctx) {
64490
+ const { content, theme, palette } = ctx;
64491
+ const { parseTreemap: parseTreemap2 } = await Promise.resolve().then(() => (init_parser26(), parser_exports20));
64492
+ const { renderTreemapForExport: renderTreemapForExport2 } = await Promise.resolve().then(() => (init_renderer19(), renderer_exports19));
64493
+ const effectivePalette = await resolveExportPalette(theme, palette);
64494
+ const treemapParsed = parseTreemap2(content, effectivePalette);
64495
+ if (treemapParsed.error || treemapParsed.roots.length === 0) return "";
64496
+ const container = createExportContainer(EXPORT_WIDTH, EXPORT_HEIGHT);
64497
+ renderTreemapForExport2(
63579
64498
  container,
63580
- ringParsed,
64499
+ treemapParsed,
63581
64500
  effectivePalette,
63582
64501
  ctx.isDark,
63583
- { width: EXPORT_WIDTH, height: EXPORT_HEIGHT }
64502
+ {
64503
+ width: EXPORT_WIDTH,
64504
+ height: EXPORT_HEIGHT
64505
+ }
63584
64506
  );
63585
64507
  return finalizeSvgExport(container, theme, effectivePalette);
63586
64508
  }
63587
64509
  async function exportRaci(ctx) {
63588
64510
  const { content, theme, palette } = ctx;
63589
- const { parseRaci: parseRaci2 } = await Promise.resolve().then(() => (init_parser26(), parser_exports20));
63590
- const { renderRaciForExport: renderRaciForExport2 } = await Promise.resolve().then(() => (init_renderer19(), renderer_exports19));
64511
+ const { parseRaci: parseRaci2 } = await Promise.resolve().then(() => (init_parser27(), parser_exports21));
64512
+ const { renderRaciForExport: renderRaciForExport2 } = await Promise.resolve().then(() => (init_renderer20(), renderer_exports20));
63591
64513
  const effectivePalette = await resolveExportPalette(theme, palette);
63592
64514
  const raciParsed = parseRaci2(content, effectivePalette);
63593
64515
  if (raciParsed.error) return "";
63594
64516
  const container = createExportContainer(EXPORT_WIDTH, EXPORT_HEIGHT);
63595
- renderRaciForExport2(
63596
- container,
63597
- raciParsed,
63598
- effectivePalette,
63599
- ctx.isDark,
63600
- { width: EXPORT_WIDTH, height: EXPORT_HEIGHT }
63601
- );
64517
+ renderRaciForExport2(container, raciParsed, effectivePalette, ctx.isDark, {
64518
+ width: EXPORT_WIDTH,
64519
+ height: EXPORT_HEIGHT
64520
+ });
63602
64521
  return finalizeSvgExport(container, theme, effectivePalette);
63603
64522
  }
63604
64523
  function beginVizExport() {
@@ -63687,14 +64606,7 @@ async function exportVenn(ctx) {
63687
64606
  if (parsed.error || parsed.vennSets.length < 2) return "";
63688
64607
  const effectivePalette = await resolveExportPalette(theme, palette);
63689
64608
  const { container, dims } = beginVizExport();
63690
- renderVenn(
63691
- container,
63692
- parsed,
63693
- effectivePalette,
63694
- ctx.isDark,
63695
- void 0,
63696
- dims
63697
- );
64609
+ renderVenn(container, parsed, effectivePalette, ctx.isDark, void 0, dims);
63698
64610
  return finalizeSvgExport(container, theme, effectivePalette);
63699
64611
  }
63700
64612
  async function exportQuadrant(ctx) {
@@ -63728,7 +64640,7 @@ async function exportVisualization(ctx) {
63728
64640
  const isDark = ctx.isDark;
63729
64641
  const container = createExportContainer(EXPORT_WIDTH, EXPORT_HEIGHT);
63730
64642
  const { parseSequenceDgmo: parseSequenceDgmo2 } = await Promise.resolve().then(() => (init_parser7(), parser_exports));
63731
- const { renderSequenceDiagram: renderSequenceDiagram2 } = await Promise.resolve().then(() => (init_renderer20(), renderer_exports20));
64643
+ const { renderSequenceDiagram: renderSequenceDiagram2 } = await Promise.resolve().then(() => (init_renderer21(), renderer_exports21));
63732
64644
  const seqParsed = parseSequenceDgmo2(content, effectivePalette);
63733
64645
  if (seqParsed.error || seqParsed.participants.length === 0) return "";
63734
64646
  const collapsedSections = viewState?.cs ? new Set(viewState.cs) : void 0;