@opendata-ai/openchart-vanilla 7.7.0 → 7.8.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/{chunk-PSMDJEXK.js → chunk-KYRQV6KR.js} +343 -3
- package/dist/chunk-KYRQV6KR.js.map +1 -0
- package/dist/index.js +14 -357
- package/dist/index.js.map +1 -1
- package/dist/static.d.ts +2 -2
- package/dist/static.js +37 -27
- package/dist/static.js.map +1 -1
- package/package.json +3 -3
- package/src/static.ts +42 -32
- package/src/tilemap-renderer.ts +2 -3
- package/dist/chunk-PSMDJEXK.js.map +0 -1
|
@@ -1670,11 +1670,351 @@ function renderFacetedPanels(svg, layout, panels, defs) {
|
|
|
1670
1670
|
}
|
|
1671
1671
|
}
|
|
1672
1672
|
|
|
1673
|
+
// src/tilemap-renderer.ts
|
|
1674
|
+
import { textAscent as textAscent4 } from "@opendata-ai/openchart-core";
|
|
1675
|
+
var SVG_NS3 = "http://www.w3.org/2000/svg";
|
|
1676
|
+
var XLINK_NS2 = "http://www.w3.org/1999/xlink";
|
|
1677
|
+
var BRAND_URL2 = "https://tryopendata.ai";
|
|
1678
|
+
var EASE_VAR_MAP2 = {
|
|
1679
|
+
smooth: "var(--oc-ease-smooth)",
|
|
1680
|
+
snappy: "var(--oc-ease-snappy)"
|
|
1681
|
+
};
|
|
1682
|
+
function createSVGElement2(tag) {
|
|
1683
|
+
return document.createElementNS(SVG_NS3, tag);
|
|
1684
|
+
}
|
|
1685
|
+
function setAttrs2(el, attrs) {
|
|
1686
|
+
for (const [key, value] of Object.entries(attrs)) {
|
|
1687
|
+
el.setAttribute(key, String(value));
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
function renderChrome2(parent, layout) {
|
|
1691
|
+
const g = createSVGElement2("g");
|
|
1692
|
+
g.setAttribute("class", "oc-chrome");
|
|
1693
|
+
const { chrome } = layout;
|
|
1694
|
+
const bottomOffset = layout.area.y + layout.area.height;
|
|
1695
|
+
if (chrome.title) {
|
|
1696
|
+
const text = createSVGElement2("text");
|
|
1697
|
+
setAttrs2(text, {
|
|
1698
|
+
x: chrome.title.x,
|
|
1699
|
+
y: chrome.title.y + textAscent4(chrome.title.style.fontSize)
|
|
1700
|
+
});
|
|
1701
|
+
text.setAttribute("class", "oc-title");
|
|
1702
|
+
text.setAttribute("font-family", chrome.title.style.fontFamily);
|
|
1703
|
+
text.setAttribute("font-size", String(chrome.title.style.fontSize));
|
|
1704
|
+
text.setAttribute("font-weight", String(chrome.title.style.fontWeight));
|
|
1705
|
+
text.style.setProperty("fill", chrome.title.style.fill);
|
|
1706
|
+
text.textContent = chrome.title.text;
|
|
1707
|
+
g.appendChild(text);
|
|
1708
|
+
}
|
|
1709
|
+
if (chrome.subtitle) {
|
|
1710
|
+
const text = createSVGElement2("text");
|
|
1711
|
+
setAttrs2(text, {
|
|
1712
|
+
x: chrome.subtitle.x,
|
|
1713
|
+
y: chrome.subtitle.y + textAscent4(chrome.subtitle.style.fontSize)
|
|
1714
|
+
});
|
|
1715
|
+
text.setAttribute("class", "oc-subtitle");
|
|
1716
|
+
text.setAttribute("font-family", chrome.subtitle.style.fontFamily);
|
|
1717
|
+
text.setAttribute("font-size", String(chrome.subtitle.style.fontSize));
|
|
1718
|
+
text.setAttribute("font-weight", String(chrome.subtitle.style.fontWeight));
|
|
1719
|
+
text.style.setProperty(
|
|
1720
|
+
"fill",
|
|
1721
|
+
chrome.subtitle.style.fill
|
|
1722
|
+
);
|
|
1723
|
+
text.textContent = chrome.subtitle.text;
|
|
1724
|
+
g.appendChild(text);
|
|
1725
|
+
}
|
|
1726
|
+
if (chrome.source) {
|
|
1727
|
+
const text = createSVGElement2("text");
|
|
1728
|
+
setAttrs2(text, {
|
|
1729
|
+
x: chrome.source.x,
|
|
1730
|
+
y: bottomOffset + chrome.source.y + textAscent4(chrome.source.style.fontSize)
|
|
1731
|
+
});
|
|
1732
|
+
text.setAttribute("class", "oc-source");
|
|
1733
|
+
text.setAttribute("font-family", chrome.source.style.fontFamily);
|
|
1734
|
+
text.setAttribute("font-size", String(chrome.source.style.fontSize));
|
|
1735
|
+
text.setAttribute("font-weight", String(chrome.source.style.fontWeight));
|
|
1736
|
+
text.style.setProperty(
|
|
1737
|
+
"fill",
|
|
1738
|
+
chrome.source.style.fill
|
|
1739
|
+
);
|
|
1740
|
+
text.textContent = chrome.source.text;
|
|
1741
|
+
g.appendChild(text);
|
|
1742
|
+
}
|
|
1743
|
+
if (chrome.byline) {
|
|
1744
|
+
const text = createSVGElement2("text");
|
|
1745
|
+
setAttrs2(text, {
|
|
1746
|
+
x: chrome.byline.x,
|
|
1747
|
+
y: bottomOffset + chrome.byline.y + textAscent4(chrome.byline.style.fontSize)
|
|
1748
|
+
});
|
|
1749
|
+
text.setAttribute("class", "oc-byline");
|
|
1750
|
+
text.setAttribute("font-family", chrome.byline.style.fontFamily);
|
|
1751
|
+
text.setAttribute("font-size", String(chrome.byline.style.fontSize));
|
|
1752
|
+
text.setAttribute("font-weight", String(chrome.byline.style.fontWeight));
|
|
1753
|
+
text.style.setProperty(
|
|
1754
|
+
"fill",
|
|
1755
|
+
chrome.byline.style.fill
|
|
1756
|
+
);
|
|
1757
|
+
text.textContent = chrome.byline.text;
|
|
1758
|
+
g.appendChild(text);
|
|
1759
|
+
}
|
|
1760
|
+
if (chrome.footer) {
|
|
1761
|
+
const text = createSVGElement2("text");
|
|
1762
|
+
setAttrs2(text, {
|
|
1763
|
+
x: chrome.footer.x,
|
|
1764
|
+
y: bottomOffset + chrome.footer.y + textAscent4(chrome.footer.style.fontSize)
|
|
1765
|
+
});
|
|
1766
|
+
text.setAttribute("class", "oc-footer");
|
|
1767
|
+
text.setAttribute("font-family", chrome.footer.style.fontFamily);
|
|
1768
|
+
text.setAttribute("font-size", String(chrome.footer.style.fontSize));
|
|
1769
|
+
text.setAttribute("font-weight", String(chrome.footer.style.fontWeight));
|
|
1770
|
+
text.style.setProperty(
|
|
1771
|
+
"fill",
|
|
1772
|
+
chrome.footer.style.fill
|
|
1773
|
+
);
|
|
1774
|
+
text.textContent = chrome.footer.text;
|
|
1775
|
+
g.appendChild(text);
|
|
1776
|
+
}
|
|
1777
|
+
parent.appendChild(g);
|
|
1778
|
+
}
|
|
1779
|
+
function renderWatermark(parent, layout) {
|
|
1780
|
+
if (layout.width < 480) return;
|
|
1781
|
+
const { width, height } = layout;
|
|
1782
|
+
const { theme } = layout;
|
|
1783
|
+
const padding = theme.spacing.padding;
|
|
1784
|
+
const rightEdge = width - padding;
|
|
1785
|
+
const bottomEdge = height - padding;
|
|
1786
|
+
const fill = theme.colors.axis;
|
|
1787
|
+
const a = createSVGElement2("a");
|
|
1788
|
+
a.setAttribute("href", BRAND_URL2);
|
|
1789
|
+
a.setAttributeNS(XLINK_NS2, "xlink:href", BRAND_URL2);
|
|
1790
|
+
a.setAttribute("target", "_blank");
|
|
1791
|
+
a.setAttribute("rel", "noopener");
|
|
1792
|
+
a.setAttribute("class", "oc-chrome-ref");
|
|
1793
|
+
const text = createSVGElement2("text");
|
|
1794
|
+
setAttrs2(text, {
|
|
1795
|
+
x: rightEdge,
|
|
1796
|
+
y: bottomEdge,
|
|
1797
|
+
"dominant-baseline": "alphabetic",
|
|
1798
|
+
"text-anchor": "end",
|
|
1799
|
+
"font-family": theme.fonts.family,
|
|
1800
|
+
"font-size": 12,
|
|
1801
|
+
"fill-opacity": 0.55
|
|
1802
|
+
});
|
|
1803
|
+
text.style.setProperty("fill", fill);
|
|
1804
|
+
const trySpan = createSVGElement2("tspan");
|
|
1805
|
+
setAttrs2(trySpan, { "font-weight": 500 });
|
|
1806
|
+
trySpan.textContent = "try";
|
|
1807
|
+
const openDataSpan = createSVGElement2("tspan");
|
|
1808
|
+
setAttrs2(openDataSpan, { "font-weight": 600, "font-size": 16 });
|
|
1809
|
+
openDataSpan.textContent = "OpenData";
|
|
1810
|
+
const aiSpan = createSVGElement2("tspan");
|
|
1811
|
+
setAttrs2(aiSpan, { "font-weight": 500 });
|
|
1812
|
+
aiSpan.textContent = ".ai";
|
|
1813
|
+
text.appendChild(trySpan);
|
|
1814
|
+
text.appendChild(openDataSpan);
|
|
1815
|
+
text.appendChild(aiSpan);
|
|
1816
|
+
a.appendChild(text);
|
|
1817
|
+
parent.appendChild(a);
|
|
1818
|
+
}
|
|
1819
|
+
function renderTiles(parent, tiles, animation) {
|
|
1820
|
+
const g = createSVGElement2("g");
|
|
1821
|
+
g.setAttribute("class", "oc-tilemap-tiles");
|
|
1822
|
+
g.setAttribute("role", "list");
|
|
1823
|
+
const tileDelays = [];
|
|
1824
|
+
if (animation?.enabled) {
|
|
1825
|
+
const baseStagger = 800 / Math.max(tiles.length, 1);
|
|
1826
|
+
let seed = 17;
|
|
1827
|
+
for (let i = 0; i < tiles.length; i++) {
|
|
1828
|
+
const idx = tiles[i].animationIndex ?? i;
|
|
1829
|
+
seed = seed * 1103515245 + 12345 & 2147483647;
|
|
1830
|
+
const jitter = (seed % 1e3 / 1e3 - 0.5) * 0.8;
|
|
1831
|
+
tileDelays.push(Math.max(0, Math.round(idx * baseStagger * (1 + jitter))));
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
for (let i = 0; i < tiles.length; i++) {
|
|
1835
|
+
const tile = tiles[i];
|
|
1836
|
+
const tileGroup = createSVGElement2("g");
|
|
1837
|
+
tileGroup.setAttribute("class", "oc-tilemap-tile");
|
|
1838
|
+
tileGroup.setAttribute("data-state", tile.stateCode);
|
|
1839
|
+
tileGroup.setAttribute("role", "listitem");
|
|
1840
|
+
if (tile.aria?.label) {
|
|
1841
|
+
tileGroup.setAttribute("aria-label", tile.aria.label);
|
|
1842
|
+
}
|
|
1843
|
+
if (animation?.enabled) {
|
|
1844
|
+
const idx = tile.animationIndex ?? i;
|
|
1845
|
+
tileGroup.setAttribute("data-animation-index", String(idx));
|
|
1846
|
+
tileGroup.style.setProperty(
|
|
1847
|
+
"--oc-mark-index",
|
|
1848
|
+
String(idx)
|
|
1849
|
+
);
|
|
1850
|
+
tileGroup.style.setProperty(
|
|
1851
|
+
"--oc-tile-delay",
|
|
1852
|
+
`${tileDelays[i]}ms`
|
|
1853
|
+
);
|
|
1854
|
+
}
|
|
1855
|
+
const rect = createSVGElement2("rect");
|
|
1856
|
+
setAttrs2(rect, {
|
|
1857
|
+
x: tile.x,
|
|
1858
|
+
y: tile.y,
|
|
1859
|
+
width: tile.size,
|
|
1860
|
+
height: tile.size,
|
|
1861
|
+
rx: tile.cornerRadius,
|
|
1862
|
+
fill: tile.fill,
|
|
1863
|
+
"fill-opacity": tile.fillOpacity ?? 1,
|
|
1864
|
+
stroke: tile.stroke,
|
|
1865
|
+
"stroke-width": tile.strokeWidth
|
|
1866
|
+
});
|
|
1867
|
+
tileGroup.appendChild(rect);
|
|
1868
|
+
const codeLabel = createSVGElement2("text");
|
|
1869
|
+
setAttrs2(codeLabel, {
|
|
1870
|
+
x: tile.label.x,
|
|
1871
|
+
y: tile.label.y,
|
|
1872
|
+
"text-anchor": "middle",
|
|
1873
|
+
"dominant-baseline": "central",
|
|
1874
|
+
"font-family": tile.label.style.fontFamily,
|
|
1875
|
+
"font-size": tile.label.style.fontSize,
|
|
1876
|
+
"font-weight": tile.label.style.fontWeight
|
|
1877
|
+
});
|
|
1878
|
+
codeLabel.style.setProperty(
|
|
1879
|
+
"fill",
|
|
1880
|
+
tile.label.style.fill
|
|
1881
|
+
);
|
|
1882
|
+
codeLabel.textContent = tile.label.text;
|
|
1883
|
+
tileGroup.appendChild(codeLabel);
|
|
1884
|
+
if (tile.valueLabel.visible && tile.valueLabel.text) {
|
|
1885
|
+
const valueLabel = createSVGElement2("text");
|
|
1886
|
+
setAttrs2(valueLabel, {
|
|
1887
|
+
x: tile.valueLabel.x,
|
|
1888
|
+
y: tile.valueLabel.y,
|
|
1889
|
+
"text-anchor": "middle",
|
|
1890
|
+
"dominant-baseline": "central",
|
|
1891
|
+
"font-family": tile.valueLabel.style.fontFamily,
|
|
1892
|
+
"font-size": tile.valueLabel.style.fontSize,
|
|
1893
|
+
"font-weight": tile.valueLabel.style.fontWeight
|
|
1894
|
+
});
|
|
1895
|
+
valueLabel.style.setProperty(
|
|
1896
|
+
"fill",
|
|
1897
|
+
tile.valueLabel.style.fill
|
|
1898
|
+
);
|
|
1899
|
+
valueLabel.textContent = tile.valueLabel.text;
|
|
1900
|
+
tileGroup.appendChild(valueLabel);
|
|
1901
|
+
}
|
|
1902
|
+
g.appendChild(tileGroup);
|
|
1903
|
+
}
|
|
1904
|
+
parent.appendChild(g);
|
|
1905
|
+
}
|
|
1906
|
+
function renderGradientLegend(parent, layout) {
|
|
1907
|
+
if (!layout.gradientLegend) return;
|
|
1908
|
+
const { gradientLegend } = layout;
|
|
1909
|
+
const g = createSVGElement2("g");
|
|
1910
|
+
g.setAttribute("class", "oc-tilemap-legend");
|
|
1911
|
+
const defs = parent.querySelector("defs") || createSVGElement2("defs");
|
|
1912
|
+
const exists = parent.querySelector("defs");
|
|
1913
|
+
if (!exists) {
|
|
1914
|
+
parent.insertBefore(defs, parent.firstChild);
|
|
1915
|
+
}
|
|
1916
|
+
const gradientId = nextSvgId("oc-tilemap-legend-gradient");
|
|
1917
|
+
const grad = createSVGElement2("linearGradient");
|
|
1918
|
+
grad.id = gradientId;
|
|
1919
|
+
grad.setAttribute("x1", "0%");
|
|
1920
|
+
grad.setAttribute("y1", "0%");
|
|
1921
|
+
grad.setAttribute("x2", "100%");
|
|
1922
|
+
grad.setAttribute("y2", "0%");
|
|
1923
|
+
for (const stop of gradientLegend.colorStops) {
|
|
1924
|
+
const s = createSVGElement2("stop");
|
|
1925
|
+
const attrs = {
|
|
1926
|
+
offset: `${stop.offset * 100}%`,
|
|
1927
|
+
"stop-color": stop.color
|
|
1928
|
+
};
|
|
1929
|
+
if (stop.opacity !== void 0) {
|
|
1930
|
+
attrs["stop-opacity"] = stop.opacity;
|
|
1931
|
+
}
|
|
1932
|
+
setAttrs2(s, attrs);
|
|
1933
|
+
grad.appendChild(s);
|
|
1934
|
+
}
|
|
1935
|
+
defs.appendChild(grad);
|
|
1936
|
+
const barHeight = gradientLegend.bounds.height;
|
|
1937
|
+
const bar = createSVGElement2("rect");
|
|
1938
|
+
setAttrs2(bar, {
|
|
1939
|
+
x: gradientLegend.bounds.x,
|
|
1940
|
+
y: gradientLegend.bounds.y,
|
|
1941
|
+
width: gradientLegend.bounds.width,
|
|
1942
|
+
height: barHeight,
|
|
1943
|
+
rx: barHeight / 2,
|
|
1944
|
+
fill: `url(#${gradientId})`
|
|
1945
|
+
});
|
|
1946
|
+
g.appendChild(bar);
|
|
1947
|
+
const minText = createSVGElement2("text");
|
|
1948
|
+
setAttrs2(minText, {
|
|
1949
|
+
x: gradientLegend.bounds.x,
|
|
1950
|
+
y: gradientLegend.bounds.y + gradientLegend.bounds.height + 14,
|
|
1951
|
+
"text-anchor": "start",
|
|
1952
|
+
"font-family": gradientLegend.labelStyle.fontFamily,
|
|
1953
|
+
"font-size": gradientLegend.labelStyle.fontSize,
|
|
1954
|
+
"font-weight": gradientLegend.labelStyle.fontWeight
|
|
1955
|
+
});
|
|
1956
|
+
minText.style.setProperty(
|
|
1957
|
+
"fill",
|
|
1958
|
+
gradientLegend.labelStyle.fill
|
|
1959
|
+
);
|
|
1960
|
+
minText.textContent = gradientLegend.minLabel;
|
|
1961
|
+
g.appendChild(minText);
|
|
1962
|
+
const maxText = createSVGElement2("text");
|
|
1963
|
+
setAttrs2(maxText, {
|
|
1964
|
+
x: gradientLegend.bounds.x + gradientLegend.bounds.width,
|
|
1965
|
+
y: gradientLegend.bounds.y + gradientLegend.bounds.height + 14,
|
|
1966
|
+
"text-anchor": "end",
|
|
1967
|
+
"font-family": gradientLegend.labelStyle.fontFamily,
|
|
1968
|
+
"font-size": gradientLegend.labelStyle.fontSize,
|
|
1969
|
+
"font-weight": gradientLegend.labelStyle.fontWeight
|
|
1970
|
+
});
|
|
1971
|
+
maxText.style.setProperty(
|
|
1972
|
+
"fill",
|
|
1973
|
+
gradientLegend.labelStyle.fill
|
|
1974
|
+
);
|
|
1975
|
+
maxText.textContent = gradientLegend.maxLabel;
|
|
1976
|
+
g.appendChild(maxText);
|
|
1977
|
+
parent.appendChild(g);
|
|
1978
|
+
}
|
|
1979
|
+
function renderTileMapSVG(layout, opts) {
|
|
1980
|
+
const { width, height, tiles, a11y, watermark, animation } = layout;
|
|
1981
|
+
const animate = opts?.animate && animation?.enabled;
|
|
1982
|
+
const svg = createSVGElement2("svg");
|
|
1983
|
+
svg.setAttribute("viewBox", `0 0 ${width} ${height}`);
|
|
1984
|
+
svg.setAttribute("role", "img");
|
|
1985
|
+
if (a11y.altText) {
|
|
1986
|
+
svg.setAttribute("aria-label", a11y.altText);
|
|
1987
|
+
}
|
|
1988
|
+
const classes = animate ? "oc-tilemap oc-animate" : "oc-tilemap";
|
|
1989
|
+
svg.setAttribute("class", classes);
|
|
1990
|
+
if (animate && animation) {
|
|
1991
|
+
const stagger = Math.max(5, Math.round(800 / Math.max(tiles.length, 1)));
|
|
1992
|
+
svg.style.setProperty("--oc-animation-duration", `${animation.duration}ms`);
|
|
1993
|
+
svg.style.setProperty("--oc-animation-stagger", `${stagger}ms`);
|
|
1994
|
+
svg.style.setProperty("--oc-annotation-delay", `${animation.annotationDelay}ms`);
|
|
1995
|
+
const easeVar = EASE_VAR_MAP2[animation.ease] || EASE_VAR_MAP2.smooth;
|
|
1996
|
+
svg.style.setProperty("--oc-animation-ease", easeVar);
|
|
1997
|
+
}
|
|
1998
|
+
const defs = createSVGElement2("defs");
|
|
1999
|
+
svg.appendChild(defs);
|
|
2000
|
+
renderChrome2(svg, layout);
|
|
2001
|
+
renderTiles(svg, tiles, animate ? animation : void 0);
|
|
2002
|
+
if (layout.categoricalLegend) {
|
|
2003
|
+
renderLegend(svg, layout.categoricalLegend);
|
|
2004
|
+
} else {
|
|
2005
|
+
renderGradientLegend(svg, layout);
|
|
2006
|
+
}
|
|
2007
|
+
if (watermark) {
|
|
2008
|
+
renderWatermark(svg, layout);
|
|
2009
|
+
}
|
|
2010
|
+
return svg;
|
|
2011
|
+
}
|
|
2012
|
+
|
|
1673
2013
|
export {
|
|
1674
2014
|
resetSvgIdCounter,
|
|
1675
2015
|
SVG_NS,
|
|
1676
|
-
renderLegend,
|
|
1677
2016
|
registerMarkRenderer,
|
|
1678
|
-
renderChartSVG
|
|
2017
|
+
renderChartSVG,
|
|
2018
|
+
renderTileMapSVG
|
|
1679
2019
|
};
|
|
1680
|
-
//# sourceMappingURL=chunk-
|
|
2020
|
+
//# sourceMappingURL=chunk-KYRQV6KR.js.map
|