@diagrammo/dgmo 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1307,6 +1307,31 @@ function collectIndentedValues(lines, startIndex) {
1307
1307
  }
1308
1308
  return { values, newIndex: j - 1 };
1309
1309
  }
1310
+ function parseSeriesNames(value, lines, lineIndex, palette) {
1311
+ let rawNames;
1312
+ let series;
1313
+ let newIndex = lineIndex;
1314
+ if (value) {
1315
+ series = value;
1316
+ rawNames = value.split(",").map((s) => s.trim()).filter(Boolean);
1317
+ } else {
1318
+ const collected = collectIndentedValues(lines, lineIndex);
1319
+ newIndex = collected.newIndex;
1320
+ rawNames = collected.values;
1321
+ series = rawNames.join(", ");
1322
+ }
1323
+ const names = [];
1324
+ const nameColors = [];
1325
+ for (const raw of rawNames) {
1326
+ const extracted = extractColor(raw, palette);
1327
+ nameColors.push(extracted.color);
1328
+ names.push(extracted.label);
1329
+ }
1330
+ if (names.length === 1) {
1331
+ series = names[0];
1332
+ }
1333
+ return { series, names, nameColors, newIndex };
1334
+ }
1310
1335
  function parsePipeMetadata(segments, aliasMap = /* @__PURE__ */ new Map()) {
1311
1336
  const metadata = {};
1312
1337
  for (let j = 1; j < segments.length; j++) {
@@ -1612,13 +1637,18 @@ var init_participant_inference = __esm({
1612
1637
 
1613
1638
  // src/utils/arrows.ts
1614
1639
  function parseArrow(line7) {
1640
+ if (BIDI_SYNC_RE.test(line7) || BIDI_ASYNC_RE.test(line7)) {
1641
+ return {
1642
+ error: "Bidirectional arrows are no longer supported. Use two separate lines: 'A -msg-> B' and 'B -msg-> A'"
1643
+ };
1644
+ }
1615
1645
  const patterns = [
1616
- { re: BIDI_SYNC_LABELED_RE, async: false, bidirectional: true },
1617
- { re: BIDI_ASYNC_LABELED_RE, async: true, bidirectional: true },
1618
- { re: SYNC_LABELED_RE, async: false, bidirectional: false },
1619
- { re: ASYNC_LABELED_RE, async: true, bidirectional: false }
1646
+ { re: RETURN_SYNC_LABELED_RE, async: false, isReturn: true },
1647
+ { re: RETURN_ASYNC_LABELED_RE, async: true, isReturn: true },
1648
+ { re: SYNC_LABELED_RE, async: false, isReturn: false },
1649
+ { re: ASYNC_LABELED_RE, async: true, isReturn: false }
1620
1650
  ];
1621
- for (const { re, async: isAsync, bidirectional } of patterns) {
1651
+ for (const { re, async: isAsync, isReturn } of patterns) {
1622
1652
  const m = line7.match(re);
1623
1653
  if (!m) continue;
1624
1654
  const label = m[2].trim();
@@ -1626,29 +1656,40 @@ function parseArrow(line7) {
1626
1656
  for (const arrow of ARROW_CHARS) {
1627
1657
  if (label.includes(arrow)) {
1628
1658
  return {
1629
- error: "Arrow characters (->, ~>) are not allowed inside labels"
1659
+ error: "Arrow characters (->, ~>, <-, <~) are not allowed inside labels"
1630
1660
  };
1631
1661
  }
1632
1662
  }
1663
+ if (isReturn) {
1664
+ return {
1665
+ from: m[3],
1666
+ to: m[1],
1667
+ label,
1668
+ async: isAsync,
1669
+ isReturn: true
1670
+ };
1671
+ }
1633
1672
  return {
1634
1673
  from: m[1],
1635
1674
  to: m[3],
1636
1675
  label,
1637
1676
  async: isAsync,
1638
- bidirectional
1677
+ isReturn: false
1639
1678
  };
1640
1679
  }
1641
1680
  return null;
1642
1681
  }
1643
- var BIDI_SYNC_LABELED_RE, BIDI_ASYNC_LABELED_RE, SYNC_LABELED_RE, ASYNC_LABELED_RE, ARROW_CHARS;
1682
+ var SYNC_LABELED_RE, ASYNC_LABELED_RE, RETURN_SYNC_LABELED_RE, RETURN_ASYNC_LABELED_RE, BIDI_SYNC_RE, BIDI_ASYNC_RE, ARROW_CHARS;
1644
1683
  var init_arrows = __esm({
1645
1684
  "src/utils/arrows.ts"() {
1646
1685
  "use strict";
1647
- BIDI_SYNC_LABELED_RE = /^(\S+)\s+<-(.+)->\s+(\S+)$/;
1648
- BIDI_ASYNC_LABELED_RE = /^(\S+)\s+<~(.+)~>\s+(\S+)$/;
1649
1686
  SYNC_LABELED_RE = /^(\S+)\s+-(.+)->\s+(\S+)$/;
1650
1687
  ASYNC_LABELED_RE = /^(\S+)\s+~(.+)~>\s+(\S+)$/;
1651
- ARROW_CHARS = ["->", "~>", "<->", "<~>"];
1688
+ RETURN_SYNC_LABELED_RE = /^(\S+)\s+<-(.+)-\s+(\S+)$/;
1689
+ RETURN_ASYNC_LABELED_RE = /^(\S+)\s+<~(.+)~\s+(\S+)$/;
1690
+ BIDI_SYNC_RE = /^(\S+)\s+<-(.+)->\s+(\S+)$/;
1691
+ BIDI_ASYNC_RE = /^(\S+)\s+<~(.+)~>\s+(\S+)$/;
1692
+ ARROW_CHARS = ["->", "~>", "<-", "<~"];
1652
1693
  }
1653
1694
  });
1654
1695
 
@@ -1670,36 +1711,6 @@ function isSequenceSection(el) {
1670
1711
  function isSequenceNote(el) {
1671
1712
  return "kind" in el && el.kind === "note";
1672
1713
  }
1673
- function parseReturnLabel(rawLabel) {
1674
- if (!rawLabel) return { label: "" };
1675
- const standaloneMatch = rawLabel.match(/^<-\s*(.*)$/);
1676
- if (standaloneMatch) {
1677
- return {
1678
- label: standaloneMatch[1].trim(),
1679
- standaloneReturn: true
1680
- };
1681
- }
1682
- const arrowReturn = rawLabel.match(ARROW_RETURN_PATTERN);
1683
- if (arrowReturn) {
1684
- return { label: arrowReturn[1].trim(), returnLabel: arrowReturn[2].trim() };
1685
- }
1686
- const umlReturn = rawLabel.match(UML_RETURN_PATTERN);
1687
- if (umlReturn) {
1688
- return { label: umlReturn[1].trim(), returnLabel: umlReturn[2].trim() };
1689
- }
1690
- const lastColon = rawLabel.lastIndexOf(":");
1691
- if (lastColon > 0 && lastColon < rawLabel.length - 1) {
1692
- const afterColon = rawLabel.substring(lastColon + 1);
1693
- if (!afterColon.startsWith("//")) {
1694
- const reqPart = rawLabel.substring(0, lastColon).trim();
1695
- const resPart = afterColon.trim();
1696
- if (reqPart && resPart) {
1697
- return { label: reqPart, returnLabel: resPart };
1698
- }
1699
- }
1700
- }
1701
- return { label: rawLabel };
1702
- }
1703
1714
  function parseSequenceDgmo(content) {
1704
1715
  const result = {
1705
1716
  title: null,
@@ -1799,7 +1810,7 @@ function parseSequenceDgmo(content) {
1799
1810
  continue;
1800
1811
  }
1801
1812
  const colonIndex = trimmed.indexOf(":");
1802
- if (colonIndex > 0 && !trimmed.includes("->") && !trimmed.includes("~>")) {
1813
+ if (colonIndex > 0 && !trimmed.includes("->") && !trimmed.includes("~>") && !trimmed.includes("<-") && !trimmed.includes("<~")) {
1803
1814
  const key = trimmed.substring(0, colonIndex).trim().toLowerCase();
1804
1815
  if (key === "note" || key.startsWith("note ")) {
1805
1816
  } else {
@@ -1928,16 +1939,15 @@ function parseSequenceDgmo(content) {
1928
1939
  }
1929
1940
  if (labeledArrow) {
1930
1941
  contentStarted = true;
1931
- const { from, to, label, async: isAsync2, bidirectional } = labeledArrow;
1942
+ const { from, to, label, async: isAsync, isReturn } = labeledArrow;
1932
1943
  lastMsgFrom = from;
1933
1944
  const msg = {
1934
1945
  from,
1935
1946
  to,
1936
1947
  label,
1937
- returnLabel: void 0,
1938
1948
  lineNumber,
1939
- ...isAsync2 ? { async: true } : {},
1940
- ...bidirectional ? { bidirectional: true } : {}
1949
+ ...isAsync ? { async: true } : {},
1950
+ ...isReturn ? { standaloneReturn: true } : {}
1941
1951
  };
1942
1952
  result.messages.push(msg);
1943
1953
  currentContainer().push(msg);
@@ -1959,27 +1969,50 @@ function parseSequenceDgmo(content) {
1959
1969
  }
1960
1970
  continue;
1961
1971
  }
1962
- const bidiSyncMatch = trimmed.match(
1963
- /^(\S+)\s*<->\s*([^\s:]+)\s*(?::\s*(.+))?$/
1972
+ const colonPostfixSync = trimmed.match(
1973
+ /^(\S+)\s*->\s*([^\s:]+)\s*:\s*(.+)$/
1964
1974
  );
1965
- const bidiAsyncMatch = trimmed.match(
1966
- /^(\S+)\s*<~>\s*([^\s:]+)\s*(?::\s*(.+))?$/
1975
+ const colonPostfixAsync = trimmed.match(
1976
+ /^(\S+)\s*~>\s*([^\s:]+)\s*:\s*(.+)$/
1977
+ );
1978
+ const colonPostfix = colonPostfixSync || colonPostfixAsync;
1979
+ if (colonPostfix) {
1980
+ const a = colonPostfix[1];
1981
+ const b = colonPostfix[2];
1982
+ const msg = colonPostfix[3].trim();
1983
+ const arrowChar = colonPostfixAsync ? "~" : "-";
1984
+ const arrowEnd = colonPostfixAsync ? "~>" : "->";
1985
+ pushError(
1986
+ lineNumber,
1987
+ `Colon syntax is no longer supported. Use '${a} ${arrowChar}${msg}${arrowEnd} ${b}' instead`
1988
+ );
1989
+ continue;
1990
+ }
1991
+ const bidiPlainMatch = trimmed.match(
1992
+ /^(\S+)\s*(?:<->|<~>)\s*(\S+)/
1967
1993
  );
1968
- const bidiMatch = bidiSyncMatch || bidiAsyncMatch;
1969
- if (bidiMatch) {
1994
+ if (bidiPlainMatch) {
1995
+ pushError(
1996
+ lineNumber,
1997
+ "Bidirectional arrows are no longer supported. Use two separate lines: 'A -msg-> B' and 'B -msg-> A'"
1998
+ );
1999
+ continue;
2000
+ }
2001
+ const bareReturnSync = trimmed.match(/^(\S+)\s+<-\s+(\S+)$/);
2002
+ const bareReturnAsync = trimmed.match(/^(\S+)\s+<~\s+(\S+)$/);
2003
+ const bareReturn = bareReturnSync || bareReturnAsync;
2004
+ if (bareReturn) {
1970
2005
  contentStarted = true;
1971
- const from = bidiMatch[1];
1972
- const to = bidiMatch[2];
2006
+ const to = bareReturn[1];
2007
+ const from = bareReturn[2];
1973
2008
  lastMsgFrom = from;
1974
- const rawLabel = bidiMatch[3]?.trim() || "";
1975
- const isBidiAsync = !!bidiAsyncMatch;
1976
2009
  const msg = {
1977
2010
  from,
1978
2011
  to,
1979
- label: rawLabel,
2012
+ label: "",
1980
2013
  lineNumber,
1981
- bidirectional: true,
1982
- ...isBidiAsync ? { async: true } : {}
2014
+ standaloneReturn: true,
2015
+ ...bareReturnAsync ? { async: true } : {}
1983
2016
  };
1984
2017
  result.messages.push(msg);
1985
2018
  currentContainer().push(msg);
@@ -2001,30 +2034,20 @@ function parseSequenceDgmo(content) {
2001
2034
  }
2002
2035
  continue;
2003
2036
  }
2004
- let isAsync = false;
2005
- const asyncArrowMatch = trimmed.match(
2006
- /^(\S+)\s*~>\s*([^\s:]+)\s*(?::\s*(.+))?$/
2007
- );
2008
- const syncArrowMatch = trimmed.match(
2009
- /^(\S+)\s*->\s*([^\s:]+)\s*(?::\s*(.+))?$/
2010
- );
2011
- const arrowMatch = asyncArrowMatch || syncArrowMatch;
2012
- if (asyncArrowMatch) isAsync = true;
2013
- if (arrowMatch) {
2037
+ const bareCallSync = trimmed.match(/^(\S+)\s*->\s*(\S+)$/);
2038
+ const bareCallAsync = trimmed.match(/^(\S+)\s*~>\s*(\S+)$/);
2039
+ const bareCall = bareCallSync || bareCallAsync;
2040
+ if (bareCall) {
2014
2041
  contentStarted = true;
2015
- const from = arrowMatch[1];
2016
- const to = arrowMatch[2];
2042
+ const from = bareCall[1];
2043
+ const to = bareCall[2];
2017
2044
  lastMsgFrom = from;
2018
- const rawLabel = arrowMatch[3]?.trim() || "";
2019
- const { label, returnLabel, standaloneReturn } = isAsync ? { label: rawLabel, returnLabel: void 0, standaloneReturn: void 0 } : parseReturnLabel(rawLabel);
2020
2045
  const msg = {
2021
2046
  from,
2022
2047
  to,
2023
- label,
2024
- returnLabel,
2048
+ label: "",
2025
2049
  lineNumber,
2026
- ...isAsync ? { async: true } : {},
2027
- ...standaloneReturn ? { standaloneReturn: true } : {}
2050
+ ...bareCallAsync ? { async: true } : {}
2028
2051
  };
2029
2052
  result.messages.push(msg);
2030
2053
  currentContainer().push(msg);
@@ -2233,7 +2256,7 @@ function looksLikeSequence(content) {
2233
2256
  return ARROW_PATTERN.test(trimmed);
2234
2257
  });
2235
2258
  }
2236
- var VALID_PARTICIPANT_TYPES, IS_A_PATTERN, POSITION_ONLY_PATTERN, GROUP_HEADING_PATTERN, SECTION_PATTERN, ARROW_PATTERN, ARROW_RETURN_PATTERN, UML_RETURN_PATTERN, NOTE_SINGLE, NOTE_MULTI;
2259
+ var VALID_PARTICIPANT_TYPES, IS_A_PATTERN, POSITION_ONLY_PATTERN, GROUP_HEADING_PATTERN, SECTION_PATTERN, ARROW_PATTERN, NOTE_SINGLE, NOTE_MULTI;
2237
2260
  var init_parser = __esm({
2238
2261
  "src/sequence/parser.ts"() {
2239
2262
  "use strict";
@@ -2256,9 +2279,7 @@ var init_parser = __esm({
2256
2279
  POSITION_ONLY_PATTERN = /^(\S+)\s+position\s+(-?\d+)$/i;
2257
2280
  GROUP_HEADING_PATTERN = /^##\s+(.+?)(?:\(([^)]+)\))?\s*$/;
2258
2281
  SECTION_PATTERN = /^==\s+(.+?)(?:\s*==)?\s*$/;
2259
- ARROW_PATTERN = /\S+\s*(?:<->|<~>|->|~>|-\S+->|~\S+~>|<-\S+->|<~\S+~>)\s*\S+/;
2260
- ARROW_RETURN_PATTERN = /^(.+?)\s*<-\s*(.+)$/;
2261
- UML_RETURN_PATTERN = /^(\w+\([^)]*\))\s*:\s*(.+)$/;
2282
+ ARROW_PATTERN = /\S+\s*(?:<-\S+-|<~\S+~|-\S+->|~\S+~>|->|~>|<-|<~)\s*\S+/;
2262
2283
  NOTE_SINGLE = /^note(?:\s+(right|left)\s+of\s+(\S+))?\s*:\s*(.+)$/i;
2263
2284
  NOTE_MULTI = /^note(?:\s+(right|left)\s+of\s+([^\s:]+))?\s*:?\s*$/i;
2264
2285
  }
@@ -3164,49 +3185,19 @@ function parseChart(content, palette) {
3164
3185
  continue;
3165
3186
  }
3166
3187
  if (key === "series") {
3167
- let rawNames;
3168
- if (value) {
3169
- result.series = value;
3170
- rawNames = value.split(",").map((s) => s.trim()).filter(Boolean);
3171
- } else {
3172
- const collected = collectIndentedValues(lines, i);
3173
- i = collected.newIndex;
3174
- rawNames = collected.values;
3175
- result.series = rawNames.join(", ");
3176
- }
3177
- const names = [];
3178
- const nameColors = [];
3179
- for (const raw of rawNames) {
3180
- const colorMatch = raw.match(/\(([^)]+)\)\s*$/);
3181
- if (colorMatch) {
3182
- const resolved = resolveColor(colorMatch[1].trim(), palette);
3183
- nameColors.push(resolved);
3184
- names.push(raw.substring(0, colorMatch.index).trim());
3185
- } else {
3186
- nameColors.push(void 0);
3187
- names.push(raw);
3188
- }
3189
- }
3190
- if (names.length === 1) {
3191
- result.series = names[0];
3188
+ const parsed = parseSeriesNames(value, lines, i, palette);
3189
+ i = parsed.newIndex;
3190
+ result.series = parsed.series;
3191
+ if (parsed.names.length > 1) {
3192
+ result.seriesNames = parsed.names;
3192
3193
  }
3193
- if (names.length > 1) {
3194
- result.seriesNames = names;
3195
- }
3196
- if (nameColors.some(Boolean)) result.seriesNameColors = nameColors;
3194
+ if (parsed.nameColors.some(Boolean)) result.seriesNameColors = parsed.nameColors;
3197
3195
  continue;
3198
3196
  }
3199
3197
  const parts = value.split(",").map((s) => s.trim());
3200
3198
  const numValue = parseFloat(parts[0]);
3201
3199
  if (!isNaN(numValue)) {
3202
- let rawLabel = trimmed.substring(0, colonIndex).trim();
3203
- let pointColor;
3204
- const colorMatch = rawLabel.match(/\(([^)]+)\)\s*$/);
3205
- if (colorMatch) {
3206
- const resolved = resolveColor(colorMatch[1].trim(), palette);
3207
- pointColor = resolved;
3208
- rawLabel = rawLabel.substring(0, colorMatch.index).trim();
3209
- }
3200
+ const { label: rawLabel, color: pointColor } = extractColor(trimmed.substring(0, colonIndex).trim(), palette);
3210
3201
  const extra = parts.slice(1).map((s) => parseFloat(s)).filter((n) => !isNaN(n));
3211
3202
  result.data.push({
3212
3203
  label: rawLabel,
@@ -3285,13 +3276,10 @@ function parseEChart(content, palette) {
3285
3276
  if (!trimmed) continue;
3286
3277
  const mdCategoryMatch = trimmed.match(/^#{2,}\s+(.+)$/);
3287
3278
  if (mdCategoryMatch) {
3288
- let catName = mdCategoryMatch[1].trim();
3289
- const catColorMatch = catName.match(/\(([^)]+)\)\s*$/);
3290
- if (catColorMatch) {
3291
- const resolved = resolveColor(catColorMatch[1].trim(), palette);
3279
+ const { label: catName, color: catColor } = extractColor(mdCategoryMatch[1].trim(), palette);
3280
+ if (catColor) {
3292
3281
  if (!result.categoryColors) result.categoryColors = {};
3293
- catName = catName.substring(0, catColorMatch.index).trim();
3294
- result.categoryColors[catName] = resolved;
3282
+ result.categoryColors[catName] = catColor;
3295
3283
  }
3296
3284
  currentCategory = catName;
3297
3285
  continue;
@@ -3328,32 +3316,13 @@ function parseEChart(content, palette) {
3328
3316
  continue;
3329
3317
  }
3330
3318
  if (key === "series") {
3331
- let rawNames;
3332
- if (value) {
3333
- result.series = value;
3334
- rawNames = value.split(",").map((s) => s.trim()).filter(Boolean);
3335
- } else {
3336
- const collected = collectIndentedValues(lines, i);
3337
- i = collected.newIndex;
3338
- rawNames = collected.values;
3339
- result.series = rawNames.join(", ");
3340
- }
3341
- const names = [];
3342
- const nameColors = [];
3343
- for (const raw of rawNames) {
3344
- const colorMatch = raw.match(/\(([^)]+)\)\s*$/);
3345
- if (colorMatch) {
3346
- nameColors.push(resolveColor(colorMatch[1].trim(), palette));
3347
- names.push(raw.substring(0, colorMatch.index).trim());
3348
- } else {
3349
- nameColors.push(void 0);
3350
- names.push(raw);
3351
- }
3352
- }
3353
- if (names.length === 1) {
3354
- result.series = names[0];
3319
+ const parsed = parseSeriesNames(value, lines, i, palette);
3320
+ i = parsed.newIndex;
3321
+ result.series = parsed.series;
3322
+ if (parsed.names.length > 1) {
3323
+ result.seriesNames = parsed.names;
3355
3324
  }
3356
- if (nameColors.some(Boolean)) result.seriesNameColors = nameColors;
3325
+ if (parsed.nameColors.some(Boolean)) result.seriesNameColors = parsed.nameColors;
3357
3326
  continue;
3358
3327
  }
3359
3328
  if (key === "xlabel") {
@@ -3415,13 +3384,7 @@ function parseEChart(content, palette) {
3415
3384
  continue;
3416
3385
  }
3417
3386
  if (result.type === "function") {
3418
- let fnName = trimmed.substring(0, colonIndex).trim();
3419
- let fnColor;
3420
- const colorMatch = fnName.match(/\(([^)]+)\)\s*$/);
3421
- if (colorMatch) {
3422
- fnColor = resolveColor(colorMatch[1].trim(), palette);
3423
- fnName = fnName.substring(0, colorMatch.index).trim();
3424
- }
3387
+ const { label: fnName, color: fnColor } = extractColor(trimmed.substring(0, colonIndex).trim(), palette);
3425
3388
  if (!result.functions) result.functions = [];
3426
3389
  result.functions.push({
3427
3390
  name: fnName,
@@ -3436,13 +3399,7 @@ function parseEChart(content, palette) {
3436
3399
  /^(-?[\d.]+)\s*,\s*(-?[\d.]+)(?:\s*,\s*(-?[\d.]+))?$/
3437
3400
  );
3438
3401
  if (scatterMatch) {
3439
- let scatterName = trimmed.substring(0, colonIndex).trim();
3440
- let scatterColor;
3441
- const colorMatch = scatterName.match(/\(([^)]+)\)\s*$/);
3442
- if (colorMatch) {
3443
- scatterColor = resolveColor(colorMatch[1].trim(), palette);
3444
- scatterName = scatterName.substring(0, colorMatch.index).trim();
3445
- }
3402
+ const { label: scatterName, color: scatterColor } = extractColor(trimmed.substring(0, colonIndex).trim(), palette);
3446
3403
  if (!result.scatterPoints) result.scatterPoints = [];
3447
3404
  result.scatterPoints.push({
3448
3405
  name: scatterName,
@@ -3467,13 +3424,7 @@ function parseEChart(content, palette) {
3467
3424
  }
3468
3425
  const numValue = parseFloat(value);
3469
3426
  if (!isNaN(numValue)) {
3470
- let rawLabel = trimmed.substring(0, colonIndex).trim();
3471
- let pointColor;
3472
- const colorMatch = rawLabel.match(/\(([^)]+)\)\s*$/);
3473
- if (colorMatch) {
3474
- pointColor = resolveColor(colorMatch[1].trim(), palette);
3475
- rawLabel = rawLabel.substring(0, colorMatch.index).trim();
3476
- }
3427
+ const { label: rawLabel, color: pointColor } = extractColor(trimmed.substring(0, colonIndex).trim(), palette);
3477
3428
  result.data.push({
3478
3429
  label: rawLabel,
3479
3430
  value: numValue,
@@ -3520,30 +3471,21 @@ function parseEChart(content, palette) {
3520
3471
  }
3521
3472
  return result;
3522
3473
  }
3523
- function buildEChartsOption(parsed, palette, isDark) {
3474
+ function buildChartCommons(parsed, palette, isDark) {
3524
3475
  const textColor = palette.text;
3525
3476
  const axisLineColor = palette.border;
3477
+ const splitLineColor = palette.border;
3526
3478
  const gridOpacity = isDark ? 0.7 : 0.55;
3527
3479
  const colors = getSeriesColors(palette);
3480
+ const titleConfig = parsed.title ? { text: parsed.title, left: "center", top: 8, textStyle: { color: textColor, fontSize: 20, fontWeight: "bold", fontFamily: FONT_FAMILY } } : void 0;
3481
+ const tooltipTheme = { backgroundColor: palette.surface, borderColor: palette.border, textStyle: { color: palette.text } };
3482
+ return { textColor, axisLineColor, splitLineColor, gridOpacity, colors, titleConfig, tooltipTheme };
3483
+ }
3484
+ function buildEChartsOption(parsed, palette, isDark) {
3528
3485
  if (parsed.error) {
3529
3486
  return {};
3530
3487
  }
3531
- const titleConfig = parsed.title ? {
3532
- text: parsed.title,
3533
- left: "center",
3534
- top: 8,
3535
- textStyle: {
3536
- color: textColor,
3537
- fontSize: 20,
3538
- fontWeight: "bold",
3539
- fontFamily: FONT_FAMILY
3540
- }
3541
- } : void 0;
3542
- const tooltipTheme = {
3543
- backgroundColor: palette.surface,
3544
- borderColor: palette.border,
3545
- textStyle: { color: palette.text }
3546
- };
3488
+ const { textColor, axisLineColor, gridOpacity, colors, titleConfig, tooltipTheme } = buildChartCommons(parsed, palette, isDark);
3547
3489
  if (parsed.type === "sankey") {
3548
3490
  return buildSankeyOption(
3549
3491
  parsed,
@@ -3619,8 +3561,7 @@ function buildSankeyOption(parsed, textColor, colors, titleConfig, tooltipTheme)
3619
3561
  }
3620
3562
  }));
3621
3563
  return {
3622
- backgroundColor: "transparent",
3623
- animation: false,
3564
+ ...CHART_BASE,
3624
3565
  title: titleConfig,
3625
3566
  tooltip: {
3626
3567
  show: false,
@@ -3677,8 +3618,7 @@ function buildChordOption(parsed, textColor, colors, titleConfig, tooltipTheme)
3677
3618
  }
3678
3619
  }));
3679
3620
  return {
3680
- backgroundColor: "transparent",
3681
- animation: false,
3621
+ ...CHART_BASE,
3682
3622
  title: titleConfig,
3683
3623
  tooltip: {
3684
3624
  trigger: "item",
@@ -3780,15 +3720,11 @@ function buildFunctionOption(parsed, palette, textColor, axisLineColor, gridOpac
3780
3720
  itemStyle: {
3781
3721
  color: fnColor
3782
3722
  },
3783
- emphasis: {
3784
- focus: "self",
3785
- blurScope: "global"
3786
- }
3723
+ emphasis: EMPHASIS_SELF
3787
3724
  };
3788
3725
  });
3789
3726
  return {
3790
- backgroundColor: "transparent",
3791
- animation: false,
3727
+ ...CHART_BASE,
3792
3728
  title: titleConfig,
3793
3729
  tooltip: {
3794
3730
  trigger: "axis",
@@ -3933,8 +3869,7 @@ function buildScatterOption(parsed, palette, textColor, axisLineColor, gridOpaci
3933
3869
  const xPad = (xMax - xMin) * 0.1 || 1;
3934
3870
  const yPad = (yMax - yMin) * 0.1 || 1;
3935
3871
  return {
3936
- backgroundColor: "transparent",
3937
- animation: false,
3872
+ ...CHART_BASE,
3938
3873
  title: titleConfig,
3939
3874
  tooltip,
3940
3875
  ...legendData && {
@@ -4019,8 +3954,7 @@ function buildHeatmapOption(parsed, palette, textColor, axisLineColor, titleConf
4019
3954
  });
4020
3955
  });
4021
3956
  return {
4022
- backgroundColor: "transparent",
4023
- animation: false,
3957
+ ...CHART_BASE,
4024
3958
  title: titleConfig,
4025
3959
  tooltip: {
4026
3960
  trigger: "item",
@@ -4097,8 +4031,7 @@ function buildHeatmapOption(parsed, palette, textColor, axisLineColor, titleConf
4097
4031
  fontWeight: "bold"
4098
4032
  },
4099
4033
  emphasis: {
4100
- focus: "self",
4101
- blurScope: "global",
4034
+ ...EMPHASIS_SELF,
4102
4035
  itemStyle: {
4103
4036
  shadowBlur: 10,
4104
4037
  shadowColor: "rgba(0, 0, 0, 0.5)"
@@ -4137,8 +4070,7 @@ function buildFunnelOption(parsed, textColor, colors, titleConfig, tooltipTheme)
4137
4070
  minSize: "8%"
4138
4071
  };
4139
4072
  return {
4140
- backgroundColor: "transparent",
4141
- animation: false,
4073
+ ...CHART_BASE,
4142
4074
  title: titleConfig,
4143
4075
  tooltip: {
4144
4076
  trigger: "item",
@@ -4176,8 +4108,7 @@ function buildFunnelOption(parsed, textColor, colors, titleConfig, tooltipTheme)
4176
4108
  lineStyle: { color: textColor, opacity: 0.3 }
4177
4109
  },
4178
4110
  emphasis: {
4179
- focus: "self",
4180
- blurScope: "global",
4111
+ ...EMPHASIS_SELF,
4181
4112
  label: {
4182
4113
  fontSize: 15
4183
4114
  }
@@ -4217,19 +4148,36 @@ function resolveAxisLabels(parsed) {
4217
4148
  yLabel: parsed.ylabel ?? (isHorizontal ? void 0 : parsed.label)
4218
4149
  };
4219
4150
  }
4220
- function makeGridAxis(type, textColor, axisLineColor, splitLineColor, gridOpacity, label, data, nameGapOverride) {
4151
+ function makeGridAxis(type, textColor, axisLineColor, splitLineColor, gridOpacity, label, data, nameGapOverride, chartWidthHint) {
4221
4152
  const defaultGap = type === "value" ? 75 : 40;
4153
+ let catFontSize = 16;
4154
+ let catLabelExtras = {};
4155
+ if (type === "category" && data && data.length > 0) {
4156
+ const maxLabelLen = Math.max(...data.map((l) => l.length));
4157
+ const count = data.length;
4158
+ if (count > 10 || maxLabelLen > 20) catFontSize = 10;
4159
+ else if (count > 5 || maxLabelLen > 14) catFontSize = 11;
4160
+ else if (maxLabelLen > 8) catFontSize = 12;
4161
+ if (chartWidthHint && count > 0) {
4162
+ const availPerLabel = Math.floor(chartWidthHint * 0.85 / count);
4163
+ catLabelExtras = {
4164
+ width: availPerLabel,
4165
+ overflow: "break"
4166
+ };
4167
+ }
4168
+ }
4222
4169
  return {
4223
4170
  type,
4224
4171
  ...data && { data },
4225
4172
  axisLine: { lineStyle: { color: axisLineColor } },
4226
4173
  axisLabel: {
4227
4174
  color: textColor,
4228
- fontSize: type === "category" && data ? data.length > 10 ? 11 : data.length > 5 ? 12 : 16 : 16,
4175
+ fontSize: type === "category" && data ? catFontSize : 16,
4229
4176
  fontFamily: FONT_FAMILY,
4230
4177
  ...type === "category" && {
4231
4178
  interval: 0,
4232
- formatter: (value) => value.replace(/([a-z])([A-Z])/g, "$1\n$2").replace(/ /g, "\n")
4179
+ formatter: (value) => value.replace(/([a-z])([A-Z])/g, "$1\n$2"),
4180
+ ...catLabelExtras
4233
4181
  }
4234
4182
  },
4235
4183
  splitLine: { lineStyle: { color: splitLineColor, opacity: gridOpacity } },
@@ -4241,38 +4189,18 @@ function makeGridAxis(type, textColor, axisLineColor, splitLineColor, gridOpacit
4241
4189
  }
4242
4190
  };
4243
4191
  }
4244
- function buildEChartsOptionFromChart(parsed, palette, isDark) {
4192
+ function buildEChartsOptionFromChart(parsed, palette, isDark, chartWidth) {
4245
4193
  if (parsed.error) return {};
4246
- const textColor = palette.text;
4247
- const axisLineColor = palette.border;
4248
- const splitLineColor = palette.border;
4249
- const gridOpacity = isDark ? 0.7 : 0.55;
4250
- const colors = getSeriesColors(palette);
4251
- const titleConfig = parsed.title ? {
4252
- text: parsed.title,
4253
- left: "center",
4254
- top: 8,
4255
- textStyle: {
4256
- color: textColor,
4257
- fontSize: 20,
4258
- fontWeight: "bold",
4259
- fontFamily: FONT_FAMILY
4260
- }
4261
- } : void 0;
4262
- const tooltipTheme = {
4263
- backgroundColor: palette.surface,
4264
- borderColor: palette.border,
4265
- textStyle: { color: palette.text }
4266
- };
4194
+ const { textColor, axisLineColor, splitLineColor, gridOpacity, colors, titleConfig, tooltipTheme } = buildChartCommons(parsed, palette, isDark);
4267
4195
  switch (parsed.type) {
4268
4196
  case "bar":
4269
- return buildBarOption(parsed, textColor, axisLineColor, splitLineColor, gridOpacity, colors, titleConfig, tooltipTheme);
4197
+ return buildBarOption(parsed, textColor, axisLineColor, splitLineColor, gridOpacity, colors, titleConfig, tooltipTheme, chartWidth);
4270
4198
  case "bar-stacked":
4271
- return buildBarStackedOption(parsed, textColor, axisLineColor, splitLineColor, gridOpacity, colors, titleConfig, tooltipTheme);
4199
+ return buildBarStackedOption(parsed, textColor, axisLineColor, splitLineColor, gridOpacity, colors, titleConfig, tooltipTheme, chartWidth);
4272
4200
  case "line":
4273
- return parsed.seriesNames ? buildMultiLineOption(parsed, textColor, axisLineColor, splitLineColor, gridOpacity, colors, titleConfig, tooltipTheme) : buildLineOption(parsed, palette, textColor, axisLineColor, splitLineColor, gridOpacity, titleConfig, tooltipTheme);
4201
+ return parsed.seriesNames ? buildMultiLineOption(parsed, textColor, axisLineColor, splitLineColor, gridOpacity, colors, titleConfig, tooltipTheme, chartWidth) : buildLineOption(parsed, palette, textColor, axisLineColor, splitLineColor, gridOpacity, titleConfig, tooltipTheme, chartWidth);
4274
4202
  case "area":
4275
- return buildAreaOption(parsed, palette, textColor, axisLineColor, splitLineColor, gridOpacity, titleConfig, tooltipTheme);
4203
+ return buildAreaOption(parsed, palette, textColor, axisLineColor, splitLineColor, gridOpacity, titleConfig, tooltipTheme, chartWidth);
4276
4204
  case "pie":
4277
4205
  return buildPieOption(parsed, textColor, getSegmentColors(palette, parsed.data.length), titleConfig, tooltipTheme, false);
4278
4206
  case "doughnut":
@@ -4283,7 +4211,16 @@ function buildEChartsOptionFromChart(parsed, palette, isDark) {
4283
4211
  return buildPolarAreaOption(parsed, textColor, getSegmentColors(palette, parsed.data.length), titleConfig, tooltipTheme);
4284
4212
  }
4285
4213
  }
4286
- function buildBarOption(parsed, textColor, axisLineColor, splitLineColor, gridOpacity, colors, titleConfig, tooltipTheme) {
4214
+ function makeChartGrid(options) {
4215
+ return {
4216
+ left: options.yLabel ? "12%" : "3%",
4217
+ right: "4%",
4218
+ bottom: options.hasLegend ? "15%" : options.xLabel ? "10%" : "3%",
4219
+ top: options.hasTitle ? "15%" : "5%",
4220
+ containLabel: true
4221
+ };
4222
+ }
4223
+ function buildBarOption(parsed, textColor, axisLineColor, splitLineColor, gridOpacity, colors, titleConfig, tooltipTheme, chartWidth) {
4287
4224
  const { xLabel, yLabel } = resolveAxisLabels(parsed);
4288
4225
  const isHorizontal = parsed.orientation === "horizontal";
4289
4226
  const labels = parsed.data.map((d) => d.label);
@@ -4292,60 +4229,43 @@ function buildBarOption(parsed, textColor, axisLineColor, splitLineColor, gridOp
4292
4229
  itemStyle: { color: d.color ?? colors[i % colors.length] }
4293
4230
  }));
4294
4231
  const hCatGap = isHorizontal && yLabel ? Math.max(40, Math.max(...labels.map((l) => l.length)) * 8 + 16) : void 0;
4295
- const categoryAxis = makeGridAxis("category", textColor, axisLineColor, splitLineColor, gridOpacity, isHorizontal ? yLabel : xLabel, labels, hCatGap);
4232
+ const categoryAxis = makeGridAxis("category", textColor, axisLineColor, splitLineColor, gridOpacity, isHorizontal ? yLabel : xLabel, labels, hCatGap, !isHorizontal ? chartWidth : void 0);
4296
4233
  const valueAxis = makeGridAxis("value", textColor, axisLineColor, splitLineColor, gridOpacity, isHorizontal ? xLabel : yLabel);
4297
4234
  return {
4298
- backgroundColor: "transparent",
4299
- animation: false,
4235
+ ...CHART_BASE,
4300
4236
  title: titleConfig,
4301
4237
  tooltip: {
4302
4238
  trigger: "axis",
4303
4239
  ...tooltipTheme,
4304
4240
  axisPointer: { type: "shadow" }
4305
4241
  },
4306
- grid: {
4307
- left: yLabel ? "12%" : "3%",
4308
- right: "4%",
4309
- bottom: xLabel ? "10%" : "3%",
4310
- top: parsed.title ? "15%" : "5%",
4311
- containLabel: true
4312
- },
4242
+ grid: makeChartGrid({ xLabel, yLabel, hasTitle: !!parsed.title }),
4313
4243
  xAxis: isHorizontal ? valueAxis : categoryAxis,
4314
4244
  yAxis: isHorizontal ? categoryAxis : valueAxis,
4315
4245
  series: [
4316
4246
  {
4317
4247
  type: "bar",
4318
4248
  data,
4319
- emphasis: {
4320
- focus: "self",
4321
- blurScope: "global"
4322
- }
4249
+ emphasis: EMPHASIS_SELF
4323
4250
  }
4324
4251
  ]
4325
4252
  };
4326
4253
  }
4327
- function buildLineOption(parsed, palette, textColor, axisLineColor, splitLineColor, gridOpacity, titleConfig, tooltipTheme) {
4254
+ function buildLineOption(parsed, palette, textColor, axisLineColor, splitLineColor, gridOpacity, titleConfig, tooltipTheme, chartWidth) {
4328
4255
  const { xLabel, yLabel } = resolveAxisLabels(parsed);
4329
4256
  const lineColor = parsed.color ?? parsed.seriesNameColors?.[0] ?? palette.primary;
4330
4257
  const labels = parsed.data.map((d) => d.label);
4331
4258
  const values = parsed.data.map((d) => d.value);
4332
4259
  return {
4333
- backgroundColor: "transparent",
4334
- animation: false,
4260
+ ...CHART_BASE,
4335
4261
  title: titleConfig,
4336
4262
  tooltip: {
4337
4263
  trigger: "axis",
4338
4264
  ...tooltipTheme,
4339
4265
  axisPointer: { type: "line" }
4340
4266
  },
4341
- grid: {
4342
- left: yLabel ? "12%" : "3%",
4343
- right: "4%",
4344
- bottom: xLabel ? "10%" : "3%",
4345
- top: parsed.title ? "15%" : "5%",
4346
- containLabel: true
4347
- },
4348
- xAxis: makeGridAxis("category", textColor, axisLineColor, splitLineColor, gridOpacity, xLabel, labels),
4267
+ grid: makeChartGrid({ xLabel, yLabel, hasTitle: !!parsed.title }),
4268
+ xAxis: makeGridAxis("category", textColor, axisLineColor, splitLineColor, gridOpacity, xLabel, labels, void 0, chartWidth),
4349
4269
  yAxis: makeGridAxis("value", textColor, axisLineColor, splitLineColor, gridOpacity, yLabel),
4350
4270
  series: [
4351
4271
  {
@@ -4355,15 +4275,12 @@ function buildLineOption(parsed, palette, textColor, axisLineColor, splitLineCol
4355
4275
  symbolSize: 8,
4356
4276
  lineStyle: { color: lineColor, width: 3 },
4357
4277
  itemStyle: { color: lineColor },
4358
- emphasis: {
4359
- focus: "self",
4360
- blurScope: "global"
4361
- }
4278
+ emphasis: EMPHASIS_SELF
4362
4279
  }
4363
4280
  ]
4364
4281
  };
4365
4282
  }
4366
- function buildMultiLineOption(parsed, textColor, axisLineColor, splitLineColor, gridOpacity, colors, titleConfig, tooltipTheme) {
4283
+ function buildMultiLineOption(parsed, textColor, axisLineColor, splitLineColor, gridOpacity, colors, titleConfig, tooltipTheme, chartWidth) {
4367
4284
  const { xLabel, yLabel } = resolveAxisLabels(parsed);
4368
4285
  const seriesNames = parsed.seriesNames ?? [];
4369
4286
  const labels = parsed.data.map((d) => d.label);
@@ -4380,15 +4297,11 @@ function buildMultiLineOption(parsed, textColor, axisLineColor, splitLineColor,
4380
4297
  symbolSize: 8,
4381
4298
  lineStyle: { color, width: 3 },
4382
4299
  itemStyle: { color },
4383
- emphasis: {
4384
- focus: "self",
4385
- blurScope: "global"
4386
- }
4300
+ emphasis: EMPHASIS_SELF
4387
4301
  };
4388
4302
  });
4389
4303
  return {
4390
- backgroundColor: "transparent",
4391
- animation: false,
4304
+ ...CHART_BASE,
4392
4305
  title: titleConfig,
4393
4306
  tooltip: {
4394
4307
  trigger: "axis",
@@ -4400,40 +4313,27 @@ function buildMultiLineOption(parsed, textColor, axisLineColor, splitLineColor,
4400
4313
  bottom: 10,
4401
4314
  textStyle: { color: textColor }
4402
4315
  },
4403
- grid: {
4404
- left: yLabel ? "12%" : "3%",
4405
- right: "4%",
4406
- bottom: "15%",
4407
- top: parsed.title ? "15%" : "5%",
4408
- containLabel: true
4409
- },
4410
- xAxis: makeGridAxis("category", textColor, axisLineColor, splitLineColor, gridOpacity, xLabel, labels),
4316
+ grid: makeChartGrid({ xLabel, yLabel, hasTitle: !!parsed.title, hasLegend: true }),
4317
+ xAxis: makeGridAxis("category", textColor, axisLineColor, splitLineColor, gridOpacity, xLabel, labels, void 0, chartWidth),
4411
4318
  yAxis: makeGridAxis("value", textColor, axisLineColor, splitLineColor, gridOpacity, yLabel),
4412
4319
  series
4413
4320
  };
4414
4321
  }
4415
- function buildAreaOption(parsed, palette, textColor, axisLineColor, splitLineColor, gridOpacity, titleConfig, tooltipTheme) {
4322
+ function buildAreaOption(parsed, palette, textColor, axisLineColor, splitLineColor, gridOpacity, titleConfig, tooltipTheme, chartWidth) {
4416
4323
  const { xLabel, yLabel } = resolveAxisLabels(parsed);
4417
4324
  const lineColor = parsed.color ?? parsed.seriesNameColors?.[0] ?? palette.primary;
4418
4325
  const labels = parsed.data.map((d) => d.label);
4419
4326
  const values = parsed.data.map((d) => d.value);
4420
4327
  return {
4421
- backgroundColor: "transparent",
4422
- animation: false,
4328
+ ...CHART_BASE,
4423
4329
  title: titleConfig,
4424
4330
  tooltip: {
4425
4331
  trigger: "axis",
4426
4332
  ...tooltipTheme,
4427
4333
  axisPointer: { type: "line" }
4428
4334
  },
4429
- grid: {
4430
- left: yLabel ? "12%" : "3%",
4431
- right: "4%",
4432
- bottom: xLabel ? "10%" : "3%",
4433
- top: parsed.title ? "15%" : "5%",
4434
- containLabel: true
4435
- },
4436
- xAxis: makeGridAxis("category", textColor, axisLineColor, splitLineColor, gridOpacity, xLabel, labels),
4335
+ grid: makeChartGrid({ xLabel, yLabel, hasTitle: !!parsed.title }),
4336
+ xAxis: makeGridAxis("category", textColor, axisLineColor, splitLineColor, gridOpacity, xLabel, labels, void 0, chartWidth),
4437
4337
  yAxis: makeGridAxis("value", textColor, axisLineColor, splitLineColor, gridOpacity, yLabel),
4438
4338
  series: [
4439
4339
  {
@@ -4444,10 +4344,7 @@ function buildAreaOption(parsed, palette, textColor, axisLineColor, splitLineCol
4444
4344
  lineStyle: { color: lineColor, width: 3 },
4445
4345
  itemStyle: { color: lineColor },
4446
4346
  areaStyle: { opacity: 0.25 },
4447
- emphasis: {
4448
- focus: "self",
4449
- blurScope: "global"
4450
- }
4347
+ emphasis: EMPHASIS_SELF
4451
4348
  }
4452
4349
  ]
4453
4350
  };
@@ -4471,8 +4368,7 @@ function buildPieOption(parsed, textColor, colors, titleConfig, tooltipTheme, is
4471
4368
  itemStyle: { color: d.color ?? colors[i % colors.length] }
4472
4369
  }));
4473
4370
  return {
4474
- backgroundColor: "transparent",
4475
- animation: false,
4371
+ ...CHART_BASE,
4476
4372
  title: titleConfig,
4477
4373
  tooltip: {
4478
4374
  trigger: "item",
@@ -4490,10 +4386,7 @@ function buildPieOption(parsed, textColor, colors, titleConfig, tooltipTheme, is
4490
4386
  fontFamily: FONT_FAMILY
4491
4387
  },
4492
4388
  labelLine: { show: true },
4493
- emphasis: {
4494
- focus: "self",
4495
- blurScope: "global"
4496
- }
4389
+ emphasis: EMPHASIS_SELF
4497
4390
  }
4498
4391
  ]
4499
4392
  };
@@ -4507,8 +4400,7 @@ function buildRadarOption(parsed, palette, textColor, gridOpacity, colors, title
4507
4400
  max: maxValue
4508
4401
  }));
4509
4402
  return {
4510
- backgroundColor: "transparent",
4511
- animation: false,
4403
+ ...CHART_BASE,
4512
4404
  title: titleConfig,
4513
4405
  tooltip: {
4514
4406
  trigger: "item",
@@ -4550,10 +4442,7 @@ function buildRadarOption(parsed, palette, textColor, gridOpacity, colors, title
4550
4442
  }
4551
4443
  }
4552
4444
  ],
4553
- emphasis: {
4554
- focus: "self",
4555
- blurScope: "global"
4556
- }
4445
+ emphasis: EMPHASIS_SELF
4557
4446
  }
4558
4447
  ]
4559
4448
  };
@@ -4565,8 +4454,7 @@ function buildPolarAreaOption(parsed, textColor, colors, titleConfig, tooltipThe
4565
4454
  itemStyle: { color: d.color ?? colors[i % colors.length] }
4566
4455
  }));
4567
4456
  return {
4568
- backgroundColor: "transparent",
4569
- animation: false,
4457
+ ...CHART_BASE,
4570
4458
  title: titleConfig,
4571
4459
  tooltip: {
4572
4460
  trigger: "item",
@@ -4585,15 +4473,12 @@ function buildPolarAreaOption(parsed, textColor, colors, titleConfig, tooltipThe
4585
4473
  fontFamily: FONT_FAMILY
4586
4474
  },
4587
4475
  labelLine: { show: true },
4588
- emphasis: {
4589
- focus: "self",
4590
- blurScope: "global"
4591
- }
4476
+ emphasis: EMPHASIS_SELF
4592
4477
  }
4593
4478
  ]
4594
4479
  };
4595
4480
  }
4596
- function buildBarStackedOption(parsed, textColor, axisLineColor, splitLineColor, gridOpacity, colors, titleConfig, tooltipTheme) {
4481
+ function buildBarStackedOption(parsed, textColor, axisLineColor, splitLineColor, gridOpacity, colors, titleConfig, tooltipTheme, chartWidth) {
4597
4482
  const { xLabel, yLabel } = resolveAxisLabels(parsed);
4598
4483
  const isHorizontal = parsed.orientation === "horizontal";
4599
4484
  const seriesNames = parsed.seriesNames ?? [];
@@ -4618,18 +4503,15 @@ function buildBarStackedOption(parsed, textColor, axisLineColor, splitLineColor,
4618
4503
  fontWeight: "bold",
4619
4504
  fontFamily: FONT_FAMILY
4620
4505
  },
4621
- emphasis: {
4622
- focus: "self",
4623
- blurScope: "global"
4624
- }
4506
+ emphasis: EMPHASIS_SELF
4625
4507
  };
4626
4508
  });
4627
4509
  const hCatGap = isHorizontal && yLabel ? Math.max(40, Math.max(...labels.map((l) => l.length)) * 8 + 16) : void 0;
4628
- const categoryAxis = makeGridAxis("category", textColor, axisLineColor, splitLineColor, gridOpacity, isHorizontal ? yLabel : xLabel, labels, hCatGap);
4629
- const valueAxis = makeGridAxis("value", textColor, axisLineColor, splitLineColor, gridOpacity, isHorizontal ? xLabel : yLabel);
4510
+ const categoryAxis = makeGridAxis("category", textColor, axisLineColor, splitLineColor, gridOpacity, isHorizontal ? yLabel : xLabel, labels, hCatGap, !isHorizontal ? chartWidth : void 0);
4511
+ const hValueGap = isHorizontal && xLabel ? 40 : void 0;
4512
+ const valueAxis = makeGridAxis("value", textColor, axisLineColor, splitLineColor, gridOpacity, isHorizontal ? xLabel : yLabel, void 0, hValueGap);
4630
4513
  return {
4631
- backgroundColor: "transparent",
4632
- animation: false,
4514
+ ...CHART_BASE,
4633
4515
  title: titleConfig,
4634
4516
  tooltip: {
4635
4517
  trigger: "axis",
@@ -4641,13 +4523,7 @@ function buildBarStackedOption(parsed, textColor, axisLineColor, splitLineColor,
4641
4523
  bottom: 10,
4642
4524
  textStyle: { color: textColor }
4643
4525
  },
4644
- grid: {
4645
- left: yLabel ? "12%" : "3%",
4646
- right: "4%",
4647
- bottom: "15%",
4648
- top: parsed.title ? "15%" : "5%",
4649
- containLabel: true
4650
- },
4526
+ grid: makeChartGrid({ xLabel, yLabel, hasTitle: !!parsed.title, hasLegend: true }),
4651
4527
  xAxis: isHorizontal ? valueAxis : categoryAxis,
4652
4528
  yAxis: isHorizontal ? categoryAxis : valueAxis,
4653
4529
  series
@@ -4663,7 +4539,7 @@ async function renderEChartsForExport(content, theme, palette, options) {
4663
4539
  if (chartType && STANDARD_CHART_TYPES.has(chartType)) {
4664
4540
  const parsed = parseChart(content, effectivePalette);
4665
4541
  if (parsed.error) return "";
4666
- option = buildEChartsOptionFromChart(parsed, effectivePalette, isDark);
4542
+ option = buildEChartsOptionFromChart(parsed, effectivePalette, isDark, ECHART_EXPORT_WIDTH);
4667
4543
  } else {
4668
4544
  const parsed = parseEChart(content, effectivePalette);
4669
4545
  if (parsed.error) return "";
@@ -4694,31 +4570,22 @@ async function renderEChartsForExport(content, theme, palette, options) {
4694
4570
  chart.dispose();
4695
4571
  }
4696
4572
  }
4697
- var echarts, ECHART_EXPORT_WIDTH, ECHART_EXPORT_HEIGHT, STANDARD_CHART_TYPES;
4573
+ var echarts, EMPHASIS_SELF, CHART_BASE, ECHART_EXPORT_WIDTH, ECHART_EXPORT_HEIGHT;
4698
4574
  var init_echarts = __esm({
4699
4575
  "src/echarts.ts"() {
4700
4576
  "use strict";
4701
4577
  echarts = __toESM(require("echarts"), 1);
4702
4578
  init_fonts();
4703
4579
  init_branding();
4704
- init_colors();
4705
4580
  init_palettes();
4706
4581
  init_chart();
4707
4582
  init_diagnostics();
4708
4583
  init_parsing();
4584
+ init_dgmo_router();
4585
+ EMPHASIS_SELF = { focus: "self", blurScope: "global" };
4586
+ CHART_BASE = { backgroundColor: "transparent", animation: false };
4709
4587
  ECHART_EXPORT_WIDTH = 1200;
4710
4588
  ECHART_EXPORT_HEIGHT = 800;
4711
- STANDARD_CHART_TYPES = /* @__PURE__ */ new Set([
4712
- "bar",
4713
- "line",
4714
- "multi-line",
4715
- "area",
4716
- "pie",
4717
- "doughnut",
4718
- "radar",
4719
- "polar-area",
4720
- "bar-stacked"
4721
- ]);
4722
4589
  }
4723
4590
  });
4724
4591
 
@@ -6048,6 +5915,7 @@ var init_parser7 = __esm({
6048
5915
  var dgmo_router_exports = {};
6049
5916
  __export(dgmo_router_exports, {
6050
5917
  DGMO_CHART_TYPE_MAP: () => DGMO_CHART_TYPE_MAP,
5918
+ STANDARD_CHART_TYPES: () => STANDARD_CHART_TYPES,
6051
5919
  getDgmoFramework: () => getDgmoFramework,
6052
5920
  parseDgmo: () => parseDgmo,
6053
5921
  parseDgmoChartType: () => parseDgmoChartType
@@ -6075,53 +5943,19 @@ function parseDgmoChartType(content) {
6075
5943
  function parseDgmo(content) {
6076
5944
  const chartType = parseDgmoChartType(content);
6077
5945
  if (!chartType) {
6078
- const parsed2 = parseD3(content);
6079
- return { diagnostics: parsed2.diagnostics };
6080
- }
6081
- if (chartType === "sequence") {
6082
- const parsed2 = parseSequenceDgmo(content);
6083
- return { diagnostics: parsed2.diagnostics };
6084
- }
6085
- if (chartType === "flowchart") {
6086
- const parsed2 = parseFlowchart(content);
6087
- return { diagnostics: parsed2.diagnostics };
6088
- }
6089
- if (chartType === "class") {
6090
- const parsed2 = parseClassDiagram(content);
6091
- return { diagnostics: parsed2.diagnostics };
5946
+ return { diagnostics: parseD3(content).diagnostics };
6092
5947
  }
6093
- if (chartType === "er") {
6094
- const parsed2 = parseERDiagram(content);
6095
- return { diagnostics: parsed2.diagnostics };
6096
- }
6097
- if (chartType === "org") {
6098
- const parsed2 = parseOrg(content);
6099
- return { diagnostics: parsed2.diagnostics };
6100
- }
6101
- if (chartType === "kanban") {
6102
- const parsed2 = parseKanban(content);
6103
- return { diagnostics: parsed2.diagnostics };
6104
- }
6105
- if (chartType === "c4") {
6106
- const parsed2 = parseC4(content);
6107
- return { diagnostics: parsed2.diagnostics };
6108
- }
6109
- if (chartType === "initiative-status") {
6110
- const parsed2 = parseInitiativeStatus(content);
6111
- return { diagnostics: parsed2.diagnostics };
6112
- }
6113
- if (STANDARD_CHART_TYPES2.has(chartType)) {
6114
- const parsed2 = parseChart(content);
6115
- return { diagnostics: parsed2.diagnostics };
5948
+ const directParser = PARSE_DISPATCH.get(chartType);
5949
+ if (directParser) return { diagnostics: directParser(content).diagnostics };
5950
+ if (STANDARD_CHART_TYPES.has(chartType)) {
5951
+ return { diagnostics: parseChart(content).diagnostics };
6116
5952
  }
6117
5953
  if (ECHART_TYPES.has(chartType)) {
6118
- const parsed2 = parseEChart(content);
6119
- return { diagnostics: parsed2.diagnostics };
5954
+ return { diagnostics: parseEChart(content).diagnostics };
6120
5955
  }
6121
- const parsed = parseD3(content);
6122
- return { diagnostics: parsed.diagnostics };
5956
+ return { diagnostics: parseD3(content).diagnostics };
6123
5957
  }
6124
- var DGMO_CHART_TYPE_MAP, STANDARD_CHART_TYPES2, ECHART_TYPES;
5958
+ var DGMO_CHART_TYPE_MAP, STANDARD_CHART_TYPES, ECHART_TYPES, PARSE_DISPATCH;
6125
5959
  var init_dgmo_router = __esm({
6126
5960
  "src/dgmo-router.ts"() {
6127
5961
  "use strict";
@@ -6170,7 +6004,7 @@ var init_dgmo_router = __esm({
6170
6004
  c4: "d3",
6171
6005
  "initiative-status": "d3"
6172
6006
  };
6173
- STANDARD_CHART_TYPES2 = /* @__PURE__ */ new Set([
6007
+ STANDARD_CHART_TYPES = /* @__PURE__ */ new Set([
6174
6008
  "bar",
6175
6009
  "line",
6176
6010
  "multi-line",
@@ -6189,6 +6023,16 @@ var init_dgmo_router = __esm({
6189
6023
  "heatmap",
6190
6024
  "funnel"
6191
6025
  ]);
6026
+ PARSE_DISPATCH = /* @__PURE__ */ new Map([
6027
+ ["sequence", (c) => parseSequenceDgmo(c)],
6028
+ ["flowchart", (c) => parseFlowchart(c)],
6029
+ ["class", (c) => parseClassDiagram(c)],
6030
+ ["er", (c) => parseERDiagram(c)],
6031
+ ["org", (c) => parseOrg(c)],
6032
+ ["kanban", (c) => parseKanban(c)],
6033
+ ["c4", (c) => parseC4(c)],
6034
+ ["initiative-status", (c) => parseInitiativeStatus(c)]
6035
+ ]);
6192
6036
  }
6193
6037
  });
6194
6038
 
@@ -12187,7 +12031,7 @@ function buildRenderSequence(messages) {
12187
12031
  type: "return",
12188
12032
  from: top.to,
12189
12033
  to: top.from,
12190
- label: top.returnLabel || "",
12034
+ label: "",
12191
12035
  messageIndex: top.messageIndex
12192
12036
  });
12193
12037
  }
@@ -12213,12 +12057,8 @@ function buildRenderSequence(messages) {
12213
12057
  to: msg.to,
12214
12058
  label: msg.label,
12215
12059
  messageIndex: mi,
12216
- ...msg.async ? { async: true } : {},
12217
- ...msg.bidirectional ? { bidirectional: true } : {}
12060
+ ...msg.async ? { async: true } : {}
12218
12061
  });
12219
- if (msg.bidirectional) {
12220
- continue;
12221
- }
12222
12062
  if (msg.async) {
12223
12063
  continue;
12224
12064
  }
@@ -12227,14 +12067,13 @@ function buildRenderSequence(messages) {
12227
12067
  type: "return",
12228
12068
  from: msg.to,
12229
12069
  to: msg.from,
12230
- label: msg.returnLabel || "",
12070
+ label: "",
12231
12071
  messageIndex: mi
12232
12072
  });
12233
12073
  } else {
12234
12074
  stack.push({
12235
12075
  from: msg.from,
12236
12076
  to: msg.to,
12237
- returnLabel: msg.returnLabel,
12238
12077
  messageIndex: mi
12239
12078
  });
12240
12079
  }
@@ -12245,7 +12084,7 @@ function buildRenderSequence(messages) {
12245
12084
  type: "return",
12246
12085
  from: top.to,
12247
12086
  to: top.from,
12248
- label: top.returnLabel || "",
12087
+ label: "",
12249
12088
  messageIndex: top.messageIndex
12250
12089
  });
12251
12090
  }
@@ -12710,14 +12549,6 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
12710
12549
  "points",
12711
12550
  `0,0 ${ARROWHEAD_SIZE},${ARROWHEAD_SIZE / 2} 0,${ARROWHEAD_SIZE}`
12712
12551
  ).attr("fill", "none").attr("stroke", palette.text).attr("stroke-width", 1.2);
12713
- defs.append("marker").attr("id", "seq-arrowhead-reverse").attr("viewBox", `0 0 ${ARROWHEAD_SIZE} ${ARROWHEAD_SIZE}`).attr("refX", 0).attr("refY", ARROWHEAD_SIZE / 2).attr("markerWidth", ARROWHEAD_SIZE).attr("markerHeight", ARROWHEAD_SIZE).attr("orient", "auto").append("polygon").attr(
12714
- "points",
12715
- `${ARROWHEAD_SIZE},0 0,${ARROWHEAD_SIZE / 2} ${ARROWHEAD_SIZE},${ARROWHEAD_SIZE}`
12716
- ).attr("fill", palette.text);
12717
- defs.append("marker").attr("id", "seq-arrowhead-async-reverse").attr("viewBox", `0 0 ${ARROWHEAD_SIZE} ${ARROWHEAD_SIZE}`).attr("refX", 0).attr("refY", ARROWHEAD_SIZE / 2).attr("markerWidth", ARROWHEAD_SIZE).attr("markerHeight", ARROWHEAD_SIZE).attr("orient", "auto").append("polyline").attr(
12718
- "points",
12719
- `${ARROWHEAD_SIZE},0 0,${ARROWHEAD_SIZE / 2} ${ARROWHEAD_SIZE},${ARROWHEAD_SIZE}`
12720
- ).attr("fill", "none").attr("stroke", palette.text).attr("stroke-width", 1.2);
12721
12552
  if (title) {
12722
12553
  const titleEl = svg.append("text").attr("class", "chart-title").attr("x", svgWidth / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", palette.text).attr("font-size", 20).attr("font-weight", "bold").text(title);
12723
12554
  if (parsed.titleLineNumber) {
@@ -12998,17 +12829,10 @@ function renderSequenceDiagram(container, parsed, palette, isDark, _onNavigateTo
12998
12829
  const x1 = arrowEdgeX(step.from, i, goingRight ? "right" : "left");
12999
12830
  const x2 = arrowEdgeX(step.to, i, goingRight ? "left" : "right");
13000
12831
  const markerRef = step.async ? "url(#seq-arrowhead-async)" : "url(#seq-arrowhead)";
13001
- const markerStartRef = step.bidirectional ? step.async ? "url(#seq-arrowhead-async-reverse)" : "url(#seq-arrowhead-reverse)" : null;
13002
- const line7 = svg.append("line").attr("x1", x1).attr("y1", y).attr("x2", x2).attr("y2", y).attr("stroke", palette.text).attr("stroke-width", 1.2).attr("marker-end", markerRef).attr("class", "message-arrow").attr(
12832
+ svg.append("line").attr("x1", x1).attr("y1", y).attr("x2", x2).attr("y2", y).attr("stroke", palette.text).attr("stroke-width", 1.2).attr("marker-end", markerRef).attr("class", "message-arrow").attr(
13003
12833
  "data-line-number",
13004
12834
  String(messages[step.messageIndex].lineNumber)
13005
12835
  ).attr("data-msg-index", String(step.messageIndex)).attr("data-step-index", String(i));
13006
- if (markerStartRef) {
13007
- line7.attr("marker-start", markerStartRef);
13008
- }
13009
- if (step.bidirectional && step.async) {
13010
- line7.attr("stroke-dasharray", "6 4");
13011
- }
13012
12836
  if (step.label) {
13013
12837
  const midX = (x1 + x2) / 2;
13014
12838
  const labelEl = svg.append("text").attr("x", midX).attr("y", y - 8).attr("text-anchor", "middle").attr("fill", palette.text).attr("font-size", 12).attr("class", "message-label").attr(
@@ -13235,6 +13059,32 @@ var init_renderer7 = __esm({
13235
13059
  });
13236
13060
 
13237
13061
  // src/d3.ts
13062
+ function renderChartTitle(svg, title, titleLineNumber, width, textColor, onClickItem) {
13063
+ if (!title) return;
13064
+ const titleEl = svg.append("text").attr("class", "chart-title").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").style("cursor", onClickItem && titleLineNumber ? "pointer" : "default").text(title);
13065
+ if (titleLineNumber) {
13066
+ titleEl.attr("data-line-number", titleLineNumber);
13067
+ if (onClickItem) {
13068
+ titleEl.on("click", () => onClickItem(titleLineNumber)).on("mouseenter", function() {
13069
+ d3Selection9.select(this).attr("opacity", 0.7);
13070
+ }).on("mouseleave", function() {
13071
+ d3Selection9.select(this).attr("opacity", 1);
13072
+ });
13073
+ }
13074
+ }
13075
+ }
13076
+ function initD3Chart(container, palette, exportDims) {
13077
+ d3Selection9.select(container).selectAll(":not([data-d3-tooltip])").remove();
13078
+ const width = exportDims?.width ?? container.clientWidth;
13079
+ const height = exportDims?.height ?? container.clientHeight;
13080
+ if (width <= 0 || height <= 0) return null;
13081
+ const textColor = palette.text;
13082
+ const mutedColor = palette.border;
13083
+ const bgColor = palette.bg;
13084
+ const colors = getSeriesColors(palette);
13085
+ const svg = d3Selection9.select(container).append("svg").attr("width", width).attr("height", height).style("background", bgColor);
13086
+ return { svg, width, height, textColor, mutedColor, bgColor, colors };
13087
+ }
13238
13088
  function parseTimelineDate(s) {
13239
13089
  const parts = s.split("-").map((p) => parseInt(p, 10));
13240
13090
  const year = parts[0];
@@ -13797,13 +13647,28 @@ function tokenizeFreeformText(text) {
13797
13647
  }
13798
13648
  return Array.from(counts.entries()).map(([text2, count]) => ({ text: text2, weight: count, lineNumber: 0 })).sort((a, b) => b.weight - a.weight);
13799
13649
  }
13650
+ function resolveVerticalCollisions(items, minGap, maxY) {
13651
+ if (items.length === 0) return [];
13652
+ const sorted = items.map((it, i) => ({ ...it, idx: i })).sort((a, b) => a.naturalY - b.naturalY);
13653
+ const adjustedY = new Array(items.length);
13654
+ let prevBottom = -Infinity;
13655
+ for (const item of sorted) {
13656
+ const halfH = item.height / 2;
13657
+ let top = Math.max(item.naturalY - halfH, prevBottom + minGap);
13658
+ if (maxY !== void 0) {
13659
+ top = Math.min(top, maxY - item.height);
13660
+ }
13661
+ adjustedY[item.idx] = top + halfH;
13662
+ prevBottom = top + item.height;
13663
+ }
13664
+ return adjustedY;
13665
+ }
13800
13666
  function renderSlopeChart(container, parsed, palette, isDark, onClickItem, exportDims) {
13801
- d3Selection9.select(container).selectAll(":not([data-d3-tooltip])").remove();
13802
13667
  const { periods, data, title } = parsed;
13803
13668
  if (data.length === 0 || periods.length < 2) return;
13804
- const width = exportDims?.width ?? container.clientWidth;
13805
- const height = exportDims?.height ?? container.clientHeight;
13806
- if (width <= 0 || height <= 0) return;
13669
+ const init2 = initD3Chart(container, palette, exportDims);
13670
+ if (!init2) return;
13671
+ const { svg, width, height, textColor, mutedColor, bgColor, colors } = init2;
13807
13672
  const maxLabelText = data.reduce((longest, item) => {
13808
13673
  const text = `${item.values[item.values.length - 1]} \u2014 ${item.label}`;
13809
13674
  return text.length > longest.length ? text : longest;
@@ -13816,56 +13681,94 @@ function renderSlopeChart(container, parsed, palette, isDark, onClickItem, expor
13816
13681
  );
13817
13682
  const innerWidth = width - SLOPE_MARGIN.left - rightMargin;
13818
13683
  const innerHeight = height - SLOPE_MARGIN.top - SLOPE_MARGIN.bottom;
13819
- const textColor = palette.text;
13820
- const mutedColor = palette.border;
13821
- const bgColor = palette.bg;
13822
- const colors = getSeriesColors(palette);
13823
13684
  const allValues = data.flatMap((d) => d.values);
13824
13685
  const [minVal, maxVal] = d3Array.extent(allValues);
13825
13686
  const valuePadding = (maxVal - minVal) * 0.1 || 1;
13826
13687
  const yScale = d3Scale.scaleLinear().domain([minVal - valuePadding, maxVal + valuePadding]).range([innerHeight, 0]);
13827
13688
  const xScale = d3Scale.scalePoint().domain(periods).range([0, innerWidth]).padding(0);
13828
- const svg = d3Selection9.select(container).append("svg").attr("width", width).attr("height", height).style("background", bgColor);
13829
13689
  const g = svg.append("g").attr("transform", `translate(${SLOPE_MARGIN.left},${SLOPE_MARGIN.top})`);
13830
13690
  const tooltip = createTooltip(container, palette, isDark);
13831
- if (title) {
13832
- const titleEl = svg.append("text").attr("class", "chart-title").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").style("cursor", onClickItem && parsed.titleLineNumber ? "pointer" : "default").text(title);
13833
- if (parsed.titleLineNumber) {
13834
- titleEl.attr("data-line-number", parsed.titleLineNumber);
13835
- if (onClickItem) {
13836
- titleEl.on("click", () => onClickItem(parsed.titleLineNumber)).on("mouseenter", function() {
13837
- d3Selection9.select(this).attr("opacity", 0.7);
13838
- }).on("mouseleave", function() {
13839
- d3Selection9.select(this).attr("opacity", 1);
13840
- });
13841
- }
13842
- }
13843
- }
13691
+ renderChartTitle(svg, title, parsed.titleLineNumber, width, textColor, onClickItem);
13844
13692
  for (const period of periods) {
13845
13693
  const x = xScale(period);
13846
13694
  g.append("text").attr("x", x).attr("y", -15).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "18px").attr("font-weight", "600").text(period);
13847
13695
  g.append("line").attr("x1", x).attr("y1", 0).attr("x2", x).attr("y2", innerHeight).attr("stroke", mutedColor).attr("stroke-width", 1).attr("stroke-dasharray", "4,4");
13848
13696
  }
13849
13697
  const lineGen = d3Shape6.line().x((_d, i) => xScale(periods[i])).y((d) => yScale(d));
13850
- data.forEach((item, idx) => {
13698
+ const seriesInfo = data.map((item, idx) => {
13851
13699
  const color = item.color ?? colors[idx % colors.length];
13852
- const seriesG = g.append("g").attr("class", "slope-series").attr("data-line-number", String(item.lineNumber));
13853
13700
  const firstVal = item.values[0];
13854
13701
  const lastVal = item.values[item.values.length - 1];
13855
13702
  const absChange = lastVal - firstVal;
13856
13703
  const pctChange = firstVal !== 0 ? absChange / firstVal * 100 : null;
13857
13704
  const sign = absChange > 0 ? "+" : "";
13858
- const pctPart = pctChange !== null ? ` (${sign}${pctChange.toFixed(1)}%)` : "";
13859
- const tipLines = [`${sign}${absChange}`];
13705
+ const tipLines = [`${sign}${parseFloat(absChange.toFixed(2))}`];
13860
13706
  if (pctChange !== null) tipLines.push(`${sign}${pctChange.toFixed(1)}%`);
13861
13707
  const tipHtml = tipLines.join("<br>");
13708
+ const lastX = xScale(periods[periods.length - 1]);
13709
+ const labelText = `${lastVal} \u2014 ${item.label}`;
13710
+ const availableWidth = rightMargin - 15;
13711
+ const maxChars = Math.floor(availableWidth / SLOPE_CHAR_WIDTH);
13712
+ let labelLineCount = 1;
13713
+ let wrappedLines = null;
13714
+ if (labelText.length > maxChars) {
13715
+ const words = labelText.split(/\s+/);
13716
+ const lines = [];
13717
+ let current = "";
13718
+ for (const word of words) {
13719
+ const test = current ? `${current} ${word}` : word;
13720
+ if (test.length > maxChars && current) {
13721
+ lines.push(current);
13722
+ current = word;
13723
+ } else {
13724
+ current = test;
13725
+ }
13726
+ }
13727
+ if (current) lines.push(current);
13728
+ labelLineCount = lines.length;
13729
+ wrappedLines = lines;
13730
+ }
13731
+ const lineHeight = SLOPE_LABEL_FONT_SIZE * 1.2;
13732
+ const labelHeight = labelLineCount === 1 ? SLOPE_LABEL_FONT_SIZE : labelLineCount * lineHeight;
13733
+ return {
13734
+ item,
13735
+ idx,
13736
+ color,
13737
+ firstVal,
13738
+ lastVal,
13739
+ tipHtml,
13740
+ lastX,
13741
+ labelText,
13742
+ maxChars,
13743
+ wrappedLines,
13744
+ labelHeight
13745
+ };
13746
+ });
13747
+ const leftLabelHeight = 20;
13748
+ const leftLabelCollisions = /* @__PURE__ */ new Map();
13749
+ for (let pi = 0; pi < periods.length - 1; pi++) {
13750
+ const entries = data.map((item) => ({
13751
+ naturalY: yScale(item.values[pi]),
13752
+ height: leftLabelHeight
13753
+ }));
13754
+ leftLabelCollisions.set(pi, resolveVerticalCollisions(entries, 4, innerHeight));
13755
+ }
13756
+ const rightEntries = seriesInfo.map((si) => ({
13757
+ naturalY: yScale(si.lastVal),
13758
+ height: Math.max(si.labelHeight, SLOPE_LABEL_FONT_SIZE * 1.4)
13759
+ }));
13760
+ const rightAdjustedY = resolveVerticalCollisions(rightEntries, 4, innerHeight);
13761
+ data.forEach((item, idx) => {
13762
+ const si = seriesInfo[idx];
13763
+ const color = si.color;
13764
+ const seriesG = g.append("g").attr("class", "slope-series").attr("data-line-number", String(item.lineNumber));
13862
13765
  seriesG.append("path").datum(item.values).attr("fill", "none").attr("stroke", color).attr("stroke-width", 2.5).attr("d", lineGen);
13863
13766
  seriesG.append("path").datum(item.values).attr("fill", "none").attr("stroke", "transparent").attr("stroke-width", 14).attr("d", lineGen).style("cursor", onClickItem ? "pointer" : "default").on(
13864
13767
  "mouseenter",
13865
- (event) => showTooltip(tooltip, tipHtml, event)
13768
+ (event) => showTooltip(tooltip, si.tipHtml, event)
13866
13769
  ).on(
13867
13770
  "mousemove",
13868
- (event) => showTooltip(tooltip, tipHtml, event)
13771
+ (event) => showTooltip(tooltip, si.tipHtml, event)
13869
13772
  ).on("mouseleave", () => hideTooltip(tooltip)).on("click", () => {
13870
13773
  if (onClickItem && item.lineNumber) onClickItem(item.lineNumber);
13871
13774
  });
@@ -13874,46 +13777,30 @@ function renderSlopeChart(container, parsed, palette, isDark, onClickItem, expor
13874
13777
  const y = yScale(val);
13875
13778
  seriesG.append("circle").attr("cx", x).attr("cy", y).attr("r", 4).attr("fill", color).attr("stroke", bgColor).attr("stroke-width", 1.5).style("cursor", onClickItem ? "pointer" : "default").on(
13876
13779
  "mouseenter",
13877
- (event) => showTooltip(tooltip, tipHtml, event)
13780
+ (event) => showTooltip(tooltip, si.tipHtml, event)
13878
13781
  ).on(
13879
13782
  "mousemove",
13880
- (event) => showTooltip(tooltip, tipHtml, event)
13783
+ (event) => showTooltip(tooltip, si.tipHtml, event)
13881
13784
  ).on("mouseleave", () => hideTooltip(tooltip)).on("click", () => {
13882
13785
  if (onClickItem && item.lineNumber) onClickItem(item.lineNumber);
13883
13786
  });
13884
13787
  const isFirst = i === 0;
13885
13788
  const isLast = i === periods.length - 1;
13886
13789
  if (!isLast) {
13887
- seriesG.append("text").attr("x", isFirst ? x - 10 : x).attr("y", y).attr("dy", "0.35em").attr("text-anchor", isFirst ? "end" : "middle").attr("fill", textColor).attr("font-size", "16px").text(val.toString());
13790
+ const adjustedY = leftLabelCollisions.get(i)[idx];
13791
+ seriesG.append("text").attr("x", isFirst ? x - 10 : x).attr("y", adjustedY).attr("dy", "0.35em").attr("text-anchor", isFirst ? "end" : "middle").attr("fill", color).attr("font-size", "16px").text(val.toString());
13888
13792
  }
13889
13793
  });
13890
- const lastX = xScale(periods[periods.length - 1]);
13891
- const lastY = yScale(lastVal);
13892
- const labelText = `${lastVal} \u2014 ${item.label}`;
13893
- const availableWidth = rightMargin - 15;
13894
- const maxChars = Math.floor(availableWidth / SLOPE_CHAR_WIDTH);
13895
- const labelEl = seriesG.append("text").attr("x", lastX + 10).attr("y", lastY).attr("text-anchor", "start").attr("fill", color).attr("font-size", `${SLOPE_LABEL_FONT_SIZE}px`).attr("font-weight", "500");
13896
- if (labelText.length <= maxChars) {
13897
- labelEl.attr("dy", "0.35em").text(labelText);
13794
+ const adjustedLastY = rightAdjustedY[idx];
13795
+ const labelEl = seriesG.append("text").attr("x", si.lastX + 10).attr("y", adjustedLastY).attr("text-anchor", "start").attr("fill", color).attr("font-size", `${SLOPE_LABEL_FONT_SIZE}px`).attr("font-weight", "500");
13796
+ if (!si.wrappedLines) {
13797
+ labelEl.attr("dy", "0.35em").text(si.labelText);
13898
13798
  } else {
13899
- const words = labelText.split(/\s+/);
13900
- const lines = [];
13901
- let current = "";
13902
- for (const word of words) {
13903
- const test = current ? `${current} ${word}` : word;
13904
- if (test.length > maxChars && current) {
13905
- lines.push(current);
13906
- current = word;
13907
- } else {
13908
- current = test;
13909
- }
13910
- }
13911
- if (current) lines.push(current);
13912
13799
  const lineHeight = SLOPE_LABEL_FONT_SIZE * 1.2;
13913
- const totalHeight = (lines.length - 1) * lineHeight;
13800
+ const totalHeight = (si.wrappedLines.length - 1) * lineHeight;
13914
13801
  const startDy = -totalHeight / 2;
13915
- lines.forEach((line7, li) => {
13916
- labelEl.append("tspan").attr("x", lastX + 10).attr(
13802
+ si.wrappedLines.forEach((line7, li) => {
13803
+ labelEl.append("tspan").attr("x", si.lastX + 10).attr(
13917
13804
  "dy",
13918
13805
  li === 0 ? `${startDy + SLOPE_LABEL_FONT_SIZE * 0.35}px` : `${lineHeight}px`
13919
13806
  ).text(line7);
@@ -14010,12 +13897,11 @@ function orderArcNodes(links, order, groups) {
14010
13897
  return allNodes;
14011
13898
  }
14012
13899
  function renderArcDiagram(container, parsed, palette, _isDark, onClickItem, exportDims) {
14013
- d3Selection9.select(container).selectAll(":not([data-d3-tooltip])").remove();
14014
13900
  const { links, title, orientation, arcOrder, arcNodeGroups } = parsed;
14015
13901
  if (links.length === 0) return;
14016
- const width = exportDims?.width ?? container.clientWidth;
14017
- const height = exportDims?.height ?? container.clientHeight;
14018
- if (width <= 0 || height <= 0) return;
13902
+ const init2 = initD3Chart(container, palette, exportDims);
13903
+ if (!init2) return;
13904
+ const { svg, width, height, textColor, mutedColor, bgColor, colors } = init2;
14019
13905
  const isVertical = orientation === "vertical";
14020
13906
  const margin = isVertical ? {
14021
13907
  top: ARC_MARGIN.top,
@@ -14025,10 +13911,6 @@ function renderArcDiagram(container, parsed, palette, _isDark, onClickItem, expo
14025
13911
  } : ARC_MARGIN;
14026
13912
  const innerWidth = width - margin.left - margin.right;
14027
13913
  const innerHeight = height - margin.top - margin.bottom;
14028
- const textColor = palette.text;
14029
- const mutedColor = palette.border;
14030
- const bgColor = palette.bg;
14031
- const colors = getSeriesColors(palette);
14032
13914
  const nodes = orderArcNodes(links, arcOrder, arcNodeGroups);
14033
13915
  const nodeColorMap = /* @__PURE__ */ new Map();
14034
13916
  for (const group of arcNodeGroups) {
@@ -14047,21 +13929,8 @@ function renderArcDiagram(container, parsed, palette, _isDark, onClickItem, expo
14047
13929
  const values = links.map((l) => l.value);
14048
13930
  const [minVal, maxVal] = d3Array.extent(values);
14049
13931
  const strokeScale = d3Scale.scaleLinear().domain([minVal, maxVal]).range([1.5, 6]);
14050
- const svg = d3Selection9.select(container).append("svg").attr("width", width).attr("height", height).style("background", bgColor);
14051
13932
  const g = svg.append("g").attr("transform", `translate(${margin.left},${margin.top})`);
14052
- if (title) {
14053
- const titleEl = svg.append("text").attr("class", "chart-title").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").style("cursor", onClickItem && parsed.titleLineNumber ? "pointer" : "default").text(title);
14054
- if (parsed.titleLineNumber) {
14055
- titleEl.attr("data-line-number", parsed.titleLineNumber);
14056
- if (onClickItem) {
14057
- titleEl.on("click", () => onClickItem(parsed.titleLineNumber)).on("mouseenter", function() {
14058
- d3Selection9.select(this).attr("opacity", 0.7);
14059
- }).on("mouseleave", function() {
14060
- d3Selection9.select(this).attr("opacity", 1);
14061
- });
14062
- }
14063
- }
14064
- }
13933
+ renderChartTitle(svg, title, parsed.titleLineNumber, width, textColor, onClickItem);
14065
13934
  const neighbors = /* @__PURE__ */ new Map();
14066
13935
  for (const node of nodes) neighbors.set(node, /* @__PURE__ */ new Set());
14067
13936
  for (const link of links) {
@@ -14597,19 +14466,7 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
14597
14466
  const yScale = d3Scale.scaleLinear().domain([minDate - datePadding, maxDate + datePadding]).range([0, innerHeight]);
14598
14467
  const svg = d3Selection9.select(container).append("svg").attr("width", width).attr("height", height).style("background", bgColor);
14599
14468
  const g = svg.append("g").attr("transform", `translate(${margin.left},${margin.top})`);
14600
- if (title) {
14601
- const titleEl = svg.append("text").attr("class", "chart-title").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").style("cursor", onClickItem && parsed.titleLineNumber ? "pointer" : "default").text(title);
14602
- if (parsed.titleLineNumber) {
14603
- titleEl.attr("data-line-number", parsed.titleLineNumber);
14604
- if (onClickItem) {
14605
- titleEl.on("click", () => onClickItem(parsed.titleLineNumber)).on("mouseenter", function() {
14606
- d3Selection9.select(this).attr("opacity", 0.7);
14607
- }).on("mouseleave", function() {
14608
- d3Selection9.select(this).attr("opacity", 1);
14609
- });
14610
- }
14611
- }
14612
- }
14469
+ renderChartTitle(svg, title, parsed.titleLineNumber, width, textColor, onClickItem);
14613
14470
  renderEras(
14614
14471
  g,
14615
14472
  timelineEras,
@@ -14712,19 +14569,7 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
14712
14569
  const sorted = timelineEvents.slice().sort((a, b) => parseTimelineDate(a.date) - parseTimelineDate(b.date));
14713
14570
  const svg = d3Selection9.select(container).append("svg").attr("width", width).attr("height", height).style("background", bgColor);
14714
14571
  const g = svg.append("g").attr("transform", `translate(${margin.left},${margin.top})`);
14715
- if (title) {
14716
- const titleEl = svg.append("text").attr("class", "chart-title").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").style("cursor", onClickItem && parsed.titleLineNumber ? "pointer" : "default").text(title);
14717
- if (parsed.titleLineNumber) {
14718
- titleEl.attr("data-line-number", parsed.titleLineNumber);
14719
- if (onClickItem) {
14720
- titleEl.on("click", () => onClickItem(parsed.titleLineNumber)).on("mouseenter", function() {
14721
- d3Selection9.select(this).attr("opacity", 0.7);
14722
- }).on("mouseleave", function() {
14723
- d3Selection9.select(this).attr("opacity", 1);
14724
- });
14725
- }
14726
- }
14727
- }
14572
+ renderChartTitle(svg, title, parsed.titleLineNumber, width, textColor, onClickItem);
14728
14573
  renderEras(
14729
14574
  g,
14730
14575
  timelineEras,
@@ -14856,19 +14701,7 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
14856
14701
  const xScale = d3Scale.scaleLinear().domain([minDate - datePadding, maxDate + datePadding]).range([0, innerWidth]);
14857
14702
  const svg = d3Selection9.select(container).append("svg").attr("width", width).attr("height", height).style("background", bgColor);
14858
14703
  const g = svg.append("g").attr("transform", `translate(${margin.left},${margin.top})`);
14859
- if (title) {
14860
- const titleEl = svg.append("text").attr("class", "chart-title").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").style("cursor", onClickItem && parsed.titleLineNumber ? "pointer" : "default").text(title);
14861
- if (parsed.titleLineNumber) {
14862
- titleEl.attr("data-line-number", parsed.titleLineNumber);
14863
- if (onClickItem) {
14864
- titleEl.on("click", () => onClickItem(parsed.titleLineNumber)).on("mouseenter", function() {
14865
- d3Selection9.select(this).attr("opacity", 0.7);
14866
- }).on("mouseleave", function() {
14867
- d3Selection9.select(this).attr("opacity", 1);
14868
- });
14869
- }
14870
- }
14871
- }
14704
+ renderChartTitle(svg, title, parsed.titleLineNumber, width, textColor, onClickItem);
14872
14705
  renderEras(
14873
14706
  g,
14874
14707
  timelineEras,
@@ -15011,19 +14844,7 @@ function renderTimeline(container, parsed, palette, isDark, onClickItem, exportD
15011
14844
  const xScale = d3Scale.scaleLinear().domain([minDate - datePadding, maxDate + datePadding]).range([0, innerWidth]);
15012
14845
  const svg = d3Selection9.select(container).append("svg").attr("width", width).attr("height", height).style("background", bgColor);
15013
14846
  const g = svg.append("g").attr("transform", `translate(${margin.left},${margin.top})`);
15014
- if (title) {
15015
- const titleEl = svg.append("text").attr("class", "chart-title").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").style("cursor", onClickItem && parsed.titleLineNumber ? "pointer" : "default").text(title);
15016
- if (parsed.titleLineNumber) {
15017
- titleEl.attr("data-line-number", parsed.titleLineNumber);
15018
- if (onClickItem) {
15019
- titleEl.on("click", () => onClickItem(parsed.titleLineNumber)).on("mouseenter", function() {
15020
- d3Selection9.select(this).attr("opacity", 0.7);
15021
- }).on("mouseleave", function() {
15022
- d3Selection9.select(this).attr("opacity", 1);
15023
- });
15024
- }
15025
- }
15026
- }
14847
+ renderChartTitle(svg, title, parsed.titleLineNumber, width, textColor, onClickItem);
15027
14848
  renderEras(
15028
14849
  g,
15029
14850
  timelineEras,
@@ -15150,17 +14971,13 @@ function getRotateFn(mode) {
15150
14971
  return () => 0;
15151
14972
  }
15152
14973
  function renderWordCloud(container, parsed, palette, _isDark, onClickItem, exportDims) {
15153
- d3Selection9.select(container).selectAll(":not([data-d3-tooltip])").remove();
15154
14974
  const { words, title, cloudOptions } = parsed;
15155
14975
  if (words.length === 0) return;
15156
- const width = exportDims?.width ?? container.clientWidth;
15157
- const height = exportDims?.height ?? container.clientHeight;
15158
- if (width <= 0 || height <= 0) return;
14976
+ const init2 = initD3Chart(container, palette, exportDims);
14977
+ if (!init2) return;
14978
+ const { svg, width, height, textColor, colors } = init2;
15159
14979
  const titleHeight = title ? 40 : 0;
15160
14980
  const cloudHeight = height - titleHeight;
15161
- const textColor = palette.text;
15162
- const bgColor = palette.bg;
15163
- const colors = getSeriesColors(palette);
15164
14981
  const { minSize, maxSize } = cloudOptions;
15165
14982
  const weights = words.map((w) => w.weight);
15166
14983
  const minWeight = Math.min(...weights);
@@ -15171,20 +14988,7 @@ function renderWordCloud(container, parsed, palette, _isDark, onClickItem, expor
15171
14988
  return minSize + t * (maxSize - minSize);
15172
14989
  };
15173
14990
  const rotateFn = getRotateFn(cloudOptions.rotate);
15174
- const svg = d3Selection9.select(container).append("svg").attr("width", width).attr("height", height).style("background", bgColor);
15175
- if (title) {
15176
- const titleEl = svg.append("text").attr("class", "chart-title").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").style("cursor", onClickItem && parsed.titleLineNumber ? "pointer" : "default").text(title);
15177
- if (parsed.titleLineNumber) {
15178
- titleEl.attr("data-line-number", parsed.titleLineNumber);
15179
- if (onClickItem) {
15180
- titleEl.on("click", () => onClickItem(parsed.titleLineNumber)).on("mouseenter", function() {
15181
- d3Selection9.select(this).attr("opacity", 0.7);
15182
- }).on("mouseleave", function() {
15183
- d3Selection9.select(this).attr("opacity", 1);
15184
- });
15185
- }
15186
- }
15187
- }
14991
+ renderChartTitle(svg, title, parsed.titleLineNumber, width, textColor, onClickItem);
15188
14992
  const g = svg.append("g").attr(
15189
14993
  "transform",
15190
14994
  `translate(${width / 2},${titleHeight + cloudHeight / 2})`
@@ -15235,12 +15039,7 @@ function renderWordCloudAsync(container, parsed, palette, _isDark, exportDims) {
15235
15039
  };
15236
15040
  const rotateFn = getRotateFn(cloudOptions.rotate);
15237
15041
  const svg = d3Selection9.select(container).append("svg").attr("width", width).attr("height", height).style("background", bgColor);
15238
- if (title) {
15239
- const titleEl = svg.append("text").attr("class", "chart-title").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").text(title);
15240
- if (parsed.titleLineNumber) {
15241
- titleEl.attr("data-line-number", parsed.titleLineNumber);
15242
- }
15243
- }
15042
+ renderChartTitle(svg, title, parsed.titleLineNumber, width, textColor);
15244
15043
  const g = svg.append("g").attr(
15245
15044
  "transform",
15246
15045
  `translate(${width / 2},${titleHeight + cloudHeight / 2})`
@@ -15371,15 +15170,11 @@ function regionCentroid(circles, inside) {
15371
15170
  return { x: sx / count, y: sy / count };
15372
15171
  }
15373
15172
  function renderVenn(container, parsed, palette, isDark, onClickItem, exportDims) {
15374
- d3Selection9.select(container).selectAll(":not([data-d3-tooltip])").remove();
15375
15173
  const { vennSets, vennOverlaps, vennShowValues, title } = parsed;
15376
15174
  if (vennSets.length < 2) return;
15377
- const width = exportDims?.width ?? container.clientWidth;
15378
- const height = exportDims?.height ?? container.clientHeight;
15379
- if (width <= 0 || height <= 0) return;
15380
- const textColor = palette.text;
15381
- const bgColor = palette.bg;
15382
- const colors = getSeriesColors(palette);
15175
+ const init2 = initD3Chart(container, palette, exportDims);
15176
+ if (!init2) return;
15177
+ const { svg, width, height, textColor, colors } = init2;
15383
15178
  const titleHeight = title ? 40 : 0;
15384
15179
  const radii = vennSets.map((s) => radiusFromArea(s.size));
15385
15180
  const overlapMap = /* @__PURE__ */ new Map();
@@ -15458,21 +15253,8 @@ function renderVenn(container, parsed, palette, isDark, onClickItem, exportDims)
15458
15253
  marginTop,
15459
15254
  marginBottom
15460
15255
  ).map((c) => ({ ...c, y: c.y + titleHeight }));
15461
- const svg = d3Selection9.select(container).append("svg").attr("width", width).attr("height", height).style("background", bgColor);
15462
15256
  const tooltip = createTooltip(container, palette, isDark);
15463
- if (title) {
15464
- const titleEl = svg.append("text").attr("class", "chart-title").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").style("cursor", onClickItem && parsed.titleLineNumber ? "pointer" : "default").text(title);
15465
- if (parsed.titleLineNumber) {
15466
- titleEl.attr("data-line-number", parsed.titleLineNumber);
15467
- if (onClickItem) {
15468
- titleEl.on("click", () => onClickItem(parsed.titleLineNumber)).on("mouseenter", function() {
15469
- d3Selection9.select(this).attr("opacity", 0.7);
15470
- }).on("mouseleave", function() {
15471
- d3Selection9.select(this).attr("opacity", 1);
15472
- });
15473
- }
15474
- }
15475
- }
15257
+ renderChartTitle(svg, title, parsed.titleLineNumber, width, textColor, onClickItem);
15476
15258
  const circleEls = [];
15477
15259
  const circleGroup = svg.append("g");
15478
15260
  circles.forEach((c, i) => {
@@ -15616,7 +15398,6 @@ function renderVenn(container, parsed, palette, isDark, onClickItem, exportDims)
15616
15398
  });
15617
15399
  }
15618
15400
  function renderQuadrant(container, parsed, palette, isDark, onClickItem, exportDims) {
15619
- d3Selection9.select(container).selectAll(":not([data-d3-tooltip])").remove();
15620
15401
  const {
15621
15402
  title,
15622
15403
  quadrantLabels,
@@ -15628,12 +15409,10 @@ function renderQuadrant(container, parsed, palette, isDark, onClickItem, exportD
15628
15409
  quadrantYAxisLineNumber
15629
15410
  } = parsed;
15630
15411
  if (quadrantPoints.length === 0) return;
15631
- const width = exportDims?.width ?? container.clientWidth;
15632
- const height = exportDims?.height ?? container.clientHeight;
15633
- if (width <= 0 || height <= 0) return;
15634
- const textColor = palette.text;
15412
+ const init2 = initD3Chart(container, palette, exportDims);
15413
+ if (!init2) return;
15414
+ const { svg, width, height, textColor } = init2;
15635
15415
  const mutedColor = palette.textMuted;
15636
- const bgColor = palette.bg;
15637
15416
  const borderColor = palette.border;
15638
15417
  const defaultColors = [
15639
15418
  palette.colors.blue,
@@ -15648,24 +15427,8 @@ function renderQuadrant(container, parsed, palette, isDark, onClickItem, exportD
15648
15427
  const chartHeight = height - margin.top - margin.bottom;
15649
15428
  const xScale = d3Scale.scaleLinear().domain([0, 1]).range([0, chartWidth]);
15650
15429
  const yScale = d3Scale.scaleLinear().domain([0, 1]).range([chartHeight, 0]);
15651
- const svg = d3Selection9.select(container).append("svg").attr("width", width).attr("height", height).style("background", bgColor);
15652
15430
  const tooltip = createTooltip(container, palette, isDark);
15653
- if (title) {
15654
- const titleText = svg.append("text").attr("class", "chart-title").attr("x", width / 2).attr("y", 30).attr("text-anchor", "middle").attr("fill", textColor).attr("font-size", "20px").attr("font-weight", "700").style(
15655
- "cursor",
15656
- onClickItem && quadrantTitleLineNumber ? "pointer" : "default"
15657
- ).text(title);
15658
- if (quadrantTitleLineNumber) {
15659
- titleText.attr("data-line-number", quadrantTitleLineNumber);
15660
- }
15661
- if (onClickItem && quadrantTitleLineNumber) {
15662
- titleText.on("click", () => onClickItem(quadrantTitleLineNumber)).on("mouseenter", function() {
15663
- d3Selection9.select(this).attr("opacity", 0.7);
15664
- }).on("mouseleave", function() {
15665
- d3Selection9.select(this).attr("opacity", 1);
15666
- });
15667
- }
15668
- }
15431
+ renderChartTitle(svg, title, quadrantTitleLineNumber, width, textColor, onClickItem);
15669
15432
  const chartG = svg.append("g").attr("transform", `translate(${margin.left}, ${margin.top})`);
15670
15433
  const mixHex = (a, b, pct) => {
15671
15434
  const parse = (h) => {
@@ -15914,6 +15677,38 @@ function renderQuadrant(container, parsed, palette, isDark, onClickItem, exportD
15914
15677
  }
15915
15678
  });
15916
15679
  }
15680
+ async function resolveExportPalette(theme, palette) {
15681
+ if (palette) return palette;
15682
+ const { getPalette: getPalette2 } = await Promise.resolve().then(() => (init_palettes(), palettes_exports));
15683
+ return theme === "dark" ? getPalette2("nord").dark : getPalette2("nord").light;
15684
+ }
15685
+ function createExportContainer(width, height) {
15686
+ const container = document.createElement("div");
15687
+ container.style.width = `${width}px`;
15688
+ container.style.height = `${height}px`;
15689
+ container.style.position = "absolute";
15690
+ container.style.left = "-9999px";
15691
+ document.body.appendChild(container);
15692
+ return container;
15693
+ }
15694
+ function finalizeSvgExport(container, theme, palette, options) {
15695
+ const svgEl = container.querySelector("svg");
15696
+ if (!svgEl) return "";
15697
+ if (theme === "transparent") {
15698
+ svgEl.style.background = "none";
15699
+ } else if (!svgEl.style.background) {
15700
+ svgEl.style.background = palette.bg;
15701
+ }
15702
+ svgEl.setAttribute("xmlns", "http://www.w3.org/2000/svg");
15703
+ svgEl.style.fontFamily = FONT_FAMILY;
15704
+ const svgHtml = svgEl.outerHTML;
15705
+ document.body.removeChild(container);
15706
+ if (options?.branding !== false) {
15707
+ const brandColor = theme === "transparent" ? "#888" : palette.textMuted;
15708
+ return injectBranding(svgHtml, brandColor);
15709
+ }
15710
+ return svgHtml;
15711
+ }
15917
15712
  async function renderD3ForExport(content, theme, palette, orgExportState, options) {
15918
15713
  const { parseDgmoChartType: parseDgmoChartType2 } = await Promise.resolve().then(() => (init_dgmo_router(), dgmo_router_exports));
15919
15714
  const detectedType = parseDgmoChartType2(content);
@@ -15923,8 +15718,7 @@ async function renderD3ForExport(content, theme, palette, orgExportState, option
15923
15718
  const { collapseOrgTree: collapseOrgTree2 } = await Promise.resolve().then(() => (init_collapse(), collapse_exports));
15924
15719
  const { renderOrg: renderOrg2 } = await Promise.resolve().then(() => (init_renderer(), renderer_exports));
15925
15720
  const isDark2 = theme === "dark";
15926
- const { getPalette: getPalette3 } = await Promise.resolve().then(() => (init_palettes(), palettes_exports));
15927
- const effectivePalette2 = palette ?? (isDark2 ? getPalette3("nord").dark : getPalette3("nord").light);
15721
+ const effectivePalette2 = await resolveExportPalette(theme, palette);
15928
15722
  const orgParsed = parseOrg2(content, effectivePalette2);
15929
15723
  if (orgParsed.error) return "";
15930
15724
  const collapsedNodes = orgExportState?.collapsedNodes;
@@ -15941,83 +15735,28 @@ async function renderD3ForExport(content, theme, palette, orgExportState, option
15941
15735
  const titleOffset = effectiveParsed.title ? 30 : 0;
15942
15736
  const exportWidth = orgLayout.width + PADDING * 2;
15943
15737
  const exportHeight = orgLayout.height + PADDING * 2 + titleOffset;
15944
- const container2 = document.createElement("div");
15945
- container2.style.width = `${exportWidth}px`;
15946
- container2.style.height = `${exportHeight}px`;
15947
- container2.style.position = "absolute";
15948
- container2.style.left = "-9999px";
15949
- document.body.appendChild(container2);
15950
- try {
15951
- renderOrg2(
15952
- container2,
15953
- effectiveParsed,
15954
- orgLayout,
15955
- effectivePalette2,
15956
- isDark2,
15957
- void 0,
15958
- { width: exportWidth, height: exportHeight },
15959
- activeTagGroup,
15960
- hiddenAttributes
15961
- );
15962
- const svgEl = container2.querySelector("svg");
15963
- if (!svgEl) return "";
15964
- if (theme === "transparent") {
15965
- svgEl.style.background = "none";
15966
- } else if (!svgEl.style.background) {
15967
- svgEl.style.background = effectivePalette2.bg;
15968
- }
15969
- svgEl.setAttribute("xmlns", "http://www.w3.org/2000/svg");
15970
- svgEl.style.fontFamily = FONT_FAMILY;
15971
- const svgHtml = svgEl.outerHTML;
15972
- if (options?.branding !== false) {
15973
- const brandColor = theme === "transparent" ? "#888" : effectivePalette2.textMuted;
15974
- return injectBranding(svgHtml, brandColor);
15975
- }
15976
- return svgHtml;
15977
- } finally {
15978
- document.body.removeChild(container2);
15979
- }
15738
+ const container2 = createExportContainer(exportWidth, exportHeight);
15739
+ renderOrg2(container2, effectiveParsed, orgLayout, effectivePalette2, isDark2, void 0, { width: exportWidth, height: exportHeight }, activeTagGroup, hiddenAttributes);
15740
+ return finalizeSvgExport(container2, theme, effectivePalette2, options);
15980
15741
  }
15981
15742
  if (detectedType === "kanban") {
15982
15743
  const { parseKanban: parseKanban2 } = await Promise.resolve().then(() => (init_parser5(), parser_exports5));
15983
15744
  const { renderKanban: renderKanban2 } = await Promise.resolve().then(() => (init_renderer2(), renderer_exports2));
15984
- const isDark2 = theme === "dark";
15985
- const { getPalette: getPalette3 } = await Promise.resolve().then(() => (init_palettes(), palettes_exports));
15986
- const effectivePalette2 = palette ?? (isDark2 ? getPalette3("nord").dark : getPalette3("nord").light);
15745
+ const effectivePalette2 = await resolveExportPalette(theme, palette);
15987
15746
  const kanbanParsed = parseKanban2(content, effectivePalette2);
15988
15747
  if (kanbanParsed.error || kanbanParsed.columns.length === 0) return "";
15989
15748
  const container2 = document.createElement("div");
15990
15749
  container2.style.position = "absolute";
15991
15750
  container2.style.left = "-9999px";
15992
15751
  document.body.appendChild(container2);
15993
- try {
15994
- renderKanban2(container2, kanbanParsed, effectivePalette2, isDark2);
15995
- const svgEl = container2.querySelector("svg");
15996
- if (!svgEl) return "";
15997
- if (theme === "transparent") {
15998
- svgEl.style.background = "none";
15999
- } else if (!svgEl.style.background) {
16000
- svgEl.style.background = effectivePalette2.bg;
16001
- }
16002
- svgEl.setAttribute("xmlns", "http://www.w3.org/2000/svg");
16003
- svgEl.style.fontFamily = FONT_FAMILY;
16004
- const svgHtml = svgEl.outerHTML;
16005
- if (options?.branding !== false) {
16006
- const brandColor = theme === "transparent" ? "#888" : effectivePalette2.textMuted;
16007
- return injectBranding(svgHtml, brandColor);
16008
- }
16009
- return svgHtml;
16010
- } finally {
16011
- document.body.removeChild(container2);
16012
- }
15752
+ renderKanban2(container2, kanbanParsed, effectivePalette2, theme === "dark");
15753
+ return finalizeSvgExport(container2, theme, effectivePalette2, options);
16013
15754
  }
16014
15755
  if (detectedType === "class") {
16015
15756
  const { parseClassDiagram: parseClassDiagram2 } = await Promise.resolve().then(() => (init_parser2(), parser_exports2));
16016
15757
  const { layoutClassDiagram: layoutClassDiagram2 } = await Promise.resolve().then(() => (init_layout2(), layout_exports2));
16017
15758
  const { renderClassDiagram: renderClassDiagram2 } = await Promise.resolve().then(() => (init_renderer3(), renderer_exports3));
16018
- const isDark2 = theme === "dark";
16019
- const { getPalette: getPalette3 } = await Promise.resolve().then(() => (init_palettes(), palettes_exports));
16020
- const effectivePalette2 = palette ?? (isDark2 ? getPalette3("nord").dark : getPalette3("nord").light);
15759
+ const effectivePalette2 = await resolveExportPalette(theme, palette);
16021
15760
  const classParsed = parseClassDiagram2(content, effectivePalette2);
16022
15761
  if (classParsed.error || classParsed.classes.length === 0) return "";
16023
15762
  const classLayout = layoutClassDiagram2(classParsed);
@@ -16025,48 +15764,15 @@ async function renderD3ForExport(content, theme, palette, orgExportState, option
16025
15764
  const titleOffset = classParsed.title ? 40 : 0;
16026
15765
  const exportWidth = classLayout.width + PADDING * 2;
16027
15766
  const exportHeight = classLayout.height + PADDING * 2 + titleOffset;
16028
- const container2 = document.createElement("div");
16029
- container2.style.width = `${exportWidth}px`;
16030
- container2.style.height = `${exportHeight}px`;
16031
- container2.style.position = "absolute";
16032
- container2.style.left = "-9999px";
16033
- document.body.appendChild(container2);
16034
- try {
16035
- renderClassDiagram2(
16036
- container2,
16037
- classParsed,
16038
- classLayout,
16039
- effectivePalette2,
16040
- isDark2,
16041
- void 0,
16042
- { width: exportWidth, height: exportHeight }
16043
- );
16044
- const svgEl = container2.querySelector("svg");
16045
- if (!svgEl) return "";
16046
- if (theme === "transparent") {
16047
- svgEl.style.background = "none";
16048
- } else if (!svgEl.style.background) {
16049
- svgEl.style.background = effectivePalette2.bg;
16050
- }
16051
- svgEl.setAttribute("xmlns", "http://www.w3.org/2000/svg");
16052
- svgEl.style.fontFamily = FONT_FAMILY;
16053
- const svgHtml = svgEl.outerHTML;
16054
- if (options?.branding !== false) {
16055
- const brandColor = theme === "transparent" ? "#888" : effectivePalette2.textMuted;
16056
- return injectBranding(svgHtml, brandColor);
16057
- }
16058
- return svgHtml;
16059
- } finally {
16060
- document.body.removeChild(container2);
16061
- }
15767
+ const container2 = createExportContainer(exportWidth, exportHeight);
15768
+ renderClassDiagram2(container2, classParsed, classLayout, effectivePalette2, theme === "dark", void 0, { width: exportWidth, height: exportHeight });
15769
+ return finalizeSvgExport(container2, theme, effectivePalette2, options);
16062
15770
  }
16063
15771
  if (detectedType === "er") {
16064
15772
  const { parseERDiagram: parseERDiagram2 } = await Promise.resolve().then(() => (init_parser3(), parser_exports3));
16065
15773
  const { layoutERDiagram: layoutERDiagram2 } = await Promise.resolve().then(() => (init_layout3(), layout_exports3));
16066
15774
  const { renderERDiagram: renderERDiagram2 } = await Promise.resolve().then(() => (init_renderer4(), renderer_exports4));
16067
- const isDark2 = theme === "dark";
16068
- const { getPalette: getPalette3 } = await Promise.resolve().then(() => (init_palettes(), palettes_exports));
16069
- const effectivePalette2 = palette ?? (isDark2 ? getPalette3("nord").dark : getPalette3("nord").light);
15775
+ const effectivePalette2 = await resolveExportPalette(theme, palette);
16070
15776
  const erParsed = parseERDiagram2(content, effectivePalette2);
16071
15777
  if (erParsed.error || erParsed.tables.length === 0) return "";
16072
15778
  const erLayout = layoutERDiagram2(erParsed);
@@ -16074,48 +15780,15 @@ async function renderD3ForExport(content, theme, palette, orgExportState, option
16074
15780
  const titleOffset = erParsed.title ? 40 : 0;
16075
15781
  const exportWidth = erLayout.width + PADDING * 2;
16076
15782
  const exportHeight = erLayout.height + PADDING * 2 + titleOffset;
16077
- const container2 = document.createElement("div");
16078
- container2.style.width = `${exportWidth}px`;
16079
- container2.style.height = `${exportHeight}px`;
16080
- container2.style.position = "absolute";
16081
- container2.style.left = "-9999px";
16082
- document.body.appendChild(container2);
16083
- try {
16084
- renderERDiagram2(
16085
- container2,
16086
- erParsed,
16087
- erLayout,
16088
- effectivePalette2,
16089
- isDark2,
16090
- void 0,
16091
- { width: exportWidth, height: exportHeight }
16092
- );
16093
- const svgEl = container2.querySelector("svg");
16094
- if (!svgEl) return "";
16095
- if (theme === "transparent") {
16096
- svgEl.style.background = "none";
16097
- } else if (!svgEl.style.background) {
16098
- svgEl.style.background = effectivePalette2.bg;
16099
- }
16100
- svgEl.setAttribute("xmlns", "http://www.w3.org/2000/svg");
16101
- svgEl.style.fontFamily = FONT_FAMILY;
16102
- const svgHtml = svgEl.outerHTML;
16103
- if (options?.branding !== false) {
16104
- const brandColor = theme === "transparent" ? "#888" : effectivePalette2.textMuted;
16105
- return injectBranding(svgHtml, brandColor);
16106
- }
16107
- return svgHtml;
16108
- } finally {
16109
- document.body.removeChild(container2);
16110
- }
15783
+ const container2 = createExportContainer(exportWidth, exportHeight);
15784
+ renderERDiagram2(container2, erParsed, erLayout, effectivePalette2, theme === "dark", void 0, { width: exportWidth, height: exportHeight });
15785
+ return finalizeSvgExport(container2, theme, effectivePalette2, options);
16111
15786
  }
16112
15787
  if (detectedType === "initiative-status") {
16113
15788
  const { parseInitiativeStatus: parseInitiativeStatus2 } = await Promise.resolve().then(() => (init_parser7(), parser_exports7));
16114
15789
  const { layoutInitiativeStatus: layoutInitiativeStatus2 } = await Promise.resolve().then(() => (init_layout4(), layout_exports4));
16115
15790
  const { renderInitiativeStatus: renderInitiativeStatus2 } = await Promise.resolve().then(() => (init_renderer5(), renderer_exports5));
16116
- const isDark2 = theme === "dark";
16117
- const { getPalette: getPalette3 } = await Promise.resolve().then(() => (init_palettes(), palettes_exports));
16118
- const effectivePalette2 = palette ?? (isDark2 ? getPalette3("nord").dark : getPalette3("nord").light);
15791
+ const effectivePalette2 = await resolveExportPalette(theme, palette);
16119
15792
  const isParsed = parseInitiativeStatus2(content);
16120
15793
  if (isParsed.error || isParsed.nodes.length === 0) return "";
16121
15794
  const isLayout = layoutInitiativeStatus2(isParsed);
@@ -16123,48 +15796,15 @@ async function renderD3ForExport(content, theme, palette, orgExportState, option
16123
15796
  const titleOffset = isParsed.title ? 40 : 0;
16124
15797
  const exportWidth = isLayout.width + PADDING * 2;
16125
15798
  const exportHeight = isLayout.height + PADDING * 2 + titleOffset;
16126
- const container2 = document.createElement("div");
16127
- container2.style.width = `${exportWidth}px`;
16128
- container2.style.height = `${exportHeight}px`;
16129
- container2.style.position = "absolute";
16130
- container2.style.left = "-9999px";
16131
- document.body.appendChild(container2);
16132
- try {
16133
- renderInitiativeStatus2(
16134
- container2,
16135
- isParsed,
16136
- isLayout,
16137
- effectivePalette2,
16138
- isDark2,
16139
- void 0,
16140
- { width: exportWidth, height: exportHeight }
16141
- );
16142
- const svgEl = container2.querySelector("svg");
16143
- if (!svgEl) return "";
16144
- if (theme === "transparent") {
16145
- svgEl.style.background = "none";
16146
- } else if (!svgEl.style.background) {
16147
- svgEl.style.background = effectivePalette2.bg;
16148
- }
16149
- svgEl.setAttribute("xmlns", "http://www.w3.org/2000/svg");
16150
- svgEl.style.fontFamily = FONT_FAMILY;
16151
- const svgHtml = svgEl.outerHTML;
16152
- if (options?.branding !== false) {
16153
- const brandColor = theme === "transparent" ? "#888" : effectivePalette2.textMuted;
16154
- return injectBranding(svgHtml, brandColor);
16155
- }
16156
- return svgHtml;
16157
- } finally {
16158
- document.body.removeChild(container2);
16159
- }
15799
+ const container2 = createExportContainer(exportWidth, exportHeight);
15800
+ renderInitiativeStatus2(container2, isParsed, isLayout, effectivePalette2, theme === "dark", void 0, { width: exportWidth, height: exportHeight });
15801
+ return finalizeSvgExport(container2, theme, effectivePalette2, options);
16160
15802
  }
16161
15803
  if (detectedType === "c4") {
16162
15804
  const { parseC4: parseC42 } = await Promise.resolve().then(() => (init_parser6(), parser_exports6));
16163
15805
  const { layoutC4Context: layoutC4Context2, layoutC4Containers: layoutC4Containers2, layoutC4Components: layoutC4Components2, layoutC4Deployment: layoutC4Deployment2 } = await Promise.resolve().then(() => (init_layout5(), layout_exports5));
16164
15806
  const { renderC4Context: renderC4Context2, renderC4Containers: renderC4Containers2 } = await Promise.resolve().then(() => (init_renderer6(), renderer_exports6));
16165
- const isDark2 = theme === "dark";
16166
- const { getPalette: getPalette3 } = await Promise.resolve().then(() => (init_palettes(), palettes_exports));
16167
- const effectivePalette2 = palette ?? (isDark2 ? getPalette3("nord").dark : getPalette3("nord").light);
15807
+ const effectivePalette2 = await resolveExportPalette(theme, palette);
16168
15808
  const c4Parsed = parseC42(content, effectivePalette2);
16169
15809
  if (c4Parsed.error || c4Parsed.elements.length === 0) return "";
16170
15810
  const c4Level = options?.c4Level ?? "context";
@@ -16176,81 +15816,22 @@ async function renderD3ForExport(content, theme, palette, orgExportState, option
16176
15816
  const titleOffset = c4Parsed.title ? 40 : 0;
16177
15817
  const exportWidth = c4Layout.width + PADDING * 2;
16178
15818
  const exportHeight = c4Layout.height + PADDING * 2 + titleOffset;
16179
- const container2 = document.createElement("div");
16180
- container2.style.width = `${exportWidth}px`;
16181
- container2.style.height = `${exportHeight}px`;
16182
- container2.style.position = "absolute";
16183
- container2.style.left = "-9999px";
16184
- document.body.appendChild(container2);
16185
- try {
16186
- const renderFn = c4Level === "deployment" || c4Level === "components" && c4System && c4Container || c4Level === "containers" && c4System ? renderC4Containers2 : renderC4Context2;
16187
- renderFn(
16188
- container2,
16189
- c4Parsed,
16190
- c4Layout,
16191
- effectivePalette2,
16192
- isDark2,
16193
- void 0,
16194
- { width: exportWidth, height: exportHeight }
16195
- );
16196
- const svgEl = container2.querySelector("svg");
16197
- if (!svgEl) return "";
16198
- if (theme === "transparent") {
16199
- svgEl.style.background = "none";
16200
- } else if (!svgEl.style.background) {
16201
- svgEl.style.background = effectivePalette2.bg;
16202
- }
16203
- svgEl.setAttribute("xmlns", "http://www.w3.org/2000/svg");
16204
- svgEl.style.fontFamily = FONT_FAMILY;
16205
- const svgHtml = svgEl.outerHTML;
16206
- if (options?.branding !== false) {
16207
- const brandColor = theme === "transparent" ? "#888" : effectivePalette2.textMuted;
16208
- return injectBranding(svgHtml, brandColor);
16209
- }
16210
- return svgHtml;
16211
- } finally {
16212
- document.body.removeChild(container2);
16213
- }
15819
+ const container2 = createExportContainer(exportWidth, exportHeight);
15820
+ const renderFn = c4Level === "deployment" || c4Level === "components" && c4System && c4Container || c4Level === "containers" && c4System ? renderC4Containers2 : renderC4Context2;
15821
+ renderFn(container2, c4Parsed, c4Layout, effectivePalette2, theme === "dark", void 0, { width: exportWidth, height: exportHeight });
15822
+ return finalizeSvgExport(container2, theme, effectivePalette2, options);
16214
15823
  }
16215
15824
  if (detectedType === "flowchart") {
16216
15825
  const { parseFlowchart: parseFlowchart2 } = await Promise.resolve().then(() => (init_flowchart_parser(), flowchart_parser_exports));
16217
15826
  const { layoutGraph: layoutGraph2 } = await Promise.resolve().then(() => (init_layout6(), layout_exports6));
16218
15827
  const { renderFlowchart: renderFlowchart2 } = await Promise.resolve().then(() => (init_flowchart_renderer(), flowchart_renderer_exports));
16219
- const isDark2 = theme === "dark";
16220
- const { getPalette: getPalette3 } = await Promise.resolve().then(() => (init_palettes(), palettes_exports));
16221
- const effectivePalette2 = palette ?? (isDark2 ? getPalette3("nord").dark : getPalette3("nord").light);
15828
+ const effectivePalette2 = await resolveExportPalette(theme, palette);
16222
15829
  const fcParsed = parseFlowchart2(content, effectivePalette2);
16223
15830
  if (fcParsed.error || fcParsed.nodes.length === 0) return "";
16224
15831
  const layout = layoutGraph2(fcParsed);
16225
- const container2 = document.createElement("div");
16226
- container2.style.width = `${EXPORT_WIDTH}px`;
16227
- container2.style.height = `${EXPORT_HEIGHT}px`;
16228
- container2.style.position = "absolute";
16229
- container2.style.left = "-9999px";
16230
- document.body.appendChild(container2);
16231
- try {
16232
- renderFlowchart2(container2, fcParsed, layout, effectivePalette2, isDark2, void 0, {
16233
- width: EXPORT_WIDTH,
16234
- height: EXPORT_HEIGHT
16235
- });
16236
- const svgEl = container2.querySelector("svg");
16237
- if (!svgEl) return "";
16238
- if (theme === "transparent") {
16239
- svgEl.style.background = "none";
16240
- } else if (!svgEl.style.background) {
16241
- svgEl.style.background = effectivePalette2.bg;
16242
- }
16243
- svgEl.setAttribute("xmlns", "http://www.w3.org/2000/svg");
16244
- svgEl.style.fontFamily = FONT_FAMILY;
16245
- const svgHtml = svgEl.outerHTML;
16246
- if (options?.branding !== false) {
16247
- const brandColor = theme === "transparent" ? "#888" : effectivePalette2.textMuted;
16248
- return injectBranding(svgHtml, brandColor);
16249
- }
16250
- return svgHtml;
16251
- } finally {
16252
- document.body.removeChild(container2);
16253
- }
15832
+ const container2 = createExportContainer(EXPORT_WIDTH, EXPORT_HEIGHT);
15833
+ renderFlowchart2(container2, fcParsed, layout, effectivePalette2, theme === "dark", void 0, { width: EXPORT_WIDTH, height: EXPORT_HEIGHT });
15834
+ return finalizeSvgExport(container2, theme, effectivePalette2, options);
16254
15835
  }
16255
15836
  const parsed = parseD3(content, palette);
16256
15837
  if (parsed.error && parsed.type !== "sequence") {
@@ -16266,56 +15847,32 @@ async function renderD3ForExport(content, theme, palette, orgExportState, option
16266
15847
  if (parsed.type === "venn" && parsed.vennSets.length < 2) return "";
16267
15848
  if (parsed.type === "quadrant" && parsed.quadrantPoints.length === 0)
16268
15849
  return "";
15850
+ const effectivePalette = await resolveExportPalette(theme, palette);
16269
15851
  const isDark = theme === "dark";
16270
- const { getPalette: getPalette2 } = await Promise.resolve().then(() => (init_palettes(), palettes_exports));
16271
- const effectivePalette = palette ?? (isDark ? getPalette2("nord").dark : getPalette2("nord").light);
16272
- const container = document.createElement("div");
16273
- container.style.width = `${EXPORT_WIDTH}px`;
16274
- container.style.height = `${EXPORT_HEIGHT}px`;
16275
- container.style.position = "absolute";
16276
- container.style.left = "-9999px";
16277
- document.body.appendChild(container);
15852
+ const container = createExportContainer(EXPORT_WIDTH, EXPORT_HEIGHT);
16278
15853
  const dims = { width: EXPORT_WIDTH, height: EXPORT_HEIGHT };
16279
- try {
16280
- if (parsed.type === "sequence") {
16281
- const { parseSequenceDgmo: parseSequenceDgmo2 } = await Promise.resolve().then(() => (init_parser(), parser_exports));
16282
- const { renderSequenceDiagram: renderSequenceDiagram2 } = await Promise.resolve().then(() => (init_renderer7(), renderer_exports7));
16283
- const seqParsed = parseSequenceDgmo2(content);
16284
- if (seqParsed.error || seqParsed.participants.length === 0) return "";
16285
- renderSequenceDiagram2(container, seqParsed, effectivePalette, isDark, void 0, {
16286
- exportWidth: EXPORT_WIDTH
16287
- });
16288
- } else if (parsed.type === "wordcloud") {
16289
- await renderWordCloudAsync(container, parsed, effectivePalette, isDark, dims);
16290
- } else if (parsed.type === "arc") {
16291
- renderArcDiagram(container, parsed, effectivePalette, isDark, void 0, dims);
16292
- } else if (parsed.type === "timeline") {
16293
- renderTimeline(container, parsed, effectivePalette, isDark, void 0, dims);
16294
- } else if (parsed.type === "venn") {
16295
- renderVenn(container, parsed, effectivePalette, isDark, void 0, dims);
16296
- } else if (parsed.type === "quadrant") {
16297
- renderQuadrant(container, parsed, effectivePalette, isDark, void 0, dims);
16298
- } else {
16299
- renderSlopeChart(container, parsed, effectivePalette, isDark, void 0, dims);
16300
- }
16301
- const svgEl = container.querySelector("svg");
16302
- if (!svgEl) return "";
16303
- if (theme === "transparent") {
16304
- svgEl.style.background = "none";
16305
- } else if (!svgEl.style.background) {
16306
- svgEl.style.background = effectivePalette.bg;
16307
- }
16308
- svgEl.setAttribute("xmlns", "http://www.w3.org/2000/svg");
16309
- svgEl.style.fontFamily = FONT_FAMILY;
16310
- const svgHtml = svgEl.outerHTML;
16311
- if (options?.branding !== false) {
16312
- const brandColor = theme === "transparent" ? "#888" : effectivePalette.textMuted;
16313
- return injectBranding(svgHtml, brandColor);
16314
- }
16315
- return svgHtml;
16316
- } finally {
16317
- document.body.removeChild(container);
15854
+ if (parsed.type === "sequence") {
15855
+ const { parseSequenceDgmo: parseSequenceDgmo2 } = await Promise.resolve().then(() => (init_parser(), parser_exports));
15856
+ const { renderSequenceDiagram: renderSequenceDiagram2 } = await Promise.resolve().then(() => (init_renderer7(), renderer_exports7));
15857
+ const seqParsed = parseSequenceDgmo2(content);
15858
+ if (seqParsed.error || seqParsed.participants.length === 0) return "";
15859
+ renderSequenceDiagram2(container, seqParsed, effectivePalette, isDark, void 0, {
15860
+ exportWidth: EXPORT_WIDTH
15861
+ });
15862
+ } else if (parsed.type === "wordcloud") {
15863
+ await renderWordCloudAsync(container, parsed, effectivePalette, isDark, dims);
15864
+ } else if (parsed.type === "arc") {
15865
+ renderArcDiagram(container, parsed, effectivePalette, isDark, void 0, dims);
15866
+ } else if (parsed.type === "timeline") {
15867
+ renderTimeline(container, parsed, effectivePalette, isDark, void 0, dims);
15868
+ } else if (parsed.type === "venn") {
15869
+ renderVenn(container, parsed, effectivePalette, isDark, void 0, dims);
15870
+ } else if (parsed.type === "quadrant") {
15871
+ renderQuadrant(container, parsed, effectivePalette, isDark, void 0, dims);
15872
+ } else {
15873
+ renderSlopeChart(container, parsed, effectivePalette, isDark, void 0, dims);
16318
15874
  }
15875
+ return finalizeSvgExport(container, theme, effectivePalette, options);
16319
15876
  }
16320
15877
  var d3Scale, d3Selection9, d3Shape6, d3Array, import_d3_cloud, DEFAULT_CLOUD_OPTIONS, STOP_WORDS, SLOPE_MARGIN, SLOPE_LABEL_FONT_SIZE, SLOPE_CHAR_WIDTH, ARC_MARGIN, MONTH_ABBR, EXPORT_WIDTH, EXPORT_HEIGHT;
16321
15878
  var init_d3 = __esm({
@@ -16477,6 +16034,7 @@ var index_exports = {};
16477
16034
  __export(index_exports, {
16478
16035
  DGMO_CHART_TYPE_MAP: () => DGMO_CHART_TYPE_MAP,
16479
16036
  RULE_COUNT: () => RULE_COUNT,
16037
+ STANDARD_CHART_TYPES: () => STANDARD_CHART_TYPES,
16480
16038
  addDurationToDate: () => addDurationToDate,
16481
16039
  applyGroupOrdering: () => applyGroupOrdering,
16482
16040
  applyPositionOverrides: () => applyPositionOverrides,
@@ -17159,6 +16717,7 @@ init_branding();
17159
16717
  0 && (module.exports = {
17160
16718
  DGMO_CHART_TYPE_MAP,
17161
16719
  RULE_COUNT,
16720
+ STANDARD_CHART_TYPES,
17162
16721
  addDurationToDate,
17163
16722
  applyGroupOrdering,
17164
16723
  applyPositionOverrides,