@pixerate/editor 0.165.0 → 0.167.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/THIRD_PARTY_NOTICES.md +11 -0
- package/dist/agent/index.cjs +34 -34
- package/dist/agent/index.js +5 -5
- package/dist/canvas/index.cjs +6 -6
- package/dist/canvas/index.js +2 -2
- package/dist/chart/controller.d.cts +29 -0
- package/dist/chart/controller.d.ts +29 -0
- package/dist/chart/index.cjs +352 -179
- package/dist/chart/index.d.cts +2 -0
- package/dist/chart/index.d.ts +2 -0
- package/dist/chart/index.js +183 -10
- package/dist/chart/layout-families.d.cts +15 -0
- package/dist/chart/layout-families.d.ts +15 -0
- package/dist/chart/layout-shared.d.cts +5 -0
- package/dist/chart/layout-shared.d.ts +5 -0
- package/dist/chart/maps.d.cts +43 -0
- package/dist/chart/maps.d.ts +43 -0
- package/dist/chart/race.d.cts +26 -0
- package/dist/chart/race.d.ts +26 -0
- package/dist/chart/schemas.d.cts +2 -0
- package/dist/chart/schemas.d.ts +2 -0
- package/dist/chart/spec.d.cts +1 -1
- package/dist/chart/spec.d.ts +1 -1
- package/dist/chart/types.d.cts +14 -2
- package/dist/chart/types.d.ts +14 -2
- package/dist/chart-maps/europe.d.cts +7 -0
- package/dist/chart-maps/europe.d.ts +7 -0
- package/dist/chart-maps/index.cjs +66 -0
- package/dist/chart-maps/index.d.cts +1 -0
- package/dist/chart-maps/index.d.ts +1 -0
- package/dist/chart-maps/index.js +66 -0
- package/dist/{chunk-IMRXC7OA.cjs → chunk-2F4GAZL5.cjs} +186 -96
- package/dist/{chunk-FEU2XVQH.js → chunk-34UCPHYO.js} +8 -2
- package/dist/{chunk-ODFCS7HF.cjs → chunk-E45AIIWY.cjs} +8 -8
- package/dist/{chunk-N7NBGT2Y.js → chunk-FKYGM35R.js} +2 -2
- package/dist/{chunk-64VWWR5U.cjs → chunk-GD34ICEX.cjs} +16 -16
- package/dist/{chunk-TVQW26AV.cjs → chunk-GTF4RYXJ.cjs} +29 -23
- package/dist/{chunk-V5GSY3NC.js → chunk-M52UCHVZ.js} +203 -3
- package/dist/{chunk-FRBRLKNQ.js → chunk-N3ACT6VJ.js} +92 -2
- package/dist/{chunk-CRFSQWKQ.js → chunk-OLCHKGGO.js} +7 -1
- package/dist/{chunk-2ZRN43IN.js → chunk-ORZF4JOO.js} +32 -4
- package/dist/{chunk-UVXTOZ2B.cjs → chunk-OUO3DSRT.cjs} +32 -4
- package/dist/{chunk-MKXK6E4O.cjs → chunk-SBAPXFPB.cjs} +51 -51
- package/dist/{chunk-2J5VLJHC.js → chunk-T62BRXMS.js} +3 -3
- package/dist/{chunk-Q25WAFTD.cjs → chunk-VKHJJUBK.cjs} +24 -18
- package/dist/{chunk-QO2T6KA5.cjs → chunk-WOIXNDHV.cjs} +247 -47
- package/dist/{chunk-X5W645RI.js → chunk-ZUPP4NKM.js} +3 -3
- package/dist/export/index.cjs +4 -4
- package/dist/export/index.js +3 -3
- package/dist/extensions/index.cjs +7 -7
- package/dist/extensions/index.js +6 -6
- package/dist/index.cjs +13 -13
- package/dist/index.js +7 -7
- package/package.json +11 -1
- package/skills/pixerate-chart/SKILL.md +36 -2
package/dist/chart/index.d.cts
CHANGED
|
@@ -2,6 +2,8 @@ export * from './types.cjs';
|
|
|
2
2
|
export * from './spec.cjs';
|
|
3
3
|
export * from './tree.cjs';
|
|
4
4
|
export * from './links.cjs';
|
|
5
|
+
export * from './race.cjs';
|
|
6
|
+
export * from './maps.cjs';
|
|
5
7
|
export * from './scale.cjs';
|
|
6
8
|
export * from './numfmt.cjs';
|
|
7
9
|
export * from './color.cjs';
|
package/dist/chart/index.d.ts
CHANGED
package/dist/chart/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
HEIGHT,
|
|
5
5
|
LINK_INDEX,
|
|
6
6
|
LINK_PROPS,
|
|
7
|
+
RACE_TIME,
|
|
7
8
|
REFERENCE_BAND_PATCH,
|
|
8
9
|
REFERENCE_BAND_PROPS,
|
|
9
10
|
REFERENCE_INDEX,
|
|
@@ -16,7 +17,7 @@ import {
|
|
|
16
17
|
TRENDLINE_PROPS,
|
|
17
18
|
VALUE,
|
|
18
19
|
WIDTH
|
|
19
|
-
} from "../chunk-
|
|
20
|
+
} from "../chunk-34UCPHYO.js";
|
|
20
21
|
import {
|
|
21
22
|
CHART_OOXML_CONTENT_TYPE,
|
|
22
23
|
CHART_OOXML_NS,
|
|
@@ -24,7 +25,7 @@ import {
|
|
|
24
25
|
chartFormatToCode,
|
|
25
26
|
chartFromOoxml,
|
|
26
27
|
chartToOoxml
|
|
27
|
-
} from "../chunk-
|
|
28
|
+
} from "../chunk-OLCHKGGO.js";
|
|
28
29
|
import {
|
|
29
30
|
CHART_COLOR_SCHEMES,
|
|
30
31
|
CHART_LAYOUT_PRESETS,
|
|
@@ -46,7 +47,7 @@ import {
|
|
|
46
47
|
monochromeChartPalette,
|
|
47
48
|
sparklineToSvg,
|
|
48
49
|
summarizeChart
|
|
49
|
-
} from "../chunk-
|
|
50
|
+
} from "../chunk-N3ACT6VJ.js";
|
|
50
51
|
import "../chunk-KGRZMHZB.js";
|
|
51
52
|
import {
|
|
52
53
|
CHART_DATE_STEPS,
|
|
@@ -57,8 +58,14 @@ import {
|
|
|
57
58
|
chartDateLabels,
|
|
58
59
|
chartDateToSerial,
|
|
59
60
|
chartHistogram,
|
|
61
|
+
chartMapBreaks,
|
|
62
|
+
chartMapClass,
|
|
63
|
+
chartMapRamp,
|
|
60
64
|
chartMovingAverage,
|
|
61
65
|
chartQuantile,
|
|
66
|
+
chartRaceMoment,
|
|
67
|
+
chartRaceRanking,
|
|
68
|
+
chartRaceValueAt,
|
|
62
69
|
chartScaleFromPixel,
|
|
63
70
|
chartScaleToPixel,
|
|
64
71
|
chartSerialToDate,
|
|
@@ -75,19 +82,23 @@ import {
|
|
|
75
82
|
formatChartDate,
|
|
76
83
|
formatChartNumber,
|
|
77
84
|
formatChartValueWithCode,
|
|
85
|
+
getChartMap,
|
|
78
86
|
layoutChart,
|
|
79
87
|
linearMap,
|
|
88
|
+
listChartMaps,
|
|
89
|
+
matchChartMapRegions,
|
|
80
90
|
niceLogScale,
|
|
81
91
|
niceScale,
|
|
82
92
|
niceStep,
|
|
83
93
|
parseChartDate,
|
|
94
|
+
registerChartMap,
|
|
84
95
|
sameChartSelection,
|
|
85
96
|
snapChartValue,
|
|
86
97
|
stepDecimals,
|
|
87
98
|
suggestChartReferences,
|
|
88
99
|
summarizeChartSeries,
|
|
89
100
|
trendNumberText
|
|
90
|
-
} from "../chunk-
|
|
101
|
+
} from "../chunk-M52UCHVZ.js";
|
|
91
102
|
import {
|
|
92
103
|
CHART_AXIS_KINDS,
|
|
93
104
|
CHART_AXIS_SCALES,
|
|
@@ -181,7 +192,7 @@ import {
|
|
|
181
192
|
shadeChartColor,
|
|
182
193
|
simulateChartVision,
|
|
183
194
|
uniqueChartSeriesId
|
|
184
|
-
} from "../chunk-
|
|
195
|
+
} from "../chunk-ORZF4JOO.js";
|
|
185
196
|
import "../chunk-O6OGNDND.js";
|
|
186
197
|
import "../chunk-II2WIF5Z.js";
|
|
187
198
|
import {
|
|
@@ -396,6 +407,7 @@ function recommendForShape(shape) {
|
|
|
396
407
|
add("area", "Area", "Shows change over time with volume.");
|
|
397
408
|
add("bar", "Column", "Compares each period.");
|
|
398
409
|
if (shape.series > 1) add("area", "Stacked area", "Shows how the parts add up over time.", "stacked");
|
|
410
|
+
if (shape.series >= 5 && shape.points >= 3) add("barrace", "Bar race", "Many series over time: an animated ranking shows who leads when.");
|
|
399
411
|
return out;
|
|
400
412
|
}
|
|
401
413
|
if (shape.series === 1) {
|
|
@@ -430,6 +442,7 @@ function recommendForShape(shape) {
|
|
|
430
442
|
add("bar", "Stacked column", "Shows how the series add up.", "stacked");
|
|
431
443
|
add("line", "Line", "Shows the series in order.");
|
|
432
444
|
if (shape.points >= 3 && shape.series <= 6) add("radar", "Radar", "Compares several measures across the series.");
|
|
445
|
+
if (shape.nonNegative && shape.series >= 5 && shape.points >= 3) add("barrace", "Bar race", "Many series across ordered categories (such as years): an animated ranking shows who leads when.");
|
|
433
446
|
if (shape.nonNegative && shape.series >= 3 && shape.series <= 7) add("likert", "Likert", "Survey answers per question (columns from most negative to most positive): shows agreement against disagreement.");
|
|
434
447
|
}
|
|
435
448
|
return out;
|
|
@@ -475,6 +488,12 @@ function createChartCommands(controller, options = {}) {
|
|
|
475
488
|
if (index < 0 || index >= categories.length || !Number.isInteger(index)) fail(`There is no category ${JSON.stringify(ref)}; expected an index from 0 to ${categories.length - 1} or one of the labels.`);
|
|
476
489
|
return index;
|
|
477
490
|
};
|
|
491
|
+
const raceFrame = (time) => {
|
|
492
|
+
const cats = controller.getSpec().categories;
|
|
493
|
+
const frame = typeof time === "number" ? time : cats.indexOf(time);
|
|
494
|
+
if (!(Number.isFinite(frame) && frame >= 0 && frame <= cats.length - 1)) fail(`There is no time point ${JSON.stringify(time)}; expected an index from 0 to ${Math.max(0, cats.length - 1)} or a category label.`);
|
|
495
|
+
return frame;
|
|
496
|
+
};
|
|
478
497
|
const object = (properties, required) => ({ type: "object", properties, ...required ? { required } : {}, additionalProperties: false });
|
|
479
498
|
return [
|
|
480
499
|
{
|
|
@@ -887,6 +906,73 @@ function createChartCommands(controller, options = {}) {
|
|
|
887
906
|
return { links: controller.getSpec().links };
|
|
888
907
|
}
|
|
889
908
|
},
|
|
909
|
+
{
|
|
910
|
+
...base,
|
|
911
|
+
id: `${prefix}mapRegions`,
|
|
912
|
+
label: "Map Regions",
|
|
913
|
+
readOnly: true,
|
|
914
|
+
keywords: ["chart", "map", "choropleth", "regions", "countries", "codes"],
|
|
915
|
+
description: "Lists the regions of the chart's map (or another registered map) and which categories match none.",
|
|
916
|
+
params: object({ map: { type: "string", description: "Map id (default: the chart's map)." } }),
|
|
917
|
+
run: (_ctx, params = {}) => {
|
|
918
|
+
const id = params?.map ?? controller.getSpec().map;
|
|
919
|
+
const geometry = getChartMap(id);
|
|
920
|
+
if (!geometry) fail(`There is no map "${id}"; register it with registerChartMap.`);
|
|
921
|
+
const matches = matchChartMapRegions(geometry, controller.getSpec().categories);
|
|
922
|
+
return { regions: geometry.regions.map((r) => ({ id: r.id, name: r.name })), unmatched: controller.getSpec().categories.filter((_, i) => !matches[i]) };
|
|
923
|
+
}
|
|
924
|
+
},
|
|
925
|
+
{
|
|
926
|
+
...base,
|
|
927
|
+
id: `${prefix}raceRanking`,
|
|
928
|
+
label: "Bar Race Ranking",
|
|
929
|
+
readOnly: true,
|
|
930
|
+
keywords: ["chart", "race", "ranking", "leader", "time"],
|
|
931
|
+
description: "Returns the top names of a bar race at a moment (default: the one shown).",
|
|
932
|
+
params: object({ time: RACE_TIME }),
|
|
933
|
+
run: (_ctx, params = {}) => {
|
|
934
|
+
const spec = controller.getSpec();
|
|
935
|
+
const frame = params?.time !== void 0 ? raceFrame(params.time) : controller.getState().raceFrame ?? spec.categories.length - 1;
|
|
936
|
+
return { frame, ranking: chartRaceRanking(spec, frame).slice(0, spec.raceTopN).map((e) => ({ rank: e.rank + 1, series: e.seriesId, name: e.name, value: e.value })) };
|
|
937
|
+
}
|
|
938
|
+
},
|
|
939
|
+
{
|
|
940
|
+
...base,
|
|
941
|
+
id: `${prefix}setRaceFrame`,
|
|
942
|
+
label: "Show Bar Race Moment\u2026",
|
|
943
|
+
keywords: ["chart", "race", "frame", "time", "scrub"],
|
|
944
|
+
description: "Shows the bar race at a time point (null for the last) and stops playback. View state, not an undo step.",
|
|
945
|
+
params: object({ time: { ...RACE_TIME, type: ["string", "number", "null"], description: `${RACE_TIME.description} null shows the last time point.` } }, ["time"]),
|
|
946
|
+
run: (_ctx, params) => {
|
|
947
|
+
const frame = params.time === null ? null : raceFrame(params.time);
|
|
948
|
+
check(controller.setRaceFrame(frame));
|
|
949
|
+
return { frame };
|
|
950
|
+
}
|
|
951
|
+
},
|
|
952
|
+
{
|
|
953
|
+
...base,
|
|
954
|
+
id: `${prefix}playRace`,
|
|
955
|
+
label: "Play Bar Race",
|
|
956
|
+
keywords: ["chart", "race", "play", "animate"],
|
|
957
|
+
description: "Plays the bar race from the moment shown, one time point every msPerStep ms.",
|
|
958
|
+
params: object({ msPerStep: { type: "number", minimum: 50, maximum: 1e4, description: "Milliseconds per time point (default 1000)." } }),
|
|
959
|
+
run: (_ctx, params = {}) => {
|
|
960
|
+
check(controller.playRace({ msPerStep: params?.msPerStep }));
|
|
961
|
+
return { playing: true };
|
|
962
|
+
}
|
|
963
|
+
},
|
|
964
|
+
{
|
|
965
|
+
...base,
|
|
966
|
+
id: `${prefix}pauseRace`,
|
|
967
|
+
label: "Pause Bar Race",
|
|
968
|
+
keywords: ["chart", "race", "pause", "stop"],
|
|
969
|
+
description: "Pauses bar race playback where it is.",
|
|
970
|
+
enabled: () => controller.getState().racePlaying || "The race is not playing",
|
|
971
|
+
run: () => {
|
|
972
|
+
controller.pauseRace();
|
|
973
|
+
return { frame: controller.getState().raceFrame };
|
|
974
|
+
}
|
|
975
|
+
},
|
|
890
976
|
{
|
|
891
977
|
...base,
|
|
892
978
|
id: `${prefix}applyPreset`,
|
|
@@ -1484,6 +1570,10 @@ function planChartToolPlayback(tool, args) {
|
|
|
1484
1570
|
return click(control("series.callout"));
|
|
1485
1571
|
case "highlight_chart":
|
|
1486
1572
|
return click(control("highlight"));
|
|
1573
|
+
case "set_chart_race_frame":
|
|
1574
|
+
return click(control("raceFrame"));
|
|
1575
|
+
case "play_chart_race":
|
|
1576
|
+
return click({ kind: "action", id: "race-play" });
|
|
1487
1577
|
case "render_chart":
|
|
1488
1578
|
return [{ type: "target", ref: { kind: "action", id: "download-png" } }];
|
|
1489
1579
|
case "undo_chart":
|
|
@@ -1548,6 +1638,22 @@ function createChartToolProvider(controller, options = {}) {
|
|
|
1548
1638
|
const depth = chartTreeDepth(spec().tree);
|
|
1549
1639
|
return [[...Array.from({ length: depth }, (_, k) => k === 0 ? "Group" : k === depth - 1 ? "Item" : `Level ${k + 1}`), "Value"], ...rows.map((r) => [...r.path, ...Array(depth - r.path.length).fill(""), r.value])];
|
|
1550
1640
|
};
|
|
1641
|
+
const raceFrameOf = (time) => {
|
|
1642
|
+
const cats = spec().categories;
|
|
1643
|
+
const frame = typeof time === "number" ? time : cats.indexOf(time);
|
|
1644
|
+
if (!(Number.isFinite(frame) && frame >= 0 && frame <= cats.length - 1))
|
|
1645
|
+
fail2(`There is no time point ${JSON.stringify(time)}; expected an index from 0 to ${Math.max(0, cats.length - 1)} or one of ${cats.slice(0, 20).map((c) => JSON.stringify(c)).join(", ")}.`);
|
|
1646
|
+
return frame;
|
|
1647
|
+
};
|
|
1648
|
+
const raceAt = (frame) => {
|
|
1649
|
+
const s = spec();
|
|
1650
|
+
const at = frame ?? s.categories.length - 1;
|
|
1651
|
+
return {
|
|
1652
|
+
frame: at,
|
|
1653
|
+
time: s.categories[Math.round(at)] ?? null,
|
|
1654
|
+
ranking: chartRaceRanking(s, at).slice(0, s.raceTopN).map((e) => ({ rank: e.rank + 1, series: e.seriesId, name: e.name, value: e.value }))
|
|
1655
|
+
};
|
|
1656
|
+
};
|
|
1551
1657
|
const linksSummary = () => ({ links: spec().links, nodes: spec().sankeyNodes.map((name, i) => ({ name, value: chartSankeyNodeValues(spec().links, spec().sankeyNodes)[i] })) });
|
|
1552
1658
|
const treeSummary = () => ({ tree: spec().tree, groups: spec().tree.map((n) => ({ name: n.name, total: chartTreeTotal(n) })), depth: chartTreeDepth(spec().tree) });
|
|
1553
1659
|
const Parser = () => options.DOMParser ?? globalThis.DOMParser;
|
|
@@ -1579,14 +1685,16 @@ function createChartToolProvider(controller, options = {}) {
|
|
|
1579
1685
|
properties: {
|
|
1580
1686
|
width: WIDTH,
|
|
1581
1687
|
height: HEIGHT,
|
|
1582
|
-
format: { type: "string", enum: ["svg", "png"], description: "svg (default): the SVG document as text. png: an image to look at (only when the host can rasterize; costs image tokens)." }
|
|
1688
|
+
format: { type: "string", enum: ["svg", "png"], description: "svg (default): the SVG document as text. png: an image to look at (only when the host can rasterize; costs image tokens)." },
|
|
1689
|
+
time: { ...RACE_TIME, description: `Bar race only: the moment to draw (default: the one shown). ${RACE_TIME.description}` }
|
|
1583
1690
|
},
|
|
1584
1691
|
additionalProperties: false
|
|
1585
1692
|
},
|
|
1586
1693
|
annotations: { title: "Render the chart", ...READ },
|
|
1587
|
-
handler: async ({ width = size.width, height = size.height, format = "svg" }) => {
|
|
1694
|
+
handler: async ({ width = size.width, height = size.height, format = "svg", time }) => {
|
|
1588
1695
|
const json = controller.toJSON();
|
|
1589
|
-
const
|
|
1696
|
+
const raceFrame = time !== void 0 ? raceFrameOf(time) : controller.getState().raceFrame;
|
|
1697
|
+
const scene = layoutChart(json, { width, height, selection: null, raceFrame });
|
|
1590
1698
|
const svg = chartSceneToSvg(scene, { ariaLabel: json.title || void 0, description: describeChart(json) });
|
|
1591
1699
|
const warnings = scene.warnings;
|
|
1592
1700
|
if (format === "png") {
|
|
@@ -1659,6 +1767,35 @@ function createChartToolProvider(controller, options = {}) {
|
|
|
1659
1767
|
return { trendline: line, coefficients: fit.coefficients, r2: fit.r2, equation: fit.equation, points: fit.points };
|
|
1660
1768
|
}
|
|
1661
1769
|
};
|
|
1770
|
+
const raceRanking = {
|
|
1771
|
+
name: "get_chart_race_ranking",
|
|
1772
|
+
title: "Read a bar race ranking",
|
|
1773
|
+
description: "Returns who leads a bar race at a moment without changing what is shown: the top raceTopN names with their rank, series id and value (eased between time points). Defaults to the moment shown. Works for any chart, reading categories as time points and series as names.",
|
|
1774
|
+
inputSchema: { type: "object", properties: { time: RACE_TIME }, additionalProperties: false },
|
|
1775
|
+
annotations: { title: "Read a bar race ranking", ...READ },
|
|
1776
|
+
handler: ({ time }) => raceAt(time !== void 0 ? raceFrameOf(time) : controller.getState().raceFrame)
|
|
1777
|
+
};
|
|
1778
|
+
const mapRegions = {
|
|
1779
|
+
name: "list_chart_map_regions",
|
|
1780
|
+
title: "List map regions",
|
|
1781
|
+
description: "Lists the maps a choropleth can draw and the regions of one (default: the chart's map), each with the id and name that categories may use, and how the chart's categories match them: matched (category \u2192 region id) and unmatched. Use it to pick category labels before set_chart_data, and to fix unmatched ones.",
|
|
1782
|
+
inputSchema: { type: "object", properties: { map: { type: "string", description: "Map id (default: the chart's map)." } }, additionalProperties: false },
|
|
1783
|
+
annotations: { title: "List map regions", ...READ },
|
|
1784
|
+
handler: ({ map }) => {
|
|
1785
|
+
const id = map ?? spec().map;
|
|
1786
|
+
const maps = listChartMaps().map((m) => ({ id: m.id, name: m.name, regions: m.regions.length }));
|
|
1787
|
+
const geometry = getChartMap(id);
|
|
1788
|
+
if (!geometry) fail2(maps.length ? `There is no map "${id}"; the host has ${maps.map((m) => `"${m.id}"`).join(", ")}.` : `There is no map "${id}": the host has not registered any maps (EUROPE_CHART_MAP in @pixerate/editor/chart-maps).`);
|
|
1789
|
+
const matches = matchChartMapRegions(geometry, spec().categories);
|
|
1790
|
+
return {
|
|
1791
|
+
maps,
|
|
1792
|
+
map: id,
|
|
1793
|
+
regions: geometry.regions.map((r) => ({ id: r.id, name: r.name })),
|
|
1794
|
+
matched: spec().categories.flatMap((c, i) => matches[i] ? [{ category: c, region: matches[i].id }] : []),
|
|
1795
|
+
unmatched: spec().categories.filter((_, i) => !matches[i])
|
|
1796
|
+
};
|
|
1797
|
+
}
|
|
1798
|
+
};
|
|
1662
1799
|
const listPresets = {
|
|
1663
1800
|
name: "list_chart_presets",
|
|
1664
1801
|
title: "List chart presets",
|
|
@@ -2150,6 +2287,30 @@ function createChartToolProvider(controller, options = {}) {
|
|
|
2150
2287
|
return { links: spec().links };
|
|
2151
2288
|
}
|
|
2152
2289
|
};
|
|
2290
|
+
const setRaceFrame = {
|
|
2291
|
+
name: "set_chart_race_frame",
|
|
2292
|
+
title: "Show a bar race moment",
|
|
2293
|
+
description: "Shows the bar race at a time point (or between two), and stops playback. This is view state like the selection: it is not an undo step and is not saved in the chart. Returns the moment and the ranking shown.",
|
|
2294
|
+
inputSchema: { type: "object", properties: { time: { ...RACE_TIME, type: ["string", "number", "null"], description: `${RACE_TIME.description} null shows the last time point.` } }, required: ["time"], additionalProperties: false },
|
|
2295
|
+
annotations: { title: "Show a bar race moment", ...WRITE_IDEMPOTENT },
|
|
2296
|
+
handler: ({ time }) => {
|
|
2297
|
+
const frame = time === null ? null : raceFrameOf(time);
|
|
2298
|
+
resolve(controller.setRaceFrame(frame));
|
|
2299
|
+
return raceAt(frame);
|
|
2300
|
+
}
|
|
2301
|
+
};
|
|
2302
|
+
const playRace = {
|
|
2303
|
+
name: "play_chart_race",
|
|
2304
|
+
title: "Play the bar race",
|
|
2305
|
+
description: "Starts playing the bar race for the user from the moment shown (from the start when it is at the end), one time point every msPerStep ms, and returns at once. set_chart_race_frame stops it. Nothing in the chart changes.",
|
|
2306
|
+
inputSchema: { type: "object", properties: { msPerStep: { type: "number", minimum: 50, maximum: 1e4, description: "Milliseconds per time point (default 1000)." } }, additionalProperties: false },
|
|
2307
|
+
annotations: { title: "Play the bar race", ...WRITE },
|
|
2308
|
+
handler: ({ msPerStep }) => {
|
|
2309
|
+
resolve(controller.playRace({ msPerStep }));
|
|
2310
|
+
const n = spec().categories.length;
|
|
2311
|
+
return { playing: true, from: controller.getState().raceFrame ?? 0, durationMs: Math.round((n - 1 - (controller.getState().raceFrame ?? 0)) * (msPerStep ?? 1e3)) };
|
|
2312
|
+
}
|
|
2313
|
+
};
|
|
2153
2314
|
const applyPreset = {
|
|
2154
2315
|
name: "apply_chart_preset",
|
|
2155
2316
|
title: "Apply a chart style",
|
|
@@ -2315,7 +2476,7 @@ function createChartToolProvider(controller, options = {}) {
|
|
|
2315
2476
|
return { redone, ...redone ? { label } : {} };
|
|
2316
2477
|
}
|
|
2317
2478
|
};
|
|
2318
|
-
const reads = [getChart, renderChart, checkColors, recommend, getTrendline, listPresets, exportMermaid, exportOoxml];
|
|
2479
|
+
const reads = [getChart, renderChart, checkColors, recommend, getTrendline, raceRanking, mapRegions, listPresets, exportMermaid, exportOoxml];
|
|
2319
2480
|
const writes = [
|
|
2320
2481
|
updateChart,
|
|
2321
2482
|
setData,
|
|
@@ -2347,6 +2508,8 @@ function createChartToolProvider(controller, options = {}) {
|
|
|
2347
2508
|
addLink,
|
|
2348
2509
|
updateLink,
|
|
2349
2510
|
removeLink,
|
|
2511
|
+
setRaceFrame,
|
|
2512
|
+
playRace,
|
|
2350
2513
|
applyPreset,
|
|
2351
2514
|
transpose,
|
|
2352
2515
|
select,
|
|
@@ -2359,7 +2522,7 @@ function createChartToolProvider(controller, options = {}) {
|
|
|
2359
2522
|
id: options.id ?? "chart",
|
|
2360
2523
|
namespace: options.namespace,
|
|
2361
2524
|
title: "Chart editor",
|
|
2362
|
-
description: "One chart: its spec, data and values, series and categories, trendlines, reference lines and bands, callouts, highlight, grouped data, flows and presets, CSV, Mermaid and OOXML import, rendering and colour checks.",
|
|
2525
|
+
description: "One chart: its spec, data and values, series and categories, trendlines, reference lines and bands, callouts, highlight, grouped data, flows, bar race playback and presets, CSV, Mermaid and OOXML import, rendering and colour checks.",
|
|
2363
2526
|
skill: "pixerate-chart",
|
|
2364
2527
|
tools: () => {
|
|
2365
2528
|
if (readOnlyReason()) return reads;
|
|
@@ -3105,6 +3268,9 @@ export {
|
|
|
3105
3268
|
chartLikertColor,
|
|
3106
3269
|
chartLinksFromTable,
|
|
3107
3270
|
chartLuminance,
|
|
3271
|
+
chartMapBreaks,
|
|
3272
|
+
chartMapClass,
|
|
3273
|
+
chartMapRamp,
|
|
3108
3274
|
chartMermaidFamily,
|
|
3109
3275
|
chartMovingAverage,
|
|
3110
3276
|
chartPointAnchor,
|
|
@@ -3112,6 +3278,9 @@ export {
|
|
|
3112
3278
|
chartPointRef,
|
|
3113
3279
|
chartPresetPatch,
|
|
3114
3280
|
chartQuantile,
|
|
3281
|
+
chartRaceMoment,
|
|
3282
|
+
chartRaceRanking,
|
|
3283
|
+
chartRaceValueAt,
|
|
3115
3284
|
chartRasterSize,
|
|
3116
3285
|
chartRgbToHex,
|
|
3117
3286
|
chartRgbToOklab,
|
|
@@ -3184,13 +3353,16 @@ export {
|
|
|
3184
3353
|
formatChartDate,
|
|
3185
3354
|
formatChartNumber,
|
|
3186
3355
|
formatChartValueWithCode,
|
|
3356
|
+
getChartMap,
|
|
3187
3357
|
handleChartKey,
|
|
3188
3358
|
isCartesianChart,
|
|
3189
3359
|
isXyChart,
|
|
3190
3360
|
layoutChart,
|
|
3191
3361
|
layoutSparkline,
|
|
3192
3362
|
linearMap,
|
|
3363
|
+
listChartMaps,
|
|
3193
3364
|
locateChartPoint,
|
|
3365
|
+
matchChartMapRegions,
|
|
3194
3366
|
monochromeChartPalette,
|
|
3195
3367
|
niceLogScale,
|
|
3196
3368
|
niceScale,
|
|
@@ -3215,6 +3387,7 @@ export {
|
|
|
3215
3387
|
realChartClock,
|
|
3216
3388
|
recommendChartTypes,
|
|
3217
3389
|
recommendForShape,
|
|
3390
|
+
registerChartMap,
|
|
3218
3391
|
removeChartTreeRow,
|
|
3219
3392
|
resolveChartSvgPaints,
|
|
3220
3393
|
sameChartSelection,
|
|
@@ -45,3 +45,18 @@ export declare function layoutSunburst(ctx: LayoutCtx, area: ChartRect, series:
|
|
|
45
45
|
* in the order of the nodes at their other end, so they cross as little as the order allows.
|
|
46
46
|
*/
|
|
47
47
|
export declare function layoutSankey(ctx: LayoutCtx, area: ChartRect, series: ChartSeries | undefined): FamilyResult;
|
|
48
|
+
/**
|
|
49
|
+
* Bar race: the top `raceTopN` names at one moment (`frame`, a fractional category index;
|
|
50
|
+
* default the last time point) as ranked horizontal bars. Values ease between time points and
|
|
51
|
+
* places slide from one ranking to the next, so drawing frame after frame (or blending scenes,
|
|
52
|
+
* which match bars by series) animates the race. The time point is written large in a corner.
|
|
53
|
+
*/
|
|
54
|
+
export declare function layoutBarRace(ctx: LayoutCtx, area: ChartRect, frame: number | null | undefined): FamilyResult;
|
|
55
|
+
/**
|
|
56
|
+
* Choropleth: the regions of a registered map (`spec.map`) shaded by the first series, one class
|
|
57
|
+
* per `mapSteps` (or `mapThresholds`), light to dark. Each category names a region by id or name;
|
|
58
|
+
* regions without data are grey and neighbouring land is drawn behind. Regions too small to see
|
|
59
|
+
* get a marker at their centre. The class legend runs along the bottom. The map must be
|
|
60
|
+
* registered and match a category (`layoutChart` draws bars otherwise).
|
|
61
|
+
*/
|
|
62
|
+
export declare function layoutChoropleth(ctx: LayoutCtx, area: ChartRect, series: ChartSeries): FamilyResult;
|
|
@@ -45,3 +45,18 @@ export declare function layoutSunburst(ctx: LayoutCtx, area: ChartRect, series:
|
|
|
45
45
|
* in the order of the nodes at their other end, so they cross as little as the order allows.
|
|
46
46
|
*/
|
|
47
47
|
export declare function layoutSankey(ctx: LayoutCtx, area: ChartRect, series: ChartSeries | undefined): FamilyResult;
|
|
48
|
+
/**
|
|
49
|
+
* Bar race: the top `raceTopN` names at one moment (`frame`, a fractional category index;
|
|
50
|
+
* default the last time point) as ranked horizontal bars. Values ease between time points and
|
|
51
|
+
* places slide from one ranking to the next, so drawing frame after frame (or blending scenes,
|
|
52
|
+
* which match bars by series) animates the race. The time point is written large in a corner.
|
|
53
|
+
*/
|
|
54
|
+
export declare function layoutBarRace(ctx: LayoutCtx, area: ChartRect, frame: number | null | undefined): FamilyResult;
|
|
55
|
+
/**
|
|
56
|
+
* Choropleth: the regions of a registered map (`spec.map`) shaded by the first series, one class
|
|
57
|
+
* per `mapSteps` (or `mapThresholds`), light to dark. Each category names a region by id or name;
|
|
58
|
+
* regions without data are grey and neighbouring land is drawn behind. Regions too small to see
|
|
59
|
+
* get a marker at their centre. The class legend runs along the bottom. The map must be
|
|
60
|
+
* registered and match a category (`layoutChart` draws bars otherwise).
|
|
61
|
+
*/
|
|
62
|
+
export declare function layoutChoropleth(ctx: LayoutCtx, area: ChartRect, series: ChartSeries): FamilyResult;
|
|
@@ -34,6 +34,11 @@ export interface ChartLayoutOptions {
|
|
|
34
34
|
seriesId: string;
|
|
35
35
|
index: number;
|
|
36
36
|
} | null;
|
|
37
|
+
/**
|
|
38
|
+
* Bar race: the moment to draw, as a category index that may be fractional (2.5 is halfway
|
|
39
|
+
* between the third and fourth time points). Default: the last time point.
|
|
40
|
+
*/
|
|
41
|
+
raceFrame?: number | null;
|
|
37
42
|
}
|
|
38
43
|
/** A DOM-free text width estimate (average glyph ≈ 0.56 em, bold ≈ 0.6 em). */
|
|
39
44
|
export declare const estimateChartTextWidth: ChartTextMeasure;
|
|
@@ -34,6 +34,11 @@ export interface ChartLayoutOptions {
|
|
|
34
34
|
seriesId: string;
|
|
35
35
|
index: number;
|
|
36
36
|
} | null;
|
|
37
|
+
/**
|
|
38
|
+
* Bar race: the moment to draw, as a category index that may be fractional (2.5 is halfway
|
|
39
|
+
* between the third and fourth time points). Default: the last time point.
|
|
40
|
+
*/
|
|
41
|
+
raceFrame?: number | null;
|
|
37
42
|
}
|
|
38
43
|
/** A DOM-free text width estimate (average glyph ≈ 0.56 em, bold ≈ 0.6 em). */
|
|
39
44
|
export declare const estimateChartTextWidth: ChartTextMeasure;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/** One region of a map: an id (ISO 3166-1 alpha-3 for countries), a name and its outline. */
|
|
2
|
+
export interface ChartMapRegion {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
/** SVG path data in the map's box (absolute M / L / Z commands). */
|
|
6
|
+
d: string;
|
|
7
|
+
/** Where a label or a marker goes, in the map's box. */
|
|
8
|
+
center: [number, number];
|
|
9
|
+
/** Area in square box units (0 for a region too small to outline, drawn as a marker). */
|
|
10
|
+
area: number;
|
|
11
|
+
}
|
|
12
|
+
export interface ChartMapGeometry {
|
|
13
|
+
/** What `spec.map` names, e.g. `europe`. */
|
|
14
|
+
id: string;
|
|
15
|
+
name: string;
|
|
16
|
+
width: number;
|
|
17
|
+
height: number;
|
|
18
|
+
regions: ChartMapRegion[];
|
|
19
|
+
/** Land in the frame that is not a region (neighbouring countries), drawn as background. */
|
|
20
|
+
land?: string;
|
|
21
|
+
/** Credit to show with the map (Natural Earth asks for none, but welcomes it). */
|
|
22
|
+
attribution?: string;
|
|
23
|
+
}
|
|
24
|
+
/** Makes a map available to choropleth charts (`spec.map` = its id). Registering an id again replaces it. */
|
|
25
|
+
export declare function registerChartMap(map: ChartMapGeometry): void;
|
|
26
|
+
/** A registered map by id, or undefined. */
|
|
27
|
+
export declare function getChartMap(id: string): ChartMapGeometry | undefined;
|
|
28
|
+
/** Every registered map. */
|
|
29
|
+
export declare function listChartMaps(): ChartMapGeometry[];
|
|
30
|
+
/**
|
|
31
|
+
* The region each category names, matched by id (any case) or by name (ignoring case and
|
|
32
|
+
* accents), or null. Several categories may not name the same region: the first wins.
|
|
33
|
+
*/
|
|
34
|
+
export declare function matchChartMapRegions(map: ChartMapGeometry, categories: readonly string[]): (ChartMapRegion | null)[];
|
|
35
|
+
/**
|
|
36
|
+
* Class breaks for a choropleth: `thresholds` when given (ascending), else `steps` equal
|
|
37
|
+
* intervals between the smallest and largest value. Returns the inner breaks (one fewer than the classes).
|
|
38
|
+
*/
|
|
39
|
+
export declare function chartMapBreaks(values: readonly number[], steps: number, thresholds: readonly number[]): number[];
|
|
40
|
+
/** The class (0-based) a value falls in: the number of breaks at or below it. */
|
|
41
|
+
export declare const chartMapClass: (value: number, breaks: readonly number[]) => number;
|
|
42
|
+
/** A light-to-dark ramp of `count` shades of `base`, one per class. */
|
|
43
|
+
export declare function chartMapRamp(base: string, count: number): string[];
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/** One region of a map: an id (ISO 3166-1 alpha-3 for countries), a name and its outline. */
|
|
2
|
+
export interface ChartMapRegion {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
/** SVG path data in the map's box (absolute M / L / Z commands). */
|
|
6
|
+
d: string;
|
|
7
|
+
/** Where a label or a marker goes, in the map's box. */
|
|
8
|
+
center: [number, number];
|
|
9
|
+
/** Area in square box units (0 for a region too small to outline, drawn as a marker). */
|
|
10
|
+
area: number;
|
|
11
|
+
}
|
|
12
|
+
export interface ChartMapGeometry {
|
|
13
|
+
/** What `spec.map` names, e.g. `europe`. */
|
|
14
|
+
id: string;
|
|
15
|
+
name: string;
|
|
16
|
+
width: number;
|
|
17
|
+
height: number;
|
|
18
|
+
regions: ChartMapRegion[];
|
|
19
|
+
/** Land in the frame that is not a region (neighbouring countries), drawn as background. */
|
|
20
|
+
land?: string;
|
|
21
|
+
/** Credit to show with the map (Natural Earth asks for none, but welcomes it). */
|
|
22
|
+
attribution?: string;
|
|
23
|
+
}
|
|
24
|
+
/** Makes a map available to choropleth charts (`spec.map` = its id). Registering an id again replaces it. */
|
|
25
|
+
export declare function registerChartMap(map: ChartMapGeometry): void;
|
|
26
|
+
/** A registered map by id, or undefined. */
|
|
27
|
+
export declare function getChartMap(id: string): ChartMapGeometry | undefined;
|
|
28
|
+
/** Every registered map. */
|
|
29
|
+
export declare function listChartMaps(): ChartMapGeometry[];
|
|
30
|
+
/**
|
|
31
|
+
* The region each category names, matched by id (any case) or by name (ignoring case and
|
|
32
|
+
* accents), or null. Several categories may not name the same region: the first wins.
|
|
33
|
+
*/
|
|
34
|
+
export declare function matchChartMapRegions(map: ChartMapGeometry, categories: readonly string[]): (ChartMapRegion | null)[];
|
|
35
|
+
/**
|
|
36
|
+
* Class breaks for a choropleth: `thresholds` when given (ascending), else `steps` equal
|
|
37
|
+
* intervals between the smallest and largest value. Returns the inner breaks (one fewer than the classes).
|
|
38
|
+
*/
|
|
39
|
+
export declare function chartMapBreaks(values: readonly number[], steps: number, thresholds: readonly number[]): number[];
|
|
40
|
+
/** The class (0-based) a value falls in: the number of breaks at or below it. */
|
|
41
|
+
export declare const chartMapClass: (value: number, breaks: readonly number[]) => number;
|
|
42
|
+
/** A light-to-dark ramp of `count` shades of `base`, one per class. */
|
|
43
|
+
export declare function chartMapRamp(base: string, count: number): string[];
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ChartSeries, ChartSpec } from './types.cjs';
|
|
2
|
+
/** A series' value at time point `index`: its own, else the last value before it (0 before the first). */
|
|
3
|
+
export declare function chartRaceValueAt(series: Pick<ChartSeries, 'values'>, index: number): number;
|
|
4
|
+
/** The moment `frame` stands for: the time points either side and how far between them (0–1). */
|
|
5
|
+
export declare function chartRaceMoment(count: number, frame: number | null | undefined): {
|
|
6
|
+
from: number;
|
|
7
|
+
to: number;
|
|
8
|
+
t: number;
|
|
9
|
+
at: number;
|
|
10
|
+
};
|
|
11
|
+
export interface ChartRaceEntry {
|
|
12
|
+
seriesId: string;
|
|
13
|
+
name: string;
|
|
14
|
+
/** The value at the moment (between time points, eased from one to the next). */
|
|
15
|
+
value: number;
|
|
16
|
+
/** 0-based place at the moment, fractional while two names swap. */
|
|
17
|
+
position: number;
|
|
18
|
+
/** 0-based place at the nearest time point. */
|
|
19
|
+
rank: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Every visible series at a moment, best first: its value between the two time points and its
|
|
23
|
+
* position, which slides from its rank at one time point to its rank at the next so bars swap
|
|
24
|
+
* smoothly. Ties keep the series order.
|
|
25
|
+
*/
|
|
26
|
+
export declare function chartRaceRanking(spec: Pick<ChartSpec, 'series' | 'categories'>, frame: number | null | undefined): ChartRaceEntry[];
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ChartSeries, ChartSpec } from './types.js';
|
|
2
|
+
/** A series' value at time point `index`: its own, else the last value before it (0 before the first). */
|
|
3
|
+
export declare function chartRaceValueAt(series: Pick<ChartSeries, 'values'>, index: number): number;
|
|
4
|
+
/** The moment `frame` stands for: the time points either side and how far between them (0–1). */
|
|
5
|
+
export declare function chartRaceMoment(count: number, frame: number | null | undefined): {
|
|
6
|
+
from: number;
|
|
7
|
+
to: number;
|
|
8
|
+
t: number;
|
|
9
|
+
at: number;
|
|
10
|
+
};
|
|
11
|
+
export interface ChartRaceEntry {
|
|
12
|
+
seriesId: string;
|
|
13
|
+
name: string;
|
|
14
|
+
/** The value at the moment (between time points, eased from one to the next). */
|
|
15
|
+
value: number;
|
|
16
|
+
/** 0-based place at the moment, fractional while two names swap. */
|
|
17
|
+
position: number;
|
|
18
|
+
/** 0-based place at the nearest time point. */
|
|
19
|
+
rank: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Every visible series at a moment, best first: its value between the two time points and its
|
|
23
|
+
* position, which slides from its rank at one time point to its rank at the next so bars swap
|
|
24
|
+
* smoothly. Ties keep the series order.
|
|
25
|
+
*/
|
|
26
|
+
export declare function chartRaceRanking(spec: Pick<ChartSpec, 'series' | 'categories'>, frame: number | null | undefined): ChartRaceEntry[];
|
package/dist/chart/schemas.d.cts
CHANGED
|
@@ -22,6 +22,8 @@ export declare const TREE_DEFS: {
|
|
|
22
22
|
export declare const TREE_PATH: JsonSchema;
|
|
23
23
|
/** One Sankey flow's fields; source, target and value are required when adding. */
|
|
24
24
|
export declare const LINK_PROPS: Record<string, JsonSchema>;
|
|
25
|
+
/** A moment of a bar race: a time point by label, or a category index (fractional between time points). */
|
|
26
|
+
export declare const RACE_TIME: JsonSchema;
|
|
25
27
|
export declare const LINK_INDEX: JsonSchema;
|
|
26
28
|
export declare const ERROR_BARS: (what: string) => JsonSchema;
|
|
27
29
|
export declare const SERIES_PROPS: Record<string, JsonSchema>;
|
package/dist/chart/schemas.d.ts
CHANGED
|
@@ -22,6 +22,8 @@ export declare const TREE_DEFS: {
|
|
|
22
22
|
export declare const TREE_PATH: JsonSchema;
|
|
23
23
|
/** One Sankey flow's fields; source, target and value are required when adding. */
|
|
24
24
|
export declare const LINK_PROPS: Record<string, JsonSchema>;
|
|
25
|
+
/** A moment of a bar race: a time point by label, or a category index (fractional between time points). */
|
|
26
|
+
export declare const RACE_TIME: JsonSchema;
|
|
25
27
|
export declare const LINK_INDEX: JsonSchema;
|
|
26
28
|
export declare const ERROR_BARS: (what: string) => JsonSchema;
|
|
27
29
|
export declare const SERIES_PROPS: Record<string, JsonSchema>;
|
package/dist/chart/spec.d.cts
CHANGED
|
@@ -19,7 +19,7 @@ export declare const CHART_NUMBER_STYLES: readonly NonNullable<ChartNumberFormat
|
|
|
19
19
|
/** Labels for pickers, shared by the React and Svelte components. */
|
|
20
20
|
export declare const CHART_TYPE_LABELS: Readonly<Record<ChartType, string>>;
|
|
21
21
|
/** How a chart type is laid out. */
|
|
22
|
-
export type ChartFamily = 'cartesian' | 'xy' | 'pie' | 'radar' | 'waterfall' | 'histogram' | 'box' | 'funnel' | 'treemap' | 'slope' | 'likert' | 'parliament' | 'sunburst' | 'sankey';
|
|
22
|
+
export type ChartFamily = 'cartesian' | 'xy' | 'pie' | 'radar' | 'waterfall' | 'histogram' | 'box' | 'funnel' | 'treemap' | 'slope' | 'likert' | 'parliament' | 'sunburst' | 'sankey' | 'barrace' | 'choropleth';
|
|
23
23
|
/** A colour-blind-friendly categorical palette (Okabe–Ito order, tuned for light and dark backgrounds). */
|
|
24
24
|
export declare const DEFAULT_CHART_PALETTE: readonly string[];
|
|
25
25
|
export declare const DEFAULT_CHART_THEME: ChartTheme;
|
package/dist/chart/spec.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ export declare const CHART_NUMBER_STYLES: readonly NonNullable<ChartNumberFormat
|
|
|
19
19
|
/** Labels for pickers, shared by the React and Svelte components. */
|
|
20
20
|
export declare const CHART_TYPE_LABELS: Readonly<Record<ChartType, string>>;
|
|
21
21
|
/** How a chart type is laid out. */
|
|
22
|
-
export type ChartFamily = 'cartesian' | 'xy' | 'pie' | 'radar' | 'waterfall' | 'histogram' | 'box' | 'funnel' | 'treemap' | 'slope' | 'likert' | 'parliament' | 'sunburst' | 'sankey';
|
|
22
|
+
export type ChartFamily = 'cartesian' | 'xy' | 'pie' | 'radar' | 'waterfall' | 'histogram' | 'box' | 'funnel' | 'treemap' | 'slope' | 'likert' | 'parliament' | 'sunburst' | 'sankey' | 'barrace' | 'choropleth';
|
|
23
23
|
/** A colour-blind-friendly categorical palette (Okabe–Ito order, tuned for light and dark backgrounds). */
|
|
24
24
|
export declare const DEFAULT_CHART_PALETTE: readonly string[];
|
|
25
25
|
export declare const DEFAULT_CHART_THEME: ChartTheme;
|