@opendata-ai/openchart-vanilla 8.0.0-rc.8 → 8.0.0-rc.9
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-UZ7J3NOF.js → chunk-IZQBT6QM.js} +338 -31
- package/dist/chunk-IZQBT6QM.js.map +1 -0
- package/dist/{chunk-5EOV5JQZ.js → chunk-QW7ZB6NE.js} +2 -2
- package/dist/{chunk-5EOV5JQZ.js.map → chunk-QW7ZB6NE.js.map} +1 -1
- package/dist/{chunk-W34KN7FD.js → chunk-SPILUE5S.js} +2 -2
- package/dist/index.js +3 -3
- package/dist/static.js +2 -2
- package/dist/story/index.js +2 -2
- package/dist/styles.css +1 -1
- package/dist/styles.css.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/edit-events.test.ts +528 -1
- package/src/__tests__/editable-prop.test.ts +174 -0
- package/src/__tests__/invert.test.ts +187 -0
- package/src/__tests__/selection-events.test.ts +194 -1
- package/src/interactions/editing-drags.ts +145 -11
- package/src/interactions/index.ts +2 -0
- package/src/interactions/invert.ts +54 -0
- package/src/interactions/selection.ts +10 -4
- package/src/map-mount.ts +13 -8
- package/src/map-renderer.ts +20 -4
- package/src/mount.ts +63 -11
- package/src/renderers/legend.ts +2 -1
- package/src/text-edit-overlay.ts +134 -0
- package/dist/chunk-UZ7J3NOF.js.map +0 -1
- /package/dist/{chunk-W34KN7FD.js.map → chunk-SPILUE5S.js.map} +0 -0
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
resolveMarkFill,
|
|
12
12
|
setAttrs,
|
|
13
13
|
stampAnimationVars
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-QW7ZB6NE.js";
|
|
15
15
|
|
|
16
16
|
// src/export.ts
|
|
17
17
|
function getSVGDimensions(svg) {
|
|
@@ -876,6 +876,11 @@ function renderMapSVG(layout, opts) {
|
|
|
876
876
|
focusIdSet
|
|
877
877
|
);
|
|
878
878
|
renderBorders(cameraGroup, borders);
|
|
879
|
+
if (animate && animation?.enter && layout.pointMarks.length > 1) {
|
|
880
|
+
const pointStaggerBudget = animation.enter.duration * 0.5;
|
|
881
|
+
const perPoint = pointStaggerBudget / (layout.pointMarks.length - 1);
|
|
882
|
+
svg.style.setProperty("--oc-point-stagger", `${perPoint}ms`);
|
|
883
|
+
}
|
|
879
884
|
renderPointMarks(cameraGroup, layout.pointMarks, animate ? animation : void 0);
|
|
880
885
|
mapGroup.appendChild(cameraGroup);
|
|
881
886
|
svg.appendChild(mapGroup);
|
|
@@ -906,12 +911,14 @@ function renderMapSVG(layout, opts) {
|
|
|
906
911
|
contentWidth = Math.min(w, ptLegend.bounds.width);
|
|
907
912
|
}
|
|
908
913
|
}
|
|
914
|
+
const isOverlayContinuous = ptLegend.position === "top-left" && !("entries" in ptLegend && ptLegend.entries);
|
|
909
915
|
const contentCenterY = ptLegend.bounds.y + swatchSize / 2;
|
|
910
|
-
const bgHeight = swatchSize + padY * 2;
|
|
916
|
+
const bgHeight = isOverlayContinuous ? ptLegend.bounds.height + padY * 2 : swatchSize + padY * 2;
|
|
917
|
+
const bgY = isOverlayContinuous ? ptLegend.bounds.y - padY : contentCenterY - bgHeight / 2;
|
|
911
918
|
const bg = createSVGElement2("rect");
|
|
912
919
|
setAttrs2(bg, {
|
|
913
920
|
x: ptLegend.bounds.x - padX,
|
|
914
|
-
y:
|
|
921
|
+
y: bgY,
|
|
915
922
|
width: contentWidth + padX * 2,
|
|
916
923
|
height: bgHeight,
|
|
917
924
|
rx: 4,
|
|
@@ -1825,13 +1832,17 @@ function createMap(container, spec, options) {
|
|
|
1825
1832
|
fontsReloadPending = false;
|
|
1826
1833
|
container.dataset.ocFontsState = "ready";
|
|
1827
1834
|
}
|
|
1828
|
-
if (isFirstRender
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
+
if (isFirstRender) {
|
|
1836
|
+
if (currentLayout.focus) {
|
|
1837
|
+
const target = currentLayout.focus.target;
|
|
1838
|
+
currentFocusIds = [...currentLayout.focus.ids];
|
|
1839
|
+
const cam = cameraForTarget(currentLayout, target);
|
|
1840
|
+
currentCamera = cam;
|
|
1841
|
+
if (svgElement) applyMapCamera(svgElement, cam, currentLayout);
|
|
1842
|
+
if (!isAnimating) applyFocusDim(currentFocusIds);
|
|
1843
|
+
} else {
|
|
1844
|
+
currentCamera = cameraForTarget(currentLayout, null);
|
|
1845
|
+
}
|
|
1835
1846
|
}
|
|
1836
1847
|
isFirstRender = false;
|
|
1837
1848
|
}
|
|
@@ -2173,6 +2184,104 @@ function createTextEditOverlay(config) {
|
|
|
2173
2184
|
resizeObserver.observe(container);
|
|
2174
2185
|
return { destroy };
|
|
2175
2186
|
}
|
|
2187
|
+
function createTextEditOverlayAtPosition(config) {
|
|
2188
|
+
const { container, svg, position, onCommit, onCancel } = config;
|
|
2189
|
+
let destroyed = false;
|
|
2190
|
+
const scale = getScale(svg);
|
|
2191
|
+
const svgRect = svg.getBoundingClientRect();
|
|
2192
|
+
const containerRect = container.getBoundingClientRect();
|
|
2193
|
+
const padding = 4;
|
|
2194
|
+
const left = position.x * scale.scaleX + (svgRect.left - containerRect.left) - padding;
|
|
2195
|
+
const top = position.y * scale.scaleY + (svgRect.top - containerRect.top) - padding;
|
|
2196
|
+
const computedStyle = window.getComputedStyle(svg);
|
|
2197
|
+
const fontFamily = computedStyle.getPropertyValue("--oc-font-family").trim() || "inherit";
|
|
2198
|
+
const textColor = computedStyle.getPropertyValue("--oc-text-color").trim() || computedStyle.color || "#333";
|
|
2199
|
+
const surfaceColor = computedStyle.getPropertyValue("--oc-surface-color").trim() || "rgba(255, 255, 255, 0.95)";
|
|
2200
|
+
const fontSize = 13 * scale.scaleY;
|
|
2201
|
+
const textarea = document.createElement("textarea");
|
|
2202
|
+
textarea.value = "";
|
|
2203
|
+
textarea.placeholder = "Type annotation text...";
|
|
2204
|
+
const containerPosition = window.getComputedStyle(container).position;
|
|
2205
|
+
const containerWasStatic = containerPosition === "static";
|
|
2206
|
+
if (containerWasStatic) {
|
|
2207
|
+
container.style.position = "relative";
|
|
2208
|
+
}
|
|
2209
|
+
Object.assign(textarea.style, {
|
|
2210
|
+
position: "absolute",
|
|
2211
|
+
top: `${Math.max(0, top)}px`,
|
|
2212
|
+
left: `${Math.max(0, left)}px`,
|
|
2213
|
+
width: "160px",
|
|
2214
|
+
minHeight: "24px",
|
|
2215
|
+
fontFamily,
|
|
2216
|
+
fontSize: `${fontSize}px`,
|
|
2217
|
+
fontWeight: "400",
|
|
2218
|
+
color: textColor,
|
|
2219
|
+
textAlign: "left",
|
|
2220
|
+
lineHeight: "1.3",
|
|
2221
|
+
padding: "2px 4px",
|
|
2222
|
+
margin: "0",
|
|
2223
|
+
border: "1px solid rgba(79, 70, 229, 0.4)",
|
|
2224
|
+
borderRadius: "3px",
|
|
2225
|
+
background: surfaceColor,
|
|
2226
|
+
outline: "none",
|
|
2227
|
+
resize: "none",
|
|
2228
|
+
overflow: "hidden",
|
|
2229
|
+
boxSizing: "border-box",
|
|
2230
|
+
zIndex: "10000",
|
|
2231
|
+
WebkitAppearance: "none",
|
|
2232
|
+
appearance: "none"
|
|
2233
|
+
});
|
|
2234
|
+
container.appendChild(textarea);
|
|
2235
|
+
textarea.focus();
|
|
2236
|
+
function destroy() {
|
|
2237
|
+
if (destroyed) return;
|
|
2238
|
+
destroyed = true;
|
|
2239
|
+
textarea.removeEventListener("keydown", handleKeyDown);
|
|
2240
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
2241
|
+
if (containerWasStatic) {
|
|
2242
|
+
container.style.position = "";
|
|
2243
|
+
}
|
|
2244
|
+
if (textarea.parentNode) {
|
|
2245
|
+
textarea.parentNode.removeChild(textarea);
|
|
2246
|
+
}
|
|
2247
|
+
}
|
|
2248
|
+
function commit() {
|
|
2249
|
+
if (destroyed) return;
|
|
2250
|
+
const text = textarea.value.trim();
|
|
2251
|
+
destroy();
|
|
2252
|
+
if (text) {
|
|
2253
|
+
onCommit(text);
|
|
2254
|
+
} else {
|
|
2255
|
+
onCancel();
|
|
2256
|
+
}
|
|
2257
|
+
}
|
|
2258
|
+
function cancel() {
|
|
2259
|
+
if (destroyed) return;
|
|
2260
|
+
destroy();
|
|
2261
|
+
onCancel();
|
|
2262
|
+
}
|
|
2263
|
+
const handleKeyDown = (e) => {
|
|
2264
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
2265
|
+
e.preventDefault();
|
|
2266
|
+
commit();
|
|
2267
|
+
} else if (e.key === "Escape") {
|
|
2268
|
+
e.preventDefault();
|
|
2269
|
+
cancel();
|
|
2270
|
+
}
|
|
2271
|
+
};
|
|
2272
|
+
textarea.addEventListener("keydown", handleKeyDown);
|
|
2273
|
+
const handleClickOutside = (e) => {
|
|
2274
|
+
if (!textarea.contains(e.target)) {
|
|
2275
|
+
commit();
|
|
2276
|
+
}
|
|
2277
|
+
};
|
|
2278
|
+
requestAnimationFrame(() => {
|
|
2279
|
+
if (!destroyed) {
|
|
2280
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
2281
|
+
}
|
|
2282
|
+
});
|
|
2283
|
+
return { destroy };
|
|
2284
|
+
}
|
|
2176
2285
|
|
|
2177
2286
|
// src/you-draw-it.ts
|
|
2178
2287
|
var MIN_TOUCH_TARGET = 24;
|
|
@@ -2947,6 +3056,53 @@ function createDragHandler(config) {
|
|
|
2947
3056
|
};
|
|
2948
3057
|
}
|
|
2949
3058
|
|
|
3059
|
+
// src/interactions/editing-drags.ts
|
|
3060
|
+
import {
|
|
3061
|
+
elementRef
|
|
3062
|
+
} from "@opendata-ai/openchart-core";
|
|
3063
|
+
|
|
3064
|
+
// src/interactions/invert.ts
|
|
3065
|
+
function invertScale(invert, pixel) {
|
|
3066
|
+
if (invert.domain && invert.positions && invert.domain.length > 0) {
|
|
3067
|
+
let closest = 0;
|
|
3068
|
+
let minDist = Infinity;
|
|
3069
|
+
for (let i = 0; i < invert.positions.length; i++) {
|
|
3070
|
+
const dist = Math.abs(invert.positions[i] - pixel);
|
|
3071
|
+
if (dist < minDist) {
|
|
3072
|
+
minDist = dist;
|
|
3073
|
+
closest = i;
|
|
3074
|
+
}
|
|
3075
|
+
}
|
|
3076
|
+
return invert.domain[closest];
|
|
3077
|
+
}
|
|
3078
|
+
const span = invert.bottomPixel - invert.topPixel;
|
|
3079
|
+
if (span === 0) return invert.topData;
|
|
3080
|
+
const t = (pixel - invert.topPixel) / span;
|
|
3081
|
+
const { topData, bottomData, scaleType } = invert;
|
|
3082
|
+
if (scaleType === "log") {
|
|
3083
|
+
if (topData <= 0 || bottomData <= 0) return topData + t * (bottomData - topData);
|
|
3084
|
+
return Math.exp(Math.log(topData) + t * (Math.log(bottomData) - Math.log(topData)));
|
|
3085
|
+
}
|
|
3086
|
+
if (scaleType === "sqrt") {
|
|
3087
|
+
const sqrtTop = Math.sqrt(Math.abs(topData)) * Math.sign(topData);
|
|
3088
|
+
const sqrtBottom = Math.sqrt(Math.abs(bottomData)) * Math.sign(bottomData);
|
|
3089
|
+
const sqrtVal = sqrtTop + t * (sqrtBottom - sqrtTop);
|
|
3090
|
+
return sqrtVal * Math.abs(sqrtVal);
|
|
3091
|
+
}
|
|
3092
|
+
if (scaleType === "pow") {
|
|
3093
|
+
const powTop = Math.sign(topData) * Math.abs(topData) ** 0.5;
|
|
3094
|
+
const powBottom = Math.sign(bottomData) * Math.abs(bottomData) ** 0.5;
|
|
3095
|
+
const powVal = powTop + t * (powBottom - powTop);
|
|
3096
|
+
return Math.sign(powVal) * Math.abs(powVal) ** 2;
|
|
3097
|
+
}
|
|
3098
|
+
if (scaleType === "symlog") {
|
|
3099
|
+
const symlog = (x) => Math.sign(x) * Math.log1p(Math.abs(x));
|
|
3100
|
+
const symexp = (x) => Math.sign(x) * Math.expm1(Math.abs(x));
|
|
3101
|
+
return symexp(symlog(topData) + t * (symlog(bottomData) - symlog(topData)));
|
|
3102
|
+
}
|
|
3103
|
+
return topData + t * (bottomData - topData);
|
|
3104
|
+
}
|
|
3105
|
+
|
|
2950
3106
|
// src/interactions/editing-drags.ts
|
|
2951
3107
|
function wireAnnotationDrag(svg, specAnnotations, onAnnotationEdit, onEdit, setDragging) {
|
|
2952
3108
|
const annotationElements = svg.querySelectorAll(".oc-annotation-text");
|
|
@@ -2998,7 +3154,16 @@ function wireAnnotationDrag(svg, specAnnotations, onAnnotationEdit, onEdit, setD
|
|
|
2998
3154
|
dy: origDy + dy
|
|
2999
3155
|
};
|
|
3000
3156
|
onAnnotationEdit?.(textAnnotation, newOffset);
|
|
3001
|
-
onEdit?.({
|
|
3157
|
+
onEdit?.({
|
|
3158
|
+
type: "annotation",
|
|
3159
|
+
element: elementRef.annotation(
|
|
3160
|
+
index,
|
|
3161
|
+
textAnnotation.id,
|
|
3162
|
+
`/annotations/${index}/offset`
|
|
3163
|
+
),
|
|
3164
|
+
annotation: textAnnotation,
|
|
3165
|
+
offset: newOffset
|
|
3166
|
+
});
|
|
3002
3167
|
}
|
|
3003
3168
|
},
|
|
3004
3169
|
setDragging
|
|
@@ -3106,6 +3271,11 @@ function wireConnectorEndpointDrag(svg, specAnnotations, onEdit, setDragging) {
|
|
|
3106
3271
|
const origEndDy = existingOffset?.dy ?? 0;
|
|
3107
3272
|
onEdit({
|
|
3108
3273
|
type: "annotation-connector",
|
|
3274
|
+
element: elementRef.annotation(
|
|
3275
|
+
index,
|
|
3276
|
+
textAnnotation.id,
|
|
3277
|
+
`/annotations/${index}/connectorOffset/${ep.name}`
|
|
3278
|
+
),
|
|
3109
3279
|
annotation: textAnnotation,
|
|
3110
3280
|
endpoint: ep.name,
|
|
3111
3281
|
offset: { dx: origEndDx + dx, dy: origEndDy + dy }
|
|
@@ -3176,12 +3346,22 @@ function wireAnnotationLabelDrag(svg, specAnnotations, onEdit, setDragging) {
|
|
|
3176
3346
|
if (isRange) {
|
|
3177
3347
|
onEdit({
|
|
3178
3348
|
type: "range-label",
|
|
3349
|
+
element: elementRef.annotation(
|
|
3350
|
+
index,
|
|
3351
|
+
specAnnotation.id,
|
|
3352
|
+
`/annotations/${index}/labelOffset`
|
|
3353
|
+
),
|
|
3179
3354
|
annotation: specAnnotation,
|
|
3180
3355
|
labelOffset: { dx: origLabelDx + dx, dy: origLabelDy + dy }
|
|
3181
3356
|
});
|
|
3182
3357
|
} else {
|
|
3183
3358
|
onEdit({
|
|
3184
3359
|
type: "refline-label",
|
|
3360
|
+
element: elementRef.annotation(
|
|
3361
|
+
index,
|
|
3362
|
+
specAnnotation.id,
|
|
3363
|
+
`/annotations/${index}/labelOffset`
|
|
3364
|
+
),
|
|
3185
3365
|
annotation: specAnnotation,
|
|
3186
3366
|
labelOffset: { dx: origLabelDx + dx, dy: origLabelDy + dy }
|
|
3187
3367
|
});
|
|
@@ -3308,6 +3488,88 @@ function wireSeriesLabelDrag(svg, spec, onEdit, setDragging) {
|
|
|
3308
3488
|
}
|
|
3309
3489
|
};
|
|
3310
3490
|
}
|
|
3491
|
+
function wireAnchorDrag(svg, specAnnotations, layout, onEdit, setDragging) {
|
|
3492
|
+
if (!onEdit || !layout.xInvert || !layout.yInvert) return () => {
|
|
3493
|
+
};
|
|
3494
|
+
const SVG_NS4 = "http://www.w3.org/2000/svg";
|
|
3495
|
+
const cleanups = [];
|
|
3496
|
+
const annotationGroups = svg.querySelectorAll(".oc-annotation-text");
|
|
3497
|
+
for (const el of annotationGroups) {
|
|
3498
|
+
const annotationG = el;
|
|
3499
|
+
const indexStr = annotationG.getAttribute("data-annotation-index");
|
|
3500
|
+
if (indexStr === null) continue;
|
|
3501
|
+
const index = Number(indexStr);
|
|
3502
|
+
const specAnnotation = specAnnotations[index];
|
|
3503
|
+
if (!specAnnotation || specAnnotation.type !== "text") continue;
|
|
3504
|
+
const textAnnotation = specAnnotation;
|
|
3505
|
+
const resolved = layout.annotations.find((a) => a.specIndex === index);
|
|
3506
|
+
if (!resolved?.dot) continue;
|
|
3507
|
+
const anchorX = resolved.dot.x;
|
|
3508
|
+
const anchorY = resolved.dot.y;
|
|
3509
|
+
const handleEl = document.createElementNS(SVG_NS4, "circle");
|
|
3510
|
+
handleEl.setAttribute("class", "oc-anchor-handle");
|
|
3511
|
+
handleEl.setAttribute("cx", String(anchorX));
|
|
3512
|
+
handleEl.setAttribute("cy", String(anchorY));
|
|
3513
|
+
handleEl.setAttribute("r", "4");
|
|
3514
|
+
handleEl.setAttribute("opacity", "0");
|
|
3515
|
+
handleEl.setAttribute("fill", "currentColor");
|
|
3516
|
+
handleEl.setAttribute("stroke", "currentColor");
|
|
3517
|
+
handleEl.style.cursor = "grab";
|
|
3518
|
+
annotationG.appendChild(handleEl);
|
|
3519
|
+
const stopProp = (e) => {
|
|
3520
|
+
e.stopPropagation();
|
|
3521
|
+
};
|
|
3522
|
+
handleEl.addEventListener("mousedown", stopProp);
|
|
3523
|
+
handleEl.addEventListener("touchstart", stopProp);
|
|
3524
|
+
cleanups.push(() => {
|
|
3525
|
+
handleEl.removeEventListener("mousedown", stopProp);
|
|
3526
|
+
handleEl.removeEventListener("touchstart", stopProp);
|
|
3527
|
+
});
|
|
3528
|
+
const cleanup = createDragHandler({
|
|
3529
|
+
element: handleEl,
|
|
3530
|
+
svg,
|
|
3531
|
+
onMove: (dx, dy) => {
|
|
3532
|
+
handleEl.setAttribute("cx", String(anchorX + dx));
|
|
3533
|
+
handleEl.setAttribute("cy", String(anchorY + dy));
|
|
3534
|
+
},
|
|
3535
|
+
onEnd: (dx, dy, moved) => {
|
|
3536
|
+
handleEl.setAttribute("cx", String(anchorX));
|
|
3537
|
+
handleEl.setAttribute("cy", String(anchorY));
|
|
3538
|
+
if (moved) {
|
|
3539
|
+
const newX = invertScale(layout.xInvert, anchorX + dx);
|
|
3540
|
+
const newY = invertScale(layout.yInvert, anchorY + dy);
|
|
3541
|
+
onEdit({
|
|
3542
|
+
type: "annotation-anchor",
|
|
3543
|
+
element: elementRef.annotation(index, textAnnotation.id, `/annotations/${index}`),
|
|
3544
|
+
annotation: textAnnotation,
|
|
3545
|
+
x: newX,
|
|
3546
|
+
y: newY
|
|
3547
|
+
});
|
|
3548
|
+
}
|
|
3549
|
+
},
|
|
3550
|
+
setDragging
|
|
3551
|
+
});
|
|
3552
|
+
cleanups.push(cleanup);
|
|
3553
|
+
const showHandle = () => {
|
|
3554
|
+
handleEl.setAttribute("opacity", "0.6");
|
|
3555
|
+
};
|
|
3556
|
+
const hideHandle = () => {
|
|
3557
|
+
handleEl.setAttribute("opacity", "0");
|
|
3558
|
+
};
|
|
3559
|
+
annotationG.addEventListener("mouseenter", showHandle);
|
|
3560
|
+
annotationG.addEventListener("mouseleave", hideHandle);
|
|
3561
|
+
cleanups.push(() => {
|
|
3562
|
+
annotationG.removeEventListener("mouseenter", showHandle);
|
|
3563
|
+
annotationG.removeEventListener("mouseleave", hideHandle);
|
|
3564
|
+
handleEl.remove();
|
|
3565
|
+
});
|
|
3566
|
+
}
|
|
3567
|
+
return () => {
|
|
3568
|
+
for (const cleanup of cleanups) {
|
|
3569
|
+
cleanup();
|
|
3570
|
+
}
|
|
3571
|
+
};
|
|
3572
|
+
}
|
|
3311
3573
|
|
|
3312
3574
|
// src/interactions/keyboard-nav.ts
|
|
3313
3575
|
function wireKeyboardNav(svg, container, tooltipDescriptors, tooltipManager, layout) {
|
|
@@ -3421,7 +3683,7 @@ function wireLegendInteraction(svg, _layout, toggleSeries, onLegendToggle, onEdi
|
|
|
3421
3683
|
}
|
|
3422
3684
|
|
|
3423
3685
|
// src/interactions/selection.ts
|
|
3424
|
-
import { elementRef } from "@opendata-ai/openchart-core";
|
|
3686
|
+
import { elementRef as elementRef2 } from "@opendata-ai/openchart-core";
|
|
3425
3687
|
function findElementByRef(svg, ref) {
|
|
3426
3688
|
switch (ref.type) {
|
|
3427
3689
|
case "annotation": {
|
|
@@ -3447,31 +3709,36 @@ function findElementByRef(svg, ref) {
|
|
|
3447
3709
|
);
|
|
3448
3710
|
}
|
|
3449
3711
|
}
|
|
3712
|
+
function encodePointerToken(token) {
|
|
3713
|
+
return token.replace(/~/g, "~0").replace(/\//g, "~1");
|
|
3714
|
+
}
|
|
3450
3715
|
function buildElementRef(element, _specAnnotations) {
|
|
3451
3716
|
const annotationEl = element.closest("[data-annotation-index]");
|
|
3452
3717
|
if (annotationEl) {
|
|
3453
3718
|
const index = Number(annotationEl.getAttribute("data-annotation-index"));
|
|
3454
3719
|
const id = annotationEl.getAttribute("data-annotation-id") ?? void 0;
|
|
3455
|
-
return
|
|
3720
|
+
return elementRef2.annotation(index, id, `/annotations/${index}`);
|
|
3456
3721
|
}
|
|
3457
3722
|
const chromeEl = element.closest("[data-chrome-key]");
|
|
3458
3723
|
if (chromeEl) {
|
|
3459
3724
|
const key = chromeEl.getAttribute("data-chrome-key");
|
|
3460
|
-
if (key) return
|
|
3725
|
+
if (key) return elementRef2.chrome(key, `/chrome/${key}`);
|
|
3461
3726
|
}
|
|
3462
3727
|
const seriesLabelEl = element.closest(".oc-mark-label[data-series]");
|
|
3463
3728
|
if (seriesLabelEl) {
|
|
3464
3729
|
const series = seriesLabelEl.getAttribute("data-series");
|
|
3465
|
-
if (series)
|
|
3730
|
+
if (series)
|
|
3731
|
+
return elementRef2.seriesLabel(series, `/labels/offsets/${encodePointerToken(series)}`);
|
|
3466
3732
|
}
|
|
3467
3733
|
const legendEntryEl = element.closest("[data-legend-index]");
|
|
3468
3734
|
if (legendEntryEl) {
|
|
3469
3735
|
const index = Number(legendEntryEl.getAttribute("data-legend-index"));
|
|
3470
3736
|
const series = legendEntryEl.getAttribute("data-legend-label") ?? "";
|
|
3471
|
-
return
|
|
3737
|
+
return elementRef2.legendEntry(series, index);
|
|
3472
3738
|
}
|
|
3473
3739
|
const legendEl = element.closest(".oc-legend");
|
|
3474
|
-
if (legendEl && !legendEl.classList.contains("oc-legend--size"))
|
|
3740
|
+
if (legendEl && !legendEl.classList.contains("oc-legend--size"))
|
|
3741
|
+
return elementRef2.legend("/legend");
|
|
3475
3742
|
return null;
|
|
3476
3743
|
}
|
|
3477
3744
|
function getEditableElements(spec, layout) {
|
|
@@ -3479,12 +3746,12 @@ function getEditableElements(spec, layout) {
|
|
|
3479
3746
|
const chromeKeys = ["title", "subtitle", "source", "byline", "footer"];
|
|
3480
3747
|
for (const key of chromeKeys) {
|
|
3481
3748
|
if (layout.chrome[key]) {
|
|
3482
|
-
refs.push(
|
|
3749
|
+
refs.push(elementRef2.chrome(key));
|
|
3483
3750
|
}
|
|
3484
3751
|
}
|
|
3485
3752
|
const annotations = "annotations" in spec && Array.isArray(spec.annotations) ? spec.annotations : [];
|
|
3486
3753
|
for (let i = 0; i < annotations.length; i++) {
|
|
3487
|
-
refs.push(
|
|
3754
|
+
refs.push(elementRef2.annotation(i, annotations[i].id));
|
|
3488
3755
|
}
|
|
3489
3756
|
const seriesLabels = [];
|
|
3490
3757
|
for (const mark of layout.marks) {
|
|
@@ -3494,10 +3761,10 @@ function getEditableElements(spec, layout) {
|
|
|
3494
3761
|
}
|
|
3495
3762
|
seriesLabels.sort();
|
|
3496
3763
|
for (const series of seriesLabels) {
|
|
3497
|
-
refs.push(
|
|
3764
|
+
refs.push(elementRef2.seriesLabel(series));
|
|
3498
3765
|
}
|
|
3499
3766
|
if ("entries" in layout.legend && layout.legend.entries.length > 0) {
|
|
3500
|
-
refs.push(
|
|
3767
|
+
refs.push(elementRef2.legend());
|
|
3501
3768
|
}
|
|
3502
3769
|
return refs;
|
|
3503
3770
|
}
|
|
@@ -6153,6 +6420,39 @@ function createChart(container, spec, options) {
|
|
|
6153
6420
|
selectElement(ref);
|
|
6154
6421
|
}
|
|
6155
6422
|
enterTextEditing();
|
|
6423
|
+
return;
|
|
6424
|
+
}
|
|
6425
|
+
if (!ref && options?.onEdit && currentLayout?.xInvert && currentLayout?.yInvert) {
|
|
6426
|
+
const svgEl = svg;
|
|
6427
|
+
const viewBox = svgEl.viewBox?.baseVal;
|
|
6428
|
+
const svgRect = svgEl.getBoundingClientRect();
|
|
6429
|
+
if (!viewBox || !svgRect.width || !svgRect.height) return;
|
|
6430
|
+
const vbScaleX = viewBox.width / svgRect.width;
|
|
6431
|
+
const vbScaleY = viewBox.height / svgRect.height;
|
|
6432
|
+
const svgX = (mouseEvent.clientX - svgRect.left) * vbScaleX;
|
|
6433
|
+
const svgY = (mouseEvent.clientY - svgRect.top) * vbScaleY;
|
|
6434
|
+
const area = currentLayout.area;
|
|
6435
|
+
if (svgX < area.x || svgX > area.x + area.width) return;
|
|
6436
|
+
if (svgY < area.y || svgY > area.y + area.height) return;
|
|
6437
|
+
const dataX = invertScale(currentLayout.xInvert, svgX);
|
|
6438
|
+
const dataY = invertScale(currentLayout.yInvert, svgY);
|
|
6439
|
+
isTextEditingActive = true;
|
|
6440
|
+
const overlay = createTextEditOverlayAtPosition({
|
|
6441
|
+
container,
|
|
6442
|
+
svg: svgEl,
|
|
6443
|
+
position: { x: svgX, y: svgY },
|
|
6444
|
+
onCommit: (text) => {
|
|
6445
|
+
isTextEditingActive = false;
|
|
6446
|
+
textEditCleanup = null;
|
|
6447
|
+
const annotation = { type: "text", x: dataX, y: dataY, text };
|
|
6448
|
+
options.onEdit({ type: "add", annotation });
|
|
6449
|
+
},
|
|
6450
|
+
onCancel: () => {
|
|
6451
|
+
isTextEditingActive = false;
|
|
6452
|
+
textEditCleanup = null;
|
|
6453
|
+
}
|
|
6454
|
+
});
|
|
6455
|
+
textEditCleanup = overlay.destroy;
|
|
6156
6456
|
}
|
|
6157
6457
|
};
|
|
6158
6458
|
svg.addEventListener("dblclick", handleDblClick);
|
|
@@ -6303,7 +6603,7 @@ function createChart(container, spec, options) {
|
|
|
6303
6603
|
);
|
|
6304
6604
|
}
|
|
6305
6605
|
const editSuppressed = wantsSeriesSearch(currentSpec);
|
|
6306
|
-
if (editSuppressed && !editSuppressWarned && (hasEditingCallbacks(options) || options?.onAnnotationEdit)) {
|
|
6606
|
+
if (editSuppressed && !editSuppressWarned && (options?.editable || hasEditingCallbacks(options) || options?.onAnnotationEdit)) {
|
|
6307
6607
|
editSuppressWarned = true;
|
|
6308
6608
|
console.warn(
|
|
6309
6609
|
"[openchart] seriesSearch and edit mode are mutually exclusive; edit interactions are disabled while seriesSearch is enabled."
|
|
@@ -6328,7 +6628,7 @@ function createChart(container, spec, options) {
|
|
|
6328
6628
|
}
|
|
6329
6629
|
};
|
|
6330
6630
|
const dragAnnotations = "annotations" in currentSpec && Array.isArray(currentSpec.annotations) ? currentSpec.annotations : [];
|
|
6331
|
-
if (!editSuppressed && (options?.onAnnotationEdit || options?.onEdit)) {
|
|
6631
|
+
if (!editSuppressed && (options?.editable ?? Boolean(options?.onAnnotationEdit || options?.onEdit))) {
|
|
6332
6632
|
cleanupAnnotationDrag = wireAnnotationDrag(
|
|
6333
6633
|
svgElement,
|
|
6334
6634
|
dragAnnotations,
|
|
@@ -6337,25 +6637,32 @@ function createChart(container, spec, options) {
|
|
|
6337
6637
|
setDragging
|
|
6338
6638
|
);
|
|
6339
6639
|
}
|
|
6340
|
-
if (!editSuppressed && options?.onEdit) {
|
|
6640
|
+
if (!editSuppressed && (options?.editable ?? Boolean(options?.onEdit))) {
|
|
6341
6641
|
const editCleanups = [];
|
|
6642
|
+
const onEditFn = options?.onEdit ?? (() => {
|
|
6643
|
+
});
|
|
6342
6644
|
editCleanups.push(
|
|
6343
|
-
wireConnectorEndpointDrag(svgElement, dragAnnotations,
|
|
6645
|
+
wireConnectorEndpointDrag(svgElement, dragAnnotations, onEditFn, setDragging)
|
|
6344
6646
|
);
|
|
6345
6647
|
editCleanups.push(
|
|
6346
|
-
wireAnnotationLabelDrag(svgElement, dragAnnotations,
|
|
6648
|
+
wireAnnotationLabelDrag(svgElement, dragAnnotations, onEditFn, setDragging)
|
|
6347
6649
|
);
|
|
6650
|
+
if (currentLayout.xInvert && currentLayout.yInvert) {
|
|
6651
|
+
editCleanups.push(
|
|
6652
|
+
wireAnchorDrag(svgElement, dragAnnotations, currentLayout, onEditFn, setDragging)
|
|
6653
|
+
);
|
|
6654
|
+
}
|
|
6348
6655
|
const editSpec = currentSpec;
|
|
6349
|
-
editCleanups.push(wireChromeDrag(svgElement, editSpec,
|
|
6350
|
-
editCleanups.push(wireLegendDrag(svgElement, editSpec,
|
|
6351
|
-
editCleanups.push(wireSeriesLabelDrag(svgElement, editSpec,
|
|
6656
|
+
editCleanups.push(wireChromeDrag(svgElement, editSpec, onEditFn, setDragging));
|
|
6657
|
+
editCleanups.push(wireLegendDrag(svgElement, editSpec, onEditFn, setDragging));
|
|
6658
|
+
editCleanups.push(wireSeriesLabelDrag(svgElement, editSpec, onEditFn, setDragging));
|
|
6352
6659
|
cleanupEditDrags = () => {
|
|
6353
6660
|
for (const cleanup of editCleanups) {
|
|
6354
6661
|
cleanup();
|
|
6355
6662
|
}
|
|
6356
6663
|
};
|
|
6357
6664
|
}
|
|
6358
|
-
if (!editSuppressed && hasEditingCallbacks(options)) {
|
|
6665
|
+
if (!editSuppressed && (options?.editable ?? hasEditingCallbacks(options))) {
|
|
6359
6666
|
makeEditable(svgElement);
|
|
6360
6667
|
cleanupSelection = wireSelectionEvents();
|
|
6361
6668
|
cleanupKeyboardEdit = wireKeyboardEditEvents();
|
|
@@ -6696,4 +7003,4 @@ export {
|
|
|
6696
7003
|
createYouDrawIt,
|
|
6697
7004
|
createChart
|
|
6698
7005
|
};
|
|
6699
|
-
//# sourceMappingURL=chunk-
|
|
7006
|
+
//# sourceMappingURL=chunk-IZQBT6QM.js.map
|