@diagrammo/dgmo 0.37.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.
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"
@@ -18970,7 +18976,7 @@ function parseMap(content, palette) {
18970
18976
  continue;
18971
18977
  }
18972
18978
  if (DIRECTIVE_SET.has(firstWord) && !trimmed.slice(firstWord.length).trimStart().startsWith(":")) {
18973
- handleDirective(
18979
+ handleDirective2(
18974
18980
  firstWord,
18975
18981
  trimmed.slice(firstWord.length).trim(),
18976
18982
  lineNumber
@@ -19009,7 +19015,7 @@ function parseMap(content, palette) {
19009
19015
  }
19010
19016
  }
19011
19017
  return result;
19012
- function handleDirective(key, value, line11) {
19018
+ function handleDirective2(key, value, line11) {
19013
19019
  const d = result.directives;
19014
19020
  const dup = (have) => {
19015
19021
  if (have !== void 0)
@@ -22879,6 +22885,344 @@ var init_parser25 = __esm({
22879
22885
  }
22880
22886
  });
22881
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
+
22882
23226
  // src/raci/variants.ts
22883
23227
  function inferVariant(markers) {
22884
23228
  let hasD = false;
@@ -23133,8 +23477,8 @@ var init_variants = __esm({
23133
23477
  });
23134
23478
 
23135
23479
  // src/raci/parser.ts
23136
- var parser_exports20 = {};
23137
- __export(parser_exports20, {
23480
+ var parser_exports21 = {};
23481
+ __export(parser_exports21, {
23138
23482
  allTasks: () => allTasks,
23139
23483
  parseRaci: () => parseRaci
23140
23484
  });
@@ -23655,7 +23999,7 @@ function* allTasks(parsed) {
23655
23999
  }
23656
24000
  }
23657
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;
23658
- var init_parser26 = __esm({
24002
+ var init_parser27 = __esm({
23659
24003
  "src/raci/parser.ts"() {
23660
24004
  "use strict";
23661
24005
  init_diagnostics();
@@ -23901,6 +24245,7 @@ var init_chart_type_registry = __esm({
23901
24245
  init_parser24();
23902
24246
  init_parser25();
23903
24247
  init_parser26();
24248
+ init_parser27();
23904
24249
  CHART_TYPE_REGISTRY = [
23905
24250
  // ── Structured diagrams ───────────────────────────────────
23906
24251
  {
@@ -24041,6 +24386,9 @@ var init_chart_type_registry = __esm({
24041
24386
  { id: "cycle", category: "visualization", parse: parseCycle },
24042
24387
  { id: "pyramid", category: "visualization", parse: parsePyramid },
24043
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 },
24044
24392
  // ── Geographic map (own parser → resolver → layout → renderer) ──
24045
24393
  { id: "map", category: "visualization", parse: parseMap }
24046
24394
  ];
@@ -26773,10 +27121,10 @@ async function renderSitemapForExport(content, theme, palette) {
26773
27121
  const parsed = parseSitemap2(content, effectivePalette);
26774
27122
  if (parsed.error || parsed.roots.length === 0) return "";
26775
27123
  const sitemapLayout = layoutSitemap2(parsed, void 0, null, void 0, true);
26776
- const PADDING3 = 20;
27124
+ const PADDING4 = 20;
26777
27125
  const titleOffset = parsed.title ? 30 : 0;
26778
- const exportWidth = sitemapLayout.width + PADDING3 * 2;
26779
- const exportHeight = sitemapLayout.height + PADDING3 * 2 + titleOffset;
27126
+ const exportWidth = sitemapLayout.width + PADDING4 * 2;
27127
+ const exportHeight = sitemapLayout.height + PADDING4 * 2 + titleOffset;
26780
27128
  const container = document.createElement("div");
26781
27129
  container.style.width = `${exportWidth}px`;
26782
27130
  container.style.height = `${exportHeight}px`;
@@ -31804,6 +32152,10 @@ async function layoutBoxesAndLinesSearch(parsed, collapseInfo, opts) {
31804
32152
  const reserveEdgeLabels = opts?.reserveEdgeLabels ?? false;
31805
32153
  const onProgress = opts?.onProgress;
31806
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;
31807
32159
  const collapsedGroupLabels = /* @__PURE__ */ new Set();
31808
32160
  if (collapseInfo) {
31809
32161
  const missing = /* @__PURE__ */ new Set();
@@ -32233,7 +32585,11 @@ async function layoutBoxesAndLinesSearch(parsed, collapseInfo, opts) {
32233
32585
  const step = async (phase) => {
32234
32586
  if (!onProgress) return;
32235
32587
  onProgress(++progressDone, progressTotal, phase);
32236
- 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
+ }
32237
32593
  };
32238
32594
  const pool = [];
32239
32595
  for (const cfg of configs) {
@@ -50623,7 +50979,7 @@ function computeEdgeLabelPosition(midAngle, radius, cx, cy, lineCount, labelPxW,
50623
50979
  };
50624
50980
  }
50625
50981
  function fitToCanvas(nodes, edges, parsed, _cx, _cy, radius, width, height, _isClockwise) {
50626
- const PADDING3 = 30;
50982
+ const PADDING4 = 30;
50627
50983
  let contentMinX = Infinity, contentMaxX = -Infinity;
50628
50984
  let contentMinY = Infinity, contentMaxY = -Infinity;
50629
50985
  for (const n of nodes) {
@@ -50665,13 +51021,13 @@ function fitToCanvas(nodes, edges, parsed, _cx, _cy, radius, width, height, _isC
50665
51021
  contentMinY = Math.min(contentMinY, le.labelY - 12);
50666
51022
  contentMaxY = Math.max(contentMaxY, le.labelY + (lineCount - 1) * 15);
50667
51023
  }
50668
- const overflowX = Math.max(0, PADDING3 - contentMinX) + Math.max(0, contentMaxX - (width - PADDING3));
50669
- 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));
50670
51026
  if (overflowX <= 0 && overflowY <= 0) return null;
50671
51027
  const contentW = contentMaxX - contentMinX;
50672
51028
  const contentH = contentMaxY - contentMinY;
50673
- const availW = width - 2 * PADDING3;
50674
- const availH = height - 2 * PADDING3;
51029
+ const availW = width - 2 * PADDING4;
51030
+ const availH = height - 2 * PADDING4;
50675
51031
  const shrink = Math.min(availW / contentW, availH / contentH);
50676
51032
  const newRadius = Math.max(80, radius * shrink);
50677
51033
  return { radius: newRadius };
@@ -50869,7 +51225,7 @@ function renderCycle(container, parsed, palette, isDark, onClickItem, exportDims
50869
51225
  }
50870
51226
  edgeLabelInfo.push({ le, edge });
50871
51227
  }
50872
- const HEADER_H = 36 * layout.scale;
51228
+ const HEADER_H2 = 36 * layout.scale;
50873
51229
  const scaledNodeFont = Math.max(6, Math.round(NODE_FONT_SIZE7 * layout.scale));
50874
51230
  const scaledEdgeLabelFont = Math.max(
50875
51231
  6,
@@ -50933,10 +51289,10 @@ function renderCycle(container, parsed, palette, isDark, onClickItem, exportDims
50933
51289
  const rx = 6;
50934
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);
50935
51291
  if (hasDesc) {
50936
- const headerCenterY = ln.y - nodeH / 2 + HEADER_H / 2;
51292
+ const headerCenterY = ln.y - nodeH / 2 + HEADER_H2 / 2;
50937
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");
50938
51294
  renderInlineText(labelText, node.label, palette, scaledNodeFont);
50939
- const sepY = ln.y - nodeH / 2 + HEADER_H;
51295
+ const sepY = ln.y - nodeH / 2 + HEADER_H2;
50940
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);
50941
51297
  const descStartY = sepY + 4 + scaledDescFont;
50942
51298
  const descPadX = Math.max(8, 12 * layout.scale);
@@ -55748,7 +56104,9 @@ function mapContentAspect(resolved, data, ref = REF) {
55748
56104
  function mapExportDimensions(resolved, data, baseWidth = 1200, aspectOverride) {
55749
56105
  const useOverride = aspectOverride !== void 0 && Number.isFinite(aspectOverride) && aspectOverride > 0;
55750
56106
  const raw = useOverride ? aspectOverride : mapContentAspect(resolved, data);
55751
- 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));
55752
56110
  const width = baseWidth;
55753
56111
  let height = Math.round(width / clamped);
55754
56112
  let chromeReserve = 0;
@@ -55761,10 +56119,10 @@ function mapExportDimensions(resolved, data, baseWidth = 1200, aspectOverride) {
55761
56119
  height = Math.round(chromeReserve + MIN_MAP_BAND);
55762
56120
  floored = true;
55763
56121
  }
55764
- const preferContain = useOverride ? floored : clamped !== raw || floored;
56122
+ const preferContain = useOverride ? floored : clamped !== target || floored;
55765
56123
  return { width, height, preferContain };
55766
56124
  }
55767
- 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;
55768
56126
  var init_dimensions = __esm({
55769
56127
  "src/map/dimensions.ts"() {
55770
56128
  "use strict";
@@ -55775,6 +56133,7 @@ var init_dimensions = __esm({
55775
56133
  TITLE_GAP = 16;
55776
56134
  ASPECT_MAX = 3;
55777
56135
  ASPECT_MIN = 0.9;
56136
+ GLOBAL_HEIGHT_BOOST = 1.12;
55778
56137
  MIN_MAP_BAND = 200;
55779
56138
  FALLBACK_ASPECT = 1.5;
55780
56139
  REF = 1e3;
@@ -56564,9 +56923,469 @@ var init_renderer18 = __esm({
56564
56923
  }
56565
56924
  });
56566
56925
 
56567
- // 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
56568
57012
  var renderer_exports19 = {};
56569
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, {
56570
57389
  MARKER_LABELS: () => MARKER_LABELS,
56571
57390
  renderRaci: () => renderRaci,
56572
57391
  renderRaciForExport: () => renderRaciForExport
@@ -56642,7 +57461,7 @@ function renderRaci(container, parsed, palette, isDark, handlers, exportDims) {
56642
57461
  const hideLegend = opts.hideLegend ?? false;
56643
57462
  const collapsedPhases = opts.collapsedPhases ?? /* @__PURE__ */ new Set();
56644
57463
  const hideTitle = (opts.hideTitle ?? false) || parsed.options["no-title"] === "on";
56645
- d3Selection26.select(container).selectAll(":not([data-d3-tooltip])").remove();
57464
+ d3Selection27.select(container).selectAll(":not([data-d3-tooltip])").remove();
56646
57465
  const width = exportDims?.width ?? container.clientWidth;
56647
57466
  const height = exportDims?.height ?? container.clientHeight;
56648
57467
  if (width <= 0 || height <= 0) return;
@@ -56749,7 +57568,7 @@ function renderRaci(container, parsed, palette, isDark, handlers, exportDims) {
56749
57568
  const colBottomY = cursorY + sColumnBottomPad;
56750
57569
  const totalHeight = colBottomY + sVMargin;
56751
57570
  const svgHeight = exportDims ? totalHeight : Math.max(height, totalHeight);
56752
- 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");
56753
57572
  if (ctx.isBelowFloor) {
56754
57573
  svg.attr("width", "100%");
56755
57574
  }
@@ -57229,15 +58048,15 @@ function parseQuotedSegments(message) {
57229
58048
  out.push({ text: message.slice(last), bold: false });
57230
58049
  return out;
57231
58050
  }
57232
- 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;
57233
- 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({
57234
58053
  "src/raci/renderer.ts"() {
57235
58054
  "use strict";
57236
- d3Selection26 = __toESM(require("d3-selection"), 1);
58055
+ d3Selection27 = __toESM(require("d3-selection"), 1);
57237
58056
  init_fonts();
57238
58057
  init_title_constants();
57239
58058
  init_color_utils();
57240
- init_parser26();
58059
+ init_parser27();
57241
58060
  init_variants();
57242
58061
  init_scaling();
57243
58062
  init_text_measure();
@@ -57494,8 +58313,8 @@ var init_tag_resolution = __esm({
57494
58313
  });
57495
58314
 
57496
58315
  // src/sequence/renderer.ts
57497
- var renderer_exports20 = {};
57498
- __export(renderer_exports20, {
58316
+ var renderer_exports21 = {};
58317
+ __export(renderer_exports21, {
57499
58318
  applyGroupOrdering: () => applyGroupOrdering,
57500
58319
  applyPositionOverrides: () => applyPositionOverrides,
57501
58320
  buildNoteMessageMap: () => buildNoteMessageMap,
@@ -57835,7 +58654,7 @@ function applyGroupOrdering(participants, groups, messages = []) {
57835
58654
  return result;
57836
58655
  }
57837
58656
  function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateToLine, options) {
57838
- d3Selection27.select(container).selectAll("*").remove();
58657
+ d3Selection28.select(container).selectAll("*").remove();
57839
58658
  const { title, options: parsedOptions } = parsed;
57840
58659
  const solid = parsedOptions["solid-fill"] === "on";
57841
58660
  const effectiveCollapsedGroups = /* @__PURE__ */ new Set();
@@ -58486,7 +59305,7 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
58486
59305
  offsetX = leftMargin + Math.max(0, (svgWidth - totalWidth) / 2);
58487
59306
  buildParticipantX();
58488
59307
  }
58489
- 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);
58490
59309
  const defs = svg.append("defs");
58491
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(
58492
59311
  "points",
@@ -59098,12 +59917,12 @@ function renderParticipant(svg, participant, cx, cy, palette, isDark, color, tag
59098
59917
  });
59099
59918
  }
59100
59919
  }
59101
- 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;
59102
- 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({
59103
59922
  "src/sequence/renderer.ts"() {
59104
59923
  "use strict";
59105
59924
  init_tag_groups();
59106
- d3Selection27 = __toESM(require("d3-selection"), 1);
59925
+ d3Selection28 = __toESM(require("d3-selection"), 1);
59107
59926
  init_color_utils();
59108
59927
  init_inline_markdown();
59109
59928
  init_fonts();
@@ -63000,6 +63819,7 @@ var DIAGRAM_EXPORT_HANDLERS = {
63000
63819
  map: exportMap,
63001
63820
  pyramid: exportPyramid,
63002
63821
  ring: exportRing,
63822
+ treemap: exportTreemap,
63003
63823
  raci: exportRaci,
63004
63824
  rasci: exportRaci,
63005
63825
  daci: exportRaci,
@@ -63057,10 +63877,10 @@ async function exportOrg(ctx) {
63057
63877
  false
63058
63878
  // expandAllLegend off — collapsed-by-default per §1.3
63059
63879
  );
63060
- const PADDING3 = 20;
63880
+ const PADDING4 = 20;
63061
63881
  const titleOffset = effectiveParsed.title ? 30 : 0;
63062
- const exportWidth = orgLayout.width + PADDING3 * 2;
63063
- const exportHeight = orgLayout.height + PADDING3 * 2 + titleOffset;
63882
+ const exportWidth = orgLayout.width + PADDING4 * 2;
63883
+ const exportHeight = orgLayout.height + PADDING4 * 2 + titleOffset;
63064
63884
  const container = createExportContainer(exportWidth, exportHeight);
63065
63885
  renderOrg2(
63066
63886
  container,
@@ -63102,10 +63922,10 @@ async function exportSitemap(ctx) {
63102
63922
  hiddenAttributes,
63103
63923
  true
63104
63924
  );
63105
- const PADDING3 = 20;
63925
+ const PADDING4 = 20;
63106
63926
  const titleOffset = effectiveParsed.title ? 30 : 0;
63107
- const exportWidth = sitemapLayout.width + PADDING3 * 2;
63108
- const exportHeight = sitemapLayout.height + PADDING3 * 2 + titleOffset;
63927
+ const exportWidth = sitemapLayout.width + PADDING4 * 2;
63928
+ const exportHeight = sitemapLayout.height + PADDING4 * 2 + titleOffset;
63109
63929
  const container = createExportContainer(exportWidth, exportHeight);
63110
63930
  renderSitemap2(
63111
63931
  container,
@@ -63161,10 +63981,10 @@ async function exportClass(ctx) {
63161
63981
  const classParsed = parseClassDiagram2(content, effectivePalette);
63162
63982
  if (classParsed.error || classParsed.classes.length === 0) return "";
63163
63983
  const classLayout = layoutClassDiagram2(classParsed);
63164
- const PADDING3 = 20;
63984
+ const PADDING4 = 20;
63165
63985
  const titleOffset = classParsed.title ? 40 : 0;
63166
- const exportWidth = classLayout.width + PADDING3 * 2;
63167
- const exportHeight = classLayout.height + PADDING3 * 2 + titleOffset;
63986
+ const exportWidth = classLayout.width + PADDING4 * 2;
63987
+ const exportHeight = classLayout.height + PADDING4 * 2 + titleOffset;
63168
63988
  const container = createExportContainer(exportWidth, exportHeight);
63169
63989
  renderClassDiagram2(
63170
63990
  container,
@@ -63188,10 +64008,10 @@ async function exportEr(ctx) {
63188
64008
  const erParsed = parseERDiagram2(content, effectivePalette);
63189
64009
  if (erParsed.error || erParsed.tables.length === 0) return "";
63190
64010
  const erLayout = layoutERDiagram2(erParsed);
63191
- const PADDING3 = 20;
64011
+ const PADDING4 = 20;
63192
64012
  const titleOffset = erParsed.title ? 40 : 0;
63193
- const exportWidth = erLayout.width + PADDING3 * 2;
63194
- const exportHeight = erLayout.height + PADDING3 * 2 + titleOffset;
64013
+ const exportWidth = erLayout.width + PADDING4 * 2;
64014
+ const exportHeight = erLayout.height + PADDING4 * 2 + titleOffset;
63195
64015
  const container = createExportContainer(exportWidth, exportHeight);
63196
64016
  renderERDiagram2(
63197
64017
  container,
@@ -63227,10 +64047,10 @@ async function exportBoxesAndLines(ctx) {
63227
64047
  const { renderBoxesAndLinesForExport: renderBoxesAndLinesForExport2 } = await Promise.resolve().then(() => (init_renderer6(), renderer_exports6));
63228
64048
  const { layoutBoxesAndLines: layoutBoxesAndLines2 } = await Promise.resolve().then(() => (init_layout5(), layout_exports5));
63229
64049
  const blLayout = await layoutBoxesAndLines2(blParsed);
63230
- const PADDING3 = 20;
64050
+ const PADDING4 = 20;
63231
64051
  const titleOffset = blParsed.title ? 40 : 0;
63232
- const exportWidth = blLayout.width + PADDING3 * 2;
63233
- const exportHeight = blLayout.height + PADDING3 * 2 + titleOffset;
64052
+ const exportWidth = blLayout.width + PADDING4 * 2;
64053
+ const exportHeight = blLayout.height + PADDING4 * 2 + titleOffset;
63234
64054
  const container = createExportContainer(exportWidth, exportHeight);
63235
64055
  const blActiveTagGroup = ctxTagOverride(ctx);
63236
64056
  renderBoxesAndLinesForExport2(
@@ -63277,10 +64097,10 @@ async function exportMindmap(ctx) {
63277
64097
  activeTagGroup,
63278
64098
  hideDescriptions
63279
64099
  });
63280
- const PADDING3 = 20;
64100
+ const PADDING4 = 20;
63281
64101
  const titleOffset = effectiveParsed.title ? 30 : 0;
63282
- const exportWidth = mmLayout.width + PADDING3 * 2;
63283
- const exportHeight = mmLayout.height + PADDING3 * 2 + titleOffset;
64102
+ const exportWidth = mmLayout.width + PADDING4 * 2;
64103
+ const exportHeight = mmLayout.height + PADDING4 * 2 + titleOffset;
63284
64104
  const container = createExportContainer(exportWidth, exportHeight);
63285
64105
  const colorByDepth = viewState?.cbd === true;
63286
64106
  renderMindmap2(
@@ -63341,10 +64161,10 @@ async function exportC4(ctx) {
63341
64161
  const c4Container = ctx.options?.c4Container ?? viewState?.c4c;
63342
64162
  const c4Layout = c4Level === "deployment" ? layoutC4Deployment2(c4Parsed) : c4Level === "components" && c4System && c4Container ? layoutC4Components2(c4Parsed, c4System, c4Container) : c4Level === "containers" && c4System ? layoutC4Containers2(c4Parsed, c4System) : layoutC4Context2(c4Parsed);
63343
64163
  if (c4Layout.nodes.length === 0) return "";
63344
- const PADDING3 = 20;
64164
+ const PADDING4 = 20;
63345
64165
  const titleOffset = c4Parsed.title ? 40 : 0;
63346
- const exportWidth = c4Layout.width + PADDING3 * 2;
63347
- const exportHeight = c4Layout.height + PADDING3 * 2 + titleOffset;
64166
+ const exportWidth = c4Layout.width + PADDING4 * 2;
64167
+ const exportHeight = c4Layout.height + PADDING4 * 2 + titleOffset;
63348
64168
  const container = createExportContainer(exportWidth, exportHeight);
63349
64169
  const renderFn = c4Level === "deployment" || c4Level === "components" && c4System && c4Container || c4Level === "containers" && c4System ? renderC4Containers2 : renderC4Context2;
63350
64170
  renderFn(
@@ -63660,30 +64480,44 @@ async function exportRing(ctx) {
63660
64480
  const ringParsed = parseRing2(content);
63661
64481
  if (ringParsed.error || ringParsed.layers.length === 0) return "";
63662
64482
  const container = createExportContainer(EXPORT_WIDTH, EXPORT_HEIGHT);
63663
- 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(
63664
64498
  container,
63665
- ringParsed,
64499
+ treemapParsed,
63666
64500
  effectivePalette,
63667
64501
  ctx.isDark,
63668
- { width: EXPORT_WIDTH, height: EXPORT_HEIGHT }
64502
+ {
64503
+ width: EXPORT_WIDTH,
64504
+ height: EXPORT_HEIGHT
64505
+ }
63669
64506
  );
63670
64507
  return finalizeSvgExport(container, theme, effectivePalette);
63671
64508
  }
63672
64509
  async function exportRaci(ctx) {
63673
64510
  const { content, theme, palette } = ctx;
63674
- const { parseRaci: parseRaci2 } = await Promise.resolve().then(() => (init_parser26(), parser_exports20));
63675
- 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));
63676
64513
  const effectivePalette = await resolveExportPalette(theme, palette);
63677
64514
  const raciParsed = parseRaci2(content, effectivePalette);
63678
64515
  if (raciParsed.error) return "";
63679
64516
  const container = createExportContainer(EXPORT_WIDTH, EXPORT_HEIGHT);
63680
- renderRaciForExport2(
63681
- container,
63682
- raciParsed,
63683
- effectivePalette,
63684
- ctx.isDark,
63685
- { width: EXPORT_WIDTH, height: EXPORT_HEIGHT }
63686
- );
64517
+ renderRaciForExport2(container, raciParsed, effectivePalette, ctx.isDark, {
64518
+ width: EXPORT_WIDTH,
64519
+ height: EXPORT_HEIGHT
64520
+ });
63687
64521
  return finalizeSvgExport(container, theme, effectivePalette);
63688
64522
  }
63689
64523
  function beginVizExport() {
@@ -63772,14 +64606,7 @@ async function exportVenn(ctx) {
63772
64606
  if (parsed.error || parsed.vennSets.length < 2) return "";
63773
64607
  const effectivePalette = await resolveExportPalette(theme, palette);
63774
64608
  const { container, dims } = beginVizExport();
63775
- renderVenn(
63776
- container,
63777
- parsed,
63778
- effectivePalette,
63779
- ctx.isDark,
63780
- void 0,
63781
- dims
63782
- );
64609
+ renderVenn(container, parsed, effectivePalette, ctx.isDark, void 0, dims);
63783
64610
  return finalizeSvgExport(container, theme, effectivePalette);
63784
64611
  }
63785
64612
  async function exportQuadrant(ctx) {
@@ -63813,7 +64640,7 @@ async function exportVisualization(ctx) {
63813
64640
  const isDark = ctx.isDark;
63814
64641
  const container = createExportContainer(EXPORT_WIDTH, EXPORT_HEIGHT);
63815
64642
  const { parseSequenceDgmo: parseSequenceDgmo2 } = await Promise.resolve().then(() => (init_parser7(), parser_exports));
63816
- const { renderSequenceDiagram: renderSequenceDiagram2 } = await Promise.resolve().then(() => (init_renderer20(), renderer_exports20));
64643
+ const { renderSequenceDiagram: renderSequenceDiagram2 } = await Promise.resolve().then(() => (init_renderer21(), renderer_exports21));
63817
64644
  const seqParsed = parseSequenceDgmo2(content, effectivePalette);
63818
64645
  if (seqParsed.error || seqParsed.participants.length === 0) return "";
63819
64646
  const collapsedSections = viewState?.cs ? new Set(viewState.cs) : void 0;