@opendata-ai/openchart-vanilla 8.0.0-rc.3 → 8.0.0-rc.5
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/{chunk-SBIGNRAH.js → chunk-XZZGLZDA.js} +78 -28
- package/dist/chunk-XZZGLZDA.js.map +1 -0
- package/dist/index.d.ts +11 -13
- package/dist/index.js +1 -1
- package/dist/story/index.js +1 -1
- package/dist/styles.css +1 -1
- package/dist/styles.css.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/map.test.ts +35 -0
- package/src/index.ts +1 -1
- package/src/map-camera.ts +7 -2
- package/src/map-mount.ts +45 -29
- package/src/map-renderer.ts +81 -17
- package/dist/chunk-SBIGNRAH.js.map +0 -1
|
@@ -552,6 +552,7 @@ function setupTableAnimationCleanup(wrapper) {
|
|
|
552
552
|
}
|
|
553
553
|
|
|
554
554
|
// src/map-camera.ts
|
|
555
|
+
var FOCUS_DIM_OPACITY = 0.25;
|
|
555
556
|
function focusTargetForFeatures(layout, ids, padding = 16) {
|
|
556
557
|
const idSet = new Set(ids.map(String));
|
|
557
558
|
let minX = Infinity;
|
|
@@ -594,7 +595,6 @@ function applyMapCamera(svg, camera, layout) {
|
|
|
594
595
|
const baseSW = Number(p.getAttribute("data-base-stroke-width") ?? 1);
|
|
595
596
|
p.setAttribute("r", String(baseR / camera.k));
|
|
596
597
|
p.setAttribute("stroke-width", String(baseSW / camera.k));
|
|
597
|
-
p.setAttribute("vector-effect", "non-scaling-stroke");
|
|
598
598
|
}
|
|
599
599
|
} else {
|
|
600
600
|
cameraGroup.removeAttribute("transform");
|
|
@@ -736,7 +736,7 @@ function renderBorders(parent, borders) {
|
|
|
736
736
|
}
|
|
737
737
|
parent.appendChild(g);
|
|
738
738
|
}
|
|
739
|
-
function renderFeatures(parent, features, animation, staggerBudget = 0) {
|
|
739
|
+
function renderFeatures(parent, features, animation, staggerBudget = 0, focusIds) {
|
|
740
740
|
const g = createSVGElement2("g");
|
|
741
741
|
g.setAttribute("class", "oc-map-features");
|
|
742
742
|
g.setAttribute("role", "list");
|
|
@@ -779,12 +779,19 @@ function renderFeatures(parent, features, animation, staggerBudget = 0) {
|
|
|
779
779
|
if (feature.aria?.label) {
|
|
780
780
|
path.setAttribute("aria-label", feature.aria.label);
|
|
781
781
|
}
|
|
782
|
+
const dimmed = focusIds ? !focusIds.has(String(feature.id)) : false;
|
|
783
|
+
const s = path.style;
|
|
784
|
+
if (dimmed) {
|
|
785
|
+
s.setProperty("opacity", String(FOCUS_DIM_OPACITY));
|
|
786
|
+
}
|
|
782
787
|
if (!bulk && animation?.enter) {
|
|
783
788
|
const idx = feature.animationIndex ?? i;
|
|
784
789
|
path.setAttribute("data-animation-index", String(idx));
|
|
785
|
-
const s = path.style;
|
|
786
790
|
s.setProperty("--oc-mark-index", String(idx));
|
|
787
791
|
s.setProperty("--oc-feature-fill", feature.fill);
|
|
792
|
+
if (dimmed) {
|
|
793
|
+
s.setProperty("--oc-feature-target-opacity", String(FOCUS_DIM_OPACITY));
|
|
794
|
+
}
|
|
788
795
|
if (staggerBudget > 0 && maxIdx > 0) {
|
|
789
796
|
s.setProperty("--oc-map-delay", `${shuffledDelays[i]}ms`);
|
|
790
797
|
}
|
|
@@ -797,16 +804,15 @@ function renderPointMarks(parent, points, animation) {
|
|
|
797
804
|
if (points.length === 0) return;
|
|
798
805
|
const g = createSVGElement2("g");
|
|
799
806
|
g.setAttribute("class", "oc-map-points");
|
|
800
|
-
g.setAttribute("role", "list");
|
|
801
807
|
for (const pt of points) {
|
|
802
808
|
const circle = createSVGElement2("circle");
|
|
803
809
|
circle.setAttribute("class", "oc-map-point");
|
|
804
|
-
circle.setAttribute("role", "listitem");
|
|
805
810
|
setAttrs2(circle, {
|
|
806
811
|
cx: pt.cx,
|
|
807
812
|
cy: pt.cy,
|
|
808
813
|
r: pt.r,
|
|
809
814
|
fill: pt.fill,
|
|
815
|
+
"fill-opacity": pt.fillOpacity,
|
|
810
816
|
stroke: pt.stroke,
|
|
811
817
|
"stroke-width": pt.strokeWidth
|
|
812
818
|
});
|
|
@@ -817,10 +823,9 @@ function renderPointMarks(parent, points, animation) {
|
|
|
817
823
|
circle.setAttribute("aria-label", pt.aria.label);
|
|
818
824
|
}
|
|
819
825
|
if (animation?.enter) {
|
|
820
|
-
circle.style
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
);
|
|
826
|
+
const s = circle.style;
|
|
827
|
+
s.setProperty("--oc-mark-index", String(pt.animationIndex));
|
|
828
|
+
s.setProperty("transform-origin", `${pt.cx}px ${pt.cy}px`);
|
|
824
829
|
}
|
|
825
830
|
g.appendChild(circle);
|
|
826
831
|
}
|
|
@@ -856,28 +861,64 @@ function renderMapSVG(layout, opts) {
|
|
|
856
861
|
}
|
|
857
862
|
const defs = createSVGElement2("defs");
|
|
858
863
|
svg.appendChild(defs);
|
|
859
|
-
renderChrome(svg, layout);
|
|
860
864
|
const mapGroup = createSVGElement2("g");
|
|
861
865
|
mapGroup.setAttribute("class", "oc-map-group");
|
|
862
866
|
mapGroup.setAttribute("transform", `translate(${layout.area.x},${layout.area.y})`);
|
|
863
867
|
const cameraGroup = createSVGElement2("g");
|
|
864
868
|
cameraGroup.setAttribute("class", "oc-map-camera");
|
|
865
869
|
cameraGroup.setAttribute("data-oc-map-camera", "");
|
|
866
|
-
|
|
870
|
+
const focusIdSet = layout.focus ? new Set(layout.focus.ids.map(String)) : void 0;
|
|
871
|
+
renderFeatures(
|
|
872
|
+
cameraGroup,
|
|
873
|
+
features,
|
|
874
|
+
animate ? animation : void 0,
|
|
875
|
+
mapStaggerBudget,
|
|
876
|
+
focusIdSet
|
|
877
|
+
);
|
|
867
878
|
renderBorders(cameraGroup, borders);
|
|
868
879
|
renderPointMarks(cameraGroup, layout.pointMarks, animate ? animation : void 0);
|
|
869
880
|
mapGroup.appendChild(cameraGroup);
|
|
870
881
|
svg.appendChild(mapGroup);
|
|
882
|
+
renderChrome(svg, layout);
|
|
871
883
|
if (layout.continuousLegend) {
|
|
872
884
|
renderLegend(svg, layout.continuousLegend);
|
|
873
885
|
} else if (layout.categoricalLegend) {
|
|
874
886
|
renderLegend(svg, layout.categoricalLegend);
|
|
875
887
|
}
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
888
|
+
const ptLegend = layout.pointCategoricalLegend ?? layout.pointContinuousLegend;
|
|
889
|
+
if (ptLegend) {
|
|
890
|
+
const isDark = layout.theme.isDark;
|
|
891
|
+
const padX = 10;
|
|
892
|
+
const padY = 8;
|
|
893
|
+
const swatchSize = "swatchSize" in ptLegend ? ptLegend.swatchSize : 10;
|
|
894
|
+
const swatchGap = "swatchGap" in ptLegend ? ptLegend.swatchGap : 6;
|
|
895
|
+
const entryGap = "entryGap" in ptLegend ? ptLegend.entryGap : 16;
|
|
896
|
+
let contentWidth = ptLegend.bounds.width;
|
|
897
|
+
if ("entries" in ptLegend && ptLegend.entries) {
|
|
898
|
+
const cat = ptLegend;
|
|
899
|
+
if (cat && cat.entries.length > 0) {
|
|
900
|
+
const fontSize = ptLegend.labelStyle.fontSize;
|
|
901
|
+
let w = 0;
|
|
902
|
+
for (const entry of cat.entries) {
|
|
903
|
+
w += swatchSize + swatchGap + entry.label.length * fontSize * 0.6 + entryGap;
|
|
904
|
+
}
|
|
905
|
+
w -= entryGap;
|
|
906
|
+
contentWidth = Math.min(w, ptLegend.bounds.width);
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
const contentCenterY = ptLegend.bounds.y + swatchSize / 2;
|
|
910
|
+
const bgHeight = swatchSize + padY * 2;
|
|
911
|
+
const bg = createSVGElement2("rect");
|
|
912
|
+
setAttrs2(bg, {
|
|
913
|
+
x: ptLegend.bounds.x - padX,
|
|
914
|
+
y: contentCenterY - bgHeight / 2,
|
|
915
|
+
width: contentWidth + padX * 2,
|
|
916
|
+
height: bgHeight,
|
|
917
|
+
rx: 4,
|
|
918
|
+
fill: isDark ? "rgba(24,24,27,0.9)" : "rgba(255,255,255,0.9)"
|
|
919
|
+
});
|
|
920
|
+
svg.appendChild(bg);
|
|
921
|
+
renderLegend(svg, ptLegend);
|
|
881
922
|
}
|
|
882
923
|
if (watermark) {
|
|
883
924
|
renderWatermark(svg, layout);
|
|
@@ -1456,6 +1497,12 @@ function scheduleFontReload(fontFamily, isAlive, onReady) {
|
|
|
1456
1497
|
}
|
|
1457
1498
|
|
|
1458
1499
|
// src/map-mount.ts
|
|
1500
|
+
function focusSignature(focus) {
|
|
1501
|
+
if (!focus) return null;
|
|
1502
|
+
const t = focus.target;
|
|
1503
|
+
const ids = focus.ids.map(String).sort().join(",");
|
|
1504
|
+
return `${ids}|${Math.round(t.x)},${Math.round(t.y)},${Math.round(t.width)},${Math.round(t.height)},${t.padding}`;
|
|
1505
|
+
}
|
|
1459
1506
|
function prefersReducedMotion() {
|
|
1460
1507
|
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
|
|
1461
1508
|
try {
|
|
@@ -1540,6 +1587,7 @@ function createMap(container, spec, options) {
|
|
|
1540
1587
|
}
|
|
1541
1588
|
if (feature) {
|
|
1542
1589
|
options?.onMarkHover?.({
|
|
1590
|
+
kind: "feature",
|
|
1543
1591
|
id: feature.id,
|
|
1544
1592
|
name: feature.name,
|
|
1545
1593
|
data: feature.data
|
|
@@ -1564,6 +1612,7 @@ function createMap(container, spec, options) {
|
|
|
1564
1612
|
const handleClick = () => {
|
|
1565
1613
|
if (feature) {
|
|
1566
1614
|
options?.onMarkClick?.({
|
|
1615
|
+
kind: "feature",
|
|
1567
1616
|
id: feature.id,
|
|
1568
1617
|
name: feature.name,
|
|
1569
1618
|
data: feature.data
|
|
@@ -1600,8 +1649,8 @@ function createMap(container, spec, options) {
|
|
|
1600
1649
|
}
|
|
1601
1650
|
if (pointMark) {
|
|
1602
1651
|
options?.onMarkHover?.({
|
|
1652
|
+
kind: "point",
|
|
1603
1653
|
id: pointKey,
|
|
1604
|
-
name: pointKey,
|
|
1605
1654
|
data: pointMark.data
|
|
1606
1655
|
});
|
|
1607
1656
|
}
|
|
@@ -1624,8 +1673,8 @@ function createMap(container, spec, options) {
|
|
|
1624
1673
|
const handlePointClick = () => {
|
|
1625
1674
|
if (pointMark) {
|
|
1626
1675
|
options?.onMarkClick?.({
|
|
1676
|
+
kind: "point",
|
|
1627
1677
|
id: pointKey,
|
|
1628
|
-
name: pointKey,
|
|
1629
1678
|
data: pointMark.data
|
|
1630
1679
|
});
|
|
1631
1680
|
}
|
|
@@ -1708,7 +1757,7 @@ function createMap(container, spec, options) {
|
|
|
1708
1757
|
const fid = el.getAttribute("data-feature-id");
|
|
1709
1758
|
el.style.setProperty(
|
|
1710
1759
|
"opacity",
|
|
1711
|
-
fid && focusSet.has(fid) ? "1" :
|
|
1760
|
+
fid && focusSet.has(fid) ? "1" : String(FOCUS_DIM_OPACITY)
|
|
1712
1761
|
);
|
|
1713
1762
|
}
|
|
1714
1763
|
}
|
|
@@ -1721,15 +1770,17 @@ function createMap(container, spec, options) {
|
|
|
1721
1770
|
fillTransitionHandle.cancel();
|
|
1722
1771
|
fillTransitionHandle = null;
|
|
1723
1772
|
}
|
|
1724
|
-
|
|
1773
|
+
const oldSvg = svgElement;
|
|
1774
|
+
const newSvg = renderMapSVG(currentLayout, { animate });
|
|
1775
|
+
if (oldSvg) {
|
|
1725
1776
|
if (cleanupTooltipEvents) {
|
|
1726
1777
|
cleanupTooltipEvents();
|
|
1727
1778
|
cleanupTooltipEvents = null;
|
|
1728
1779
|
}
|
|
1729
|
-
|
|
1780
|
+
container.replaceChild(newSvg, oldSvg);
|
|
1781
|
+
} else {
|
|
1782
|
+
container.appendChild(newSvg);
|
|
1730
1783
|
}
|
|
1731
|
-
const newSvg = renderMapSVG(currentLayout, { animate });
|
|
1732
|
-
container.appendChild(newSvg);
|
|
1733
1784
|
svgElement = newSvg;
|
|
1734
1785
|
cleanupTooltipEvents = wireTooltipAndInteraction(newSvg, currentLayout);
|
|
1735
1786
|
if (options?.tooltip !== false) {
|
|
@@ -1778,7 +1829,7 @@ function createMap(container, spec, options) {
|
|
|
1778
1829
|
const canAnimate = !animationCleanup && !prefersReducedMotion();
|
|
1779
1830
|
const prevFills = canAnimate ? captureFeatureFills(svgElement) : null;
|
|
1780
1831
|
const prevFocusIds = currentFocusIds ? currentFocusIds.map(String).sort().join(",") : null;
|
|
1781
|
-
const
|
|
1832
|
+
const prevFocusSig = focusSignature(currentLayout.focus);
|
|
1782
1833
|
currentLayout = compile();
|
|
1783
1834
|
render();
|
|
1784
1835
|
if (canAnimate && prevFills && prevFills.size > 0 && svgElement && currentLayout.animation?.update) {
|
|
@@ -1787,9 +1838,8 @@ function createMap(container, spec, options) {
|
|
|
1787
1838
|
});
|
|
1788
1839
|
}
|
|
1789
1840
|
const nextFocus = currentLayout.focus;
|
|
1790
|
-
const
|
|
1791
|
-
|
|
1792
|
-
if (nextFocusIds !== prevFocusIds || nextFocusPadding !== prevFocusPadding) {
|
|
1841
|
+
const nextFocusSig = focusSignature(nextFocus);
|
|
1842
|
+
if (nextFocusSig !== prevFocusSig) {
|
|
1793
1843
|
if (nextFocus) {
|
|
1794
1844
|
currentFocusIds = [...nextFocus.ids];
|
|
1795
1845
|
const cam = cameraForTarget(currentLayout, nextFocus.target);
|
|
@@ -6626,4 +6676,4 @@ export {
|
|
|
6626
6676
|
createYouDrawIt,
|
|
6627
6677
|
createChart
|
|
6628
6678
|
};
|
|
6629
|
-
//# sourceMappingURL=chunk-
|
|
6679
|
+
//# sourceMappingURL=chunk-XZZGLZDA.js.map
|