@opendata-ai/openchart-vanilla 7.0.4 → 7.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.js +46 -12
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +3 -3
- package/src/renderers/axes.ts +18 -2
- package/src/renderers/marks.ts +54 -10
- package/src/svg-renderer.ts +12 -2
package/dist/index.js
CHANGED
|
@@ -5259,6 +5259,7 @@ function renderAnnotations(parent, layout) {
|
|
|
5259
5259
|
|
|
5260
5260
|
// src/renderers/axes.ts
|
|
5261
5261
|
import {
|
|
5262
|
+
AXIS_TITLE_OFFSET_COMPACT,
|
|
5262
5263
|
estimateTextWidth as estimateTextWidth2,
|
|
5263
5264
|
getAxisTitleOffset,
|
|
5264
5265
|
TICK_LABEL_OFFSET
|
|
@@ -5473,7 +5474,17 @@ function renderAxis(parent, axis, orientation, layout) {
|
|
|
5473
5474
|
transform: `rotate(90, ${titleX}, ${area.y + area.height / 2})`
|
|
5474
5475
|
});
|
|
5475
5476
|
} else {
|
|
5476
|
-
const
|
|
5477
|
+
const AXIS_TITLE_GAP = 8;
|
|
5478
|
+
const maxTickLabelWidth = axis.ticks.reduce((max, t) => {
|
|
5479
|
+
const w = estimateTextWidth2(
|
|
5480
|
+
t.label,
|
|
5481
|
+
axis.tickLabelStyle.fontSize,
|
|
5482
|
+
axis.tickLabelStyle.fontWeight ?? 400
|
|
5483
|
+
);
|
|
5484
|
+
return Math.max(max, w);
|
|
5485
|
+
}, 0);
|
|
5486
|
+
const dynamicOffset = TICK_LABEL_OFFSET + maxTickLabelWidth + AXIS_TITLE_GAP;
|
|
5487
|
+
const titleOffset = Math.max(dynamicOffset, AXIS_TITLE_OFFSET_COMPACT);
|
|
5477
5488
|
setAttrs2(axisLabel, {
|
|
5478
5489
|
x: area.x - titleOffset,
|
|
5479
5490
|
y: area.y + area.height / 2,
|
|
@@ -6027,14 +6038,6 @@ function renderRectMark(mark, index2) {
|
|
|
6027
6038
|
shapeEl.setAttribute("stroke-width", String(mark.strokeWidth));
|
|
6028
6039
|
}
|
|
6029
6040
|
g.appendChild(shapeEl);
|
|
6030
|
-
if (mark.label?.visible) {
|
|
6031
|
-
const label = createSVGElement2("text");
|
|
6032
|
-
label.setAttribute("class", "oc-mark-label");
|
|
6033
|
-
setAttrs2(label, { x: mark.label.x, y: mark.label.y });
|
|
6034
|
-
applyTextStyle(label, mark.label.style);
|
|
6035
|
-
label.textContent = mark.label.text;
|
|
6036
|
-
g.appendChild(label);
|
|
6037
|
-
}
|
|
6038
6041
|
return g;
|
|
6039
6042
|
}
|
|
6040
6043
|
function renderArcMark(mark, index2) {
|
|
@@ -6208,6 +6211,32 @@ function renderMarks(parent, layout) {
|
|
|
6208
6211
|
g.appendChild(el);
|
|
6209
6212
|
}
|
|
6210
6213
|
parent.appendChild(g);
|
|
6214
|
+
let labelsGroup;
|
|
6215
|
+
for (let i = 0; i < layout.marks.length; i++) {
|
|
6216
|
+
const mark = layout.marks[i];
|
|
6217
|
+
if (mark.type !== "rect") continue;
|
|
6218
|
+
const rect = mark;
|
|
6219
|
+
if (!rect.label?.visible) continue;
|
|
6220
|
+
if (!labelsGroup) {
|
|
6221
|
+
labelsGroup = createSVGElement2("g");
|
|
6222
|
+
labelsGroup.setAttribute("class", "oc-mark-labels");
|
|
6223
|
+
}
|
|
6224
|
+
const label = createSVGElement2("text");
|
|
6225
|
+
label.setAttribute("class", "oc-mark-label");
|
|
6226
|
+
setAttrs2(label, { x: rect.label.x, y: rect.label.y });
|
|
6227
|
+
applyTextStyle(label, rect.label.style);
|
|
6228
|
+
label.textContent = rect.label.text;
|
|
6229
|
+
if (currentAnimation?.enabled) {
|
|
6230
|
+
const idx = rect.animationIndex ?? i;
|
|
6231
|
+
label.setAttribute("data-animation-index", String(idx));
|
|
6232
|
+
label.style.setProperty(
|
|
6233
|
+
"--oc-mark-index",
|
|
6234
|
+
String(idx)
|
|
6235
|
+
);
|
|
6236
|
+
}
|
|
6237
|
+
labelsGroup.appendChild(label);
|
|
6238
|
+
}
|
|
6239
|
+
return labelsGroup;
|
|
6211
6240
|
}
|
|
6212
6241
|
|
|
6213
6242
|
// src/renderers/metrics.ts
|
|
@@ -6263,7 +6292,9 @@ function renderChartSVG(layout, container, opts) {
|
|
|
6263
6292
|
// overflow is "hidden", which clips this phantom extent. Setting
|
|
6264
6293
|
// overflow:visible prevents the clipping. Chart marks are already
|
|
6265
6294
|
// constrained by a clipPath, so nothing bleeds out.
|
|
6266
|
-
overflow: "visible"
|
|
6295
|
+
overflow: "visible",
|
|
6296
|
+
// Hint browsers to enable sub-pixel font hinting and kerning for chart text.
|
|
6297
|
+
"text-rendering": "optimizeLegibility"
|
|
6267
6298
|
});
|
|
6268
6299
|
svg.style.height = `${height}px`;
|
|
6269
6300
|
svg.setAttribute("role", layout.a11y.role);
|
|
@@ -6331,7 +6362,7 @@ function renderChartSVG(layout, container, opts) {
|
|
|
6331
6362
|
renderAxes(svg, layout);
|
|
6332
6363
|
const clippedGroup = createSVGElement2("g");
|
|
6333
6364
|
clippedGroup.setAttribute("clip-path", `url(#${clipId})`);
|
|
6334
|
-
renderMarks(clippedGroup, layout);
|
|
6365
|
+
const markLabelsOverlay = renderMarks(clippedGroup, layout);
|
|
6335
6366
|
const hasLineOrAreaWithDataPoints = layout.marks.some(
|
|
6336
6367
|
(m2) => (m2.type === "line" || m2.type === "area") && m2.dataPoints && m2.dataPoints.length > 0
|
|
6337
6368
|
);
|
|
@@ -6376,6 +6407,9 @@ function renderChartSVG(layout, container, opts) {
|
|
|
6376
6407
|
clippedGroup.appendChild(dotsGroup);
|
|
6377
6408
|
}
|
|
6378
6409
|
svg.appendChild(clippedGroup);
|
|
6410
|
+
if (markLabelsOverlay) {
|
|
6411
|
+
svg.appendChild(markLabelsOverlay);
|
|
6412
|
+
}
|
|
6379
6413
|
renderAnnotations(svg, layout);
|
|
6380
6414
|
renderEndpointLabels(svg, layout);
|
|
6381
6415
|
const epEntries = layout.endpointLabels?.entries ?? [];
|
|
@@ -6383,7 +6417,7 @@ function renderChartSVG(layout, container, opts) {
|
|
|
6383
6417
|
const pointEls = clippedGroup.querySelectorAll("circle.oc-mark-point");
|
|
6384
6418
|
for (const entry of epEntries) {
|
|
6385
6419
|
if (!entry.marker) continue;
|
|
6386
|
-
const mx = entry.marker.
|
|
6420
|
+
const mx = entry.marker.dataX;
|
|
6387
6421
|
const my = entry.marker.y;
|
|
6388
6422
|
for (const el of pointEls) {
|
|
6389
6423
|
const cx = Number(el.getAttribute("cx"));
|