@opendata-ai/openchart-vanilla 8.0.0-rc.2 → 8.0.0-rc.3
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-ENXSUXC5.js → chunk-SBIGNRAH.js} +117 -1
- package/dist/{chunk-ENXSUXC5.js.map → chunk-SBIGNRAH.js.map} +1 -1
- 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 +81 -0
- package/src/map-camera.ts +18 -0
- package/src/map-mount.ts +69 -0
- package/src/map-renderer.ts +57 -0
|
@@ -588,12 +588,28 @@ function applyMapCamera(svg, camera, layout) {
|
|
|
588
588
|
for (const p of paths) {
|
|
589
589
|
p.setAttribute("vector-effect", "non-scaling-stroke");
|
|
590
590
|
}
|
|
591
|
+
const points = svg.querySelectorAll(".oc-map-point");
|
|
592
|
+
for (const p of points) {
|
|
593
|
+
const baseR = Number(p.getAttribute("data-base-r") ?? 5);
|
|
594
|
+
const baseSW = Number(p.getAttribute("data-base-stroke-width") ?? 1);
|
|
595
|
+
p.setAttribute("r", String(baseR / camera.k));
|
|
596
|
+
p.setAttribute("stroke-width", String(baseSW / camera.k));
|
|
597
|
+
p.setAttribute("vector-effect", "non-scaling-stroke");
|
|
598
|
+
}
|
|
591
599
|
} else {
|
|
592
600
|
cameraGroup.removeAttribute("transform");
|
|
593
601
|
const paths = svg.querySelectorAll(".oc-map-feature, .oc-map-borders path");
|
|
594
602
|
for (const p of paths) {
|
|
595
603
|
p.removeAttribute("vector-effect");
|
|
596
604
|
}
|
|
605
|
+
const points = svg.querySelectorAll(".oc-map-point");
|
|
606
|
+
for (const p of points) {
|
|
607
|
+
const baseR = Number(p.getAttribute("data-base-r") ?? 5);
|
|
608
|
+
const baseSW = Number(p.getAttribute("data-base-stroke-width") ?? 1);
|
|
609
|
+
p.setAttribute("r", String(baseR));
|
|
610
|
+
p.setAttribute("stroke-width", String(baseSW));
|
|
611
|
+
p.removeAttribute("vector-effect");
|
|
612
|
+
}
|
|
597
613
|
}
|
|
598
614
|
}
|
|
599
615
|
|
|
@@ -777,6 +793,39 @@ function renderFeatures(parent, features, animation, staggerBudget = 0) {
|
|
|
777
793
|
}
|
|
778
794
|
parent.appendChild(g);
|
|
779
795
|
}
|
|
796
|
+
function renderPointMarks(parent, points, animation) {
|
|
797
|
+
if (points.length === 0) return;
|
|
798
|
+
const g = createSVGElement2("g");
|
|
799
|
+
g.setAttribute("class", "oc-map-points");
|
|
800
|
+
g.setAttribute("role", "list");
|
|
801
|
+
for (const pt of points) {
|
|
802
|
+
const circle = createSVGElement2("circle");
|
|
803
|
+
circle.setAttribute("class", "oc-map-point");
|
|
804
|
+
circle.setAttribute("role", "listitem");
|
|
805
|
+
setAttrs2(circle, {
|
|
806
|
+
cx: pt.cx,
|
|
807
|
+
cy: pt.cy,
|
|
808
|
+
r: pt.r,
|
|
809
|
+
fill: pt.fill,
|
|
810
|
+
stroke: pt.stroke,
|
|
811
|
+
"stroke-width": pt.strokeWidth
|
|
812
|
+
});
|
|
813
|
+
circle.setAttribute("data-point-key", pt.key);
|
|
814
|
+
circle.setAttribute("data-base-r", String(pt.r));
|
|
815
|
+
circle.setAttribute("data-base-stroke-width", String(pt.strokeWidth));
|
|
816
|
+
if (pt.aria?.label) {
|
|
817
|
+
circle.setAttribute("aria-label", pt.aria.label);
|
|
818
|
+
}
|
|
819
|
+
if (animation?.enter) {
|
|
820
|
+
circle.style.setProperty(
|
|
821
|
+
"--oc-mark-index",
|
|
822
|
+
String(pt.animationIndex)
|
|
823
|
+
);
|
|
824
|
+
}
|
|
825
|
+
g.appendChild(circle);
|
|
826
|
+
}
|
|
827
|
+
parent.appendChild(g);
|
|
828
|
+
}
|
|
780
829
|
function renderMapSVG(layout, opts) {
|
|
781
830
|
const { width, height, features, borders, a11y, watermark, animation } = layout;
|
|
782
831
|
const animate = opts?.animate && !!animation?.enter;
|
|
@@ -816,6 +865,7 @@ function renderMapSVG(layout, opts) {
|
|
|
816
865
|
cameraGroup.setAttribute("data-oc-map-camera", "");
|
|
817
866
|
renderFeatures(cameraGroup, features, animate ? animation : void 0, mapStaggerBudget);
|
|
818
867
|
renderBorders(cameraGroup, borders);
|
|
868
|
+
renderPointMarks(cameraGroup, layout.pointMarks, animate ? animation : void 0);
|
|
819
869
|
mapGroup.appendChild(cameraGroup);
|
|
820
870
|
svg.appendChild(mapGroup);
|
|
821
871
|
if (layout.continuousLegend) {
|
|
@@ -823,6 +873,12 @@ function renderMapSVG(layout, opts) {
|
|
|
823
873
|
} else if (layout.categoricalLegend) {
|
|
824
874
|
renderLegend(svg, layout.categoricalLegend);
|
|
825
875
|
}
|
|
876
|
+
if (layout.pointCategoricalLegend) {
|
|
877
|
+
renderLegend(svg, layout.pointCategoricalLegend);
|
|
878
|
+
}
|
|
879
|
+
if (layout.pointContinuousLegend) {
|
|
880
|
+
renderLegend(svg, layout.pointContinuousLegend);
|
|
881
|
+
}
|
|
826
882
|
if (watermark) {
|
|
827
883
|
renderWatermark(svg, layout);
|
|
828
884
|
}
|
|
@@ -1525,6 +1581,66 @@ function createMap(container, spec, options) {
|
|
|
1525
1581
|
el.removeEventListener("click", handleClick);
|
|
1526
1582
|
});
|
|
1527
1583
|
}
|
|
1584
|
+
const pointMarksByKey = new Map(layout.pointMarks.map((p) => [p.key, p]));
|
|
1585
|
+
const pointElements = svg.querySelectorAll(".oc-map-point");
|
|
1586
|
+
for (const el of pointElements) {
|
|
1587
|
+
const pointKey = el.getAttribute("data-point-key");
|
|
1588
|
+
if (!pointKey) continue;
|
|
1589
|
+
const content = layout.tooltipDescriptors.get(`point:${pointKey}`);
|
|
1590
|
+
const pointMark = pointMarksByKey.get(pointKey);
|
|
1591
|
+
const handlePointMouseEnter = (e) => {
|
|
1592
|
+
const mouseEvent = e;
|
|
1593
|
+
el.style.setProperty("cursor", "pointer");
|
|
1594
|
+
el.style.setProperty("filter", "brightness(1.15)");
|
|
1595
|
+
if (content && tooltipManager && options?.tooltip !== false) {
|
|
1596
|
+
const svgRect = svg.getBoundingClientRect();
|
|
1597
|
+
const x = mouseEvent.clientX - svgRect.left;
|
|
1598
|
+
const y = mouseEvent.clientY - svgRect.top;
|
|
1599
|
+
tooltipManager.show(content, x, y);
|
|
1600
|
+
}
|
|
1601
|
+
if (pointMark) {
|
|
1602
|
+
options?.onMarkHover?.({
|
|
1603
|
+
id: pointKey,
|
|
1604
|
+
name: pointKey,
|
|
1605
|
+
data: pointMark.data
|
|
1606
|
+
});
|
|
1607
|
+
}
|
|
1608
|
+
};
|
|
1609
|
+
const handlePointMouseMove = (e) => {
|
|
1610
|
+
if (content && tooltipManager && options?.tooltip !== false) {
|
|
1611
|
+
const mouseEvent = e;
|
|
1612
|
+
const svgRect = svg.getBoundingClientRect();
|
|
1613
|
+
const x = mouseEvent.clientX - svgRect.left;
|
|
1614
|
+
const y = mouseEvent.clientY - svgRect.top;
|
|
1615
|
+
tooltipManager.show(content, x, y);
|
|
1616
|
+
}
|
|
1617
|
+
};
|
|
1618
|
+
const handlePointMouseLeave = () => {
|
|
1619
|
+
el.style.removeProperty("cursor");
|
|
1620
|
+
el.style.removeProperty("filter");
|
|
1621
|
+
tooltipManager?.hide();
|
|
1622
|
+
options?.onMarkHover?.(null);
|
|
1623
|
+
};
|
|
1624
|
+
const handlePointClick = () => {
|
|
1625
|
+
if (pointMark) {
|
|
1626
|
+
options?.onMarkClick?.({
|
|
1627
|
+
id: pointKey,
|
|
1628
|
+
name: pointKey,
|
|
1629
|
+
data: pointMark.data
|
|
1630
|
+
});
|
|
1631
|
+
}
|
|
1632
|
+
};
|
|
1633
|
+
el.addEventListener("mouseenter", handlePointMouseEnter);
|
|
1634
|
+
el.addEventListener("mousemove", handlePointMouseMove);
|
|
1635
|
+
el.addEventListener("mouseleave", handlePointMouseLeave);
|
|
1636
|
+
el.addEventListener("click", handlePointClick);
|
|
1637
|
+
cleanups.push(() => {
|
|
1638
|
+
el.removeEventListener("mouseenter", handlePointMouseEnter);
|
|
1639
|
+
el.removeEventListener("mousemove", handlePointMouseMove);
|
|
1640
|
+
el.removeEventListener("mouseleave", handlePointMouseLeave);
|
|
1641
|
+
el.removeEventListener("click", handlePointClick);
|
|
1642
|
+
});
|
|
1643
|
+
}
|
|
1528
1644
|
return () => {
|
|
1529
1645
|
for (const cleanup of cleanups) {
|
|
1530
1646
|
cleanup();
|
|
@@ -6510,4 +6626,4 @@ export {
|
|
|
6510
6626
|
createYouDrawIt,
|
|
6511
6627
|
createChart
|
|
6512
6628
|
};
|
|
6513
|
-
//# sourceMappingURL=chunk-
|
|
6629
|
+
//# sourceMappingURL=chunk-SBIGNRAH.js.map
|