@opendata-ai/openchart-vanilla 3.0.0 → 6.1.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/index.d.ts +3 -3
- package/dist/index.js +211 -14
- package/dist/index.js.map +1 -1
- package/dist/simulation-worker.js +0 -38
- package/package.json +3 -3
- package/src/__test-fixtures__/specs.ts +7 -7
- package/src/__tests__/svg-renderer.test.ts +2 -2
- package/src/mount.ts +169 -14
- package/src/svg-renderer.ts +115 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { ChartLayout, ChartSpec, CompileOptions, TableLayout, TableSpec, VizSpec } from '@opendata-ai/openchart-engine';
|
|
2
|
-
import { GraphSpec, ThemeConfig, DarkMode, ChartSpec, ChartLayout, ChartEventHandlers, BarTableCell, CategoryTableCell, TableCell, FlagTableCell, HeatmapTableCell, ImageTableCell, SparklineTableCell, TextTableCell, Mark, TableSpec, SortState, TableLayout, TooltipContent } from '@opendata-ai/openchart-core';
|
|
2
|
+
import { GraphSpec, ThemeConfig, DarkMode, ChartSpec, LayerSpec, ChartLayout, ChartEventHandlers, BarTableCell, CategoryTableCell, TableCell, FlagTableCell, HeatmapTableCell, ImageTableCell, SparklineTableCell, TextTableCell, Mark, TableSpec, SortState, TableLayout, TooltipContent } from '@opendata-ai/openchart-core';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Export utilities: serialize charts to SVG, PNG, JPG, or CSV.
|
|
@@ -166,7 +166,7 @@ interface ExportOptions extends JPGExportOptions {
|
|
|
166
166
|
}
|
|
167
167
|
interface ChartInstance {
|
|
168
168
|
/** Re-compile and re-render with a new spec. */
|
|
169
|
-
update(spec: ChartSpec | GraphSpec): void;
|
|
169
|
+
update(spec: ChartSpec | LayerSpec | GraphSpec): void;
|
|
170
170
|
/** Re-compile at current container dimensions. */
|
|
171
171
|
resize(): void;
|
|
172
172
|
/** Export the chart. */
|
|
@@ -189,7 +189,7 @@ interface ChartInstance {
|
|
|
189
189
|
* @param options - Mount options (theme, darkMode, responsive, etc.).
|
|
190
190
|
* @returns A ChartInstance with update/resize/export/destroy methods.
|
|
191
191
|
*/
|
|
192
|
-
declare function createChart(container: HTMLElement, spec: ChartSpec | GraphSpec, options?: MountOptions): ChartInstance;
|
|
192
|
+
declare function createChart(container: HTMLElement, spec: ChartSpec | LayerSpec | GraphSpec, options?: MountOptions): ChartInstance;
|
|
193
193
|
|
|
194
194
|
/**
|
|
195
195
|
* Table cell renderers: produce DOM elements for each cell type.
|
package/dist/index.js
CHANGED
|
@@ -3210,7 +3210,8 @@ function escapeHtml(str) {
|
|
|
3210
3210
|
}
|
|
3211
3211
|
|
|
3212
3212
|
// src/mount.ts
|
|
3213
|
-
import {
|
|
3213
|
+
import { isLayerSpec } from "@opendata-ai/openchart-core";
|
|
3214
|
+
import { compileChart, compileLayer } from "@opendata-ai/openchart-engine";
|
|
3214
3215
|
|
|
3215
3216
|
// src/svg-renderer.ts
|
|
3216
3217
|
import { estimateTextWidth } from "@opendata-ai/openchart-core";
|
|
@@ -3419,7 +3420,7 @@ function renderAxis(parent, axis, orientation, layout) {
|
|
|
3419
3420
|
y2: gridline.position,
|
|
3420
3421
|
stroke: layout.theme.colors.gridline,
|
|
3421
3422
|
"stroke-width": 1,
|
|
3422
|
-
"stroke-opacity": 0.
|
|
3423
|
+
"stroke-opacity": 0.6
|
|
3423
3424
|
});
|
|
3424
3425
|
} else {
|
|
3425
3426
|
setAttrs(gl, {
|
|
@@ -3429,7 +3430,7 @@ function renderAxis(parent, axis, orientation, layout) {
|
|
|
3429
3430
|
y2: area.y + area.height,
|
|
3430
3431
|
stroke: layout.theme.colors.gridline,
|
|
3431
3432
|
"stroke-width": 1,
|
|
3432
|
-
"stroke-opacity": 0.
|
|
3433
|
+
"stroke-opacity": 0.6
|
|
3433
3434
|
});
|
|
3434
3435
|
}
|
|
3435
3436
|
g.appendChild(gl);
|
|
@@ -3633,11 +3634,86 @@ function renderPointMark(mark, index2) {
|
|
|
3633
3634
|
}
|
|
3634
3635
|
return circle;
|
|
3635
3636
|
}
|
|
3637
|
+
function renderTextMark(mark, index2) {
|
|
3638
|
+
const text = createSVGElement("text");
|
|
3639
|
+
text.setAttribute("data-mark-id", `textMark-${index2}`);
|
|
3640
|
+
text.setAttribute("class", "viz-mark viz-mark-text");
|
|
3641
|
+
setAttrs(text, {
|
|
3642
|
+
x: mark.x,
|
|
3643
|
+
y: mark.y,
|
|
3644
|
+
"font-size": mark.fontSize,
|
|
3645
|
+
"text-anchor": mark.textAnchor
|
|
3646
|
+
});
|
|
3647
|
+
text.style.setProperty("fill", mark.fill);
|
|
3648
|
+
if (mark.fontWeight) {
|
|
3649
|
+
text.setAttribute("font-weight", String(mark.fontWeight));
|
|
3650
|
+
}
|
|
3651
|
+
if (mark.fontFamily) {
|
|
3652
|
+
text.setAttribute("font-family", mark.fontFamily);
|
|
3653
|
+
}
|
|
3654
|
+
if (mark.angle) {
|
|
3655
|
+
text.setAttribute("transform", `rotate(${mark.angle}, ${mark.x}, ${mark.y})`);
|
|
3656
|
+
}
|
|
3657
|
+
text.textContent = mark.text;
|
|
3658
|
+
return text;
|
|
3659
|
+
}
|
|
3660
|
+
function renderRuleMark(mark, index2) {
|
|
3661
|
+
const line = createSVGElement("line");
|
|
3662
|
+
line.setAttribute("data-mark-id", `rule-${index2}`);
|
|
3663
|
+
line.setAttribute("class", "viz-mark viz-mark-rule");
|
|
3664
|
+
setAttrs(line, {
|
|
3665
|
+
x1: mark.x1,
|
|
3666
|
+
y1: mark.y1,
|
|
3667
|
+
x2: mark.x2,
|
|
3668
|
+
y2: mark.y2,
|
|
3669
|
+
stroke: mark.stroke,
|
|
3670
|
+
"stroke-width": mark.strokeWidth
|
|
3671
|
+
});
|
|
3672
|
+
if (mark.strokeDasharray) {
|
|
3673
|
+
line.setAttribute("stroke-dasharray", mark.strokeDasharray);
|
|
3674
|
+
}
|
|
3675
|
+
if (mark.opacity != null) {
|
|
3676
|
+
line.setAttribute("opacity", String(mark.opacity));
|
|
3677
|
+
}
|
|
3678
|
+
return line;
|
|
3679
|
+
}
|
|
3680
|
+
function renderTickMark(mark, index2) {
|
|
3681
|
+
const line = createSVGElement("line");
|
|
3682
|
+
line.setAttribute("data-mark-id", `tick-${index2}`);
|
|
3683
|
+
line.setAttribute("class", "viz-mark viz-mark-tick");
|
|
3684
|
+
const half = mark.length / 2;
|
|
3685
|
+
if (mark.orient === "vertical") {
|
|
3686
|
+
setAttrs(line, {
|
|
3687
|
+
x1: mark.x,
|
|
3688
|
+
y1: mark.y - half,
|
|
3689
|
+
x2: mark.x,
|
|
3690
|
+
y2: mark.y + half,
|
|
3691
|
+
stroke: mark.stroke,
|
|
3692
|
+
"stroke-width": mark.strokeWidth
|
|
3693
|
+
});
|
|
3694
|
+
} else {
|
|
3695
|
+
setAttrs(line, {
|
|
3696
|
+
x1: mark.x - half,
|
|
3697
|
+
y1: mark.y,
|
|
3698
|
+
x2: mark.x + half,
|
|
3699
|
+
y2: mark.y,
|
|
3700
|
+
stroke: mark.stroke,
|
|
3701
|
+
"stroke-width": mark.strokeWidth
|
|
3702
|
+
});
|
|
3703
|
+
}
|
|
3704
|
+
if (mark.opacity != null) {
|
|
3705
|
+
line.setAttribute("opacity", String(mark.opacity));
|
|
3706
|
+
}
|
|
3707
|
+
return line;
|
|
3708
|
+
}
|
|
3636
3709
|
registerMarkRenderer("line", renderLineMark);
|
|
3637
3710
|
registerMarkRenderer("area", renderAreaMark);
|
|
3638
3711
|
registerMarkRenderer("rect", renderRectMark);
|
|
3639
3712
|
registerMarkRenderer("arc", renderArcMark);
|
|
3640
3713
|
registerMarkRenderer("point", renderPointMark);
|
|
3714
|
+
registerMarkRenderer("textMark", renderTextMark);
|
|
3715
|
+
registerMarkRenderer("rule", renderRuleMark);
|
|
3716
|
+
registerMarkRenderer("tick", renderTickMark);
|
|
3641
3717
|
function getMarkSeries(mark) {
|
|
3642
3718
|
if (mark.type === "line" || mark.type === "area") {
|
|
3643
3719
|
return mark.seriesKey;
|
|
@@ -3974,10 +4050,10 @@ function renderBrand(parent, layout) {
|
|
|
3974
4050
|
setAttrs(text, {
|
|
3975
4051
|
x: rightEdge,
|
|
3976
4052
|
y: chromeY,
|
|
4053
|
+
"dominant-baseline": "hanging",
|
|
3977
4054
|
"font-family": layout.theme.fonts.family,
|
|
3978
4055
|
"font-size": BRAND_FONT_SIZE,
|
|
3979
4056
|
"text-anchor": "end",
|
|
3980
|
-
"dominant-baseline": "hanging",
|
|
3981
4057
|
"fill-opacity": 0.55
|
|
3982
4058
|
});
|
|
3983
4059
|
text.style.setProperty("fill", fill);
|
|
@@ -3997,7 +4073,13 @@ function renderChartSVG(layout, container) {
|
|
|
3997
4073
|
const svg = createSVGElement("svg");
|
|
3998
4074
|
setAttrs(svg, {
|
|
3999
4075
|
viewBox: `0 0 ${width} ${height}`,
|
|
4000
|
-
xmlns: SVG_NS
|
|
4076
|
+
xmlns: SVG_NS,
|
|
4077
|
+
// WebKit/iOS Safari getBBox() bug: text with dominant-baseline:hanging
|
|
4078
|
+
// reports bounding boxes extending above y=0. The SVG spec default
|
|
4079
|
+
// overflow is "hidden", which clips this phantom extent. Setting
|
|
4080
|
+
// overflow:visible prevents the clipping. Chart marks are already
|
|
4081
|
+
// constrained by a clipPath, so nothing bleeds out.
|
|
4082
|
+
overflow: "visible"
|
|
4001
4083
|
});
|
|
4002
4084
|
svg.style.height = `${height}px`;
|
|
4003
4085
|
svg.setAttribute("role", layout.a11y.role);
|
|
@@ -4030,6 +4112,23 @@ function renderChartSVG(layout, container) {
|
|
|
4030
4112
|
const clippedGroup = createSVGElement("g");
|
|
4031
4113
|
clippedGroup.setAttribute("clip-path", `url(#${clipId})`);
|
|
4032
4114
|
renderMarks(clippedGroup, layout);
|
|
4115
|
+
const hasLineOrAreaWithDataPoints = layout.marks.some(
|
|
4116
|
+
(m2) => (m2.type === "line" || m2.type === "area") && m2.dataPoints && m2.dataPoints.length > 0
|
|
4117
|
+
);
|
|
4118
|
+
const hasPointMarks = layout.marks.some((m2) => m2.type === "point");
|
|
4119
|
+
if (hasLineOrAreaWithDataPoints && !hasPointMarks) {
|
|
4120
|
+
const overlay = createSVGElement("rect");
|
|
4121
|
+
setAttrs(overlay, {
|
|
4122
|
+
x: layout.area.x,
|
|
4123
|
+
y: layout.area.y,
|
|
4124
|
+
width: layout.area.width,
|
|
4125
|
+
height: layout.area.height,
|
|
4126
|
+
fill: "transparent"
|
|
4127
|
+
});
|
|
4128
|
+
overlay.setAttribute("class", "viz-voronoi-overlay");
|
|
4129
|
+
overlay.setAttribute("data-voronoi-overlay", "true");
|
|
4130
|
+
clippedGroup.appendChild(overlay);
|
|
4131
|
+
}
|
|
4033
4132
|
svg.appendChild(clippedGroup);
|
|
4034
4133
|
renderAnnotations(svg, layout);
|
|
4035
4134
|
renderLegend(svg, layout.legend);
|
|
@@ -4120,6 +4219,89 @@ function wireTooltipEvents(svg, tooltipDescriptors, tooltipManager) {
|
|
|
4120
4219
|
}
|
|
4121
4220
|
};
|
|
4122
4221
|
}
|
|
4222
|
+
function collectVoronoiPoints(layout) {
|
|
4223
|
+
const points = [];
|
|
4224
|
+
for (const mark of layout.marks) {
|
|
4225
|
+
if ((mark.type === "line" || mark.type === "area") && mark.dataPoints) {
|
|
4226
|
+
const color = mark.type === "line" ? mark.stroke : mark.fill;
|
|
4227
|
+
for (const dp of mark.dataPoints) {
|
|
4228
|
+
points.push({ ...dp, color });
|
|
4229
|
+
}
|
|
4230
|
+
}
|
|
4231
|
+
}
|
|
4232
|
+
return points;
|
|
4233
|
+
}
|
|
4234
|
+
function findNearestPoint(points, x3, y3) {
|
|
4235
|
+
if (points.length === 0) return null;
|
|
4236
|
+
let nearest = points[0];
|
|
4237
|
+
let minDist = (points[0].x - x3) ** 2 + (points[0].y - y3) ** 2;
|
|
4238
|
+
for (let i = 1; i < points.length; i++) {
|
|
4239
|
+
const dist = (points[i].x - x3) ** 2 + (points[i].y - y3) ** 2;
|
|
4240
|
+
if (dist < minDist) {
|
|
4241
|
+
minDist = dist;
|
|
4242
|
+
nearest = points[i];
|
|
4243
|
+
}
|
|
4244
|
+
}
|
|
4245
|
+
return nearest;
|
|
4246
|
+
}
|
|
4247
|
+
function wireVoronoiTooltipEvents(svg, layout, tooltipManager) {
|
|
4248
|
+
const overlay = svg.querySelector("[data-voronoi-overlay]");
|
|
4249
|
+
if (!overlay) return () => {
|
|
4250
|
+
};
|
|
4251
|
+
const voronoiPoints = collectVoronoiPoints(layout);
|
|
4252
|
+
if (voronoiPoints.length === 0) return () => {
|
|
4253
|
+
};
|
|
4254
|
+
const cleanups = [];
|
|
4255
|
+
const handleMouseMove = (e) => {
|
|
4256
|
+
const mouseEvent = e;
|
|
4257
|
+
const svgEl = svg;
|
|
4258
|
+
const svgRect = svgEl.getBoundingClientRect();
|
|
4259
|
+
const viewBox = svgEl.viewBox?.baseVal;
|
|
4260
|
+
const scaleX = viewBox?.width && svgRect.width ? viewBox.width / svgRect.width : 1;
|
|
4261
|
+
const scaleY = viewBox?.height && svgRect.height ? viewBox.height / svgRect.height : 1;
|
|
4262
|
+
const svgX = (mouseEvent.clientX - svgRect.left) * scaleX;
|
|
4263
|
+
const svgY = (mouseEvent.clientY - svgRect.top) * scaleY;
|
|
4264
|
+
const nearest = findNearestPoint(voronoiPoints, svgX, svgY);
|
|
4265
|
+
if (!nearest?.tooltip) return;
|
|
4266
|
+
const containerX = mouseEvent.clientX - svgRect.left;
|
|
4267
|
+
const containerY = mouseEvent.clientY - svgRect.top;
|
|
4268
|
+
tooltipManager.show(nearest.tooltip, containerX, containerY);
|
|
4269
|
+
};
|
|
4270
|
+
const handleMouseLeave = () => {
|
|
4271
|
+
tooltipManager.hide();
|
|
4272
|
+
};
|
|
4273
|
+
const handleTouchStart = (e) => {
|
|
4274
|
+
const touchEvent = e;
|
|
4275
|
+
if (touchEvent.touches.length > 0) {
|
|
4276
|
+
const touch = touchEvent.touches[0];
|
|
4277
|
+
const svgEl = svg;
|
|
4278
|
+
const svgRect = svgEl.getBoundingClientRect();
|
|
4279
|
+
const viewBox = svgEl.viewBox?.baseVal;
|
|
4280
|
+
const scaleX = viewBox?.width && svgRect.width ? viewBox.width / svgRect.width : 1;
|
|
4281
|
+
const scaleY = viewBox?.height && svgRect.height ? viewBox.height / svgRect.height : 1;
|
|
4282
|
+
const svgX = (touch.clientX - svgRect.left) * scaleX;
|
|
4283
|
+
const svgY = (touch.clientY - svgRect.top) * scaleY;
|
|
4284
|
+
const nearest = findNearestPoint(voronoiPoints, svgX, svgY);
|
|
4285
|
+
if (!nearest?.tooltip) return;
|
|
4286
|
+
const containerX = touch.clientX - svgRect.left;
|
|
4287
|
+
const containerY = touch.clientY - svgRect.top;
|
|
4288
|
+
tooltipManager.show(nearest.tooltip, containerX, containerY);
|
|
4289
|
+
}
|
|
4290
|
+
};
|
|
4291
|
+
overlay.addEventListener("mousemove", handleMouseMove);
|
|
4292
|
+
overlay.addEventListener("mouseleave", handleMouseLeave);
|
|
4293
|
+
overlay.addEventListener("touchstart", handleTouchStart);
|
|
4294
|
+
cleanups.push(() => {
|
|
4295
|
+
overlay.removeEventListener("mousemove", handleMouseMove);
|
|
4296
|
+
overlay.removeEventListener("mouseleave", handleMouseLeave);
|
|
4297
|
+
overlay.removeEventListener("touchstart", handleTouchStart);
|
|
4298
|
+
});
|
|
4299
|
+
return () => {
|
|
4300
|
+
for (const cleanup of cleanups) {
|
|
4301
|
+
cleanup();
|
|
4302
|
+
}
|
|
4303
|
+
};
|
|
4304
|
+
}
|
|
4123
4305
|
function buildMarkDataMap(layout) {
|
|
4124
4306
|
const map = /* @__PURE__ */ new Map();
|
|
4125
4307
|
for (let i = 0; i < layout.marks.length; i++) {
|
|
@@ -4448,10 +4630,10 @@ function wireConnectorEndpointDrag(svg, specAnnotations, onEdit, setDragging) {
|
|
|
4448
4630
|
if (!connectorLine && !curvedPath) continue;
|
|
4449
4631
|
let fromX, fromY, toX, toY;
|
|
4450
4632
|
if (connectorLine) {
|
|
4451
|
-
fromX = Number(connectorLine.getAttribute("x1"));
|
|
4452
|
-
fromY = Number(connectorLine.getAttribute("y1"));
|
|
4453
|
-
toX = Number(connectorLine.getAttribute("x2"));
|
|
4454
|
-
toY = Number(connectorLine.getAttribute("y2"));
|
|
4633
|
+
fromX = Number(connectorLine.getAttribute("x1")) || 0;
|
|
4634
|
+
fromY = Number(connectorLine.getAttribute("y1")) || 0;
|
|
4635
|
+
toX = Number(connectorLine.getAttribute("x2")) || 0;
|
|
4636
|
+
toY = Number(connectorLine.getAttribute("y2")) || 0;
|
|
4455
4637
|
} else {
|
|
4456
4638
|
const pathD = curvedPath.getAttribute("d") ?? "";
|
|
4457
4639
|
const mMatch = pathD.match(/M\s*([\d.e+-]+)\s+([\d.e+-]+)/);
|
|
@@ -4461,8 +4643,8 @@ function wireConnectorEndpointDrag(svg, specAnnotations, onEdit, setDragging) {
|
|
|
4461
4643
|
const points = arrowhead?.getAttribute("points") ?? "";
|
|
4462
4644
|
const firstPoint = points.split(" ")[0] ?? "0,0";
|
|
4463
4645
|
const [px, py] = firstPoint.split(",");
|
|
4464
|
-
toX = Number(px);
|
|
4465
|
-
toY = Number(py);
|
|
4646
|
+
toX = Number(px) || 0;
|
|
4647
|
+
toY = Number(py) || 0;
|
|
4466
4648
|
}
|
|
4467
4649
|
const endpoints = [
|
|
4468
4650
|
{ name: "from", cx: fromX, cy: fromY },
|
|
@@ -4470,6 +4652,7 @@ function wireConnectorEndpointDrag(svg, specAnnotations, onEdit, setDragging) {
|
|
|
4470
4652
|
];
|
|
4471
4653
|
const createdHandles = [];
|
|
4472
4654
|
for (const ep of endpoints) {
|
|
4655
|
+
if (!Number.isFinite(ep.cx) || !Number.isFinite(ep.cy)) continue;
|
|
4473
4656
|
const handleEl = document.createElementNS(SVG_NS2, "circle");
|
|
4474
4657
|
handleEl.setAttribute("class", "viz-connector-handle");
|
|
4475
4658
|
handleEl.setAttribute("data-endpoint", ep.name);
|
|
@@ -4906,6 +5089,7 @@ function createChart(container, spec, options) {
|
|
|
4906
5089
|
let tooltipManager = null;
|
|
4907
5090
|
let disconnectResize = null;
|
|
4908
5091
|
let cleanupTooltipEvents = null;
|
|
5092
|
+
let cleanupVoronoiEvents = null;
|
|
4909
5093
|
let cleanupKeyboardNav = null;
|
|
4910
5094
|
let cleanupLegend = null;
|
|
4911
5095
|
let cleanupChartEvents = null;
|
|
@@ -4927,6 +5111,9 @@ function createChart(container, spec, options) {
|
|
|
4927
5111
|
darkMode,
|
|
4928
5112
|
measureText
|
|
4929
5113
|
};
|
|
5114
|
+
if (isLayerSpec(currentSpec)) {
|
|
5115
|
+
return compileLayer(currentSpec, compileOpts);
|
|
5116
|
+
}
|
|
4930
5117
|
return compileChart(currentSpec, compileOpts);
|
|
4931
5118
|
}
|
|
4932
5119
|
function getContainerDimensions() {
|
|
@@ -4945,6 +5132,10 @@ function createChart(container, spec, options) {
|
|
|
4945
5132
|
cleanupTooltipEvents();
|
|
4946
5133
|
cleanupTooltipEvents = null;
|
|
4947
5134
|
}
|
|
5135
|
+
if (cleanupVoronoiEvents) {
|
|
5136
|
+
cleanupVoronoiEvents();
|
|
5137
|
+
cleanupVoronoiEvents = null;
|
|
5138
|
+
}
|
|
4948
5139
|
if (cleanupKeyboardNav) {
|
|
4949
5140
|
cleanupKeyboardNav();
|
|
4950
5141
|
cleanupKeyboardNav = null;
|
|
@@ -4983,6 +5174,7 @@ function createChart(container, spec, options) {
|
|
|
4983
5174
|
currentLayout.tooltipDescriptors,
|
|
4984
5175
|
tooltipManager
|
|
4985
5176
|
);
|
|
5177
|
+
cleanupVoronoiEvents = wireVoronoiTooltipEvents(svgElement, currentLayout, tooltipManager);
|
|
4986
5178
|
cleanupKeyboardNav = wireKeyboardNav(
|
|
4987
5179
|
svgElement,
|
|
4988
5180
|
container,
|
|
@@ -5025,9 +5217,10 @@ function createChart(container, spec, options) {
|
|
|
5025
5217
|
editCleanups.push(
|
|
5026
5218
|
wireAnnotationLabelDrag(svgElement, dragAnnotations, options.onEdit, setDragging)
|
|
5027
5219
|
);
|
|
5028
|
-
|
|
5029
|
-
editCleanups.push(
|
|
5030
|
-
editCleanups.push(
|
|
5220
|
+
const editSpec = currentSpec;
|
|
5221
|
+
editCleanups.push(wireChromeDrag(svgElement, editSpec, options.onEdit, setDragging));
|
|
5222
|
+
editCleanups.push(wireLegendDrag(svgElement, editSpec, options.onEdit, setDragging));
|
|
5223
|
+
editCleanups.push(wireSeriesLabelDrag(svgElement, editSpec, options.onEdit, setDragging));
|
|
5031
5224
|
cleanupEditDrags = () => {
|
|
5032
5225
|
for (const cleanup of editCleanups) {
|
|
5033
5226
|
cleanup();
|
|
@@ -5084,6 +5277,10 @@ function createChart(container, spec, options) {
|
|
|
5084
5277
|
cleanupTooltipEvents();
|
|
5085
5278
|
cleanupTooltipEvents = null;
|
|
5086
5279
|
}
|
|
5280
|
+
if (cleanupVoronoiEvents) {
|
|
5281
|
+
cleanupVoronoiEvents();
|
|
5282
|
+
cleanupVoronoiEvents = null;
|
|
5283
|
+
}
|
|
5087
5284
|
if (cleanupKeyboardNav) {
|
|
5088
5285
|
cleanupKeyboardNav();
|
|
5089
5286
|
cleanupKeyboardNav = null;
|