@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/auto.mjs CHANGED
@@ -600,7 +600,7 @@ function withTagAliases(base, aliases) {
600
600
  function isReservedKey(registry, key) {
601
601
  return registry.keys.has(key) || registry.tagAliases.has(key);
602
602
  }
603
- 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;
603
+ 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;
604
604
  var init_reserved_key_registry = __esm({
605
605
  "src/utils/reserved-key-registry.ts"() {
606
606
  "use strict";
@@ -719,6 +719,7 @@ var init_reserved_key_registry = __esm({
719
719
  "color",
720
720
  "description"
721
721
  ]);
722
+ TREEMAP_REGISTRY = staticRegistry(["heat"]);
722
723
  RACI_REGISTRY = staticRegistry([
723
724
  "color",
724
725
  "description"
@@ -1148,6 +1149,7 @@ var init_parsing = __esm({
1148
1149
  "journey-map",
1149
1150
  "pyramid",
1150
1151
  "ring",
1152
+ "treemap",
1151
1153
  "raci",
1152
1154
  "rasci",
1153
1155
  "daci",
@@ -11807,6 +11809,10 @@ var init_chart_types = __esm({
11807
11809
  id: "ring",
11808
11810
  description: "Concentric rings showing nested or hierarchical categories (read core-out)"
11809
11811
  },
11812
+ {
11813
+ id: "treemap",
11814
+ description: "Nested rectangles sized by value \u2014 show a hierarchy\u2019s proportions (budgets, disk usage, portfolios) with color by category, value heatmap, or branch"
11815
+ },
11810
11816
  {
11811
11817
  id: "map",
11812
11818
  description: "Geographic concept map: highlight/score regions, drop points of interest, connect with routes or edges"
@@ -18986,7 +18992,7 @@ function parseMap(content, palette) {
18986
18992
  continue;
18987
18993
  }
18988
18994
  if (DIRECTIVE_SET.has(firstWord) && !trimmed.slice(firstWord.length).trimStart().startsWith(":")) {
18989
- handleDirective(
18995
+ handleDirective2(
18990
18996
  firstWord,
18991
18997
  trimmed.slice(firstWord.length).trim(),
18992
18998
  lineNumber
@@ -19025,7 +19031,7 @@ function parseMap(content, palette) {
19025
19031
  }
19026
19032
  }
19027
19033
  return result;
19028
- function handleDirective(key, value, line11) {
19034
+ function handleDirective2(key, value, line11) {
19029
19035
  const d = result.directives;
19030
19036
  const dup = (have) => {
19031
19037
  if (have !== void 0)
@@ -22895,6 +22901,344 @@ var init_parser25 = __esm({
22895
22901
  }
22896
22902
  });
22897
22903
 
22904
+ // src/treemap/parser.ts
22905
+ var parser_exports20 = {};
22906
+ __export(parser_exports20, {
22907
+ TREEMAP_DIAGNOSTIC_CODES: () => TREEMAP_DIAGNOSTIC_CODES,
22908
+ parseTreemap: () => parseTreemap
22909
+ });
22910
+ function isFullyQuoted(s) {
22911
+ return s.length >= 2 && (s.startsWith('"') && s.endsWith('"') || s.startsWith("'") && s.endsWith("'"));
22912
+ }
22913
+ function parseTreemap(content, palette) {
22914
+ const options = {
22915
+ heatColors: [],
22916
+ noValues: false,
22917
+ noPercent: false,
22918
+ noHeaders: false,
22919
+ noLegend: false
22920
+ };
22921
+ const result = {
22922
+ type: "treemap",
22923
+ title: null,
22924
+ titleLineNumber: null,
22925
+ roots: [],
22926
+ tagGroups: [],
22927
+ hasHeat: false,
22928
+ defaultColorMode: "branch",
22929
+ options,
22930
+ diagnostics: [],
22931
+ error: null
22932
+ };
22933
+ const fail = makeFail(result);
22934
+ const pushError = (line11, message, code) => {
22935
+ const diag = makeDgmoError(line11, message, "error", code);
22936
+ result.diagnostics.push(diag);
22937
+ if (!result.error) result.error = formatDgmoError(diag);
22938
+ };
22939
+ const pushWarning = (line11, message, code) => {
22940
+ result.diagnostics.push(makeDgmoError(line11, message, "warning", code));
22941
+ };
22942
+ if (!content?.trim()) {
22943
+ return fail(0, "No content provided");
22944
+ }
22945
+ const lines = content.split("\n");
22946
+ let contentStarted = false;
22947
+ let nodeCounter = 0;
22948
+ let currentTagGroup = null;
22949
+ const aliasMap = /* @__PURE__ */ new Map();
22950
+ const indentStack = [];
22951
+ for (let i = 0; i < lines.length; i++) {
22952
+ const line11 = lines[i];
22953
+ const lineNumber = i + 1;
22954
+ const trimmed = line11.trim();
22955
+ if (!trimmed) {
22956
+ currentTagGroup = null;
22957
+ continue;
22958
+ }
22959
+ if (trimmed.startsWith("//")) continue;
22960
+ if (!contentStarted) {
22961
+ const firstLine = parseFirstLine(trimmed);
22962
+ if (firstLine && result.titleLineNumber === null && i === 0) {
22963
+ if (firstLine.chartType !== "treemap") {
22964
+ let msg = `Expected chart type "treemap", got "${firstLine.chartType}"`;
22965
+ const hint = suggest(firstLine.chartType, ["treemap"]);
22966
+ if (hint) msg += `. ${hint}`;
22967
+ return fail(lineNumber, msg);
22968
+ }
22969
+ result.title = firstLine.title ?? null;
22970
+ result.titleLineNumber = lineNumber;
22971
+ continue;
22972
+ }
22973
+ }
22974
+ const tagBlockMatch = matchTagBlockHeading(trimmed);
22975
+ if (tagBlockMatch) {
22976
+ emitTagLegacyDiagnostic(tagBlockMatch, lineNumber, result.diagnostics);
22977
+ if (contentStarted) {
22978
+ pushError(
22979
+ lineNumber,
22980
+ "Tag groups must appear before treemap content",
22981
+ "E_TAG_DECLARED_AFTER_CONTENT"
22982
+ );
22983
+ continue;
22984
+ }
22985
+ currentTagGroup = {
22986
+ name: tagBlockMatch.name,
22987
+ ...tagBlockMatch.alias !== void 0 && {
22988
+ alias: tagBlockMatch.alias
22989
+ },
22990
+ entries: [],
22991
+ lineNumber
22992
+ };
22993
+ if (tagBlockMatch.alias) {
22994
+ aliasMap.set(
22995
+ tagBlockMatch.alias.toLowerCase(),
22996
+ tagAttrKey(tagBlockMatch.name)
22997
+ );
22998
+ }
22999
+ aliasMap.set(
23000
+ tagAttrKey(tagBlockMatch.name),
23001
+ tagAttrKey(tagBlockMatch.name)
23002
+ );
23003
+ result.tagGroups.push(currentTagGroup);
23004
+ continue;
23005
+ }
23006
+ if (currentTagGroup && !contentStarted) {
23007
+ const indent2 = measureIndent(line11);
23008
+ if (indent2 > 0) {
23009
+ const { text: cleanEntry, isDefault } = stripDefaultModifier(trimmed);
23010
+ const { label, color } = extractColor(
23011
+ cleanEntry,
23012
+ palette,
23013
+ result.diagnostics,
23014
+ lineNumber
23015
+ );
23016
+ if (isDefault) {
23017
+ currentTagGroup.defaultValue = label;
23018
+ } else if (currentTagGroup.entries.length === 0) {
23019
+ currentTagGroup.defaultValue = label;
23020
+ }
23021
+ currentTagGroup.entries.push({
23022
+ value: label,
23023
+ color: color ?? AUTO_TAG_COLOR_SENTINEL,
23024
+ lineNumber
23025
+ });
23026
+ continue;
23027
+ }
23028
+ currentTagGroup = null;
23029
+ }
23030
+ if (!contentStarted && measureIndent(line11) === 0) {
23031
+ if (handleDirective(trimmed, options, result, pushWarning, lineNumber)) {
23032
+ continue;
23033
+ }
23034
+ }
23035
+ contentStarted = true;
23036
+ currentTagGroup = null;
23037
+ const indent = measureIndent(line11);
23038
+ const node = parseNodeLine3(
23039
+ trimmed,
23040
+ lineNumber,
23041
+ ++nodeCounter,
23042
+ aliasMap,
23043
+ result.diagnostics,
23044
+ pushWarning
23045
+ );
23046
+ if (node.heat !== void 0) result.hasHeat = true;
23047
+ attachNode4(node, indent, indentStack, result);
23048
+ }
23049
+ finalizeAutoTagColors(result.tagGroups, palette);
23050
+ const allNodes = [];
23051
+ const collectAll = (nodes) => {
23052
+ for (const n of nodes) {
23053
+ allNodes.push(n);
23054
+ collectAll(n.children);
23055
+ }
23056
+ };
23057
+ collectAll(result.roots);
23058
+ for (const n of allNodes) {
23059
+ const node = n;
23060
+ const isBranch = node.children.length > 0;
23061
+ if (isBranch) {
23062
+ if (node.value !== void 0) {
23063
+ pushWarning(
23064
+ node.lineNumber,
23065
+ `"${node.label}" is a branch \u2014 its trailing number is ignored; the area is the auto-sum of its children`,
23066
+ TREEMAP_DIAGNOSTIC_CODES.BRANCH_VALUE_IGNORED
23067
+ );
23068
+ delete node.value;
23069
+ }
23070
+ } else if (node.value === void 0) {
23071
+ pushWarning(
23072
+ node.lineNumber,
23073
+ `Leaf "${node.label}" has no value \u2014 it renders with zero area`,
23074
+ TREEMAP_DIAGNOSTIC_CODES.LEAF_NO_VALUE
23075
+ );
23076
+ node.value = 0;
23077
+ } else if (node.value < 0) {
23078
+ pushError(
23079
+ node.lineNumber,
23080
+ `Leaf "${node.label}" has a negative value (${node.value}) \u2014 treemap sizes must be \u2265 0`,
23081
+ TREEMAP_DIAGNOSTIC_CODES.NEGATIVE_VALUE
23082
+ );
23083
+ }
23084
+ }
23085
+ if (result.hasHeat || options.heatLabel !== void 0) {
23086
+ result.hasHeat = true;
23087
+ }
23088
+ if (result.tagGroups.length > 0) {
23089
+ validateTagValues(allNodes, result.tagGroups, pushWarning, suggest);
23090
+ validateTagGroupNames(result.tagGroups, pushWarning);
23091
+ cascadeTagMetadata(result.roots, result.tagGroups);
23092
+ }
23093
+ result.defaultColorMode = resolveDefaultColorMode(result);
23094
+ if (result.roots.length === 0 && !result.error) {
23095
+ const diag = makeDgmoError(1, "No nodes found in treemap");
23096
+ result.diagnostics.push(diag);
23097
+ result.error = formatDgmoError(diag);
23098
+ }
23099
+ return result;
23100
+ }
23101
+ function handleDirective(trimmed, options, result, pushWarning, lineNumber) {
23102
+ const depthMatch = trimmed.match(/^depth\s+(-?\d+)\s*$/i);
23103
+ if (depthMatch) {
23104
+ const n = parseInt(depthMatch[1], 10);
23105
+ if (n >= 1) options.maxDepth = n;
23106
+ else pushWarning(lineNumber, '"depth" must be \u2265 1 \u2014 ignored');
23107
+ return true;
23108
+ }
23109
+ if (/^other-below\b/i.test(trimmed)) {
23110
+ pushWarning(
23111
+ lineNumber,
23112
+ '"other-below" is no longer supported \u2014 remove this line'
23113
+ );
23114
+ return true;
23115
+ }
23116
+ const heatMatch = trimmed.match(/^heat\s+(.+)$/i);
23117
+ if (heatMatch) {
23118
+ const { label, low, high } = peelRampColors(heatMatch[1].trim());
23119
+ options.heatLabel = label || "Value";
23120
+ const colors = [];
23121
+ if (low !== void 0) colors.push(low);
23122
+ if (high !== void 0) colors.push(high);
23123
+ options.heatColors = colors;
23124
+ result.hasHeat = true;
23125
+ return true;
23126
+ }
23127
+ const noMatch = trimmed.match(/^no-(values|percent|headers|legend)\s*$/i);
23128
+ if (noMatch) {
23129
+ const key = noMatch[1].toLowerCase();
23130
+ if (key === "values") options.noValues = true;
23131
+ else if (key === "percent") options.noPercent = true;
23132
+ else if (key === "headers") options.noHeaders = true;
23133
+ else if (key === "legend") options.noLegend = true;
23134
+ return true;
23135
+ }
23136
+ return false;
23137
+ }
23138
+ function resolveDefaultColorMode(result) {
23139
+ if (result.tagGroups.length > 0) return "tag";
23140
+ if (result.hasHeat) return "heat";
23141
+ return "branch";
23142
+ }
23143
+ function parseNodeLine3(trimmed, lineNumber, counter, aliasMap, diagnostics, pushWarning) {
23144
+ if (trimmed.includes("|")) {
23145
+ diagnostics.push(
23146
+ makeDgmoError(
23147
+ lineNumber,
23148
+ pipeOperatorRemovedMessage(),
23149
+ "error",
23150
+ METADATA_DIAGNOSTIC_CODES.PIPE_OPERATOR_REMOVED
23151
+ )
23152
+ );
23153
+ }
23154
+ const registry = withTagAliases(TREEMAP_REGISTRY, new Set(aliasMap.keys()));
23155
+ const split = splitNameAndMeta(
23156
+ trimmed,
23157
+ registry,
23158
+ aliasMap,
23159
+ void 0,
23160
+ diagnostics,
23161
+ lineNumber
23162
+ );
23163
+ warnUnknownMetaKeys(
23164
+ split.meta,
23165
+ registry,
23166
+ (msg) => diagnostics.push(makeDgmoError(lineNumber, msg, "warning")),
23167
+ split.name
23168
+ );
23169
+ const metadata = { ...split.meta };
23170
+ let heat;
23171
+ if ("heat" in metadata) {
23172
+ const h = parseFloat(metadata["heat"].replace(/_/g, ""));
23173
+ if (Number.isFinite(h)) heat = h;
23174
+ delete metadata["heat"];
23175
+ }
23176
+ const rawName = split.name;
23177
+ let label;
23178
+ let value;
23179
+ if (isFullyQuoted(rawName)) {
23180
+ label = stripQuotes(rawName);
23181
+ } else {
23182
+ const vm = rawName.match(VALUE_TOKEN_RE);
23183
+ if (vm) {
23184
+ const labelPart = vm[1].trim();
23185
+ const token = vm[2];
23186
+ if (token.includes(",")) {
23187
+ pushWarning(lineNumber, dataCommaRemovedMessage(labelPart));
23188
+ }
23189
+ const cleaned = token.replace(/[_,]/g, "");
23190
+ const parsed = parseFloat(cleaned);
23191
+ if (Number.isFinite(parsed)) {
23192
+ value = parsed;
23193
+ label = isFullyQuoted(labelPart) ? stripQuotes(labelPart) : labelPart;
23194
+ } else {
23195
+ label = rawName;
23196
+ }
23197
+ } else {
23198
+ label = rawName;
23199
+ }
23200
+ }
23201
+ return {
23202
+ id: `treemap-node-${counter}`,
23203
+ label,
23204
+ ...value !== void 0 && { value },
23205
+ ...heat !== void 0 && { heat },
23206
+ metadata,
23207
+ children: [],
23208
+ lineNumber
23209
+ };
23210
+ }
23211
+ function attachNode4(node, indent, indentStack, result) {
23212
+ while (indentStack.length > 0) {
23213
+ const top = indentStack[indentStack.length - 1];
23214
+ if (top.indent < indent) break;
23215
+ indentStack.pop();
23216
+ }
23217
+ if (indentStack.length > 0) {
23218
+ const parent = indentStack[indentStack.length - 1].node;
23219
+ parent.children.push(node);
23220
+ } else {
23221
+ result.roots.push(node);
23222
+ }
23223
+ indentStack.push({ node, indent });
23224
+ }
23225
+ var TREEMAP_DIAGNOSTIC_CODES, VALUE_TOKEN_RE;
23226
+ var init_parser26 = __esm({
23227
+ "src/treemap/parser.ts"() {
23228
+ "use strict";
23229
+ init_diagnostics();
23230
+ init_tag_groups();
23231
+ init_parsing();
23232
+ init_reserved_key_registry();
23233
+ TREEMAP_DIAGNOSTIC_CODES = {
23234
+ NEGATIVE_VALUE: "E_TREEMAP_NEGATIVE_VALUE",
23235
+ LEAF_NO_VALUE: "W_TREEMAP_LEAF_NO_VALUE",
23236
+ BRANCH_VALUE_IGNORED: "W_TREEMAP_BRANCH_VALUE_IGNORED"
23237
+ };
23238
+ VALUE_TOKEN_RE = /^(.+?)\s+(-?\d[\d_,.]*)$/;
23239
+ }
23240
+ });
23241
+
22898
23242
  // src/raci/variants.ts
22899
23243
  function inferVariant(markers) {
22900
23244
  let hasD = false;
@@ -23149,8 +23493,8 @@ var init_variants = __esm({
23149
23493
  });
23150
23494
 
23151
23495
  // src/raci/parser.ts
23152
- var parser_exports20 = {};
23153
- __export(parser_exports20, {
23496
+ var parser_exports21 = {};
23497
+ __export(parser_exports21, {
23154
23498
  allTasks: () => allTasks,
23155
23499
  parseRaci: () => parseRaci
23156
23500
  });
@@ -23671,7 +24015,7 @@ function* allTasks(parsed) {
23671
24015
  }
23672
24016
  }
23673
24017
  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;
23674
- var init_parser26 = __esm({
24018
+ var init_parser27 = __esm({
23675
24019
  "src/raci/parser.ts"() {
23676
24020
  "use strict";
23677
24021
  init_diagnostics();
@@ -23917,6 +24261,7 @@ var init_chart_type_registry = __esm({
23917
24261
  init_parser24();
23918
24262
  init_parser25();
23919
24263
  init_parser26();
24264
+ init_parser27();
23920
24265
  CHART_TYPE_REGISTRY = [
23921
24266
  // ── Structured diagrams ───────────────────────────────────
23922
24267
  {
@@ -24057,6 +24402,9 @@ var init_chart_type_registry = __esm({
24057
24402
  { id: "cycle", category: "visualization", parse: parseCycle },
24058
24403
  { id: "pyramid", category: "visualization", parse: parsePyramid },
24059
24404
  { id: "ring", category: "visualization", parse: parseRing },
24405
+ // Treemap: squarified hierarchy. No measure/minDims — a treemap fills whatever
24406
+ // rectangle it's given and has no intrinsic aspect/size (F11).
24407
+ { id: "treemap", category: "visualization", parse: parseTreemap },
24060
24408
  // ── Geographic map (own parser → resolver → layout → renderer) ──
24061
24409
  { id: "map", category: "visualization", parse: parseMap }
24062
24410
  ];
@@ -26791,10 +27139,10 @@ async function renderSitemapForExport(content, theme, palette) {
26791
27139
  const parsed = parseSitemap2(content, effectivePalette);
26792
27140
  if (parsed.error || parsed.roots.length === 0) return "";
26793
27141
  const sitemapLayout = layoutSitemap2(parsed, void 0, null, void 0, true);
26794
- const PADDING3 = 20;
27142
+ const PADDING4 = 20;
26795
27143
  const titleOffset = parsed.title ? 30 : 0;
26796
- const exportWidth = sitemapLayout.width + PADDING3 * 2;
26797
- const exportHeight = sitemapLayout.height + PADDING3 * 2 + titleOffset;
27144
+ const exportWidth = sitemapLayout.width + PADDING4 * 2;
27145
+ const exportHeight = sitemapLayout.height + PADDING4 * 2 + titleOffset;
26798
27146
  const container = document.createElement("div");
26799
27147
  container.style.width = `${exportWidth}px`;
26800
27148
  container.style.height = `${exportHeight}px`;
@@ -31822,6 +32170,10 @@ async function layoutBoxesAndLinesSearch(parsed, collapseInfo, opts) {
31822
32170
  const reserveEdgeLabels = opts?.reserveEdgeLabels ?? false;
31823
32171
  const onProgress = opts?.onProgress;
31824
32172
  const tick = onProgress ? () => new Promise((r) => setTimeout(r)) : () => void 0;
32173
+ const YIELD_AFTER_MS = 150;
32174
+ const YIELD_EVERY_MS = 30;
32175
+ const searchStart = performance.now();
32176
+ let lastYield = searchStart;
31825
32177
  const collapsedGroupLabels = /* @__PURE__ */ new Set();
31826
32178
  if (collapseInfo) {
31827
32179
  const missing = /* @__PURE__ */ new Set();
@@ -32251,7 +32603,11 @@ async function layoutBoxesAndLinesSearch(parsed, collapseInfo, opts) {
32251
32603
  const step = async (phase) => {
32252
32604
  if (!onProgress) return;
32253
32605
  onProgress(++progressDone, progressTotal, phase);
32254
- await tick();
32606
+ const now = performance.now();
32607
+ if (now - searchStart > YIELD_AFTER_MS && now - lastYield > YIELD_EVERY_MS) {
32608
+ lastYield = now;
32609
+ await tick();
32610
+ }
32255
32611
  };
32256
32612
  const pool = [];
32257
32613
  for (const cfg of configs) {
@@ -50639,7 +50995,7 @@ function computeEdgeLabelPosition(midAngle, radius, cx, cy, lineCount, labelPxW,
50639
50995
  };
50640
50996
  }
50641
50997
  function fitToCanvas(nodes, edges, parsed, _cx, _cy, radius, width, height, _isClockwise) {
50642
- const PADDING3 = 30;
50998
+ const PADDING4 = 30;
50643
50999
  let contentMinX = Infinity, contentMaxX = -Infinity;
50644
51000
  let contentMinY = Infinity, contentMaxY = -Infinity;
50645
51001
  for (const n of nodes) {
@@ -50681,13 +51037,13 @@ function fitToCanvas(nodes, edges, parsed, _cx, _cy, radius, width, height, _isC
50681
51037
  contentMinY = Math.min(contentMinY, le.labelY - 12);
50682
51038
  contentMaxY = Math.max(contentMaxY, le.labelY + (lineCount - 1) * 15);
50683
51039
  }
50684
- const overflowX = Math.max(0, PADDING3 - contentMinX) + Math.max(0, contentMaxX - (width - PADDING3));
50685
- const overflowY = Math.max(0, PADDING3 - contentMinY) + Math.max(0, contentMaxY - (height - PADDING3));
51040
+ const overflowX = Math.max(0, PADDING4 - contentMinX) + Math.max(0, contentMaxX - (width - PADDING4));
51041
+ const overflowY = Math.max(0, PADDING4 - contentMinY) + Math.max(0, contentMaxY - (height - PADDING4));
50686
51042
  if (overflowX <= 0 && overflowY <= 0) return null;
50687
51043
  const contentW = contentMaxX - contentMinX;
50688
51044
  const contentH = contentMaxY - contentMinY;
50689
- const availW = width - 2 * PADDING3;
50690
- const availH = height - 2 * PADDING3;
51045
+ const availW = width - 2 * PADDING4;
51046
+ const availH = height - 2 * PADDING4;
50691
51047
  const shrink = Math.min(availW / contentW, availH / contentH);
50692
51048
  const newRadius = Math.max(80, radius * shrink);
50693
51049
  return { radius: newRadius };
@@ -50886,7 +51242,7 @@ function renderCycle(container, parsed, palette, isDark, onClickItem, exportDims
50886
51242
  }
50887
51243
  edgeLabelInfo.push({ le, edge });
50888
51244
  }
50889
- const HEADER_H = 36 * layout.scale;
51245
+ const HEADER_H2 = 36 * layout.scale;
50890
51246
  const scaledNodeFont = Math.max(6, Math.round(NODE_FONT_SIZE7 * layout.scale));
50891
51247
  const scaledEdgeLabelFont = Math.max(
50892
51248
  6,
@@ -50950,10 +51306,10 @@ function renderCycle(container, parsed, palette, isDark, onClickItem, exportDims
50950
51306
  const rx = 6;
50951
51307
  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);
50952
51308
  if (hasDesc) {
50953
- const headerCenterY = ln.y - nodeH / 2 + HEADER_H / 2;
51309
+ const headerCenterY = ln.y - nodeH / 2 + HEADER_H2 / 2;
50954
51310
  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");
50955
51311
  renderInlineText(labelText, node.label, palette, scaledNodeFont);
50956
- const sepY = ln.y - nodeH / 2 + HEADER_H;
51312
+ const sepY = ln.y - nodeH / 2 + HEADER_H2;
50957
51313
  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);
50958
51314
  const descStartY = sepY + 4 + scaledDescFont;
50959
51315
  const descPadX = Math.max(8, 12 * layout.scale);
@@ -55774,7 +56130,9 @@ function mapContentAspect(resolved, data, ref = REF) {
55774
56130
  function mapExportDimensions(resolved, data, baseWidth = 1200, aspectOverride) {
55775
56131
  const useOverride = aspectOverride !== void 0 && Number.isFinite(aspectOverride) && aspectOverride > 0;
55776
56132
  const raw = useOverride ? aspectOverride : mapContentAspect(resolved, data);
55777
- const clamped = useOverride ? raw : Math.max(ASPECT_MIN, Math.min(ASPECT_MAX, raw));
56133
+ const isGlobal = !useOverride && buildMapProjection(resolved, data).fitIsGlobal;
56134
+ const target = isGlobal ? raw / GLOBAL_HEIGHT_BOOST : raw;
56135
+ const clamped = useOverride ? raw : Math.max(ASPECT_MIN, Math.min(ASPECT_MAX, target));
55778
56136
  const width = baseWidth;
55779
56137
  let height = Math.round(width / clamped);
55780
56138
  let chromeReserve = 0;
@@ -55787,10 +56145,10 @@ function mapExportDimensions(resolved, data, baseWidth = 1200, aspectOverride) {
55787
56145
  height = Math.round(chromeReserve + MIN_MAP_BAND);
55788
56146
  floored = true;
55789
56147
  }
55790
- const preferContain = useOverride ? floored : clamped !== raw || floored;
56148
+ const preferContain = useOverride ? floored : clamped !== target || floored;
55791
56149
  return { width, height, preferContain };
55792
56150
  }
55793
- var FIT_PAD2, TITLE_GAP, ASPECT_MAX, ASPECT_MIN, MIN_MAP_BAND, FALLBACK_ASPECT, REF;
56151
+ var FIT_PAD2, TITLE_GAP, ASPECT_MAX, ASPECT_MIN, GLOBAL_HEIGHT_BOOST, MIN_MAP_BAND, FALLBACK_ASPECT, REF;
55794
56152
  var init_dimensions = __esm({
55795
56153
  "src/map/dimensions.ts"() {
55796
56154
  "use strict";
@@ -55800,6 +56158,7 @@ var init_dimensions = __esm({
55800
56158
  TITLE_GAP = 16;
55801
56159
  ASPECT_MAX = 3;
55802
56160
  ASPECT_MIN = 0.9;
56161
+ GLOBAL_HEIGHT_BOOST = 1.12;
55803
56162
  MIN_MAP_BAND = 200;
55804
56163
  FALLBACK_ASPECT = 1.5;
55805
56164
  REF = 1e3;
@@ -56588,14 +56947,477 @@ var init_renderer18 = __esm({
56588
56947
  }
56589
56948
  });
56590
56949
 
56591
- // src/raci/renderer.ts
56950
+ // src/treemap/layout.ts
56951
+ import {
56952
+ hierarchy as hierarchy2,
56953
+ treemap,
56954
+ treemapSquarify
56955
+ } from "d3-hierarchy";
56956
+ function toDatum(node) {
56957
+ if (node.children.length === 0) {
56958
+ return {
56959
+ ref: node,
56960
+ label: node.label,
56961
+ value: node.value ?? 0,
56962
+ ...node.heat !== void 0 && { heat: node.heat },
56963
+ lineNumber: node.lineNumber
56964
+ };
56965
+ }
56966
+ return {
56967
+ ref: node,
56968
+ label: node.label,
56969
+ ...node.heat !== void 0 && { heat: node.heat },
56970
+ lineNumber: node.lineNumber,
56971
+ children: node.children.map((c) => toDatum(c))
56972
+ };
56973
+ }
56974
+ function datumHeat(node) {
56975
+ if (node.data.heat !== void 0) return node.data.heat;
56976
+ const xs = [];
56977
+ for (const l of node.leaves()) {
56978
+ if (l.data.heat !== void 0) xs.push(l.data.heat);
56979
+ }
56980
+ if (xs.length === 0) return void 0;
56981
+ return xs.reduce((a, b) => a + b, 0) / xs.length;
56982
+ }
56983
+ function layoutTreemap(roots, opts) {
56984
+ const maxDepth = opts.maxDepth ?? Infinity;
56985
+ const rootDatum = {
56986
+ label: "__root",
56987
+ children: roots.map((r) => toDatum(r))
56988
+ };
56989
+ const h = hierarchy2(rootDatum).sum((d) => d.children?.length ? 0 : d.value ?? 0).sort((a, b) => (b.value ?? 0) - (a.value ?? 0));
56990
+ const hroot = treemap().tile(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);
56991
+ const total = hroot.value ?? 0;
56992
+ (hroot.children ?? []).forEach((top, i) => {
56993
+ top.each((d) => {
56994
+ d._topIndex = i;
56995
+ });
56996
+ });
56997
+ const cells = [];
56998
+ for (const d of hroot.descendants()) {
56999
+ if (d.depth === 0) continue;
57000
+ if (d.depth > maxDepth) continue;
57001
+ const hasChildren = !!d.children && d.children.length > 0;
57002
+ const isCollapsed = hasChildren && d.depth >= maxDepth;
57003
+ const isContainer = hasChildren && !isCollapsed;
57004
+ const path = [];
57005
+ let p = d;
57006
+ while (p && p.depth > 0) {
57007
+ path.unshift(p.data.label);
57008
+ p = p.parent;
57009
+ }
57010
+ const heatVal = datumHeat(d);
57011
+ cells.push({
57012
+ node: d.data.ref ?? null,
57013
+ label: d.data.label,
57014
+ x0: d.x0,
57015
+ y0: d.y0,
57016
+ x1: d.x1,
57017
+ y1: d.y1,
57018
+ depth: d.depth,
57019
+ value: d.value ?? 0,
57020
+ isContainer,
57021
+ isCollapsed,
57022
+ topIndex: d._topIndex ?? 0,
57023
+ pctOfRoot: total > 0 ? (d.value ?? 0) / total : 0,
57024
+ pctOfParent: d.parent && (d.parent.value ?? 0) > 0 ? (d.value ?? 0) / (d.parent.value ?? 1) : 1,
57025
+ ...heatVal !== void 0 && { heat: heatVal },
57026
+ path,
57027
+ ...d.data.lineNumber !== void 0 && { lineNumber: d.data.lineNumber }
57028
+ });
57029
+ }
57030
+ return { cells, total };
57031
+ }
57032
+ var init_layout16 = __esm({
57033
+ "src/treemap/layout.ts"() {
57034
+ "use strict";
57035
+ }
57036
+ });
57037
+
57038
+ // src/treemap/renderer.ts
56592
57039
  var renderer_exports19 = {};
56593
57040
  __export(renderer_exports19, {
57041
+ compactNumber: () => compactNumber2,
57042
+ renderTreemap: () => renderTreemap,
57043
+ renderTreemapForExport: () => renderTreemapForExport
57044
+ });
57045
+ import * as d3Selection26 from "d3-selection";
57046
+ import { scaleLinear as scaleLinear6 } from "d3-scale";
57047
+ function renderTreemapForExport(container, parsed, palette, isDark, exportDims, options) {
57048
+ renderTreemap(container, parsed, palette, isDark, exportDims, {
57049
+ exportMode: true,
57050
+ ...options
57051
+ });
57052
+ }
57053
+ function renderTreemap(container, parsed, palette, isDark, exportDims, options = {}) {
57054
+ if (parsed.error || parsed.roots.length === 0) return;
57055
+ void isDark;
57056
+ d3Selection26.select(container).selectAll(":not([data-d3-tooltip])").remove();
57057
+ const width = exportDims?.width ?? container.clientWidth;
57058
+ const height = exportDims?.height ?? container.clientHeight;
57059
+ if (width <= 0 || height <= 0) return;
57060
+ const mode = resolveColorMode(parsed, options.colorMode);
57061
+ const opts = parsed.options;
57062
+ const exportMode = options.exportMode ?? false;
57063
+ const seriesColorsTop = getSeriesColors(palette);
57064
+ const showTitle = !!parsed.title;
57065
+ const titleH = showTitle ? TITLE_BAND : 0;
57066
+ const heat = buildHeatScale(parsed, palette);
57067
+ const legend = !opts.noLegend ? buildLegend(mode, parsed, heat, seriesColorsTop, options.colorOffset ?? 0) : null;
57068
+ const legendReserve = legend ? getMaxLegendReservedHeight(
57069
+ { groups: legend.groups, position: LEGEND_POSITION, mode: "preview" },
57070
+ width
57071
+ ) + LEGEND_GROUP_GAP : 0;
57072
+ const headerH = opts.noHeaders ? 0 : HEADER_H;
57073
+ const areaX = PADDING3;
57074
+ const areaY = titleH + legendReserve + PADDING3;
57075
+ const areaW = Math.max(1, width - PADDING3 * 2);
57076
+ const areaH = Math.max(1, height - areaY - PADDING3);
57077
+ const layout = layoutTreemap(parsed.roots, {
57078
+ width: areaW,
57079
+ height: areaH,
57080
+ headerH,
57081
+ ...options.maxDepth !== void 0 && { maxDepth: options.maxDepth }
57082
+ });
57083
+ 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);
57084
+ svg.append("style").text(
57085
+ ".dgmo-treemap-focus{opacity:.3;transition:opacity .12s}.dgmo-treemap-cell:hover .dgmo-treemap-focus{opacity:.7}"
57086
+ );
57087
+ svg.append("rect").attr("width", width).attr("height", height).attr("fill", palette.bg);
57088
+ if (showTitle) {
57089
+ 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);
57090
+ if (parsed.titleLineNumber !== null) {
57091
+ title.attr("data-line-number", parsed.titleLineNumber);
57092
+ }
57093
+ }
57094
+ const root = svg.append("g").attr("class", "dgmo-treemap-cells").attr("transform", `translate(${areaX},${areaY})`);
57095
+ const seriesColors2 = seriesColorsTop;
57096
+ const colorOffset = options.colorOffset ?? 0;
57097
+ const activeGroup = parsed.tagGroups.length > 0 ? parsed.tagGroups[0].name : null;
57098
+ const rootIndexByLabel = new Map(parsed.roots.map((r, i) => [r.label, i]));
57099
+ const colorOf = (cell) => {
57100
+ if (mode === "heat") {
57101
+ return cell.heat !== void 0 && heat ? heat.scale(cell.heat) : MUTED_FILL;
57102
+ }
57103
+ if (mode === "tag") {
57104
+ if (!cell.node) return MUTED_FILL;
57105
+ return resolveTagColor(cell.node.metadata, parsed.tagGroups, activeGroup) ?? MUTED_FILL;
57106
+ }
57107
+ const topLabel = cell.path[0] ?? cell.label;
57108
+ const idx = (rootIndexByLabel.get(topLabel) ?? cell.topIndex) + colorOffset;
57109
+ const hue = seriesColors2[idx % seriesColors2.length];
57110
+ if (cell.depth <= 1) return hue;
57111
+ const keepPct = Math.max(55, 100 - (cell.depth - 1) * 18);
57112
+ return mix(hue, palette.bg, keepPct);
57113
+ };
57114
+ for (const cell of layout.cells) {
57115
+ const w = Math.max(0, cell.x1 - cell.x0);
57116
+ const h = Math.max(0, cell.y1 - cell.y0);
57117
+ if (w <= 0 || h <= 0) continue;
57118
+ const baseColor = colorOf(cell);
57119
+ const fill2 = cell.isContainer ? baseColor : mix(baseColor, palette.bg, LEAF_MUTE_PCT);
57120
+ const drillable = cell.isContainer || cell.isCollapsed;
57121
+ const g = root.append("g").attr("class", "dgmo-treemap-cell").attr("transform", `translate(${cell.x0},${cell.y0})`).attr("data-node-path", cell.path.join(" / "));
57122
+ if (cell.lineNumber !== void 0) {
57123
+ g.attr("data-line-number", cell.lineNumber);
57124
+ }
57125
+ if (cell.heat !== void 0) g.attr("data-heat", cell.heat);
57126
+ if (cell.node && activeGroup) {
57127
+ const key = tagAttrKey(activeGroup);
57128
+ const tagVal = cell.node.metadata[key];
57129
+ if (tagVal) g.attr(`data-tag-${key}`, tagVal);
57130
+ }
57131
+ const rect = g.append("rect").attr(
57132
+ "class",
57133
+ cell.isContainer ? "dgmo-treemap-rect branch" : "dgmo-treemap-rect"
57134
+ ).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);
57135
+ if (drillable && options.onClickItem && cell.lineNumber !== void 0) {
57136
+ const ln = cell.lineNumber;
57137
+ rect.style("cursor", "pointer").on("click", () => options.onClickItem(ln));
57138
+ }
57139
+ const ink = contrastText(
57140
+ fill2,
57141
+ palette.textOnFillLight,
57142
+ palette.textOnFillDark
57143
+ );
57144
+ if (cell.isContainer && headerH > 0 && w > 34 && h > headerH) {
57145
+ const valParts = [];
57146
+ if (!opts.noValues) valParts.push(compactNumber2(cell.value));
57147
+ if (!opts.noPercent) valParts.push(formatPct(cell.pctOfRoot));
57148
+ const valStr = valParts.join(" \xB7 ");
57149
+ const ICON_RESERVE = drillable ? 16 : 4;
57150
+ const showVal = valStr.length > 0 && w > 110;
57151
+ const valW = showVal ? measureText(valStr, 10.5) : 0;
57152
+ const labelMax = w - 8 - ICON_RESERVE - (showVal ? valW + 10 : 0);
57153
+ 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));
57154
+ if (showVal) {
57155
+ 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);
57156
+ }
57157
+ }
57158
+ const PAD = Math.max(4, Math.min(14, Math.floor(Math.min(w, h) / 5)));
57159
+ const MIN_FS = 7;
57160
+ if (!cell.isContainer && w >= 2 * PAD + 8 && h >= 2 * PAD + 8) {
57161
+ const maxW = w - 2 * PAD;
57162
+ let fs = clamp3(Math.round(Math.min(w / 3.6, h / 3.4)), MIN_FS, 72);
57163
+ const nameW = measureText(cell.label, fs) * 1.06;
57164
+ if (nameW > maxW) fs = Math.max(MIN_FS, Math.floor(fs * maxW / nameW));
57165
+ const tg = clamp3((fs - MIN_FS) / (72 - MIN_FS), 0, 1);
57166
+ const nameOpacity = 0.95 - tg * 0.5;
57167
+ const vfs = clamp3(Math.round(fs * 0.42), 11, 28);
57168
+ const valOpacity = Math.max(0.45, nameOpacity - 0.1);
57169
+ let y = PAD + Math.round(fs * 0.78);
57170
+ 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));
57171
+ const valParts = [
57172
+ opts.noValues ? "" : compactNumber2(cell.value),
57173
+ opts.noPercent ? "" : formatPct(cell.pctOfRoot)
57174
+ ].filter(Boolean);
57175
+ const combined = valParts.join(" \xB7 ");
57176
+ const nameBaseY = y;
57177
+ const addLineAt = (text, yy, size, opacity) => {
57178
+ 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);
57179
+ };
57180
+ if (combined) {
57181
+ const fitsW = measureText(combined, vfs) <= maxW;
57182
+ const roomBelow = h - PAD > y + vfs + 6;
57183
+ if (fitsW && roomBelow) {
57184
+ addLineAt(combined, y + vfs + 6, vfs, valOpacity);
57185
+ } else if (fitsW) {
57186
+ const ivfs = clamp3(Math.round(fs * 0.5), 11, Math.max(11, vfs));
57187
+ const rendered = clipLabel(cell.label, maxW, fs);
57188
+ const nW = measureText(rendered, fs) * 1.12;
57189
+ const gap = Math.max(12, Math.round(fs * 0.25));
57190
+ if (PAD + nW + gap + measureText(combined, ivfs) <= w - PAD) {
57191
+ 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);
57192
+ }
57193
+ } else if (valParts.length === 2) {
57194
+ if (h - PAD > y + vfs + 6) {
57195
+ y += vfs + 6;
57196
+ addLineAt(valParts[0], y, vfs, valOpacity);
57197
+ }
57198
+ const pfs = Math.max(10, Math.round(vfs * 0.9));
57199
+ if (h - PAD > y + pfs + 4) {
57200
+ y += pfs + 4;
57201
+ addLineAt(valParts[1], y, pfs, valOpacity);
57202
+ }
57203
+ } else if (h - PAD > y + vfs + 6) {
57204
+ addLineAt(combined, y + vfs + 6, vfs, valOpacity);
57205
+ }
57206
+ }
57207
+ }
57208
+ if (drillable && w > 30 && h > 22) {
57209
+ drawFocusIcon(g, w, ink, 9);
57210
+ }
57211
+ }
57212
+ if (legend) {
57213
+ const legendG = svg.append("g").attr("class", "dgmo-treemap-legend").attr("transform", `translate(0, ${titleH})`);
57214
+ renderIntegratedLegend(legendG, {
57215
+ groups: legend.groups,
57216
+ palette: {
57217
+ bg: palette.bg,
57218
+ surface: palette.surface,
57219
+ text: palette.text,
57220
+ textMuted: palette.textMuted,
57221
+ primary: palette.primary
57222
+ },
57223
+ isDark,
57224
+ width,
57225
+ mode: exportMode ? "export" : "preview",
57226
+ position: LEGEND_POSITION,
57227
+ activeGroup: legend.activeGroup,
57228
+ // The color-mode switcher is the legend itself: each applicable mode is a
57229
+ // group pill; the active one is the open capsule, the rest are clickable
57230
+ // pills that switch mode. Export shows only the active group.
57231
+ showInactivePills: !exportMode,
57232
+ showEmptyGroups: !exportMode,
57233
+ ...options.onSelectMode !== void 0 && {
57234
+ callbacks: {
57235
+ onGroupToggle: (name) => {
57236
+ const m = legend.modeByName.get(name);
57237
+ if (m) options.onSelectMode(m);
57238
+ }
57239
+ }
57240
+ }
57241
+ });
57242
+ }
57243
+ }
57244
+ function buildLegend(activeMode, parsed, heat, seriesColors2, colorOffset) {
57245
+ const groups = [];
57246
+ const modeByName = /* @__PURE__ */ new Map();
57247
+ let activeGroup = null;
57248
+ if (parsed.tagGroups.length > 0) {
57249
+ const tg = parsed.tagGroups[0];
57250
+ const used = /* @__PURE__ */ new Set();
57251
+ const collect = (nodes) => {
57252
+ for (const n of nodes) {
57253
+ const v = n.metadata[tagAttrKey(tg.name)];
57254
+ if (v) used.add(v.toLowerCase());
57255
+ collect(n.children);
57256
+ }
57257
+ };
57258
+ collect(parsed.roots);
57259
+ groups.push({
57260
+ name: tg.name,
57261
+ entries: tg.entries.filter((e) => used.has(e.value.toLowerCase())).map((e) => ({ value: e.value, color: e.color }))
57262
+ });
57263
+ modeByName.set(tg.name, "tag");
57264
+ if (activeMode === "tag") activeGroup = tg.name;
57265
+ }
57266
+ if (heat) {
57267
+ const name = parsed.options.heatLabel ?? "Value";
57268
+ groups.push({
57269
+ name,
57270
+ entries: [],
57271
+ gradient: {
57272
+ min: heat.min,
57273
+ max: heat.max,
57274
+ low: heat.stops[0],
57275
+ high: heat.stops[heat.stops.length - 1]
57276
+ }
57277
+ });
57278
+ modeByName.set(name, "heat");
57279
+ if (activeMode === "heat") activeGroup = name;
57280
+ }
57281
+ groups.push({
57282
+ name: "Branch",
57283
+ entries: parsed.roots.map((r, i) => ({
57284
+ value: r.label,
57285
+ color: seriesColors2[(i + colorOffset) % seriesColors2.length]
57286
+ }))
57287
+ });
57288
+ modeByName.set("Branch", "branch");
57289
+ if (activeMode === "branch" || activeGroup === null) activeGroup = "Branch";
57290
+ return { groups, activeGroup, modeByName };
57291
+ }
57292
+ function buildHeatScale(parsed, palette) {
57293
+ if (!parsed.hasHeat) return null;
57294
+ const values = [];
57295
+ const collect = (nodes) => {
57296
+ for (const n of nodes) {
57297
+ if (typeof n.heat === "number") values.push(n.heat);
57298
+ collect(n.children);
57299
+ }
57300
+ };
57301
+ collect(parsed.roots);
57302
+ if (values.length === 0) return null;
57303
+ const min = Math.min(...values);
57304
+ const max = Math.max(...values);
57305
+ const signed = min < 0 && max > 0;
57306
+ const neutral = palette.surface;
57307
+ const explicit = parsed.options.heatColors.map((c) => resolveColor(c, palette) ?? c).filter((c) => !!c);
57308
+ let stops;
57309
+ let domain;
57310
+ if (explicit.length >= 2) {
57311
+ stops = [explicit[0], neutral, explicit[1]];
57312
+ const mid = signed ? 0 : (min + max) / 2;
57313
+ domain = [min, mid, max];
57314
+ } else if (explicit.length === 1) {
57315
+ stops = [neutral, explicit[0]];
57316
+ domain = [min, max];
57317
+ } else if (signed) {
57318
+ stops = [palette.colors.red, neutral, palette.colors.green];
57319
+ domain = [min, 0, max];
57320
+ } else {
57321
+ stops = [neutral, palette.primary];
57322
+ domain = [min, max];
57323
+ }
57324
+ if (domain[0] === domain[domain.length - 1]) {
57325
+ const last = stops[stops.length - 1];
57326
+ return { scale: () => last, min, max, stops, signed };
57327
+ }
57328
+ const linear = scaleLinear6().domain(domain).range(stops).clamp(true);
57329
+ return { scale: (v) => toHex(linear(v)), min, max, stops, signed };
57330
+ }
57331
+ function toHex(c) {
57332
+ if (c.startsWith("#")) return c;
57333
+ const m = c.match(/rgba?\(([^)]+)\)/);
57334
+ if (!m) return c;
57335
+ const parts = m[1].split(",").map((s) => Math.round(parseFloat(s)));
57336
+ const h = (n) => Math.max(0, Math.min(255, n || 0)).toString(16).padStart(2, "0");
57337
+ return `#${h(parts[0] ?? 0)}${h(parts[1] ?? 0)}${h(parts[2] ?? 0)}`;
57338
+ }
57339
+ function resolveColorMode(parsed, override) {
57340
+ let mode = override ?? parsed.defaultColorMode;
57341
+ if (mode === "tag" && parsed.tagGroups.length === 0) {
57342
+ mode = parsed.hasHeat ? "heat" : "branch";
57343
+ }
57344
+ if (mode === "heat" && !parsed.hasHeat) mode = "branch";
57345
+ return mode;
57346
+ }
57347
+ function drawFocusIcon(g, w, ink, cy) {
57348
+ const r = 4.5;
57349
+ const cx = w - r - 5;
57350
+ const fi = g.append("g").attr("class", "dgmo-treemap-focus").attr("data-export-ignore", "true");
57351
+ fi.append("rect").attr("x", cx - 9).attr("y", cy - 9).attr("width", 18).attr("height", 18).attr("fill", "transparent");
57352
+ fi.append("circle").attr("cx", cx).attr("cy", cy).attr("r", r).attr("fill", "none").attr("stroke", ink).attr("stroke-width", 1.25);
57353
+ fi.append("circle").attr("cx", cx).attr("cy", cy).attr("r", 1.4).attr("fill", ink);
57354
+ }
57355
+ function clamp3(x, lo, hi) {
57356
+ return Math.max(lo, Math.min(hi, x));
57357
+ }
57358
+ function clipLabel(s, maxWidth, fs) {
57359
+ if (measureText(s, fs) <= maxWidth) return s;
57360
+ let lo = 0;
57361
+ let hi = s.length;
57362
+ while (lo < hi) {
57363
+ const mid = Math.ceil((lo + hi) / 2);
57364
+ if (measureText(s.slice(0, mid) + "\u2026", fs) <= maxWidth) lo = mid;
57365
+ else hi = mid - 1;
57366
+ }
57367
+ return lo <= 0 ? "" : s.slice(0, lo) + "\u2026";
57368
+ }
57369
+ function compactNumber2(v) {
57370
+ const abs = Math.abs(v);
57371
+ if (abs >= 1e9) return strip(v / 1e9) + "B";
57372
+ if (abs >= 1e6) return strip(v / 1e6) + "M";
57373
+ if (abs >= 1e3) return strip(v / 1e3) + "k";
57374
+ return strip(Math.round(v * 100) / 100);
57375
+ }
57376
+ function strip(n) {
57377
+ return parseFloat(
57378
+ n.toFixed(n < 10 && !Number.isInteger(n) ? 1 : 0)
57379
+ ).toString();
57380
+ }
57381
+ function formatPct(frac) {
57382
+ const pct = frac * 100;
57383
+ if (pct >= 10) return `${Math.round(pct)}%`;
57384
+ if (pct >= 1) return `${pct.toFixed(0)}%`;
57385
+ return `${pct.toFixed(1)}%`;
57386
+ }
57387
+ var PADDING3, HEADER_H, TITLE_BAND, MUTED_FILL, LEAF_MUTE_PCT, LEGEND_POSITION;
57388
+ var init_renderer19 = __esm({
57389
+ "src/treemap/renderer.ts"() {
57390
+ "use strict";
57391
+ init_fonts();
57392
+ init_colors();
57393
+ init_color_utils();
57394
+ init_tag_groups();
57395
+ init_text_measure();
57396
+ init_legend_integration();
57397
+ init_legend_layout();
57398
+ init_legend_constants();
57399
+ init_title_constants();
57400
+ init_layout16();
57401
+ PADDING3 = 12;
57402
+ HEADER_H = 18;
57403
+ TITLE_BAND = 36;
57404
+ MUTED_FILL = "#cbd5e1";
57405
+ LEAF_MUTE_PCT = 50;
57406
+ LEGEND_POSITION = {
57407
+ placement: "top-center",
57408
+ titleRelation: "below-title"
57409
+ };
57410
+ }
57411
+ });
57412
+
57413
+ // src/raci/renderer.ts
57414
+ var renderer_exports20 = {};
57415
+ __export(renderer_exports20, {
56594
57416
  MARKER_LABELS: () => MARKER_LABELS,
56595
57417
  renderRaci: () => renderRaci,
56596
57418
  renderRaciForExport: () => renderRaciForExport
56597
57419
  });
56598
- import * as d3Selection26 from "d3-selection";
57420
+ import * as d3Selection27 from "d3-selection";
56599
57421
  function groupDiagnosticsByTask(parsed) {
56600
57422
  const map = /* @__PURE__ */ new Map();
56601
57423
  if (parsed.diagnostics.length === 0) return map;
@@ -56667,7 +57489,7 @@ function renderRaci(container, parsed, palette, isDark, handlers, exportDims) {
56667
57489
  const hideLegend = opts.hideLegend ?? false;
56668
57490
  const collapsedPhases = opts.collapsedPhases ?? /* @__PURE__ */ new Set();
56669
57491
  const hideTitle = (opts.hideTitle ?? false) || parsed.options["no-title"] === "on";
56670
- d3Selection26.select(container).selectAll(":not([data-d3-tooltip])").remove();
57492
+ d3Selection27.select(container).selectAll(":not([data-d3-tooltip])").remove();
56671
57493
  const width = exportDims?.width ?? container.clientWidth;
56672
57494
  const height = exportDims?.height ?? container.clientHeight;
56673
57495
  if (width <= 0 || height <= 0) return;
@@ -56774,7 +57596,7 @@ function renderRaci(container, parsed, palette, isDark, handlers, exportDims) {
56774
57596
  const colBottomY = cursorY + sColumnBottomPad;
56775
57597
  const totalHeight = colBottomY + sVMargin;
56776
57598
  const svgHeight = exportDims ? totalHeight : Math.max(height, totalHeight);
56777
- 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");
57599
+ 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");
56778
57600
  if (ctx.isBelowFloor) {
56779
57601
  svg.attr("width", "100%");
56780
57602
  }
@@ -57255,13 +58077,13 @@ function parseQuotedSegments(message) {
57255
58077
  return out;
57256
58078
  }
57257
58079
  var 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;
57258
- var init_renderer19 = __esm({
58080
+ var init_renderer20 = __esm({
57259
58081
  "src/raci/renderer.ts"() {
57260
58082
  "use strict";
57261
58083
  init_fonts();
57262
58084
  init_title_constants();
57263
58085
  init_color_utils();
57264
- init_parser26();
58086
+ init_parser27();
57265
58087
  init_variants();
57266
58088
  init_scaling();
57267
58089
  init_text_measure();
@@ -57518,8 +58340,8 @@ var init_tag_resolution = __esm({
57518
58340
  });
57519
58341
 
57520
58342
  // src/sequence/renderer.ts
57521
- var renderer_exports20 = {};
57522
- __export(renderer_exports20, {
58343
+ var renderer_exports21 = {};
58344
+ __export(renderer_exports21, {
57523
58345
  applyGroupOrdering: () => applyGroupOrdering,
57524
58346
  applyPositionOverrides: () => applyPositionOverrides,
57525
58347
  buildNoteMessageMap: () => buildNoteMessageMap,
@@ -57530,7 +58352,7 @@ __export(renderer_exports20, {
57530
58352
  renderSequenceDiagram: () => renderSequenceDiagram,
57531
58353
  truncateBareUrl: () => truncateBareUrl
57532
58354
  });
57533
- import * as d3Selection27 from "d3-selection";
58355
+ import * as d3Selection28 from "d3-selection";
57534
58356
  function wrapTextLines(text, maxWidth, fontSize) {
57535
58357
  const rawLines = text.split("\n").map((l) => l.startsWith("- ") ? "\u2022 " + l.slice(2) : l);
57536
58358
  return wrapDescriptionLines(
@@ -57860,7 +58682,7 @@ function applyGroupOrdering(participants, groups, messages = []) {
57860
58682
  return result;
57861
58683
  }
57862
58684
  function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateToLine, options) {
57863
- d3Selection27.select(container).selectAll("*").remove();
58685
+ d3Selection28.select(container).selectAll("*").remove();
57864
58686
  const { title, options: parsedOptions } = parsed;
57865
58687
  const solid = parsedOptions["solid-fill"] === "on";
57866
58688
  const effectiveCollapsedGroups = /* @__PURE__ */ new Set();
@@ -58511,7 +59333,7 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
58511
59333
  offsetX = leftMargin + Math.max(0, (svgWidth - totalWidth) / 2);
58512
59334
  buildParticipantX();
58513
59335
  }
58514
- 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);
59336
+ 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);
58515
59337
  const defs = svg.append("defs");
58516
59338
  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(
58517
59339
  "points",
@@ -59124,7 +59946,7 @@ function renderParticipant(svg, participant, cx, cy, palette, isDark, color, tag
59124
59946
  }
59125
59947
  }
59126
59948
  var 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;
59127
- var init_renderer20 = __esm({
59949
+ var init_renderer21 = __esm({
59128
59950
  "src/sequence/renderer.ts"() {
59129
59951
  "use strict";
59130
59952
  init_tag_groups();
@@ -63002,6 +63824,7 @@ var DIAGRAM_EXPORT_HANDLERS = {
63002
63824
  map: exportMap,
63003
63825
  pyramid: exportPyramid,
63004
63826
  ring: exportRing,
63827
+ treemap: exportTreemap,
63005
63828
  raci: exportRaci,
63006
63829
  rasci: exportRaci,
63007
63830
  daci: exportRaci,
@@ -63059,10 +63882,10 @@ async function exportOrg(ctx) {
63059
63882
  false
63060
63883
  // expandAllLegend off — collapsed-by-default per §1.3
63061
63884
  );
63062
- const PADDING3 = 20;
63885
+ const PADDING4 = 20;
63063
63886
  const titleOffset = effectiveParsed.title ? 30 : 0;
63064
- const exportWidth = orgLayout.width + PADDING3 * 2;
63065
- const exportHeight = orgLayout.height + PADDING3 * 2 + titleOffset;
63887
+ const exportWidth = orgLayout.width + PADDING4 * 2;
63888
+ const exportHeight = orgLayout.height + PADDING4 * 2 + titleOffset;
63066
63889
  const container = createExportContainer(exportWidth, exportHeight);
63067
63890
  renderOrg2(
63068
63891
  container,
@@ -63104,10 +63927,10 @@ async function exportSitemap(ctx) {
63104
63927
  hiddenAttributes,
63105
63928
  true
63106
63929
  );
63107
- const PADDING3 = 20;
63930
+ const PADDING4 = 20;
63108
63931
  const titleOffset = effectiveParsed.title ? 30 : 0;
63109
- const exportWidth = sitemapLayout.width + PADDING3 * 2;
63110
- const exportHeight = sitemapLayout.height + PADDING3 * 2 + titleOffset;
63932
+ const exportWidth = sitemapLayout.width + PADDING4 * 2;
63933
+ const exportHeight = sitemapLayout.height + PADDING4 * 2 + titleOffset;
63111
63934
  const container = createExportContainer(exportWidth, exportHeight);
63112
63935
  renderSitemap2(
63113
63936
  container,
@@ -63163,10 +63986,10 @@ async function exportClass(ctx) {
63163
63986
  const classParsed = parseClassDiagram2(content, effectivePalette);
63164
63987
  if (classParsed.error || classParsed.classes.length === 0) return "";
63165
63988
  const classLayout = layoutClassDiagram2(classParsed);
63166
- const PADDING3 = 20;
63989
+ const PADDING4 = 20;
63167
63990
  const titleOffset = classParsed.title ? 40 : 0;
63168
- const exportWidth = classLayout.width + PADDING3 * 2;
63169
- const exportHeight = classLayout.height + PADDING3 * 2 + titleOffset;
63991
+ const exportWidth = classLayout.width + PADDING4 * 2;
63992
+ const exportHeight = classLayout.height + PADDING4 * 2 + titleOffset;
63170
63993
  const container = createExportContainer(exportWidth, exportHeight);
63171
63994
  renderClassDiagram2(
63172
63995
  container,
@@ -63190,10 +64013,10 @@ async function exportEr(ctx) {
63190
64013
  const erParsed = parseERDiagram2(content, effectivePalette);
63191
64014
  if (erParsed.error || erParsed.tables.length === 0) return "";
63192
64015
  const erLayout = layoutERDiagram2(erParsed);
63193
- const PADDING3 = 20;
64016
+ const PADDING4 = 20;
63194
64017
  const titleOffset = erParsed.title ? 40 : 0;
63195
- const exportWidth = erLayout.width + PADDING3 * 2;
63196
- const exportHeight = erLayout.height + PADDING3 * 2 + titleOffset;
64018
+ const exportWidth = erLayout.width + PADDING4 * 2;
64019
+ const exportHeight = erLayout.height + PADDING4 * 2 + titleOffset;
63197
64020
  const container = createExportContainer(exportWidth, exportHeight);
63198
64021
  renderERDiagram2(
63199
64022
  container,
@@ -63229,10 +64052,10 @@ async function exportBoxesAndLines(ctx) {
63229
64052
  const { renderBoxesAndLinesForExport: renderBoxesAndLinesForExport2 } = await Promise.resolve().then(() => (init_renderer6(), renderer_exports6));
63230
64053
  const { layoutBoxesAndLines: layoutBoxesAndLines2 } = await Promise.resolve().then(() => (init_layout5(), layout_exports5));
63231
64054
  const blLayout = await layoutBoxesAndLines2(blParsed);
63232
- const PADDING3 = 20;
64055
+ const PADDING4 = 20;
63233
64056
  const titleOffset = blParsed.title ? 40 : 0;
63234
- const exportWidth = blLayout.width + PADDING3 * 2;
63235
- const exportHeight = blLayout.height + PADDING3 * 2 + titleOffset;
64057
+ const exportWidth = blLayout.width + PADDING4 * 2;
64058
+ const exportHeight = blLayout.height + PADDING4 * 2 + titleOffset;
63236
64059
  const container = createExportContainer(exportWidth, exportHeight);
63237
64060
  const blActiveTagGroup = ctxTagOverride(ctx);
63238
64061
  renderBoxesAndLinesForExport2(
@@ -63279,10 +64102,10 @@ async function exportMindmap(ctx) {
63279
64102
  activeTagGroup,
63280
64103
  hideDescriptions
63281
64104
  });
63282
- const PADDING3 = 20;
64105
+ const PADDING4 = 20;
63283
64106
  const titleOffset = effectiveParsed.title ? 30 : 0;
63284
- const exportWidth = mmLayout.width + PADDING3 * 2;
63285
- const exportHeight = mmLayout.height + PADDING3 * 2 + titleOffset;
64107
+ const exportWidth = mmLayout.width + PADDING4 * 2;
64108
+ const exportHeight = mmLayout.height + PADDING4 * 2 + titleOffset;
63286
64109
  const container = createExportContainer(exportWidth, exportHeight);
63287
64110
  const colorByDepth = viewState?.cbd === true;
63288
64111
  renderMindmap2(
@@ -63343,10 +64166,10 @@ async function exportC4(ctx) {
63343
64166
  const c4Container = ctx.options?.c4Container ?? viewState?.c4c;
63344
64167
  const c4Layout = c4Level === "deployment" ? layoutC4Deployment2(c4Parsed) : c4Level === "components" && c4System && c4Container ? layoutC4Components2(c4Parsed, c4System, c4Container) : c4Level === "containers" && c4System ? layoutC4Containers2(c4Parsed, c4System) : layoutC4Context2(c4Parsed);
63345
64168
  if (c4Layout.nodes.length === 0) return "";
63346
- const PADDING3 = 20;
64169
+ const PADDING4 = 20;
63347
64170
  const titleOffset = c4Parsed.title ? 40 : 0;
63348
- const exportWidth = c4Layout.width + PADDING3 * 2;
63349
- const exportHeight = c4Layout.height + PADDING3 * 2 + titleOffset;
64171
+ const exportWidth = c4Layout.width + PADDING4 * 2;
64172
+ const exportHeight = c4Layout.height + PADDING4 * 2 + titleOffset;
63350
64173
  const container = createExportContainer(exportWidth, exportHeight);
63351
64174
  const renderFn = c4Level === "deployment" || c4Level === "components" && c4System && c4Container || c4Level === "containers" && c4System ? renderC4Containers2 : renderC4Context2;
63352
64175
  renderFn(
@@ -63662,30 +64485,44 @@ async function exportRing(ctx) {
63662
64485
  const ringParsed = parseRing2(content);
63663
64486
  if (ringParsed.error || ringParsed.layers.length === 0) return "";
63664
64487
  const container = createExportContainer(EXPORT_WIDTH, EXPORT_HEIGHT);
63665
- renderRingForExport2(
64488
+ renderRingForExport2(container, ringParsed, effectivePalette, ctx.isDark, {
64489
+ width: EXPORT_WIDTH,
64490
+ height: EXPORT_HEIGHT
64491
+ });
64492
+ return finalizeSvgExport(container, theme, effectivePalette);
64493
+ }
64494
+ async function exportTreemap(ctx) {
64495
+ const { content, theme, palette } = ctx;
64496
+ const { parseTreemap: parseTreemap2 } = await Promise.resolve().then(() => (init_parser26(), parser_exports20));
64497
+ const { renderTreemapForExport: renderTreemapForExport2 } = await Promise.resolve().then(() => (init_renderer19(), renderer_exports19));
64498
+ const effectivePalette = await resolveExportPalette(theme, palette);
64499
+ const treemapParsed = parseTreemap2(content, effectivePalette);
64500
+ if (treemapParsed.error || treemapParsed.roots.length === 0) return "";
64501
+ const container = createExportContainer(EXPORT_WIDTH, EXPORT_HEIGHT);
64502
+ renderTreemapForExport2(
63666
64503
  container,
63667
- ringParsed,
64504
+ treemapParsed,
63668
64505
  effectivePalette,
63669
64506
  ctx.isDark,
63670
- { width: EXPORT_WIDTH, height: EXPORT_HEIGHT }
64507
+ {
64508
+ width: EXPORT_WIDTH,
64509
+ height: EXPORT_HEIGHT
64510
+ }
63671
64511
  );
63672
64512
  return finalizeSvgExport(container, theme, effectivePalette);
63673
64513
  }
63674
64514
  async function exportRaci(ctx) {
63675
64515
  const { content, theme, palette } = ctx;
63676
- const { parseRaci: parseRaci2 } = await Promise.resolve().then(() => (init_parser26(), parser_exports20));
63677
- const { renderRaciForExport: renderRaciForExport2 } = await Promise.resolve().then(() => (init_renderer19(), renderer_exports19));
64516
+ const { parseRaci: parseRaci2 } = await Promise.resolve().then(() => (init_parser27(), parser_exports21));
64517
+ const { renderRaciForExport: renderRaciForExport2 } = await Promise.resolve().then(() => (init_renderer20(), renderer_exports20));
63678
64518
  const effectivePalette = await resolveExportPalette(theme, palette);
63679
64519
  const raciParsed = parseRaci2(content, effectivePalette);
63680
64520
  if (raciParsed.error) return "";
63681
64521
  const container = createExportContainer(EXPORT_WIDTH, EXPORT_HEIGHT);
63682
- renderRaciForExport2(
63683
- container,
63684
- raciParsed,
63685
- effectivePalette,
63686
- ctx.isDark,
63687
- { width: EXPORT_WIDTH, height: EXPORT_HEIGHT }
63688
- );
64522
+ renderRaciForExport2(container, raciParsed, effectivePalette, ctx.isDark, {
64523
+ width: EXPORT_WIDTH,
64524
+ height: EXPORT_HEIGHT
64525
+ });
63689
64526
  return finalizeSvgExport(container, theme, effectivePalette);
63690
64527
  }
63691
64528
  function beginVizExport() {
@@ -63774,14 +64611,7 @@ async function exportVenn(ctx) {
63774
64611
  if (parsed.error || parsed.vennSets.length < 2) return "";
63775
64612
  const effectivePalette = await resolveExportPalette(theme, palette);
63776
64613
  const { container, dims } = beginVizExport();
63777
- renderVenn(
63778
- container,
63779
- parsed,
63780
- effectivePalette,
63781
- ctx.isDark,
63782
- void 0,
63783
- dims
63784
- );
64614
+ renderVenn(container, parsed, effectivePalette, ctx.isDark, void 0, dims);
63785
64615
  return finalizeSvgExport(container, theme, effectivePalette);
63786
64616
  }
63787
64617
  async function exportQuadrant(ctx) {
@@ -63815,7 +64645,7 @@ async function exportVisualization(ctx) {
63815
64645
  const isDark = ctx.isDark;
63816
64646
  const container = createExportContainer(EXPORT_WIDTH, EXPORT_HEIGHT);
63817
64647
  const { parseSequenceDgmo: parseSequenceDgmo2 } = await Promise.resolve().then(() => (init_parser7(), parser_exports));
63818
- const { renderSequenceDiagram: renderSequenceDiagram2 } = await Promise.resolve().then(() => (init_renderer20(), renderer_exports20));
64648
+ const { renderSequenceDiagram: renderSequenceDiagram2 } = await Promise.resolve().then(() => (init_renderer21(), renderer_exports21));
63819
64649
  const seqParsed = parseSequenceDgmo2(content, effectivePalette);
63820
64650
  if (seqParsed.error || seqParsed.participants.length === 0) return "";
63821
64651
  const collapsedSections = viewState?.cs ? new Set(viewState.cs) : void 0;
@@ -64026,6 +64856,7 @@ var CHART_TYPES = /* @__PURE__ */ new Set([
64026
64856
  "journey-map",
64027
64857
  "pyramid",
64028
64858
  "ring",
64859
+ "treemap",
64029
64860
  "raci",
64030
64861
  "rasci",
64031
64862
  "daci",
@@ -64217,6 +65048,8 @@ var ATTRIBUTE_KEYS = /* @__PURE__ */ new Set([
64217
65048
  "value",
64218
65049
  "label",
64219
65050
  "style",
65051
+ // Treemap color-by-value metric key
65052
+ "heat",
64220
65053
  // Infra node behavior + edge colon-keys (§4) come from the single-source
64221
65054
  // directives registry — the parser accepts them only as `key: value` node
64222
65055
  // properties, so they render as `propertyName`. The dual-use top-level SLO
@@ -64594,7 +65427,7 @@ pre.dgmo, code.language-dgmo, pre > code.language-dgmo,
64594
65427
 
64595
65428
  // src/auto/index.ts
64596
65429
  init_safe_href();
64597
- var VERSION = "0.37.0";
65430
+ var VERSION = "0.38.0";
64598
65431
  var DEFAULTS = {
64599
65432
  theme: "auto",
64600
65433
  palette: "slate",