@opendata-ai/openchart-vanilla 8.8.0 → 8.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/{chunk-SXTHPXG6.js → chunk-APMUBW72.js} +174 -65
  2. package/dist/chunk-APMUBW72.js.map +1 -0
  3. package/dist/{chunk-QBTRAQAX.js → chunk-CCRFYGHU.js} +2299 -1766
  4. package/dist/chunk-CCRFYGHU.js.map +1 -0
  5. package/dist/{chunk-5IMVUHVC.js → chunk-GX6BWMJD.js} +23 -21
  6. package/dist/chunk-GX6BWMJD.js.map +1 -0
  7. package/dist/{chunk-DFKLAB67.js → chunk-MGFXAROR.js} +20 -8
  8. package/dist/chunk-MGFXAROR.js.map +1 -0
  9. package/dist/{chunk-EZQDCLZN.js → chunk-Q7YEEF2X.js} +3 -2
  10. package/dist/{chunk-EZQDCLZN.js.map → chunk-Q7YEEF2X.js.map} +1 -1
  11. package/dist/{chunk-I73B3DJI.js → chunk-R5TZHNTG.js} +23 -5
  12. package/dist/chunk-R5TZHNTG.js.map +1 -0
  13. package/dist/{chunk-2OJZBMXM.js → chunk-REH5UQCL.js} +46 -46
  14. package/dist/{chunk-2OJZBMXM.js.map → chunk-REH5UQCL.js.map} +1 -1
  15. package/dist/{chunk-NG7CVCI2.js → chunk-UC4IHEUO.js} +16 -1
  16. package/dist/chunk-UC4IHEUO.js.map +1 -0
  17. package/dist/export-gif.d.ts +2 -2
  18. package/dist/export-gif.js +2 -2
  19. package/dist/graph-3d/index.d.ts +0 -27
  20. package/dist/graph-3d/index.js +9 -5
  21. package/dist/graph-3d/index.js.map +1 -1
  22. package/dist/index.d.ts +27 -5
  23. package/dist/index.js +635 -214
  24. package/dist/index.js.map +1 -1
  25. package/dist/{mount-WiY9BIr9.d.ts → mount-TEjIdF0m.d.ts} +16 -1
  26. package/dist/static.js +3 -3
  27. package/dist/story/index.d.ts +2 -2
  28. package/dist/story/index.js +5 -5
  29. package/dist/styles.css +1 -1
  30. package/dist/styles.css.map +1 -1
  31. package/package.json +4 -4
  32. package/dist/chunk-5IMVUHVC.js.map +0 -1
  33. package/dist/chunk-DFKLAB67.js.map +0 -1
  34. package/dist/chunk-I73B3DJI.js.map +0 -1
  35. package/dist/chunk-NG7CVCI2.js.map +0 -1
  36. package/dist/chunk-QBTRAQAX.js.map +0 -1
  37. package/dist/chunk-SXTHPXG6.js.map +0 -1
@@ -8,7 +8,7 @@ import {
8
8
  } from "./chunk-SDJHUELU.js";
9
9
  import {
10
10
  resolvedSurface
11
- } from "./chunk-NG7CVCI2.js";
11
+ } from "./chunk-UC4IHEUO.js";
12
12
 
13
13
  // src/svg-ids.ts
14
14
  var counter = 0;
@@ -196,7 +196,7 @@ function registerMarkRenderer(type, renderer) {
196
196
  }
197
197
  function renderLineMark(mark, index) {
198
198
  const g = createSVGElement("g");
199
- g.setAttribute("data-mark-id", `line-${mark.seriesKey ?? index}`);
199
+ g.setAttribute("data-mark-id", `line-${index}`);
200
200
  g.setAttribute("class", "oc-mark oc-mark-line");
201
201
  stampAnimationAttrs(g, mark, index);
202
202
  if (mark.points.length > 1) {
@@ -223,6 +223,7 @@ function renderLineMark(mark, index) {
223
223
  if (mark.label?.visible) {
224
224
  const label = createSVGElement("text");
225
225
  label.setAttribute("class", "oc-mark-label");
226
+ if (mark.key) label.setAttribute("data-label-key", mark.key);
226
227
  if (mark.seriesKey) {
227
228
  label.setAttribute("data-series", mark.seriesKey);
228
229
  }
@@ -250,7 +251,7 @@ function renderLineMark(mark, index) {
250
251
  }
251
252
  function renderAreaMark(mark, index) {
252
253
  const g = createSVGElement("g");
253
- g.setAttribute("data-mark-id", `area-${mark.seriesKey ?? index}`);
254
+ g.setAttribute("data-mark-id", `area-${index}`);
254
255
  g.setAttribute("class", "oc-mark oc-mark-area");
255
256
  stampAnimationAttrs(g, mark, index);
256
257
  if (mark.path) {
@@ -355,6 +356,7 @@ function renderArcMark(mark, index) {
355
356
  if (mark.label?.visible) {
356
357
  const label = createSVGElement("text");
357
358
  label.setAttribute("class", "oc-mark-label");
359
+ if (mark.key) label.setAttribute("data-label-key", mark.key);
358
360
  setAttrs(label, {
359
361
  x: mark.label.x - mark.center.x,
360
362
  y: mark.label.y - mark.center.y
@@ -543,6 +545,7 @@ function renderMarks(parent, layout, opts) {
543
545
  }
544
546
  const label = createSVGElement("text");
545
547
  label.setAttribute("class", "oc-mark-label");
548
+ if (mark.key) label.setAttribute("data-label-key", mark.key);
546
549
  setAttrs(label, { x: rect.label.x, y: rect.label.y });
547
550
  applyTextStyle(label, rect.label.style);
548
551
  applyLabelHalo(label, rect.label);
@@ -564,6 +567,7 @@ function renderMarks(parent, layout, opts) {
564
567
  import { clampStaggerDelay } from "@opendata-ai/openchart-engine";
565
568
 
566
569
  // src/animation-vars.ts
570
+ import { motionCSS } from "@opendata-ai/openchart-core";
567
571
  var EASE_VAR_MAP = {
568
572
  smooth: "var(--oc-ease-smooth)",
569
573
  snappy: "var(--oc-ease-snappy)"
@@ -574,7 +578,12 @@ function stampAnimationVars(el, v) {
574
578
  if (v.annotationDelay !== void 0) {
575
579
  el.style.setProperty("--oc-annotation-delay", `${v.annotationDelay}ms`);
576
580
  }
577
- if (v.ease !== void 0) {
581
+ if (v.spring) {
582
+ el.style.setProperty(
583
+ "--oc-animation-ease",
584
+ motionCSS({ duration: v.duration, spring: v.spring })
585
+ );
586
+ } else if (v.ease !== void 0) {
578
587
  el.style.setProperty("--oc-animation-ease", EASE_VAR_MAP[v.ease] || EASE_VAR_MAP.smooth);
579
588
  }
580
589
  if (v.stackSegmentDuration !== void 0) {
@@ -585,6 +594,7 @@ function stampAnimationVars(el, v) {
585
594
  // src/renderers/annotations.ts
586
595
  import {
587
596
  ARROWHEAD_LENGTH,
597
+ automaticControlPoint,
588
598
  BOLD_SPAN_FONT_WEIGHT,
589
599
  computeArrowheadPoints,
590
600
  DEFAULT_ANNOTATION_FONT_SIZE,
@@ -610,12 +620,8 @@ function renderArrowhead(parent, tipX, tipY, tangentX, tangentY, stroke) {
610
620
  });
611
621
  parent.appendChild(arrow);
612
622
  }
613
- function renderCurvedConnector(parent, from, to, stroke, showArrow, exit) {
614
- const dx = to.x - from.x;
615
- const dy = to.y - from.y;
616
- const vertical = exit ? exit === "vertical" : Math.abs(dy) >= Math.abs(dx);
617
- const cpx = from.x + dx * (vertical ? 0.2 : 0.6);
618
- const cpy = from.y + dy * (vertical ? 0.6 : 0.2);
623
+ function renderCurvedConnector(parent, from, to, stroke, showArrow, exit, control) {
624
+ const { x: cpx, y: cpy } = control ?? automaticControlPoint(from, to, exit);
619
625
  const tx = to.x - cpx;
620
626
  const ty = to.y - cpy;
621
627
  const tLen = Math.sqrt(tx * tx + ty * ty) || 1;
@@ -656,6 +662,8 @@ function renderAnnotation(parent, annotation, index, bgColor) {
656
662
  const g = createSVGElement("g");
657
663
  g.setAttribute("class", `oc-annotation oc-annotation-${annotation.type}`);
658
664
  g.setAttribute("data-annotation-index", String(annotation.specIndex ?? index));
665
+ const facet = parent.closest("[data-facet]")?.getAttribute("data-facet");
666
+ if (facet !== null && facet !== void 0) g.setAttribute("data-facet-instance", facet);
659
667
  if (annotation.id) {
660
668
  g.setAttribute("data-annotation-id", annotation.id);
661
669
  }
@@ -728,7 +736,7 @@ function renderAnnotation(parent, annotation, index, bgColor) {
728
736
  if (annotation.label.connector) {
729
737
  const c = annotation.label.connector;
730
738
  if (c.style === "curve") {
731
- renderCurvedConnector(g, c.from, c.to, c.stroke, c.arrow, c.exit);
739
+ renderCurvedConnector(g, c.from, c.to, c.stroke, c.arrow, c.exit, c.control);
732
740
  } else if (c.style === "drop-line") {
733
741
  const connector = createSVGElement("line");
734
742
  connector.setAttribute("class", "oc-annotation-connector oc-annotation-drop-line");
@@ -798,7 +806,12 @@ function renderAnnotation(parent, annotation, index, bgColor) {
798
806
  applyTextStyle(text, annotation.label.style);
799
807
  const fontSize = annotation.label.style.fontSize ?? DEFAULT_ANNOTATION_FONT_SIZE;
800
808
  const lineHeight = fontSize * (annotation.label.style.lineHeight ?? DEFAULT_LINE_HEIGHT);
801
- fillRichText(text, annotation.label.text, annotation.label.x, lineHeight);
809
+ fillRichText(
810
+ text,
811
+ annotation.label.lines?.join("\n") ?? annotation.label.text,
812
+ annotation.label.x,
813
+ lineHeight
814
+ );
802
815
  if (annotation.label.background && annotation.label.bounds) {
803
816
  const pad = 3;
804
817
  const b = annotation.label.bounds;
@@ -828,7 +841,12 @@ function renderAnnotation(parent, annotation, index, bgColor) {
828
841
  applyTextStyle(sub, annotation.subtitle.style);
829
842
  const subFontSize = annotation.subtitle.style.fontSize ?? DEFAULT_ANNOTATION_FONT_SIZE;
830
843
  const subLineHeight = subFontSize * (annotation.subtitle.style.lineHeight ?? DEFAULT_LINE_HEIGHT);
831
- fillRichText(sub, annotation.subtitle.text, annotation.subtitle.x, subLineHeight);
844
+ fillRichText(
845
+ sub,
846
+ annotation.subtitle.lines?.join("\n") ?? annotation.subtitle.text,
847
+ annotation.subtitle.x,
848
+ subLineHeight
849
+ );
832
850
  g.appendChild(sub);
833
851
  }
834
852
  }
@@ -838,11 +856,36 @@ function renderAnnotations(parent, layout) {
838
856
  if (layout.annotations.length === 0) return;
839
857
  const g = createSVGElement("g");
840
858
  g.setAttribute("class", "oc-annotations");
859
+ parent.appendChild(g);
841
860
  const bgColor = resolvedSurface(layout.theme);
842
861
  for (let i = 0; i < layout.annotations.length; i++) {
843
862
  renderAnnotation(g, layout.annotations[i], i, bgColor);
844
863
  }
845
- parent.appendChild(g);
864
+ }
865
+ function updateAnnotationGeometry(group, annotation, bgColor) {
866
+ const scratch = createSVGElement("g");
867
+ renderAnnotation(scratch, annotation, annotation.specIndex ?? 0, bgColor);
868
+ const fresh = scratch.firstElementChild;
869
+ const previous = [...group.children].filter(
870
+ (child) => [...child.classList].some((name) => name.startsWith("oc-annotation-"))
871
+ );
872
+ const used = /* @__PURE__ */ new Set();
873
+ for (const child of [...fresh.children]) {
874
+ const target = previous.find(
875
+ (old) => !used.has(old) && old.tagName === child.tagName && old.getAttribute("class") === child.getAttribute("class")
876
+ );
877
+ if (target) {
878
+ used.add(target);
879
+ for (const attr of [...target.attributes])
880
+ if (!child.hasAttribute(attr.name)) target.removeAttribute(attr.name);
881
+ for (const attr of [...child.attributes]) target.setAttribute(attr.name, attr.value);
882
+ target.replaceChildren(...child.childNodes);
883
+ group.appendChild(target);
884
+ } else group.appendChild(child);
885
+ }
886
+ for (const old of previous) if (!used.has(old)) old.remove();
887
+ for (const handle of [...group.querySelectorAll(".oc-connector-handle, .oc-anchor-handle")])
888
+ group.appendChild(handle);
846
889
  }
847
890
 
848
891
  // src/renderers/axes.ts
@@ -1141,22 +1184,55 @@ function renderAxes(parent, layout, opts) {
1141
1184
  }
1142
1185
 
1143
1186
  // src/renderers/brand.ts
1144
- import { BRAND_MIN_WIDTH, textAscent as textAscent3 } from "@opendata-ai/openchart-core";
1187
+ import { BRAND_MIN_WIDTH, computeNoteBandHeight, textAscent as textAscent2 } from "@opendata-ai/openchart-core";
1188
+ var BRAND_URL = "https://tryopendata.ai";
1189
+ function renderBrand(parent, layout) {
1190
+ if (layout.dimensions.width < BRAND_MIN_WIDTH) return;
1191
+ const { width } = layout.dimensions;
1192
+ const padding = layout.theme.spacing.padding;
1193
+ const rightEdge = width - padding;
1194
+ const fill = layout.theme.colors.axis;
1195
+ const { chrome } = layout;
1196
+ const bottomOffset = chrome.bottomAnchorY ?? layout.area.y + layout.area.height;
1197
+ const firstBottom = chrome.source ?? chrome.byline ?? chrome.footer;
1198
+ const { legend } = layout;
1199
+ const bottomLegendOffset = legend.position === "bottom" && legend.bounds.height > 0 ? legend.bounds.height + 8 : 0;
1200
+ const bandHeight = layout.chrome.noteBandHeight ?? computeNoteBandHeight(layout.chrome, layout.theme);
1201
+ const chromeY = firstBottom ? bottomOffset + firstBottom.y + bandHeight : bottomOffset + layout.theme.spacing.chartToFooter + bottomLegendOffset + bandHeight;
1202
+ const a = createSVGElement("a");
1203
+ a.setAttribute("href", BRAND_URL);
1204
+ a.setAttributeNS(XLINK_NS, "xlink:href", BRAND_URL);
1205
+ a.setAttribute("target", "_blank");
1206
+ a.setAttribute("rel", "noopener");
1207
+ a.setAttribute("class", "oc-chrome-ref");
1208
+ const BRAND_LARGE = 16;
1209
+ const text = createSVGElement("text");
1210
+ setAttrs(text, {
1211
+ x: rightEdge,
1212
+ y: chromeY + textAscent2(BRAND_LARGE),
1213
+ "font-family": layout.theme.fonts.family,
1214
+ "font-size": BRAND_LARGE,
1215
+ "font-weight": "600",
1216
+ "text-anchor": "end",
1217
+ "fill-opacity": 0.55
1218
+ });
1219
+ text.style.setProperty("fill", fill);
1220
+ text.textContent = "OpenData";
1221
+ a.appendChild(text);
1222
+ parent.appendChild(a);
1223
+ }
1145
1224
 
1146
1225
  // src/renderers/chrome.ts
1147
1226
  import {
1227
+ computeNoteBandHeight as computeNoteBandHeight2,
1148
1228
  FOOTNOTE_LINE_HEIGHT,
1149
- footnoteBandHeight as footnoteBandHeightFor,
1150
- textAscent as textAscent2,
1229
+ textAscent as textAscent3,
1151
1230
  truncateToWidth,
1152
1231
  wrapText
1153
1232
  } from "@opendata-ai/openchart-core";
1154
- function footnoteBandHeight(layout) {
1155
- return footnoteBandHeightFor(layout.chrome.footnotes?.length ?? 0, layout.theme);
1156
- }
1157
1233
  function renderChromeElement(parent, element, className, chromeKey, measureText, uppercase = false) {
1158
1234
  const text = createSVGElement("text");
1159
- setAttrs(text, { x: element.x, y: element.y + textAscent2(element.style.fontSize) });
1235
+ setAttrs(text, { x: element.x, y: element.y + textAscent3(element.style.fontSize) });
1160
1236
  applyTextStyle(text, element.style);
1161
1237
  text.setAttribute("class", className);
1162
1238
  text.setAttribute("data-chrome-key", chromeKey);
@@ -1241,7 +1317,8 @@ function renderChrome(parent, layout) {
1241
1317
  renderChromeElement(g, chrome.subtitle, "oc-subtitle", "subtitle", measureText);
1242
1318
  }
1243
1319
  const bottomOffset = layout.chrome.bottomAnchorY ?? layout.area.y + layout.area.height;
1244
- const bandHeight = footnoteBandHeight(layout);
1320
+ const bandHeight = layout.chrome.noteBandHeight ?? computeNoteBandHeight2(layout.chrome, layout.theme);
1321
+ let noteLine = 0;
1245
1322
  if (chrome.footnotes && chrome.footnotes.length > 0) {
1246
1323
  const fontSize = layout.theme.fonts.sizes.small;
1247
1324
  const pad = layout.theme.spacing.padding;
@@ -1256,15 +1333,54 @@ function renderChrome(parent, layout) {
1256
1333
  };
1257
1334
  for (let i = 0; i < chrome.footnotes.length; i++) {
1258
1335
  const f = chrome.footnotes[i];
1259
- const y = bottomOffset + layout.theme.spacing.chartToFooter + textAscent2(fontSize) + i * lineHeight;
1336
+ const y = bottomOffset + layout.theme.spacing.chartToFooter + textAscent3(fontSize) + noteLine * lineHeight;
1260
1337
  const el = createSVGElement("text");
1261
1338
  el.setAttribute("class", "oc-footnotes");
1339
+ if (f.specIndex !== void 0) el.setAttribute("data-note-spec-index", String(f.specIndex));
1340
+ if (f.id !== void 0) el.setAttribute("data-note-id", f.id);
1262
1341
  setAttrs(el, { x: pad, y });
1263
1342
  applyTextStyle(el, style);
1264
- el.textContent = `${f.index}. ${f.text}`;
1343
+ if (f.lines) {
1344
+ f.lines.forEach((line, index) => {
1345
+ const span = createSVGElement("tspan");
1346
+ setAttrs(span, { x: pad, dy: index === 0 ? 0 : lineHeight });
1347
+ span.textContent = line;
1348
+ el.appendChild(span);
1349
+ });
1350
+ } else el.textContent = `${f.index}. ${f.text}`;
1351
+ noteLine += f.lines?.length ?? 1;
1265
1352
  g.appendChild(el);
1266
1353
  }
1267
1354
  }
1355
+ let summaryLine = noteLine;
1356
+ for (const entry of chrome.seriesSummary ?? []) {
1357
+ const size = layout.theme.fonts.sizes.small;
1358
+ const el = createSVGElement("text");
1359
+ el.setAttribute("class", "oc-series-summary");
1360
+ el.setAttribute("data-series", entry.key);
1361
+ setAttrs(el, {
1362
+ x: layout.theme.spacing.padding,
1363
+ y: bottomOffset + layout.theme.spacing.chartToFooter + textAscent3(size) + summaryLine * size * FOOTNOTE_LINE_HEIGHT
1364
+ });
1365
+ applyTextStyle(el, {
1366
+ fontFamily: layout.theme.fonts.family,
1367
+ fontSize: size,
1368
+ fontWeight: 500,
1369
+ lineHeight: FOOTNOTE_LINE_HEIGHT,
1370
+ fill: entry.color
1371
+ });
1372
+ entry.lines.forEach((line, index) => {
1373
+ const span = createSVGElement("tspan");
1374
+ setAttrs(span, {
1375
+ x: layout.theme.spacing.padding,
1376
+ dy: index === 0 ? 0 : size * FOOTNOTE_LINE_HEIGHT
1377
+ });
1378
+ span.textContent = line;
1379
+ el.appendChild(span);
1380
+ });
1381
+ summaryLine += entry.lines.length;
1382
+ g.appendChild(el);
1383
+ }
1268
1384
  if (chrome.source) {
1269
1385
  renderChromeElement(
1270
1386
  g,
@@ -1299,44 +1415,6 @@ function renderChrome(parent, layout) {
1299
1415
  parent.appendChild(g);
1300
1416
  }
1301
1417
 
1302
- // src/renderers/brand.ts
1303
- var BRAND_URL = "https://tryopendata.ai";
1304
- function renderBrand(parent, layout) {
1305
- if (layout.dimensions.width < BRAND_MIN_WIDTH) return;
1306
- const { width } = layout.dimensions;
1307
- const padding = layout.theme.spacing.padding;
1308
- const rightEdge = width - padding;
1309
- const fill = layout.theme.colors.axis;
1310
- const { chrome } = layout;
1311
- const bottomOffset = chrome.bottomAnchorY ?? layout.area.y + layout.area.height;
1312
- const firstBottom = chrome.source ?? chrome.byline ?? chrome.footer;
1313
- const { legend } = layout;
1314
- const bottomLegendOffset = legend.position === "bottom" && legend.bounds.height > 0 ? legend.bounds.height + 8 : 0;
1315
- const bandHeight = footnoteBandHeight(layout);
1316
- const chromeY = firstBottom ? bottomOffset + firstBottom.y + bandHeight : bottomOffset + layout.theme.spacing.chartToFooter + bottomLegendOffset + bandHeight;
1317
- const a = createSVGElement("a");
1318
- a.setAttribute("href", BRAND_URL);
1319
- a.setAttributeNS(XLINK_NS, "xlink:href", BRAND_URL);
1320
- a.setAttribute("target", "_blank");
1321
- a.setAttribute("rel", "noopener");
1322
- a.setAttribute("class", "oc-chrome-ref");
1323
- const BRAND_LARGE = 16;
1324
- const text = createSVGElement("text");
1325
- setAttrs(text, {
1326
- x: rightEdge,
1327
- y: chromeY + textAscent3(BRAND_LARGE),
1328
- "font-family": layout.theme.fonts.family,
1329
- "font-size": BRAND_LARGE,
1330
- "font-weight": "600",
1331
- "text-anchor": "end",
1332
- "fill-opacity": 0.55
1333
- });
1334
- text.style.setProperty("fill", fill);
1335
- text.textContent = "OpenData";
1336
- a.appendChild(text);
1337
- parent.appendChild(a);
1338
- }
1339
-
1340
1418
  // src/renderers/endpoint-labels.ts
1341
1419
  var LEADER_STROKE_WIDTH = 1;
1342
1420
  var LEADER_OPACITY = 0.45;
@@ -1542,7 +1620,11 @@ function renderContinuousLegend(parent, legend) {
1542
1620
  }
1543
1621
  for (const tick of legend.ticks) {
1544
1622
  const label = createSVGElement("text");
1545
- setAttrs(label, { x: tick.x, y: legend.labelY, "text-anchor": tick.anchor });
1623
+ setAttrs(label, {
1624
+ x: tick.x,
1625
+ y: legend.labelY + (tick.offsetY ?? 0),
1626
+ "text-anchor": tick.anchor
1627
+ });
1546
1628
  applyTextStyle(label, legend.labelStyle);
1547
1629
  label.textContent = tick.label;
1548
1630
  g.appendChild(label);
@@ -1833,6 +1915,7 @@ function renderChartSVG(layout, container, opts) {
1833
1915
  const stackSegmentDuration = maxSegments > 0 ? Math.round(enterPhase.duration / maxSegments) : void 0;
1834
1916
  stampAnimationVars(svg, {
1835
1917
  duration: enterPhase.duration,
1918
+ spring: enterPhase.spring,
1836
1919
  stagger,
1837
1920
  annotationDelay: animation.annotationDelay,
1838
1921
  ease: enterPhase.ease,
@@ -1892,6 +1975,31 @@ function renderChartSVG(layout, container, opts) {
1892
1975
  clippedGroup.setAttribute("data-oc-marks-group", "true");
1893
1976
  clipGroup.appendChild(clippedGroup);
1894
1977
  const markLabelsOverlay = renderMarks(clippedGroup, layout, { skipPoints: canvasMarks });
1978
+ if (enterPhase?.spring && layout.marks.some((mark) => mark.type === "rect" && mark.stackPos !== void 0)) {
1979
+ const stacks = /* @__PURE__ */ new Map();
1980
+ for (const mark of layout.marks) {
1981
+ if (mark.type !== "rect" || mark.stackPos === void 0 || !mark.key) continue;
1982
+ const element = Array.from(clippedGroup.children).find(
1983
+ (child) => child.getAttribute("data-key") === mark.key
1984
+ );
1985
+ if (!element) continue;
1986
+ const horizontal = element.getAttribute("data-orient") === "horizontal";
1987
+ const key = `${horizontal ? "h" : "v"}:${horizontal ? mark.y : mark.x}`;
1988
+ let stack = stacks.get(key);
1989
+ if (!stack) {
1990
+ stack = createSVGElement("g");
1991
+ setAttrs(stack, {
1992
+ class: "oc-stack-reveal",
1993
+ "data-key": `stack:${key}`,
1994
+ "data-orient": horizontal ? "horizontal" : "vertical",
1995
+ "data-animation-index": 0
1996
+ });
1997
+ clippedGroup.insertBefore(stack, element);
1998
+ stacks.set(key, stack);
1999
+ }
2000
+ stack.appendChild(element);
2001
+ }
2002
+ }
1895
2003
  let pointCircles = null;
1896
2004
  let pointCircleCoords = null;
1897
2005
  const getPointCircles = () => {
@@ -2058,17 +2166,18 @@ function renderFacetedPanels(svg, layout, panels, defs) {
2058
2166
 
2059
2167
  export {
2060
2168
  stampAnimationVars,
2169
+ renderChromeElement,
2061
2170
  nextSvgId,
2062
2171
  resetSvgIdCounter,
2063
2172
  buildGradientDefs,
2064
2173
  resolveMarkFill,
2065
2174
  buildPatternDefs,
2066
2175
  resolvePatternFill,
2067
- renderChromeElement,
2176
+ updateAnnotationGeometry,
2068
2177
  renderLegend,
2069
2178
  registerMarkRenderer,
2070
2179
  rectPathWithCorners,
2071
2180
  renderSingleMark,
2072
2181
  renderChartSVG
2073
2182
  };
2074
- //# sourceMappingURL=chunk-SXTHPXG6.js.map
2183
+ //# sourceMappingURL=chunk-APMUBW72.js.map