@diagrammo/dgmo 0.36.0 → 0.38.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/.cursorrules +3 -0
  2. package/.github/copilot-instructions.md +3 -0
  3. package/.windsurfrules +3 -0
  4. package/SKILL.md +3 -0
  5. package/dist/advanced.cjs +1058 -135
  6. package/dist/advanced.d.cts +122 -8
  7. package/dist/advanced.d.ts +122 -8
  8. package/dist/advanced.js +1055 -133
  9. package/dist/auto.cjs +1047 -132
  10. package/dist/auto.js +96 -95
  11. package/dist/auto.mjs +1048 -130
  12. package/dist/cli.cjs +117 -116
  13. package/dist/editor.cjs +4 -1
  14. package/dist/editor.js +4 -1
  15. package/dist/highlight.cjs +3 -0
  16. package/dist/highlight.js +3 -0
  17. package/dist/index.cjs +1043 -131
  18. package/dist/index.js +1044 -129
  19. package/docs/ai-integration.md +3 -0
  20. package/docs/language-reference.md +106 -7
  21. package/gallery/fixtures/map-coastline.dgmo +2 -2
  22. package/gallery/fixtures/map-route.dgmo +5 -5
  23. package/gallery/fixtures/treemap-branch.dgmo +15 -0
  24. package/gallery/fixtures/treemap-heat.dgmo +12 -0
  25. package/gallery/fixtures/treemap-tag-heat.dgmo +21 -0
  26. package/gallery/fixtures/treemap-tags.dgmo +18 -0
  27. package/package.json +1 -1
  28. package/src/advanced.ts +11 -0
  29. package/src/boxes-and-lines/layout-search.ts +19 -1
  30. package/src/chart-type-registry.ts +4 -0
  31. package/src/chart-types.ts +5 -0
  32. package/src/completion.ts +64 -0
  33. package/src/d3.ts +30 -18
  34. package/src/editor/highlight-api.ts +2 -0
  35. package/src/editor/keywords.ts +3 -0
  36. package/src/infra/parser.ts +95 -38
  37. package/src/map/dimensions.ts +19 -2
  38. package/src/map/layout.ts +91 -7
  39. package/src/map/parser.ts +51 -29
  40. package/src/map/renderer.ts +10 -0
  41. package/src/map/types.ts +9 -8
  42. package/src/treemap/layout.ts +189 -0
  43. package/src/treemap/parser.ts +475 -0
  44. package/src/treemap/renderer.ts +698 -0
  45. package/src/treemap/types.ts +57 -0
  46. package/src/utils/parsing.ts +1 -0
  47. package/src/utils/reserved-key-registry.ts +5 -0
package/dist/advanced.js CHANGED
@@ -697,7 +697,7 @@ function withTagAliases(base, aliases) {
697
697
  function isReservedKey(registry, key) {
698
698
  return registry.keys.has(key) || registry.tagAliases.has(key);
699
699
  }
700
- 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;
700
+ 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;
701
701
  var init_reserved_key_registry = __esm({
702
702
  "src/utils/reserved-key-registry.ts"() {
703
703
  "use strict";
@@ -816,6 +816,7 @@ var init_reserved_key_registry = __esm({
816
816
  "color",
817
817
  "description"
818
818
  ]);
819
+ TREEMAP_REGISTRY = staticRegistry(["heat"]);
819
820
  RACI_REGISTRY = staticRegistry([
820
821
  "color",
821
822
  "description"
@@ -1245,6 +1246,7 @@ var init_parsing = __esm({
1245
1246
  "journey-map",
1246
1247
  "pyramid",
1247
1248
  "ring",
1249
+ "treemap",
1248
1250
  "raci",
1249
1251
  "rasci",
1250
1252
  "daci",
@@ -11843,6 +11845,10 @@ var init_chart_types = __esm({
11843
11845
  id: "ring",
11844
11846
  description: "Concentric rings showing nested or hierarchical categories (read core-out)"
11845
11847
  },
11848
+ {
11849
+ id: "treemap",
11850
+ description: "Nested rectangles sized by value \u2014 show a hierarchy\u2019s proportions (budgets, disk usage, portfolios) with color by category, value heatmap, or branch"
11851
+ },
11846
11852
  {
11847
11853
  id: "map",
11848
11854
  description: "Geographic concept map: highlight/score regions, drop points of interest, connect with routes or edges"
@@ -16730,6 +16736,7 @@ function parseInfra(content) {
16730
16736
  let currentGroup = null;
16731
16737
  let currentTagGroup = null;
16732
16738
  let baseIndent = 0;
16739
+ let firstLineConsumed = false;
16733
16740
  function finishCurrentNode() {
16734
16741
  if (!currentNode) return;
16735
16742
  const key = currentNode.id;
@@ -16737,7 +16744,8 @@ function parseInfra(content) {
16737
16744
  if (existing) {
16738
16745
  const incomingDisplay = displayName(currentNode.label);
16739
16746
  const existingDisplay = displayName(existing.label);
16740
- if (incomingDisplay !== existingDisplay) {
16747
+ const isAliasRef = nameAliasMap.get(currentNode.label) === key;
16748
+ if (incomingDisplay !== existingDisplay && !isAliasRef) {
16741
16749
  result.diagnostics.push(
16742
16750
  makeDgmoError(
16743
16751
  currentNode.lineNumber,
@@ -16803,19 +16811,22 @@ function parseInfra(content) {
16803
16811
  if (indent === 0 && currentNode && !trimmed.startsWith("-")) {
16804
16812
  finishCurrentNode();
16805
16813
  }
16806
- const firstLineResult = parseFirstLine(trimmed);
16807
- if (firstLineResult) {
16808
- if (firstLineResult.chartType !== "infra") {
16809
- setError(
16810
- lineNumber,
16811
- `Expected chart type 'infra', got '${firstLineResult.chartType}'`
16812
- );
16813
- }
16814
- if (firstLineResult.title) {
16815
- result.title = firstLineResult.title;
16816
- result.titleLineNumber = lineNumber;
16814
+ if (!firstLineConsumed) {
16815
+ firstLineConsumed = true;
16816
+ const firstLineResult = parseFirstLine(trimmed);
16817
+ if (firstLineResult) {
16818
+ if (firstLineResult.chartType !== "infra") {
16819
+ setError(
16820
+ lineNumber,
16821
+ `Expected chart type 'infra', got '${firstLineResult.chartType}'`
16822
+ );
16823
+ }
16824
+ if (firstLineResult.title) {
16825
+ result.title = firstLineResult.title;
16826
+ result.titleLineNumber = lineNumber;
16827
+ }
16828
+ continue;
16817
16829
  }
16818
- continue;
16819
16830
  }
16820
16831
  if (/^direction-tb$/i.test(trimmed)) {
16821
16832
  result.direction = "TB";
@@ -16881,18 +16892,20 @@ function parseInfra(content) {
16881
16892
  if (compMatch) {
16882
16893
  finishCurrentNode();
16883
16894
  finishCurrentTagGroup();
16884
- const rawName = (compMatch[1] ?? compMatch[2] ?? "").trim();
16895
+ const { qname, uname, alias: asAlias, meta } = compMatch.groups;
16896
+ const rawName = (qname ?? uname ?? "").trim();
16885
16897
  const peeled = peelInfraDecorations(rawName, lineNumber);
16886
16898
  const name = peeled.label;
16887
- const rest = compMatch[3] || "";
16899
+ const alias = asAlias ?? peeled.alias;
16900
+ const rest = meta ?? "";
16888
16901
  const { tags } = extractPipeMetadata(rest);
16889
16902
  warnUnknownMetaKeys(
16890
16903
  tags,
16891
16904
  withTagAliases(INFRA_REGISTRY, tagAliasSet),
16892
16905
  (msg) => warn(lineNumber, msg)
16893
16906
  );
16894
- const id = nodeId2(name);
16895
- if (peeled.alias) nameAliasMap.set(peeled.alias, id);
16907
+ const id = nameAliasMap.get(name) ?? nodeId2(name);
16908
+ if (alias) nameAliasMap.set(alias, id);
16896
16909
  const isEdge = EDGE_NODE_NAMES.has(id.toLowerCase());
16897
16910
  currentNode = {
16898
16911
  id,
@@ -16976,18 +16989,20 @@ function parseInfra(content) {
16976
16989
  const compMatch = trimmed.match(COMPONENT_RE);
16977
16990
  if (compMatch) {
16978
16991
  finishCurrentTagGroup();
16979
- const rawName = (compMatch[1] ?? compMatch[2] ?? "").trim();
16992
+ const { qname, uname, alias: asAlias, meta } = compMatch.groups;
16993
+ const rawName = (qname ?? uname ?? "").trim();
16980
16994
  const peeled = peelInfraDecorations(rawName, lineNumber);
16981
16995
  const name = peeled.label;
16982
- const rest = compMatch[3] || "";
16996
+ const alias = asAlias ?? peeled.alias;
16997
+ const rest = meta ?? "";
16983
16998
  const { tags: nodeTags } = extractPipeMetadata(rest);
16984
16999
  warnUnknownMetaKeys(
16985
17000
  nodeTags,
16986
17001
  withTagAliases(INFRA_REGISTRY, tagAliasSet),
16987
17002
  (msg) => warn(lineNumber, msg)
16988
17003
  );
16989
- const id = nodeId2(name);
16990
- if (peeled.alias) nameAliasMap.set(peeled.alias, id);
17004
+ const id = nameAliasMap.get(name) ?? nodeId2(name);
17005
+ if (alias) nameAliasMap.set(alias, id);
16991
17006
  const tags = currentGroup.metadata ? { ...currentGroup.metadata, ...nodeTags } : nodeTags;
16992
17007
  currentNode = {
16993
17008
  id,
@@ -17178,6 +17193,11 @@ function parseInfra(content) {
17178
17193
  }
17179
17194
  continue;
17180
17195
  }
17196
+ if (currentNode && tagAliasSet.has(normalizeName(key))) {
17197
+ const mut = nodeMutableTags.get(currentNode.id);
17198
+ if (mut) mut[tagAttrKey(key)] = rawVal;
17199
+ continue;
17200
+ }
17181
17201
  if (!INFRA_BEHAVIOR_KEYS.has(key) && !EDGE_ONLY_KEYS.has(key)) {
17182
17202
  const allKeys = [...INFRA_BEHAVIOR_KEYS, ...EDGE_ONLY_KEYS];
17183
17203
  const hint = suggest(key, allKeys);
@@ -17243,18 +17263,20 @@ function parseInfra(content) {
17243
17263
  finishCurrentNode();
17244
17264
  const compMatch = trimmed.match(COMPONENT_RE);
17245
17265
  if (compMatch) {
17246
- const rawName = (compMatch[1] ?? compMatch[2] ?? "").trim();
17266
+ const { qname, uname, alias: asAlias, meta } = compMatch.groups;
17267
+ const rawName = (qname ?? uname ?? "").trim();
17247
17268
  const peeled = peelInfraDecorations(rawName, lineNumber);
17248
17269
  const name = peeled.label;
17249
- const rest = compMatch[3] || "";
17270
+ const alias = asAlias ?? peeled.alias;
17271
+ const rest = meta ?? "";
17250
17272
  const { tags: nodeTags } = extractPipeMetadata(rest);
17251
17273
  warnUnknownMetaKeys(
17252
17274
  nodeTags,
17253
17275
  withTagAliases(INFRA_REGISTRY, tagAliasSet),
17254
17276
  (msg) => warn(lineNumber, msg)
17255
17277
  );
17256
- const id = nodeId2(name);
17257
- if (peeled.alias) nameAliasMap.set(peeled.alias, id);
17278
+ const id = nameAliasMap.get(name) ?? nodeId2(name);
17279
+ if (alias) nameAliasMap.set(alias, id);
17258
17280
  const tags = currentGroup.metadata ? { ...currentGroup.metadata, ...nodeTags } : nodeTags;
17259
17281
  currentNode = {
17260
17282
  id,
@@ -17276,18 +17298,20 @@ function parseInfra(content) {
17276
17298
  finishCurrentNode();
17277
17299
  finishCurrentTagGroup();
17278
17300
  currentGroup = null;
17279
- const rawName = (compMatch[1] ?? compMatch[2] ?? "").trim();
17301
+ const { qname, uname, alias: asAlias, meta } = compMatch.groups;
17302
+ const rawName = (qname ?? uname ?? "").trim();
17280
17303
  const peeled = peelInfraDecorations(rawName, lineNumber);
17281
17304
  const name = peeled.label;
17282
- const rest = compMatch[3] || "";
17305
+ const alias = asAlias ?? peeled.alias;
17306
+ const rest = meta ?? "";
17283
17307
  const { tags } = extractPipeMetadata(rest);
17284
17308
  warnUnknownMetaKeys(
17285
17309
  tags,
17286
17310
  withTagAliases(INFRA_REGISTRY, tagAliasSet),
17287
17311
  (msg) => warn(lineNumber, msg)
17288
17312
  );
17289
- const id = nodeId2(name);
17290
- if (peeled.alias) nameAliasMap.set(peeled.alias, id);
17313
+ const id = nameAliasMap.get(name) ?? nodeId2(name);
17314
+ if (alias) nameAliasMap.set(alias, id);
17291
17315
  currentNode = {
17292
17316
  id,
17293
17317
  label: name,
@@ -17487,7 +17511,7 @@ var init_parser15 = __esm({
17487
17511
  DEPRECATED_FANOUT_RE = /\bx(\d+)\s*$/;
17488
17512
  GROUP_RE = /^\[([^\]]+)\]\s*(?:as\s+([A-Za-z][A-Za-z0-9_]{0,11})\s*)?((?:\|.*)|(?:[a-zA-Z_]\w*\s*:.*))?$/;
17489
17513
  TAG_VALUE_RE = /^(\w[\w\s]+?)\s*$/;
17490
- COMPONENT_RE = /^(?:"([^"]+)"|([a-zA-Z_][\w -]*?))\s*((?:\|.*)|(?:[a-zA-Z_]\w*\s*:.*))?$/;
17514
+ COMPONENT_RE = /^(?:"(?<qname>[^"]+)"|(?<uname>[a-zA-Z_][\w -]*?))(?:\s+as\s+(?<alias>[A-Za-z][A-Za-z0-9_]{0,11}))?\s*(?<meta>(?:\|.*)|(?:[a-zA-Z_]\w*\s*:.*))?$/;
17491
17515
  PIPE_META_RE = /[|,]\s*(\w+)\s*:\s*([^|,]+)/g;
17492
17516
  SAMELINE_META_RE = /(?:^|[\s,])(\w+)\s*:\s*([^,]+?)(?=\s*,|\s*$)/g;
17493
17517
  PROPERTY_RE = /^([\w-]+):\s*(.+)$/;
@@ -18971,8 +18995,8 @@ function parseMap(content, palette) {
18971
18995
  continue;
18972
18996
  }
18973
18997
  if (open.route && indent > open.route.indent) {
18974
- const leg = parseLeg(trimmed, lineNumber, open.route.route.style);
18975
- open.route.route.legs.push(leg);
18998
+ const leg = parseLeg(trimmed, lineNumber);
18999
+ if (leg) open.route.route.legs.push(leg);
18976
19000
  continue;
18977
19001
  }
18978
19002
  if (open.poi && indent > open.poi.indent) {
@@ -19001,6 +19025,14 @@ function parseMap(content, palette) {
19001
19025
  Object.assign(open.poi.poi.meta, split.meta);
19002
19026
  continue;
19003
19027
  }
19028
+ if (split.name) {
19029
+ const src = open.poi.poi.alias ?? poiName(open.poi.poi.pos) ?? "the poi";
19030
+ pushError(
19031
+ lineNumber,
19032
+ `Malformed hub edge: "${trimmed}" \u2014 an indented line under a poi is an edge from "${src}" and needs an arrow glyph (\`-> dest\`, \`~> dest\`, or labeled \`-label-> dest\`). For a standalone place, declare it at the top level. (\xA724B.5)`
19033
+ );
19034
+ continue;
19035
+ }
19004
19036
  }
19005
19037
  closeBlocks();
19006
19038
  const firstWord = trimmed.split(/\s+/)[0];
@@ -19009,7 +19041,7 @@ function parseMap(content, palette) {
19009
19041
  continue;
19010
19042
  }
19011
19043
  if (DIRECTIVE_SET.has(firstWord) && !trimmed.slice(firstWord.length).trimStart().startsWith(":")) {
19012
- handleDirective(
19044
+ handleDirective2(
19013
19045
  firstWord,
19014
19046
  trimmed.slice(firstWord.length).trim(),
19015
19047
  lineNumber
@@ -19048,7 +19080,7 @@ function parseMap(content, palette) {
19048
19080
  }
19049
19081
  }
19050
19082
  return result;
19051
- function handleDirective(key, value, line11) {
19083
+ function handleDirective2(key, value, line11) {
19052
19084
  const d = result.directives;
19053
19085
  const dup = (have) => {
19054
19086
  if (have !== void 0)
@@ -19249,31 +19281,44 @@ function parseMap(content, palette) {
19249
19281
  const { tags, meta } = partitionMeta(split.meta, tagGroupNames());
19250
19282
  const originLabel = meta["label"];
19251
19283
  const originValue = meta["value"];
19252
- const style = meta["style"] === "arc" ? "arc" : "straight";
19284
+ if (meta["style"] !== void 0) {
19285
+ pushError(
19286
+ line11,
19287
+ "route header no longer takes `style:` \u2014 set leg shape with the arrow glyph instead (`~\u2026~>` for an arc leg, `-\u2026->` for a straight one). (\xA724B.6)"
19288
+ );
19289
+ }
19253
19290
  const route = {
19254
19291
  origin: pos,
19255
19292
  ...split.alias !== void 0 && { originAlias: split.alias },
19256
19293
  ...originLabel !== void 0 && { originLabel },
19257
19294
  ...originValue !== void 0 && { originValue },
19258
19295
  originTags: tags,
19259
- style,
19260
19296
  legs: [],
19261
19297
  lineNumber: line11
19262
19298
  };
19263
19299
  routes.push(route);
19264
19300
  open.route = { route, indent };
19265
19301
  }
19266
- function parseLeg(trimmed, line11, headerStyle) {
19267
- let arrowStyle = "straight";
19268
- let label;
19269
- let rest = trimmed;
19302
+ function parseLeg(trimmed, line11) {
19270
19303
  const m = trimmed.match(LEG_ARROW_RE);
19271
- if (m) {
19272
- const arr = classifyArrow(m[1], line11);
19273
- arrowStyle = arr.style;
19274
- label = arr.label;
19275
- rest = m[2];
19304
+ if (!m) {
19305
+ pushError(
19306
+ line11,
19307
+ `Malformed route leg: "${trimmed}" \u2014 a leg needs an arrow glyph (\`-> dest\`, \`~> dest\`, or labeled \`-label-> dest\` / \`~label~> dest\`). (\xA724B.6)`
19308
+ );
19309
+ return null;
19276
19310
  }
19311
+ const arr = classifyArrow(m[1], line11);
19312
+ if (!arr.directed) {
19313
+ pushError(
19314
+ line11,
19315
+ `A route leg is directional \u2014 "${trimmed}" uses an undirected glyph; use \`-> \` (straight) or \`~> \` (arc). (\xA724B.6)`
19316
+ );
19317
+ return null;
19318
+ }
19319
+ const arrowStyle = arr.style;
19320
+ const label = arr.label;
19321
+ const rest = m[2];
19277
19322
  const split = splitNameAndMeta(
19278
19323
  rest,
19279
19324
  registry(),
@@ -19289,10 +19334,9 @@ function parseMap(content, palette) {
19289
19334
  const { tags, meta } = partitionMeta(split.meta, tagGroupNames());
19290
19335
  const value = meta["value"];
19291
19336
  const destLabel = meta["label"];
19292
- const style = arrowStyle === "arc" || headerStyle === "arc" ? "arc" : "straight";
19293
19337
  return {
19294
19338
  ...label !== void 0 && { label },
19295
- style,
19339
+ style: arrowStyle,
19296
19340
  ...value !== void 0 && { value },
19297
19341
  dest: pos,
19298
19342
  ...split.alias !== void 0 && { destAlias: split.alias },
@@ -22906,6 +22950,344 @@ var init_parser25 = __esm({
22906
22950
  }
22907
22951
  });
22908
22952
 
22953
+ // src/treemap/parser.ts
22954
+ var parser_exports20 = {};
22955
+ __export(parser_exports20, {
22956
+ TREEMAP_DIAGNOSTIC_CODES: () => TREEMAP_DIAGNOSTIC_CODES,
22957
+ parseTreemap: () => parseTreemap
22958
+ });
22959
+ function isFullyQuoted(s) {
22960
+ return s.length >= 2 && (s.startsWith('"') && s.endsWith('"') || s.startsWith("'") && s.endsWith("'"));
22961
+ }
22962
+ function parseTreemap(content, palette) {
22963
+ const options = {
22964
+ heatColors: [],
22965
+ noValues: false,
22966
+ noPercent: false,
22967
+ noHeaders: false,
22968
+ noLegend: false
22969
+ };
22970
+ const result = {
22971
+ type: "treemap",
22972
+ title: null,
22973
+ titleLineNumber: null,
22974
+ roots: [],
22975
+ tagGroups: [],
22976
+ hasHeat: false,
22977
+ defaultColorMode: "branch",
22978
+ options,
22979
+ diagnostics: [],
22980
+ error: null
22981
+ };
22982
+ const fail = makeFail(result);
22983
+ const pushError = (line11, message, code) => {
22984
+ const diag = makeDgmoError(line11, message, "error", code);
22985
+ result.diagnostics.push(diag);
22986
+ if (!result.error) result.error = formatDgmoError(diag);
22987
+ };
22988
+ const pushWarning = (line11, message, code) => {
22989
+ result.diagnostics.push(makeDgmoError(line11, message, "warning", code));
22990
+ };
22991
+ if (!content?.trim()) {
22992
+ return fail(0, "No content provided");
22993
+ }
22994
+ const lines = content.split("\n");
22995
+ let contentStarted = false;
22996
+ let nodeCounter = 0;
22997
+ let currentTagGroup = null;
22998
+ const aliasMap = /* @__PURE__ */ new Map();
22999
+ const indentStack = [];
23000
+ for (let i = 0; i < lines.length; i++) {
23001
+ const line11 = lines[i];
23002
+ const lineNumber = i + 1;
23003
+ const trimmed = line11.trim();
23004
+ if (!trimmed) {
23005
+ currentTagGroup = null;
23006
+ continue;
23007
+ }
23008
+ if (trimmed.startsWith("//")) continue;
23009
+ if (!contentStarted) {
23010
+ const firstLine = parseFirstLine(trimmed);
23011
+ if (firstLine && result.titleLineNumber === null && i === 0) {
23012
+ if (firstLine.chartType !== "treemap") {
23013
+ let msg = `Expected chart type "treemap", got "${firstLine.chartType}"`;
23014
+ const hint = suggest(firstLine.chartType, ["treemap"]);
23015
+ if (hint) msg += `. ${hint}`;
23016
+ return fail(lineNumber, msg);
23017
+ }
23018
+ result.title = firstLine.title ?? null;
23019
+ result.titleLineNumber = lineNumber;
23020
+ continue;
23021
+ }
23022
+ }
23023
+ const tagBlockMatch = matchTagBlockHeading(trimmed);
23024
+ if (tagBlockMatch) {
23025
+ emitTagLegacyDiagnostic(tagBlockMatch, lineNumber, result.diagnostics);
23026
+ if (contentStarted) {
23027
+ pushError(
23028
+ lineNumber,
23029
+ "Tag groups must appear before treemap content",
23030
+ "E_TAG_DECLARED_AFTER_CONTENT"
23031
+ );
23032
+ continue;
23033
+ }
23034
+ currentTagGroup = {
23035
+ name: tagBlockMatch.name,
23036
+ ...tagBlockMatch.alias !== void 0 && {
23037
+ alias: tagBlockMatch.alias
23038
+ },
23039
+ entries: [],
23040
+ lineNumber
23041
+ };
23042
+ if (tagBlockMatch.alias) {
23043
+ aliasMap.set(
23044
+ tagBlockMatch.alias.toLowerCase(),
23045
+ tagAttrKey(tagBlockMatch.name)
23046
+ );
23047
+ }
23048
+ aliasMap.set(
23049
+ tagAttrKey(tagBlockMatch.name),
23050
+ tagAttrKey(tagBlockMatch.name)
23051
+ );
23052
+ result.tagGroups.push(currentTagGroup);
23053
+ continue;
23054
+ }
23055
+ if (currentTagGroup && !contentStarted) {
23056
+ const indent2 = measureIndent(line11);
23057
+ if (indent2 > 0) {
23058
+ const { text: cleanEntry, isDefault } = stripDefaultModifier(trimmed);
23059
+ const { label, color } = extractColor(
23060
+ cleanEntry,
23061
+ palette,
23062
+ result.diagnostics,
23063
+ lineNumber
23064
+ );
23065
+ if (isDefault) {
23066
+ currentTagGroup.defaultValue = label;
23067
+ } else if (currentTagGroup.entries.length === 0) {
23068
+ currentTagGroup.defaultValue = label;
23069
+ }
23070
+ currentTagGroup.entries.push({
23071
+ value: label,
23072
+ color: color ?? AUTO_TAG_COLOR_SENTINEL,
23073
+ lineNumber
23074
+ });
23075
+ continue;
23076
+ }
23077
+ currentTagGroup = null;
23078
+ }
23079
+ if (!contentStarted && measureIndent(line11) === 0) {
23080
+ if (handleDirective(trimmed, options, result, pushWarning, lineNumber)) {
23081
+ continue;
23082
+ }
23083
+ }
23084
+ contentStarted = true;
23085
+ currentTagGroup = null;
23086
+ const indent = measureIndent(line11);
23087
+ const node = parseNodeLine3(
23088
+ trimmed,
23089
+ lineNumber,
23090
+ ++nodeCounter,
23091
+ aliasMap,
23092
+ result.diagnostics,
23093
+ pushWarning
23094
+ );
23095
+ if (node.heat !== void 0) result.hasHeat = true;
23096
+ attachNode4(node, indent, indentStack, result);
23097
+ }
23098
+ finalizeAutoTagColors(result.tagGroups, palette);
23099
+ const allNodes = [];
23100
+ const collectAll = (nodes) => {
23101
+ for (const n of nodes) {
23102
+ allNodes.push(n);
23103
+ collectAll(n.children);
23104
+ }
23105
+ };
23106
+ collectAll(result.roots);
23107
+ for (const n of allNodes) {
23108
+ const node = n;
23109
+ const isBranch = node.children.length > 0;
23110
+ if (isBranch) {
23111
+ if (node.value !== void 0) {
23112
+ pushWarning(
23113
+ node.lineNumber,
23114
+ `"${node.label}" is a branch \u2014 its trailing number is ignored; the area is the auto-sum of its children`,
23115
+ TREEMAP_DIAGNOSTIC_CODES.BRANCH_VALUE_IGNORED
23116
+ );
23117
+ delete node.value;
23118
+ }
23119
+ } else if (node.value === void 0) {
23120
+ pushWarning(
23121
+ node.lineNumber,
23122
+ `Leaf "${node.label}" has no value \u2014 it renders with zero area`,
23123
+ TREEMAP_DIAGNOSTIC_CODES.LEAF_NO_VALUE
23124
+ );
23125
+ node.value = 0;
23126
+ } else if (node.value < 0) {
23127
+ pushError(
23128
+ node.lineNumber,
23129
+ `Leaf "${node.label}" has a negative value (${node.value}) \u2014 treemap sizes must be \u2265 0`,
23130
+ TREEMAP_DIAGNOSTIC_CODES.NEGATIVE_VALUE
23131
+ );
23132
+ }
23133
+ }
23134
+ if (result.hasHeat || options.heatLabel !== void 0) {
23135
+ result.hasHeat = true;
23136
+ }
23137
+ if (result.tagGroups.length > 0) {
23138
+ validateTagValues(allNodes, result.tagGroups, pushWarning, suggest);
23139
+ validateTagGroupNames(result.tagGroups, pushWarning);
23140
+ cascadeTagMetadata(result.roots, result.tagGroups);
23141
+ }
23142
+ result.defaultColorMode = resolveDefaultColorMode(result);
23143
+ if (result.roots.length === 0 && !result.error) {
23144
+ const diag = makeDgmoError(1, "No nodes found in treemap");
23145
+ result.diagnostics.push(diag);
23146
+ result.error = formatDgmoError(diag);
23147
+ }
23148
+ return result;
23149
+ }
23150
+ function handleDirective(trimmed, options, result, pushWarning, lineNumber) {
23151
+ const depthMatch = trimmed.match(/^depth\s+(-?\d+)\s*$/i);
23152
+ if (depthMatch) {
23153
+ const n = parseInt(depthMatch[1], 10);
23154
+ if (n >= 1) options.maxDepth = n;
23155
+ else pushWarning(lineNumber, '"depth" must be \u2265 1 \u2014 ignored');
23156
+ return true;
23157
+ }
23158
+ if (/^other-below\b/i.test(trimmed)) {
23159
+ pushWarning(
23160
+ lineNumber,
23161
+ '"other-below" is no longer supported \u2014 remove this line'
23162
+ );
23163
+ return true;
23164
+ }
23165
+ const heatMatch = trimmed.match(/^heat\s+(.+)$/i);
23166
+ if (heatMatch) {
23167
+ const { label, low, high } = peelRampColors(heatMatch[1].trim());
23168
+ options.heatLabel = label || "Value";
23169
+ const colors = [];
23170
+ if (low !== void 0) colors.push(low);
23171
+ if (high !== void 0) colors.push(high);
23172
+ options.heatColors = colors;
23173
+ result.hasHeat = true;
23174
+ return true;
23175
+ }
23176
+ const noMatch = trimmed.match(/^no-(values|percent|headers|legend)\s*$/i);
23177
+ if (noMatch) {
23178
+ const key = noMatch[1].toLowerCase();
23179
+ if (key === "values") options.noValues = true;
23180
+ else if (key === "percent") options.noPercent = true;
23181
+ else if (key === "headers") options.noHeaders = true;
23182
+ else if (key === "legend") options.noLegend = true;
23183
+ return true;
23184
+ }
23185
+ return false;
23186
+ }
23187
+ function resolveDefaultColorMode(result) {
23188
+ if (result.tagGroups.length > 0) return "tag";
23189
+ if (result.hasHeat) return "heat";
23190
+ return "branch";
23191
+ }
23192
+ function parseNodeLine3(trimmed, lineNumber, counter, aliasMap, diagnostics, pushWarning) {
23193
+ if (trimmed.includes("|")) {
23194
+ diagnostics.push(
23195
+ makeDgmoError(
23196
+ lineNumber,
23197
+ pipeOperatorRemovedMessage(),
23198
+ "error",
23199
+ METADATA_DIAGNOSTIC_CODES.PIPE_OPERATOR_REMOVED
23200
+ )
23201
+ );
23202
+ }
23203
+ const registry = withTagAliases(TREEMAP_REGISTRY, new Set(aliasMap.keys()));
23204
+ const split = splitNameAndMeta(
23205
+ trimmed,
23206
+ registry,
23207
+ aliasMap,
23208
+ void 0,
23209
+ diagnostics,
23210
+ lineNumber
23211
+ );
23212
+ warnUnknownMetaKeys(
23213
+ split.meta,
23214
+ registry,
23215
+ (msg) => diagnostics.push(makeDgmoError(lineNumber, msg, "warning")),
23216
+ split.name
23217
+ );
23218
+ const metadata = { ...split.meta };
23219
+ let heat;
23220
+ if ("heat" in metadata) {
23221
+ const h = parseFloat(metadata["heat"].replace(/_/g, ""));
23222
+ if (Number.isFinite(h)) heat = h;
23223
+ delete metadata["heat"];
23224
+ }
23225
+ const rawName = split.name;
23226
+ let label;
23227
+ let value;
23228
+ if (isFullyQuoted(rawName)) {
23229
+ label = stripQuotes(rawName);
23230
+ } else {
23231
+ const vm = rawName.match(VALUE_TOKEN_RE);
23232
+ if (vm) {
23233
+ const labelPart = vm[1].trim();
23234
+ const token = vm[2];
23235
+ if (token.includes(",")) {
23236
+ pushWarning(lineNumber, dataCommaRemovedMessage(labelPart));
23237
+ }
23238
+ const cleaned = token.replace(/[_,]/g, "");
23239
+ const parsed = parseFloat(cleaned);
23240
+ if (Number.isFinite(parsed)) {
23241
+ value = parsed;
23242
+ label = isFullyQuoted(labelPart) ? stripQuotes(labelPart) : labelPart;
23243
+ } else {
23244
+ label = rawName;
23245
+ }
23246
+ } else {
23247
+ label = rawName;
23248
+ }
23249
+ }
23250
+ return {
23251
+ id: `treemap-node-${counter}`,
23252
+ label,
23253
+ ...value !== void 0 && { value },
23254
+ ...heat !== void 0 && { heat },
23255
+ metadata,
23256
+ children: [],
23257
+ lineNumber
23258
+ };
23259
+ }
23260
+ function attachNode4(node, indent, indentStack, result) {
23261
+ while (indentStack.length > 0) {
23262
+ const top = indentStack[indentStack.length - 1];
23263
+ if (top.indent < indent) break;
23264
+ indentStack.pop();
23265
+ }
23266
+ if (indentStack.length > 0) {
23267
+ const parent = indentStack[indentStack.length - 1].node;
23268
+ parent.children.push(node);
23269
+ } else {
23270
+ result.roots.push(node);
23271
+ }
23272
+ indentStack.push({ node, indent });
23273
+ }
23274
+ var TREEMAP_DIAGNOSTIC_CODES, VALUE_TOKEN_RE;
23275
+ var init_parser26 = __esm({
23276
+ "src/treemap/parser.ts"() {
23277
+ "use strict";
23278
+ init_diagnostics();
23279
+ init_tag_groups();
23280
+ init_parsing();
23281
+ init_reserved_key_registry();
23282
+ TREEMAP_DIAGNOSTIC_CODES = {
23283
+ NEGATIVE_VALUE: "E_TREEMAP_NEGATIVE_VALUE",
23284
+ LEAF_NO_VALUE: "W_TREEMAP_LEAF_NO_VALUE",
23285
+ BRANCH_VALUE_IGNORED: "W_TREEMAP_BRANCH_VALUE_IGNORED"
23286
+ };
23287
+ VALUE_TOKEN_RE = /^(.+?)\s+(-?\d[\d_,.]*)$/;
23288
+ }
23289
+ });
23290
+
22909
23291
  // src/raci/variants.ts
22910
23292
  function inferVariant(markers) {
22911
23293
  let hasD = false;
@@ -23160,8 +23542,8 @@ var init_variants = __esm({
23160
23542
  });
23161
23543
 
23162
23544
  // src/raci/parser.ts
23163
- var parser_exports20 = {};
23164
- __export(parser_exports20, {
23545
+ var parser_exports21 = {};
23546
+ __export(parser_exports21, {
23165
23547
  allTasks: () => allTasks,
23166
23548
  parseRaci: () => parseRaci
23167
23549
  });
@@ -23682,7 +24064,7 @@ function* allTasks(parsed) {
23682
24064
  }
23683
24065
  }
23684
24066
  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;
23685
- var init_parser26 = __esm({
24067
+ var init_parser27 = __esm({
23686
24068
  "src/raci/parser.ts"() {
23687
24069
  "use strict";
23688
24070
  init_diagnostics();
@@ -23928,6 +24310,7 @@ var init_chart_type_registry = __esm({
23928
24310
  init_parser24();
23929
24311
  init_parser25();
23930
24312
  init_parser26();
24313
+ init_parser27();
23931
24314
  CHART_TYPE_REGISTRY = [
23932
24315
  // ── Structured diagrams ───────────────────────────────────
23933
24316
  {
@@ -24068,6 +24451,9 @@ var init_chart_type_registry = __esm({
24068
24451
  { id: "cycle", category: "visualization", parse: parseCycle },
24069
24452
  { id: "pyramid", category: "visualization", parse: parsePyramid },
24070
24453
  { id: "ring", category: "visualization", parse: parseRing },
24454
+ // Treemap: squarified hierarchy. No measure/minDims — a treemap fills whatever
24455
+ // rectangle it's given and has no intrinsic aspect/size (F11).
24456
+ { id: "treemap", category: "visualization", parse: parseTreemap },
24071
24457
  // ── Geographic map (own parser → resolver → layout → renderer) ──
24072
24458
  { id: "map", category: "visualization", parse: parseMap }
24073
24459
  ];
@@ -26802,10 +27188,10 @@ async function renderSitemapForExport(content, theme, palette) {
26802
27188
  const parsed = parseSitemap2(content, effectivePalette);
26803
27189
  if (parsed.error || parsed.roots.length === 0) return "";
26804
27190
  const sitemapLayout = layoutSitemap2(parsed, void 0, null, void 0, true);
26805
- const PADDING3 = 20;
27191
+ const PADDING4 = 20;
26806
27192
  const titleOffset = parsed.title ? 30 : 0;
26807
- const exportWidth = sitemapLayout.width + PADDING3 * 2;
26808
- const exportHeight = sitemapLayout.height + PADDING3 * 2 + titleOffset;
27193
+ const exportWidth = sitemapLayout.width + PADDING4 * 2;
27194
+ const exportHeight = sitemapLayout.height + PADDING4 * 2 + titleOffset;
26809
27195
  const container = document.createElement("div");
26810
27196
  container.style.width = `${exportWidth}px`;
26811
27197
  container.style.height = `${exportHeight}px`;
@@ -31923,6 +32309,10 @@ async function layoutBoxesAndLinesSearch(parsed, collapseInfo, opts) {
31923
32309
  const reserveEdgeLabels = opts?.reserveEdgeLabels ?? false;
31924
32310
  const onProgress = opts?.onProgress;
31925
32311
  const tick = onProgress ? () => new Promise((r) => setTimeout(r)) : () => void 0;
32312
+ const YIELD_AFTER_MS = 150;
32313
+ const YIELD_EVERY_MS = 30;
32314
+ const searchStart = performance.now();
32315
+ let lastYield = searchStart;
31926
32316
  const collapsedGroupLabels = /* @__PURE__ */ new Set();
31927
32317
  if (collapseInfo) {
31928
32318
  const missing = /* @__PURE__ */ new Set();
@@ -32352,7 +32742,11 @@ async function layoutBoxesAndLinesSearch(parsed, collapseInfo, opts) {
32352
32742
  const step = async (phase) => {
32353
32743
  if (!onProgress) return;
32354
32744
  onProgress(++progressDone, progressTotal, phase);
32355
- await tick();
32745
+ const now = performance.now();
32746
+ if (now - searchStart > YIELD_AFTER_MS && now - lastYield > YIELD_EVERY_MS) {
32747
+ lastYield = now;
32748
+ await tick();
32749
+ }
32356
32750
  };
32357
32751
  const pool = [];
32358
32752
  for (const cfg of configs) {
@@ -50963,7 +51357,7 @@ function computeEdgeLabelPosition(midAngle, radius, cx, cy, lineCount, labelPxW,
50963
51357
  };
50964
51358
  }
50965
51359
  function fitToCanvas(nodes, edges, parsed, _cx, _cy, radius, width, height, _isClockwise) {
50966
- const PADDING3 = 30;
51360
+ const PADDING4 = 30;
50967
51361
  let contentMinX = Infinity, contentMaxX = -Infinity;
50968
51362
  let contentMinY = Infinity, contentMaxY = -Infinity;
50969
51363
  for (const n of nodes) {
@@ -51005,13 +51399,13 @@ function fitToCanvas(nodes, edges, parsed, _cx, _cy, radius, width, height, _isC
51005
51399
  contentMinY = Math.min(contentMinY, le.labelY - 12);
51006
51400
  contentMaxY = Math.max(contentMaxY, le.labelY + (lineCount - 1) * 15);
51007
51401
  }
51008
- const overflowX = Math.max(0, PADDING3 - contentMinX) + Math.max(0, contentMaxX - (width - PADDING3));
51009
- const overflowY = Math.max(0, PADDING3 - contentMinY) + Math.max(0, contentMaxY - (height - PADDING3));
51402
+ const overflowX = Math.max(0, PADDING4 - contentMinX) + Math.max(0, contentMaxX - (width - PADDING4));
51403
+ const overflowY = Math.max(0, PADDING4 - contentMinY) + Math.max(0, contentMaxY - (height - PADDING4));
51010
51404
  if (overflowX <= 0 && overflowY <= 0) return null;
51011
51405
  const contentW = contentMaxX - contentMinX;
51012
51406
  const contentH = contentMaxY - contentMinY;
51013
- const availW = width - 2 * PADDING3;
51014
- const availH = height - 2 * PADDING3;
51407
+ const availW = width - 2 * PADDING4;
51408
+ const availH = height - 2 * PADDING4;
51015
51409
  const shrink = Math.min(availW / contentW, availH / contentH);
51016
51410
  const newRadius = Math.max(80, radius * shrink);
51017
51411
  return { radius: newRadius };
@@ -51210,7 +51604,7 @@ function renderCycle(container, parsed, palette, isDark, onClickItem, exportDims
51210
51604
  }
51211
51605
  edgeLabelInfo.push({ le, edge });
51212
51606
  }
51213
- const HEADER_H = 36 * layout.scale;
51607
+ const HEADER_H2 = 36 * layout.scale;
51214
51608
  const scaledNodeFont = Math.max(6, Math.round(NODE_FONT_SIZE7 * layout.scale));
51215
51609
  const scaledEdgeLabelFont = Math.max(
51216
51610
  6,
@@ -51274,10 +51668,10 @@ function renderCycle(container, parsed, palette, isDark, onClickItem, exportDims
51274
51668
  const rx = 6;
51275
51669
  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);
51276
51670
  if (hasDesc) {
51277
- const headerCenterY = ln.y - nodeH / 2 + HEADER_H / 2;
51671
+ const headerCenterY = ln.y - nodeH / 2 + HEADER_H2 / 2;
51278
51672
  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");
51279
51673
  renderInlineText(labelText, node.label, palette, scaledNodeFont);
51280
- const sepY = ln.y - nodeH / 2 + HEADER_H;
51674
+ const sepY = ln.y - nodeH / 2 + HEADER_H2;
51281
51675
  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);
51282
51676
  const descStartY = sepY + 4 + scaledDescFont;
51283
51677
  const descPadX = Math.max(8, 12 * layout.scale);
@@ -54107,13 +54501,15 @@ function layoutMap(resolvedIn, data, size, opts) {
54107
54501
  labelY: lp.y
54108
54502
  };
54109
54503
  const routeLabelStyle = leg.label !== void 0 ? labelOnFill(fillAt(bow.labelX, bow.labelY)) : void 0;
54504
+ const routeVal = Number(leg.value);
54110
54505
  legs.push({
54111
54506
  d: legPath(a, b, bow.curved, bow.offset),
54112
- width: routeWidthFor(Number(leg.value)),
54507
+ width: routeWidthFor(routeVal),
54113
54508
  color: lineColor(leg.tags) ?? mix(palette.text, palette.bg, 72),
54114
54509
  arrow: true,
54115
54510
  fromId: leg.fromId,
54116
54511
  toId: leg.toId,
54512
+ ...Number.isFinite(routeVal) && routeVal > 0 && { value: routeVal },
54117
54513
  ...Object.keys(leg.tags).length > 0 && { tags: leg.tags },
54118
54514
  lineNumber: leg.lineNumber,
54119
54515
  ...leg.label !== void 0 && {
@@ -54160,6 +54556,7 @@ function layoutMap(resolvedIn, data, size, opts) {
54160
54556
  labelY: lp.y
54161
54557
  };
54162
54558
  const edgeLabelStyle = e.label !== void 0 ? labelOnFill(fillAt(bow.labelX, bow.labelY)) : void 0;
54559
+ const edgeVal = Number(e.meta["value"]);
54163
54560
  legs.push({
54164
54561
  d: legPath(a, b, bow.curved, bow.offset),
54165
54562
  width: widthFor(e),
@@ -54167,6 +54564,7 @@ function layoutMap(resolvedIn, data, size, opts) {
54167
54564
  arrow: e.directed,
54168
54565
  fromId: e.fromId,
54169
54566
  toId: e.toId,
54567
+ ...Number.isFinite(edgeVal) && edgeVal > 0 && { value: edgeVal },
54170
54568
  ...Object.keys(e.tags).length > 0 && { tags: e.tags },
54171
54569
  lineNumber: e.lineNumber,
54172
54570
  ...e.label !== void 0 && {
@@ -54324,18 +54722,49 @@ function layoutMap(resolvedIn, data, size, opts) {
54324
54722
  const SHORT_HOP_MAX = Math.max(46, Math.min(width, height) * 0.11);
54325
54723
  const STEP = 4;
54326
54724
  const HOP_GAP = 9;
54725
+ const CLEAR_STEP = 6;
54726
+ const CLEAR_MAX = SHORT_HOP_MAX * 3;
54727
+ const CLEAR_TOL = CLEAR_STEP;
54728
+ const clearanceAt = (px, py, ox, oy) => {
54729
+ const baseAng = Math.atan2(oy, ox);
54730
+ let minClear = CLEAR_MAX;
54731
+ for (let k = -2; k <= 2; k++) {
54732
+ const a = baseAng + k * Math.PI / 4;
54733
+ const rx = Math.cos(a);
54734
+ const ry = Math.sin(a);
54735
+ let d = CLEAR_STEP;
54736
+ for (; d <= CLEAR_MAX; d += CLEAR_STEP) {
54737
+ const qx = px + rx * d;
54738
+ const qy = py + ry * d;
54739
+ if (qx < FIT_PAD || qy < topPad || qx > width - FIT_PAD || qy > height - FIT_PAD)
54740
+ break;
54741
+ if (fillAt(qx, qy) !== water) break;
54742
+ }
54743
+ if (d < minClear) minClear = d;
54744
+ }
54745
+ return minClear;
54746
+ };
54327
54747
  const tryShortHopCallout = (cx, cy, fill2, name, value, font = FONT2, gap = HOP_GAP, maxLen = SHORT_HOP_MAX) => {
54328
54748
  const chipW = stackW(name, value, font);
54329
54749
  const chipH = stackH(value !== void 0, font);
54750
+ const D = Math.SQRT1_2;
54330
54751
  const dirs = [
54331
54752
  [0, -1],
54332
- // north (over Canada)
54753
+ // north
54333
54754
  [0, 1],
54334
- // south (over Mexico / Gulf)
54755
+ // south
54335
54756
  [1, 0],
54336
- // east (Atlantic)
54337
- [-1, 0]
54338
- // west (Pacific)
54757
+ // east
54758
+ [-1, 0],
54759
+ // west
54760
+ [D, -D],
54761
+ // NE
54762
+ [D, D],
54763
+ // SE
54764
+ [-D, -D],
54765
+ // NW
54766
+ [-D, D]
54767
+ // SW
54339
54768
  ];
54340
54769
  let best = null;
54341
54770
  for (const [dx, dy] of dirs) {
@@ -54385,13 +54814,16 @@ function layoutMap(resolvedIn, data, size, opts) {
54385
54814
  (p) => segmentRectOverlap(cx, cy, innerX, innerY, p)
54386
54815
  ))
54387
54816
  continue;
54388
- if (best === null || len < best.len)
54817
+ const clear = clearanceAt(ccx, ccy, dx, dy);
54818
+ const better = best === null || clear > best.clear + CLEAR_TOL || clear >= best.clear - CLEAR_TOL && len < best.len;
54819
+ if (better)
54389
54820
  best = {
54390
54821
  x: ccx,
54391
54822
  y: ccy,
54392
54823
  rect,
54393
54824
  leader: [cx, cy, innerX, innerY],
54394
- len
54825
+ len,
54826
+ clear
54395
54827
  };
54396
54828
  }
54397
54829
  return best ? { x: best.x, y: best.y, rect: best.rect, leader: best.leader } : null;
@@ -55052,6 +55484,9 @@ function layoutMap(resolvedIn, data, size, opts) {
55052
55484
  const nx = -dy / len;
55053
55485
  const ny = dx / len;
55054
55486
  const perp = labelH + 2;
55487
+ const stroke2 = lg.width ?? W_MIN;
55488
+ const clearW = stroke2 / 2 + labelH / 2 + 3;
55489
+ const offList = stroke2 >= 4 ? [clearW, -clearW, clearW + perp, -(clearW + perp), 0] : [0, perp, -perp, 2 * perp, -2 * perp];
55055
55490
  const pm = /^M(-?[\d.]+),(-?[\d.]+)(?:L(-?[\d.]+),(-?[\d.]+)|Q(-?[\d.]+),(-?[\d.]+) (-?[\d.]+),(-?[\d.]+))$/.exec(
55056
55491
  lg.d
55057
55492
  );
@@ -55071,7 +55506,7 @@ function layoutMap(resolvedIn, data, size, opts) {
55071
55506
  return [a.cx + dx * t, a.cy + dy * t];
55072
55507
  };
55073
55508
  const candidates = [];
55074
- for (const off of [0, perp, -perp, 2 * perp, -2 * perp])
55509
+ for (const off of offList)
55075
55510
  for (const t of T_LIST) {
55076
55511
  const [bx, by] = pointAt(t);
55077
55512
  candidates.push([bx + nx * off, by + ny * off - 4]);
@@ -55822,6 +56257,12 @@ function renderMap(container, resolved, data, palette, isDark, onClickItem, expo
55822
56257
  }
55823
56258
  }
55824
56259
  wireSync(p, leg.lineNumber);
56260
+ if (leg.value !== void 0) {
56261
+ p.attr("data-value", leg.value);
56262
+ p.append("title").text(
56263
+ leg.label !== void 0 ? `${leg.label}: ${leg.value}` : `${leg.value}`
56264
+ );
56265
+ }
55825
56266
  if (arrowTri) {
55826
56267
  gLegs.append("path").attr("d", arrowTri).attr("fill", leg.color).attr("stroke", leg.color).attr("stroke-width", 1).attr("stroke-linejoin", "round").attr("data-from-id", leg.fromId).attr("data-to-id", leg.toId);
55827
56268
  }
@@ -56051,7 +56492,9 @@ function mapContentAspect(resolved, data, ref = REF) {
56051
56492
  function mapExportDimensions(resolved, data, baseWidth = 1200, aspectOverride) {
56052
56493
  const useOverride = aspectOverride !== void 0 && Number.isFinite(aspectOverride) && aspectOverride > 0;
56053
56494
  const raw = useOverride ? aspectOverride : mapContentAspect(resolved, data);
56054
- const clamped = useOverride ? raw : Math.max(ASPECT_MIN, Math.min(ASPECT_MAX, raw));
56495
+ const isGlobal = !useOverride && buildMapProjection(resolved, data).fitIsGlobal;
56496
+ const target = isGlobal ? raw / GLOBAL_HEIGHT_BOOST : raw;
56497
+ const clamped = useOverride ? raw : Math.max(ASPECT_MIN, Math.min(ASPECT_MAX, target));
56055
56498
  const width = baseWidth;
56056
56499
  let height = Math.round(width / clamped);
56057
56500
  let chromeReserve = 0;
@@ -56064,10 +56507,10 @@ function mapExportDimensions(resolved, data, baseWidth = 1200, aspectOverride) {
56064
56507
  height = Math.round(chromeReserve + MIN_MAP_BAND);
56065
56508
  floored = true;
56066
56509
  }
56067
- const preferContain = useOverride ? floored : clamped !== raw || floored;
56510
+ const preferContain = useOverride ? floored : clamped !== target || floored;
56068
56511
  return { width, height, preferContain };
56069
56512
  }
56070
- var FIT_PAD2, TITLE_GAP, ASPECT_MAX, ASPECT_MIN, MIN_MAP_BAND, FALLBACK_ASPECT, REF;
56513
+ var FIT_PAD2, TITLE_GAP, ASPECT_MAX, ASPECT_MIN, GLOBAL_HEIGHT_BOOST, MIN_MAP_BAND, FALLBACK_ASPECT, REF;
56071
56514
  var init_dimensions = __esm({
56072
56515
  "src/map/dimensions.ts"() {
56073
56516
  "use strict";
@@ -56077,6 +56520,7 @@ var init_dimensions = __esm({
56077
56520
  TITLE_GAP = 16;
56078
56521
  ASPECT_MAX = 3;
56079
56522
  ASPECT_MIN = 0.9;
56523
+ GLOBAL_HEIGHT_BOOST = 1.12;
56080
56524
  MIN_MAP_BAND = 200;
56081
56525
  FALLBACK_ASPECT = 1.5;
56082
56526
  REF = 1e3;
@@ -56865,14 +57309,477 @@ var init_renderer18 = __esm({
56865
57309
  }
56866
57310
  });
56867
57311
 
56868
- // src/raci/renderer.ts
57312
+ // src/treemap/layout.ts
57313
+ import {
57314
+ hierarchy as hierarchy2,
57315
+ treemap,
57316
+ treemapSquarify
57317
+ } from "d3-hierarchy";
57318
+ function toDatum(node) {
57319
+ if (node.children.length === 0) {
57320
+ return {
57321
+ ref: node,
57322
+ label: node.label,
57323
+ value: node.value ?? 0,
57324
+ ...node.heat !== void 0 && { heat: node.heat },
57325
+ lineNumber: node.lineNumber
57326
+ };
57327
+ }
57328
+ return {
57329
+ ref: node,
57330
+ label: node.label,
57331
+ ...node.heat !== void 0 && { heat: node.heat },
57332
+ lineNumber: node.lineNumber,
57333
+ children: node.children.map((c) => toDatum(c))
57334
+ };
57335
+ }
57336
+ function datumHeat(node) {
57337
+ if (node.data.heat !== void 0) return node.data.heat;
57338
+ const xs = [];
57339
+ for (const l of node.leaves()) {
57340
+ if (l.data.heat !== void 0) xs.push(l.data.heat);
57341
+ }
57342
+ if (xs.length === 0) return void 0;
57343
+ return xs.reduce((a, b) => a + b, 0) / xs.length;
57344
+ }
57345
+ function layoutTreemap(roots, opts) {
57346
+ const maxDepth = opts.maxDepth ?? Infinity;
57347
+ const rootDatum = {
57348
+ label: "__root",
57349
+ children: roots.map((r) => toDatum(r))
57350
+ };
57351
+ const h = hierarchy2(rootDatum).sum((d) => d.children?.length ? 0 : d.value ?? 0).sort((a, b) => (b.value ?? 0) - (a.value ?? 0));
57352
+ 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);
57353
+ const total = hroot.value ?? 0;
57354
+ (hroot.children ?? []).forEach((top, i) => {
57355
+ top.each((d) => {
57356
+ d._topIndex = i;
57357
+ });
57358
+ });
57359
+ const cells = [];
57360
+ for (const d of hroot.descendants()) {
57361
+ if (d.depth === 0) continue;
57362
+ if (d.depth > maxDepth) continue;
57363
+ const hasChildren = !!d.children && d.children.length > 0;
57364
+ const isCollapsed = hasChildren && d.depth >= maxDepth;
57365
+ const isContainer = hasChildren && !isCollapsed;
57366
+ const path = [];
57367
+ let p = d;
57368
+ while (p && p.depth > 0) {
57369
+ path.unshift(p.data.label);
57370
+ p = p.parent;
57371
+ }
57372
+ const heatVal = datumHeat(d);
57373
+ cells.push({
57374
+ node: d.data.ref ?? null,
57375
+ label: d.data.label,
57376
+ x0: d.x0,
57377
+ y0: d.y0,
57378
+ x1: d.x1,
57379
+ y1: d.y1,
57380
+ depth: d.depth,
57381
+ value: d.value ?? 0,
57382
+ isContainer,
57383
+ isCollapsed,
57384
+ topIndex: d._topIndex ?? 0,
57385
+ pctOfRoot: total > 0 ? (d.value ?? 0) / total : 0,
57386
+ pctOfParent: d.parent && (d.parent.value ?? 0) > 0 ? (d.value ?? 0) / (d.parent.value ?? 1) : 1,
57387
+ ...heatVal !== void 0 && { heat: heatVal },
57388
+ path,
57389
+ ...d.data.lineNumber !== void 0 && { lineNumber: d.data.lineNumber }
57390
+ });
57391
+ }
57392
+ return { cells, total };
57393
+ }
57394
+ var init_layout16 = __esm({
57395
+ "src/treemap/layout.ts"() {
57396
+ "use strict";
57397
+ }
57398
+ });
57399
+
57400
+ // src/treemap/renderer.ts
56869
57401
  var renderer_exports19 = {};
56870
57402
  __export(renderer_exports19, {
57403
+ compactNumber: () => compactNumber2,
57404
+ renderTreemap: () => renderTreemap,
57405
+ renderTreemapForExport: () => renderTreemapForExport
57406
+ });
57407
+ import * as d3Selection26 from "d3-selection";
57408
+ import { scaleLinear as scaleLinear6 } from "d3-scale";
57409
+ function renderTreemapForExport(container, parsed, palette, isDark, exportDims, options) {
57410
+ renderTreemap(container, parsed, palette, isDark, exportDims, {
57411
+ exportMode: true,
57412
+ ...options
57413
+ });
57414
+ }
57415
+ function renderTreemap(container, parsed, palette, isDark, exportDims, options = {}) {
57416
+ if (parsed.error || parsed.roots.length === 0) return;
57417
+ void isDark;
57418
+ d3Selection26.select(container).selectAll(":not([data-d3-tooltip])").remove();
57419
+ const width = exportDims?.width ?? container.clientWidth;
57420
+ const height = exportDims?.height ?? container.clientHeight;
57421
+ if (width <= 0 || height <= 0) return;
57422
+ const mode = resolveColorMode(parsed, options.colorMode);
57423
+ const opts = parsed.options;
57424
+ const exportMode = options.exportMode ?? false;
57425
+ const seriesColorsTop = getSeriesColors(palette);
57426
+ const showTitle = !!parsed.title;
57427
+ const titleH = showTitle ? TITLE_BAND : 0;
57428
+ const heat = buildHeatScale(parsed, palette);
57429
+ const legend = !opts.noLegend ? buildLegend(mode, parsed, heat, seriesColorsTop, options.colorOffset ?? 0) : null;
57430
+ const legendReserve = legend ? getMaxLegendReservedHeight(
57431
+ { groups: legend.groups, position: LEGEND_POSITION, mode: "preview" },
57432
+ width
57433
+ ) + LEGEND_GROUP_GAP : 0;
57434
+ const headerH = opts.noHeaders ? 0 : HEADER_H;
57435
+ const areaX = PADDING3;
57436
+ const areaY = titleH + legendReserve + PADDING3;
57437
+ const areaW = Math.max(1, width - PADDING3 * 2);
57438
+ const areaH = Math.max(1, height - areaY - PADDING3);
57439
+ const layout = layoutTreemap(parsed.roots, {
57440
+ width: areaW,
57441
+ height: areaH,
57442
+ headerH,
57443
+ ...options.maxDepth !== void 0 && { maxDepth: options.maxDepth }
57444
+ });
57445
+ 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);
57446
+ svg.append("style").text(
57447
+ ".dgmo-treemap-focus{opacity:.3;transition:opacity .12s}.dgmo-treemap-cell:hover .dgmo-treemap-focus{opacity:.7}"
57448
+ );
57449
+ svg.append("rect").attr("width", width).attr("height", height).attr("fill", palette.bg);
57450
+ if (showTitle) {
57451
+ 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);
57452
+ if (parsed.titleLineNumber !== null) {
57453
+ title.attr("data-line-number", parsed.titleLineNumber);
57454
+ }
57455
+ }
57456
+ const root = svg.append("g").attr("class", "dgmo-treemap-cells").attr("transform", `translate(${areaX},${areaY})`);
57457
+ const seriesColors2 = seriesColorsTop;
57458
+ const colorOffset = options.colorOffset ?? 0;
57459
+ const activeGroup = parsed.tagGroups.length > 0 ? parsed.tagGroups[0].name : null;
57460
+ const rootIndexByLabel = new Map(parsed.roots.map((r, i) => [r.label, i]));
57461
+ const colorOf = (cell) => {
57462
+ if (mode === "heat") {
57463
+ return cell.heat !== void 0 && heat ? heat.scale(cell.heat) : MUTED_FILL;
57464
+ }
57465
+ if (mode === "tag") {
57466
+ if (!cell.node) return MUTED_FILL;
57467
+ return resolveTagColor(cell.node.metadata, parsed.tagGroups, activeGroup) ?? MUTED_FILL;
57468
+ }
57469
+ const topLabel = cell.path[0] ?? cell.label;
57470
+ const idx = (rootIndexByLabel.get(topLabel) ?? cell.topIndex) + colorOffset;
57471
+ const hue = seriesColors2[idx % seriesColors2.length];
57472
+ if (cell.depth <= 1) return hue;
57473
+ const keepPct = Math.max(55, 100 - (cell.depth - 1) * 18);
57474
+ return mix(hue, palette.bg, keepPct);
57475
+ };
57476
+ for (const cell of layout.cells) {
57477
+ const w = Math.max(0, cell.x1 - cell.x0);
57478
+ const h = Math.max(0, cell.y1 - cell.y0);
57479
+ if (w <= 0 || h <= 0) continue;
57480
+ const baseColor = colorOf(cell);
57481
+ const fill2 = cell.isContainer ? baseColor : mix(baseColor, palette.bg, LEAF_MUTE_PCT);
57482
+ const drillable = cell.isContainer || cell.isCollapsed;
57483
+ const g = root.append("g").attr("class", "dgmo-treemap-cell").attr("transform", `translate(${cell.x0},${cell.y0})`).attr("data-node-path", cell.path.join(" / "));
57484
+ if (cell.lineNumber !== void 0) {
57485
+ g.attr("data-line-number", cell.lineNumber);
57486
+ }
57487
+ if (cell.heat !== void 0) g.attr("data-heat", cell.heat);
57488
+ if (cell.node && activeGroup) {
57489
+ const key = tagAttrKey(activeGroup);
57490
+ const tagVal = cell.node.metadata[key];
57491
+ if (tagVal) g.attr(`data-tag-${key}`, tagVal);
57492
+ }
57493
+ const rect = g.append("rect").attr(
57494
+ "class",
57495
+ cell.isContainer ? "dgmo-treemap-rect branch" : "dgmo-treemap-rect"
57496
+ ).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);
57497
+ if (drillable && options.onClickItem && cell.lineNumber !== void 0) {
57498
+ const ln = cell.lineNumber;
57499
+ rect.style("cursor", "pointer").on("click", () => options.onClickItem(ln));
57500
+ }
57501
+ const ink = contrastText(
57502
+ fill2,
57503
+ palette.textOnFillLight,
57504
+ palette.textOnFillDark
57505
+ );
57506
+ if (cell.isContainer && headerH > 0 && w > 34 && h > headerH) {
57507
+ const valParts = [];
57508
+ if (!opts.noValues) valParts.push(compactNumber2(cell.value));
57509
+ if (!opts.noPercent) valParts.push(formatPct(cell.pctOfRoot));
57510
+ const valStr = valParts.join(" \xB7 ");
57511
+ const ICON_RESERVE = drillable ? 16 : 4;
57512
+ const showVal = valStr.length > 0 && w > 110;
57513
+ const valW = showVal ? measureText(valStr, 10.5) : 0;
57514
+ const labelMax = w - 8 - ICON_RESERVE - (showVal ? valW + 10 : 0);
57515
+ 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));
57516
+ if (showVal) {
57517
+ 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);
57518
+ }
57519
+ }
57520
+ const PAD = Math.max(4, Math.min(14, Math.floor(Math.min(w, h) / 5)));
57521
+ const MIN_FS = 7;
57522
+ if (!cell.isContainer && w >= 2 * PAD + 8 && h >= 2 * PAD + 8) {
57523
+ const maxW = w - 2 * PAD;
57524
+ let fs = clamp3(Math.round(Math.min(w / 3.6, h / 3.4)), MIN_FS, 72);
57525
+ const nameW = measureText(cell.label, fs) * 1.06;
57526
+ if (nameW > maxW) fs = Math.max(MIN_FS, Math.floor(fs * maxW / nameW));
57527
+ const tg = clamp3((fs - MIN_FS) / (72 - MIN_FS), 0, 1);
57528
+ const nameOpacity = 0.95 - tg * 0.5;
57529
+ const vfs = clamp3(Math.round(fs * 0.42), 11, 28);
57530
+ const valOpacity = Math.max(0.45, nameOpacity - 0.1);
57531
+ let y = PAD + Math.round(fs * 0.78);
57532
+ 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));
57533
+ const valParts = [
57534
+ opts.noValues ? "" : compactNumber2(cell.value),
57535
+ opts.noPercent ? "" : formatPct(cell.pctOfRoot)
57536
+ ].filter(Boolean);
57537
+ const combined = valParts.join(" \xB7 ");
57538
+ const nameBaseY = y;
57539
+ const addLineAt = (text, yy, size, opacity) => {
57540
+ 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);
57541
+ };
57542
+ if (combined) {
57543
+ const fitsW = measureText(combined, vfs) <= maxW;
57544
+ const roomBelow = h - PAD > y + vfs + 6;
57545
+ if (fitsW && roomBelow) {
57546
+ addLineAt(combined, y + vfs + 6, vfs, valOpacity);
57547
+ } else if (fitsW) {
57548
+ const ivfs = clamp3(Math.round(fs * 0.5), 11, Math.max(11, vfs));
57549
+ const rendered = clipLabel(cell.label, maxW, fs);
57550
+ const nW = measureText(rendered, fs) * 1.12;
57551
+ const gap = Math.max(12, Math.round(fs * 0.25));
57552
+ if (PAD + nW + gap + measureText(combined, ivfs) <= w - PAD) {
57553
+ 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);
57554
+ }
57555
+ } else if (valParts.length === 2) {
57556
+ if (h - PAD > y + vfs + 6) {
57557
+ y += vfs + 6;
57558
+ addLineAt(valParts[0], y, vfs, valOpacity);
57559
+ }
57560
+ const pfs = Math.max(10, Math.round(vfs * 0.9));
57561
+ if (h - PAD > y + pfs + 4) {
57562
+ y += pfs + 4;
57563
+ addLineAt(valParts[1], y, pfs, valOpacity);
57564
+ }
57565
+ } else if (h - PAD > y + vfs + 6) {
57566
+ addLineAt(combined, y + vfs + 6, vfs, valOpacity);
57567
+ }
57568
+ }
57569
+ }
57570
+ if (drillable && w > 30 && h > 22) {
57571
+ drawFocusIcon(g, w, ink, 9);
57572
+ }
57573
+ }
57574
+ if (legend) {
57575
+ const legendG = svg.append("g").attr("class", "dgmo-treemap-legend").attr("transform", `translate(0, ${titleH})`);
57576
+ renderIntegratedLegend(legendG, {
57577
+ groups: legend.groups,
57578
+ palette: {
57579
+ bg: palette.bg,
57580
+ surface: palette.surface,
57581
+ text: palette.text,
57582
+ textMuted: palette.textMuted,
57583
+ primary: palette.primary
57584
+ },
57585
+ isDark,
57586
+ width,
57587
+ mode: exportMode ? "export" : "preview",
57588
+ position: LEGEND_POSITION,
57589
+ activeGroup: legend.activeGroup,
57590
+ // The color-mode switcher is the legend itself: each applicable mode is a
57591
+ // group pill; the active one is the open capsule, the rest are clickable
57592
+ // pills that switch mode. Export shows only the active group.
57593
+ showInactivePills: !exportMode,
57594
+ showEmptyGroups: !exportMode,
57595
+ ...options.onSelectMode !== void 0 && {
57596
+ callbacks: {
57597
+ onGroupToggle: (name) => {
57598
+ const m = legend.modeByName.get(name);
57599
+ if (m) options.onSelectMode(m);
57600
+ }
57601
+ }
57602
+ }
57603
+ });
57604
+ }
57605
+ }
57606
+ function buildLegend(activeMode, parsed, heat, seriesColors2, colorOffset) {
57607
+ const groups = [];
57608
+ const modeByName = /* @__PURE__ */ new Map();
57609
+ let activeGroup = null;
57610
+ if (parsed.tagGroups.length > 0) {
57611
+ const tg = parsed.tagGroups[0];
57612
+ const used = /* @__PURE__ */ new Set();
57613
+ const collect = (nodes) => {
57614
+ for (const n of nodes) {
57615
+ const v = n.metadata[tagAttrKey(tg.name)];
57616
+ if (v) used.add(v.toLowerCase());
57617
+ collect(n.children);
57618
+ }
57619
+ };
57620
+ collect(parsed.roots);
57621
+ groups.push({
57622
+ name: tg.name,
57623
+ entries: tg.entries.filter((e) => used.has(e.value.toLowerCase())).map((e) => ({ value: e.value, color: e.color }))
57624
+ });
57625
+ modeByName.set(tg.name, "tag");
57626
+ if (activeMode === "tag") activeGroup = tg.name;
57627
+ }
57628
+ if (heat) {
57629
+ const name = parsed.options.heatLabel ?? "Value";
57630
+ groups.push({
57631
+ name,
57632
+ entries: [],
57633
+ gradient: {
57634
+ min: heat.min,
57635
+ max: heat.max,
57636
+ low: heat.stops[0],
57637
+ high: heat.stops[heat.stops.length - 1]
57638
+ }
57639
+ });
57640
+ modeByName.set(name, "heat");
57641
+ if (activeMode === "heat") activeGroup = name;
57642
+ }
57643
+ groups.push({
57644
+ name: "Branch",
57645
+ entries: parsed.roots.map((r, i) => ({
57646
+ value: r.label,
57647
+ color: seriesColors2[(i + colorOffset) % seriesColors2.length]
57648
+ }))
57649
+ });
57650
+ modeByName.set("Branch", "branch");
57651
+ if (activeMode === "branch" || activeGroup === null) activeGroup = "Branch";
57652
+ return { groups, activeGroup, modeByName };
57653
+ }
57654
+ function buildHeatScale(parsed, palette) {
57655
+ if (!parsed.hasHeat) return null;
57656
+ const values = [];
57657
+ const collect = (nodes) => {
57658
+ for (const n of nodes) {
57659
+ if (typeof n.heat === "number") values.push(n.heat);
57660
+ collect(n.children);
57661
+ }
57662
+ };
57663
+ collect(parsed.roots);
57664
+ if (values.length === 0) return null;
57665
+ const min = Math.min(...values);
57666
+ const max = Math.max(...values);
57667
+ const signed = min < 0 && max > 0;
57668
+ const neutral = palette.surface;
57669
+ const explicit = parsed.options.heatColors.map((c) => resolveColor(c, palette) ?? c).filter((c) => !!c);
57670
+ let stops;
57671
+ let domain;
57672
+ if (explicit.length >= 2) {
57673
+ stops = [explicit[0], neutral, explicit[1]];
57674
+ const mid = signed ? 0 : (min + max) / 2;
57675
+ domain = [min, mid, max];
57676
+ } else if (explicit.length === 1) {
57677
+ stops = [neutral, explicit[0]];
57678
+ domain = [min, max];
57679
+ } else if (signed) {
57680
+ stops = [palette.colors.red, neutral, palette.colors.green];
57681
+ domain = [min, 0, max];
57682
+ } else {
57683
+ stops = [neutral, palette.primary];
57684
+ domain = [min, max];
57685
+ }
57686
+ if (domain[0] === domain[domain.length - 1]) {
57687
+ const last = stops[stops.length - 1];
57688
+ return { scale: () => last, min, max, stops, signed };
57689
+ }
57690
+ const linear = scaleLinear6().domain(domain).range(stops).clamp(true);
57691
+ return { scale: (v) => toHex(linear(v)), min, max, stops, signed };
57692
+ }
57693
+ function toHex(c) {
57694
+ if (c.startsWith("#")) return c;
57695
+ const m = c.match(/rgba?\(([^)]+)\)/);
57696
+ if (!m) return c;
57697
+ const parts = m[1].split(",").map((s) => Math.round(parseFloat(s)));
57698
+ const h = (n) => Math.max(0, Math.min(255, n || 0)).toString(16).padStart(2, "0");
57699
+ return `#${h(parts[0] ?? 0)}${h(parts[1] ?? 0)}${h(parts[2] ?? 0)}`;
57700
+ }
57701
+ function resolveColorMode(parsed, override) {
57702
+ let mode = override ?? parsed.defaultColorMode;
57703
+ if (mode === "tag" && parsed.tagGroups.length === 0) {
57704
+ mode = parsed.hasHeat ? "heat" : "branch";
57705
+ }
57706
+ if (mode === "heat" && !parsed.hasHeat) mode = "branch";
57707
+ return mode;
57708
+ }
57709
+ function drawFocusIcon(g, w, ink, cy) {
57710
+ const r = 4.5;
57711
+ const cx = w - r - 5;
57712
+ const fi = g.append("g").attr("class", "dgmo-treemap-focus").attr("data-export-ignore", "true");
57713
+ fi.append("rect").attr("x", cx - 9).attr("y", cy - 9).attr("width", 18).attr("height", 18).attr("fill", "transparent");
57714
+ fi.append("circle").attr("cx", cx).attr("cy", cy).attr("r", r).attr("fill", "none").attr("stroke", ink).attr("stroke-width", 1.25);
57715
+ fi.append("circle").attr("cx", cx).attr("cy", cy).attr("r", 1.4).attr("fill", ink);
57716
+ }
57717
+ function clamp3(x, lo, hi) {
57718
+ return Math.max(lo, Math.min(hi, x));
57719
+ }
57720
+ function clipLabel(s, maxWidth, fs) {
57721
+ if (measureText(s, fs) <= maxWidth) return s;
57722
+ let lo = 0;
57723
+ let hi = s.length;
57724
+ while (lo < hi) {
57725
+ const mid = Math.ceil((lo + hi) / 2);
57726
+ if (measureText(s.slice(0, mid) + "\u2026", fs) <= maxWidth) lo = mid;
57727
+ else hi = mid - 1;
57728
+ }
57729
+ return lo <= 0 ? "" : s.slice(0, lo) + "\u2026";
57730
+ }
57731
+ function compactNumber2(v) {
57732
+ const abs = Math.abs(v);
57733
+ if (abs >= 1e9) return strip(v / 1e9) + "B";
57734
+ if (abs >= 1e6) return strip(v / 1e6) + "M";
57735
+ if (abs >= 1e3) return strip(v / 1e3) + "k";
57736
+ return strip(Math.round(v * 100) / 100);
57737
+ }
57738
+ function strip(n) {
57739
+ return parseFloat(
57740
+ n.toFixed(n < 10 && !Number.isInteger(n) ? 1 : 0)
57741
+ ).toString();
57742
+ }
57743
+ function formatPct(frac) {
57744
+ const pct = frac * 100;
57745
+ if (pct >= 10) return `${Math.round(pct)}%`;
57746
+ if (pct >= 1) return `${pct.toFixed(0)}%`;
57747
+ return `${pct.toFixed(1)}%`;
57748
+ }
57749
+ var PADDING3, HEADER_H, TITLE_BAND, MUTED_FILL, LEAF_MUTE_PCT, LEGEND_POSITION;
57750
+ var init_renderer19 = __esm({
57751
+ "src/treemap/renderer.ts"() {
57752
+ "use strict";
57753
+ init_fonts();
57754
+ init_colors();
57755
+ init_color_utils();
57756
+ init_tag_groups();
57757
+ init_text_measure();
57758
+ init_legend_integration();
57759
+ init_legend_layout();
57760
+ init_legend_constants();
57761
+ init_title_constants();
57762
+ init_layout16();
57763
+ PADDING3 = 12;
57764
+ HEADER_H = 18;
57765
+ TITLE_BAND = 36;
57766
+ MUTED_FILL = "#cbd5e1";
57767
+ LEAF_MUTE_PCT = 50;
57768
+ LEGEND_POSITION = {
57769
+ placement: "top-center",
57770
+ titleRelation: "below-title"
57771
+ };
57772
+ }
57773
+ });
57774
+
57775
+ // src/raci/renderer.ts
57776
+ var renderer_exports20 = {};
57777
+ __export(renderer_exports20, {
56871
57778
  MARKER_LABELS: () => MARKER_LABELS,
56872
57779
  renderRaci: () => renderRaci,
56873
57780
  renderRaciForExport: () => renderRaciForExport
56874
57781
  });
56875
- import * as d3Selection26 from "d3-selection";
57782
+ import * as d3Selection27 from "d3-selection";
56876
57783
  function groupDiagnosticsByTask(parsed) {
56877
57784
  const map = /* @__PURE__ */ new Map();
56878
57785
  if (parsed.diagnostics.length === 0) return map;
@@ -56944,7 +57851,7 @@ function renderRaci(container, parsed, palette, isDark, handlers, exportDims) {
56944
57851
  const hideLegend = opts.hideLegend ?? false;
56945
57852
  const collapsedPhases = opts.collapsedPhases ?? /* @__PURE__ */ new Set();
56946
57853
  const hideTitle = (opts.hideTitle ?? false) || parsed.options["no-title"] === "on";
56947
- d3Selection26.select(container).selectAll(":not([data-d3-tooltip])").remove();
57854
+ d3Selection27.select(container).selectAll(":not([data-d3-tooltip])").remove();
56948
57855
  const width = exportDims?.width ?? container.clientWidth;
56949
57856
  const height = exportDims?.height ?? container.clientHeight;
56950
57857
  if (width <= 0 || height <= 0) return;
@@ -57051,7 +57958,7 @@ function renderRaci(container, parsed, palette, isDark, handlers, exportDims) {
57051
57958
  const colBottomY = cursorY + sColumnBottomPad;
57052
57959
  const totalHeight = colBottomY + sVMargin;
57053
57960
  const svgHeight = exportDims ? totalHeight : Math.max(height, totalHeight);
57054
- 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");
57961
+ 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");
57055
57962
  if (ctx.isBelowFloor) {
57056
57963
  svg.attr("width", "100%");
57057
57964
  }
@@ -57532,13 +58439,13 @@ function parseQuotedSegments(message) {
57532
58439
  return out;
57533
58440
  }
57534
58441
  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;
57535
- var init_renderer19 = __esm({
58442
+ var init_renderer20 = __esm({
57536
58443
  "src/raci/renderer.ts"() {
57537
58444
  "use strict";
57538
58445
  init_fonts();
57539
58446
  init_title_constants();
57540
58447
  init_color_utils();
57541
- init_parser26();
58448
+ init_parser27();
57542
58449
  init_variants();
57543
58450
  init_scaling();
57544
58451
  init_text_measure();
@@ -57795,8 +58702,8 @@ var init_tag_resolution = __esm({
57795
58702
  });
57796
58703
 
57797
58704
  // src/sequence/renderer.ts
57798
- var renderer_exports20 = {};
57799
- __export(renderer_exports20, {
58705
+ var renderer_exports21 = {};
58706
+ __export(renderer_exports21, {
57800
58707
  applyGroupOrdering: () => applyGroupOrdering,
57801
58708
  applyPositionOverrides: () => applyPositionOverrides,
57802
58709
  buildNoteMessageMap: () => buildNoteMessageMap,
@@ -57807,7 +58714,7 @@ __export(renderer_exports20, {
57807
58714
  renderSequenceDiagram: () => renderSequenceDiagram,
57808
58715
  truncateBareUrl: () => truncateBareUrl
57809
58716
  });
57810
- import * as d3Selection27 from "d3-selection";
58717
+ import * as d3Selection28 from "d3-selection";
57811
58718
  function wrapTextLines(text, maxWidth, fontSize) {
57812
58719
  const rawLines = text.split("\n").map((l) => l.startsWith("- ") ? "\u2022 " + l.slice(2) : l);
57813
58720
  return wrapDescriptionLines(
@@ -58137,7 +59044,7 @@ function applyGroupOrdering(participants, groups, messages = []) {
58137
59044
  return result;
58138
59045
  }
58139
59046
  function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateToLine, options) {
58140
- d3Selection27.select(container).selectAll("*").remove();
59047
+ d3Selection28.select(container).selectAll("*").remove();
58141
59048
  const { title, options: parsedOptions } = parsed;
58142
59049
  const solid = parsedOptions["solid-fill"] === "on";
58143
59050
  const effectiveCollapsedGroups = /* @__PURE__ */ new Set();
@@ -58788,7 +59695,7 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
58788
59695
  offsetX = leftMargin + Math.max(0, (svgWidth - totalWidth) / 2);
58789
59696
  buildParticipantX();
58790
59697
  }
58791
- 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);
59698
+ 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);
58792
59699
  const defs = svg.append("defs");
58793
59700
  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(
58794
59701
  "points",
@@ -59401,7 +60308,7 @@ function renderParticipant(svg, participant, cx, cy, palette, isDark, color, tag
59401
60308
  }
59402
60309
  }
59403
60310
  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;
59404
- var init_renderer20 = __esm({
60311
+ var init_renderer21 = __esm({
59405
60312
  "src/sequence/renderer.ts"() {
59406
60313
  "use strict";
59407
60314
  init_tag_groups();
@@ -63345,6 +64252,7 @@ var DIAGRAM_EXPORT_HANDLERS = {
63345
64252
  map: exportMap,
63346
64253
  pyramid: exportPyramid,
63347
64254
  ring: exportRing,
64255
+ treemap: exportTreemap,
63348
64256
  raci: exportRaci,
63349
64257
  rasci: exportRaci,
63350
64258
  daci: exportRaci,
@@ -63402,10 +64310,10 @@ async function exportOrg(ctx) {
63402
64310
  false
63403
64311
  // expandAllLegend off — collapsed-by-default per §1.3
63404
64312
  );
63405
- const PADDING3 = 20;
64313
+ const PADDING4 = 20;
63406
64314
  const titleOffset = effectiveParsed.title ? 30 : 0;
63407
- const exportWidth = orgLayout.width + PADDING3 * 2;
63408
- const exportHeight = orgLayout.height + PADDING3 * 2 + titleOffset;
64315
+ const exportWidth = orgLayout.width + PADDING4 * 2;
64316
+ const exportHeight = orgLayout.height + PADDING4 * 2 + titleOffset;
63409
64317
  const container = createExportContainer(exportWidth, exportHeight);
63410
64318
  renderOrg2(
63411
64319
  container,
@@ -63447,10 +64355,10 @@ async function exportSitemap(ctx) {
63447
64355
  hiddenAttributes,
63448
64356
  true
63449
64357
  );
63450
- const PADDING3 = 20;
64358
+ const PADDING4 = 20;
63451
64359
  const titleOffset = effectiveParsed.title ? 30 : 0;
63452
- const exportWidth = sitemapLayout.width + PADDING3 * 2;
63453
- const exportHeight = sitemapLayout.height + PADDING3 * 2 + titleOffset;
64360
+ const exportWidth = sitemapLayout.width + PADDING4 * 2;
64361
+ const exportHeight = sitemapLayout.height + PADDING4 * 2 + titleOffset;
63454
64362
  const container = createExportContainer(exportWidth, exportHeight);
63455
64363
  renderSitemap2(
63456
64364
  container,
@@ -63506,10 +64414,10 @@ async function exportClass(ctx) {
63506
64414
  const classParsed = parseClassDiagram2(content, effectivePalette);
63507
64415
  if (classParsed.error || classParsed.classes.length === 0) return "";
63508
64416
  const classLayout = layoutClassDiagram2(classParsed);
63509
- const PADDING3 = 20;
64417
+ const PADDING4 = 20;
63510
64418
  const titleOffset = classParsed.title ? 40 : 0;
63511
- const exportWidth = classLayout.width + PADDING3 * 2;
63512
- const exportHeight = classLayout.height + PADDING3 * 2 + titleOffset;
64419
+ const exportWidth = classLayout.width + PADDING4 * 2;
64420
+ const exportHeight = classLayout.height + PADDING4 * 2 + titleOffset;
63513
64421
  const container = createExportContainer(exportWidth, exportHeight);
63514
64422
  renderClassDiagram2(
63515
64423
  container,
@@ -63533,10 +64441,10 @@ async function exportEr(ctx) {
63533
64441
  const erParsed = parseERDiagram2(content, effectivePalette);
63534
64442
  if (erParsed.error || erParsed.tables.length === 0) return "";
63535
64443
  const erLayout = layoutERDiagram2(erParsed);
63536
- const PADDING3 = 20;
64444
+ const PADDING4 = 20;
63537
64445
  const titleOffset = erParsed.title ? 40 : 0;
63538
- const exportWidth = erLayout.width + PADDING3 * 2;
63539
- const exportHeight = erLayout.height + PADDING3 * 2 + titleOffset;
64446
+ const exportWidth = erLayout.width + PADDING4 * 2;
64447
+ const exportHeight = erLayout.height + PADDING4 * 2 + titleOffset;
63540
64448
  const container = createExportContainer(exportWidth, exportHeight);
63541
64449
  renderERDiagram2(
63542
64450
  container,
@@ -63572,10 +64480,10 @@ async function exportBoxesAndLines(ctx) {
63572
64480
  const { renderBoxesAndLinesForExport: renderBoxesAndLinesForExport2 } = await Promise.resolve().then(() => (init_renderer6(), renderer_exports6));
63573
64481
  const { layoutBoxesAndLines: layoutBoxesAndLines2 } = await Promise.resolve().then(() => (init_layout5(), layout_exports5));
63574
64482
  const blLayout = await layoutBoxesAndLines2(blParsed);
63575
- const PADDING3 = 20;
64483
+ const PADDING4 = 20;
63576
64484
  const titleOffset = blParsed.title ? 40 : 0;
63577
- const exportWidth = blLayout.width + PADDING3 * 2;
63578
- const exportHeight = blLayout.height + PADDING3 * 2 + titleOffset;
64485
+ const exportWidth = blLayout.width + PADDING4 * 2;
64486
+ const exportHeight = blLayout.height + PADDING4 * 2 + titleOffset;
63579
64487
  const container = createExportContainer(exportWidth, exportHeight);
63580
64488
  const blActiveTagGroup = ctxTagOverride(ctx);
63581
64489
  renderBoxesAndLinesForExport2(
@@ -63622,10 +64530,10 @@ async function exportMindmap(ctx) {
63622
64530
  activeTagGroup,
63623
64531
  hideDescriptions
63624
64532
  });
63625
- const PADDING3 = 20;
64533
+ const PADDING4 = 20;
63626
64534
  const titleOffset = effectiveParsed.title ? 30 : 0;
63627
- const exportWidth = mmLayout.width + PADDING3 * 2;
63628
- const exportHeight = mmLayout.height + PADDING3 * 2 + titleOffset;
64535
+ const exportWidth = mmLayout.width + PADDING4 * 2;
64536
+ const exportHeight = mmLayout.height + PADDING4 * 2 + titleOffset;
63629
64537
  const container = createExportContainer(exportWidth, exportHeight);
63630
64538
  const colorByDepth = viewState?.cbd === true;
63631
64539
  renderMindmap2(
@@ -63686,10 +64594,10 @@ async function exportC4(ctx) {
63686
64594
  const c4Container = ctx.options?.c4Container ?? viewState?.c4c;
63687
64595
  const c4Layout = c4Level === "deployment" ? layoutC4Deployment2(c4Parsed) : c4Level === "components" && c4System && c4Container ? layoutC4Components2(c4Parsed, c4System, c4Container) : c4Level === "containers" && c4System ? layoutC4Containers2(c4Parsed, c4System) : layoutC4Context2(c4Parsed);
63688
64596
  if (c4Layout.nodes.length === 0) return "";
63689
- const PADDING3 = 20;
64597
+ const PADDING4 = 20;
63690
64598
  const titleOffset = c4Parsed.title ? 40 : 0;
63691
- const exportWidth = c4Layout.width + PADDING3 * 2;
63692
- const exportHeight = c4Layout.height + PADDING3 * 2 + titleOffset;
64599
+ const exportWidth = c4Layout.width + PADDING4 * 2;
64600
+ const exportHeight = c4Layout.height + PADDING4 * 2 + titleOffset;
63693
64601
  const container = createExportContainer(exportWidth, exportHeight);
63694
64602
  const renderFn = c4Level === "deployment" || c4Level === "components" && c4System && c4Container || c4Level === "containers" && c4System ? renderC4Containers2 : renderC4Context2;
63695
64603
  renderFn(
@@ -64005,30 +64913,44 @@ async function exportRing(ctx) {
64005
64913
  const ringParsed = parseRing2(content);
64006
64914
  if (ringParsed.error || ringParsed.layers.length === 0) return "";
64007
64915
  const container = createExportContainer(EXPORT_WIDTH, EXPORT_HEIGHT);
64008
- renderRingForExport2(
64916
+ renderRingForExport2(container, ringParsed, effectivePalette, ctx.isDark, {
64917
+ width: EXPORT_WIDTH,
64918
+ height: EXPORT_HEIGHT
64919
+ });
64920
+ return finalizeSvgExport(container, theme, effectivePalette);
64921
+ }
64922
+ async function exportTreemap(ctx) {
64923
+ const { content, theme, palette } = ctx;
64924
+ const { parseTreemap: parseTreemap2 } = await Promise.resolve().then(() => (init_parser26(), parser_exports20));
64925
+ const { renderTreemapForExport: renderTreemapForExport2 } = await Promise.resolve().then(() => (init_renderer19(), renderer_exports19));
64926
+ const effectivePalette = await resolveExportPalette(theme, palette);
64927
+ const treemapParsed = parseTreemap2(content, effectivePalette);
64928
+ if (treemapParsed.error || treemapParsed.roots.length === 0) return "";
64929
+ const container = createExportContainer(EXPORT_WIDTH, EXPORT_HEIGHT);
64930
+ renderTreemapForExport2(
64009
64931
  container,
64010
- ringParsed,
64932
+ treemapParsed,
64011
64933
  effectivePalette,
64012
64934
  ctx.isDark,
64013
- { width: EXPORT_WIDTH, height: EXPORT_HEIGHT }
64935
+ {
64936
+ width: EXPORT_WIDTH,
64937
+ height: EXPORT_HEIGHT
64938
+ }
64014
64939
  );
64015
64940
  return finalizeSvgExport(container, theme, effectivePalette);
64016
64941
  }
64017
64942
  async function exportRaci(ctx) {
64018
64943
  const { content, theme, palette } = ctx;
64019
- const { parseRaci: parseRaci2 } = await Promise.resolve().then(() => (init_parser26(), parser_exports20));
64020
- const { renderRaciForExport: renderRaciForExport2 } = await Promise.resolve().then(() => (init_renderer19(), renderer_exports19));
64944
+ const { parseRaci: parseRaci2 } = await Promise.resolve().then(() => (init_parser27(), parser_exports21));
64945
+ const { renderRaciForExport: renderRaciForExport2 } = await Promise.resolve().then(() => (init_renderer20(), renderer_exports20));
64021
64946
  const effectivePalette = await resolveExportPalette(theme, palette);
64022
64947
  const raciParsed = parseRaci2(content, effectivePalette);
64023
64948
  if (raciParsed.error) return "";
64024
64949
  const container = createExportContainer(EXPORT_WIDTH, EXPORT_HEIGHT);
64025
- renderRaciForExport2(
64026
- container,
64027
- raciParsed,
64028
- effectivePalette,
64029
- ctx.isDark,
64030
- { width: EXPORT_WIDTH, height: EXPORT_HEIGHT }
64031
- );
64950
+ renderRaciForExport2(container, raciParsed, effectivePalette, ctx.isDark, {
64951
+ width: EXPORT_WIDTH,
64952
+ height: EXPORT_HEIGHT
64953
+ });
64032
64954
  return finalizeSvgExport(container, theme, effectivePalette);
64033
64955
  }
64034
64956
  function beginVizExport() {
@@ -64117,14 +65039,7 @@ async function exportVenn(ctx) {
64117
65039
  if (parsed.error || parsed.vennSets.length < 2) return "";
64118
65040
  const effectivePalette = await resolveExportPalette(theme, palette);
64119
65041
  const { container, dims } = beginVizExport();
64120
- renderVenn(
64121
- container,
64122
- parsed,
64123
- effectivePalette,
64124
- ctx.isDark,
64125
- void 0,
64126
- dims
64127
- );
65042
+ renderVenn(container, parsed, effectivePalette, ctx.isDark, void 0, dims);
64128
65043
  return finalizeSvgExport(container, theme, effectivePalette);
64129
65044
  }
64130
65045
  async function exportQuadrant(ctx) {
@@ -64158,7 +65073,7 @@ async function exportVisualization(ctx) {
64158
65073
  const isDark = ctx.isDark;
64159
65074
  const container = createExportContainer(EXPORT_WIDTH, EXPORT_HEIGHT);
64160
65075
  const { parseSequenceDgmo: parseSequenceDgmo2 } = await Promise.resolve().then(() => (init_parser7(), parser_exports));
64161
- const { renderSequenceDiagram: renderSequenceDiagram2 } = await Promise.resolve().then(() => (init_renderer20(), renderer_exports20));
65076
+ const { renderSequenceDiagram: renderSequenceDiagram2 } = await Promise.resolve().then(() => (init_renderer21(), renderer_exports21));
64162
65077
  const seqParsed = parseSequenceDgmo2(content, effectivePalette);
64163
65078
  if (seqParsed.error || seqParsed.participants.length === 0) return "";
64164
65079
  const collapsedSections = viewState?.cs ? new Set(viewState.cs) : void 0;
@@ -64789,6 +65704,9 @@ init_parser24();
64789
65704
  init_renderer17();
64790
65705
  init_parser25();
64791
65706
  init_renderer18();
65707
+ init_parser26();
65708
+ init_renderer19();
65709
+ init_layout16();
64792
65710
  init_parser17();
64793
65711
  init_resolver2();
64794
65712
  init_load_data();
@@ -65100,12 +66018,12 @@ function completeMapRegions(query, regions, opts) {
65100
66018
  }
65101
66019
 
65102
66020
  // src/raci/index.ts
65103
- init_parser26();
65104
- init_renderer19();
66021
+ init_parser27();
66022
+ init_renderer20();
65105
66023
 
65106
66024
  // src/raci/mutations.ts
65107
66025
  init_parsing();
65108
- init_parser26();
66026
+ init_parser27();
65109
66027
  function cellReplace(content, parsed, taskId, roleId, marker) {
65110
66028
  const task = findTask(parsed, taskId);
65111
66029
  if (!task) return null;
@@ -65618,7 +66536,7 @@ init_legend_svg();
65618
66536
  init_legend_constants();
65619
66537
  init_legend_d3();
65620
66538
  init_legend_layout();
65621
- init_renderer20();
66539
+ init_renderer21();
65622
66540
  init_collapse4();
65623
66541
  init_colors();
65624
66542
  init_palettes();
@@ -65850,6 +66768,7 @@ export {
65850
66768
  layoutOrg,
65851
66769
  layoutPert,
65852
66770
  layoutSitemap,
66771
+ layoutTreemap,
65853
66772
  layoutWireframe,
65854
66773
  loadMapData,
65855
66774
  looksLikeClassDiagram,
@@ -65907,6 +66826,7 @@ export {
65907
66826
  parseState,
65908
66827
  parseTechRadar,
65909
66828
  parseTimelineDate,
66829
+ parseTreemap,
65910
66830
  parseVisualization,
65911
66831
  parseWireframe,
65912
66832
  cellAppendMarker as raciCellAppendMarker,
@@ -65972,6 +66892,8 @@ export {
65972
66892
  renderTechRadar,
65973
66893
  renderTechRadarForExport,
65974
66894
  renderTimeline,
66895
+ renderTreemap,
66896
+ renderTreemapForExport,
65975
66897
  renderVenn,
65976
66898
  renderWireframe,
65977
66899
  renderWordCloud,