@oliasoft-open-source/charts-library 5.9.0-beta-2 → 5.9.0-beta-4
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/assets/{Color-6BZIO3FS-BdmyW5fF.js → Color-6BZIO3FS-DhgzADPX.js} +1 -1
- package/dist/assets/{DocsRenderer-LL677BLK-Dmh2MbD-.js → DocsRenderer-LL677BLK-BMxotIzM.js} +4 -4
- package/dist/assets/{WithTooltip-65CFNBJE-B1vNinkY.js → WithTooltip-65CFNBJE-DhFWX5Pm.js} +1 -1
- package/dist/assets/{bar-chart.stories-Ch0i7N0G.js → bar-chart.stories-BqGiinW-.js} +1 -1
- package/dist/assets/{chunk-YKABRMAI-nN4IfCIz.js → chunk-YKABRMAI-Cp0muVto.js} +1 -1
- package/dist/assets/{components-s5a1V3CD.js → components-B21IBaJ_.js} +4 -4
- package/dist/assets/formatter-EIJCOSYU-BrsmllP3.js +1 -0
- package/dist/assets/{get-draggableData-mCkevOrC.js → get-draggableData-CXsYyfeD.js} +1 -1
- package/dist/assets/{iframe-B7buKd6W.js → iframe-HxMpIt73.js} +3 -3
- package/dist/assets/{legend-Cem_14IV.js → legend-Fq0KKkQ6.js} +1 -1
- package/dist/assets/legend-context-DbDqj5Ij.js +10 -0
- package/dist/assets/{line-chart-BDauhYk8.js → line-chart-BAzukCgc.js} +1 -1
- package/dist/assets/{line-chart.stories-T04m8x5t.js → line-chart.stories-Bbt0hbp6.js} +1 -1
- package/dist/assets/{line-chart.test-case.stories-BcA_QlE1.js → line-chart.test-case.stories-DYHAsm6c.js} +174 -126
- package/dist/assets/{pie-chart.stories-D2G6WnUw.js → pie-chart.stories-DWFlVV67.js} +1 -1
- package/dist/assets/{react-18-DQODWq5X.js → react-18-iJHr1sKj.js} +1 -1
- package/dist/assets/{react-CwUuogrH.js → react-BJbrdSXX.js} +1 -1
- package/dist/assets/{react-dom-O1LTTn3X.js → react-dom-DS1BD2oL.js} +1 -1
- package/dist/assets/{scatter-chart.stories-DJ3Z3dsB.js → scatter-chart.stories-D0zx9mjm.js} +1 -1
- package/dist/assets/{syntaxhighlighter-ED5Y7EFY-DYFKPQ-I.js → syntaxhighlighter-ED5Y7EFY-CM81Ddf3.js} +1 -1
- package/dist/assets/{theming-DpsViFyv.js → theming-DBjDcFWf.js} +1 -1
- package/dist/common/helpers/callout-helpers/callout-helpers.d.ts +1 -0
- package/dist/iframe.html +1 -1
- package/dist/index.js +638 -434
- package/dist/index.json +1 -1
- package/dist/line-chart/plugins/callout-plugin/helpers.d.ts +11 -0
- package/dist/project.json +1 -1
- package/dist/src/components/common/helpers/callout-helpers/callout-helpers.d.ts +1 -0
- package/dist/src/components/line-chart/plugins/callout-plugin/helpers.d.ts +11 -0
- package/package.json +1 -1
- package/dist/assets/formatter-EIJCOSYU-Bo0DMj3p.js +0 -1
- package/dist/assets/legend-context-D1oEf-Th.js +0 -9
- package/dist/common/helpers/callout-helpers/callout-overlap-helpers.d.ts +0 -9
- package/dist/src/components/common/helpers/callout-helpers/callout-overlap-helpers.d.ts +0 -9
package/dist/index.js
CHANGED
|
@@ -802,7 +802,7 @@ function _factorize(value) {
|
|
|
802
802
|
function isNonPrimitive(n) {
|
|
803
803
|
return typeof n === "symbol" || typeof n === "object" && n !== null && !(Symbol.toPrimitive in n || "toString" in n || "valueOf" in n);
|
|
804
804
|
}
|
|
805
|
-
function isNumber$
|
|
805
|
+
function isNumber$1(n) {
|
|
806
806
|
return !isNonPrimitive(n) && !isNaN(parseFloat(n)) && isFinite(n);
|
|
807
807
|
}
|
|
808
808
|
function almostWhole(x, epsilon) {
|
|
@@ -4352,7 +4352,7 @@ var LineController = class extends DatasetController {
|
|
|
4352
4352
|
const iAxis = iScale.axis;
|
|
4353
4353
|
const vAxis = vScale.axis;
|
|
4354
4354
|
const { spanGaps, segment } = this.options;
|
|
4355
|
-
const maxGapLength = isNumber$
|
|
4355
|
+
const maxGapLength = isNumber$1(spanGaps) ? spanGaps : Number.POSITIVE_INFINITY;
|
|
4356
4356
|
const directUpdate = this.chart._animationsDisabled || reset || mode === "none";
|
|
4357
4357
|
const end = start + count;
|
|
4358
4358
|
const pointsCount = points.length;
|
|
@@ -4475,7 +4475,7 @@ var ScatterController = class extends DatasetController {
|
|
|
4475
4475
|
const iAxis = iScale.axis;
|
|
4476
4476
|
const vAxis = vScale.axis;
|
|
4477
4477
|
const { spanGaps, segment } = this.options;
|
|
4478
|
-
const maxGapLength = isNumber$
|
|
4478
|
+
const maxGapLength = isNumber$1(spanGaps) ? spanGaps : Number.POSITIVE_INFINITY;
|
|
4479
4479
|
const directUpdate = this.chart._animationsDisabled || reset || mode === "none";
|
|
4480
4480
|
let prevParsed = start > 0 && this.getParsed(start - 1);
|
|
4481
4481
|
for (let i = start; i < start + count; ++i) {
|
|
@@ -5281,7 +5281,7 @@ var Element = class {
|
|
|
5281
5281
|
};
|
|
5282
5282
|
}
|
|
5283
5283
|
hasValue() {
|
|
5284
|
-
return isNumber$
|
|
5284
|
+
return isNumber$1(this.x) && isNumber$1(this.y);
|
|
5285
5285
|
}
|
|
5286
5286
|
getProps(props, final) {
|
|
5287
5287
|
const anims = this.$animations;
|
|
@@ -11390,7 +11390,7 @@ function parse(scale, input) {
|
|
|
11390
11390
|
if (typeof parser === "function") value = parser(value);
|
|
11391
11391
|
if (!isNumberFinite(value)) value = typeof parser === "string" ? adapter.parse(value, parser) : adapter.parse(value);
|
|
11392
11392
|
if (value === null) return null;
|
|
11393
|
-
if (round) value = round === "week" && (isNumber$
|
|
11393
|
+
if (round) value = round === "week" && (isNumber$1(isoWeekday) || isoWeekday === true) ? adapter.startOf(value, "isoWeek", isoWeekday) : adapter.startOf(value, round);
|
|
11394
11394
|
return +value;
|
|
11395
11395
|
}
|
|
11396
11396
|
function determineUnitForAutoTicks(minUnit, min, max, capacity) {
|
|
@@ -11585,7 +11585,7 @@ var TimeScale = class extends Scale {
|
|
|
11585
11585
|
const minor = timeOpts.unit || determineUnitForAutoTicks(timeOpts.minUnit, min, max, this._getLabelCapacity(min));
|
|
11586
11586
|
const stepSize = valueOrDefault(options.ticks.stepSize, 1);
|
|
11587
11587
|
const weekday = minor === "week" ? timeOpts.isoWeekday : false;
|
|
11588
|
-
const hasWeekday = isNumber$
|
|
11588
|
+
const hasWeekday = isNumber$1(weekday) || weekday === true;
|
|
11589
11589
|
const ticks = {};
|
|
11590
11590
|
let first = min;
|
|
11591
11591
|
let time, count;
|
|
@@ -13597,7 +13597,7 @@ function isZoomingOrPanning(chart) {
|
|
|
13597
13597
|
const state = getState(chart);
|
|
13598
13598
|
return state.panning || state.dragging;
|
|
13599
13599
|
}
|
|
13600
|
-
var clamp$
|
|
13600
|
+
var clamp$3 = (x, from, to) => Math.min(to, Math.max(from, x));
|
|
13601
13601
|
function removeHandler(chart, type) {
|
|
13602
13602
|
const { handlers } = getState(chart);
|
|
13603
13603
|
const handler = handlers[type];
|
|
@@ -13683,8 +13683,8 @@ function applyAspectRatio({ begin, end }, aspectRatio) {
|
|
|
13683
13683
|
end.y = begin.y + height;
|
|
13684
13684
|
}
|
|
13685
13685
|
function applyMinMaxProps(rect, chartArea, points, { min, max, prop }) {
|
|
13686
|
-
rect[min] = clamp$
|
|
13687
|
-
rect[max] = clamp$
|
|
13686
|
+
rect[min] = clamp$3(Math.min(points.begin[prop], points.end[prop]), chartArea[min], chartArea[max]);
|
|
13687
|
+
rect[max] = clamp$3(Math.max(points.begin[prop], points.end[prop]), chartArea[min], chartArea[max]);
|
|
13688
13688
|
}
|
|
13689
13689
|
function getRelativePoints(chart, pointEvents, maintainAspectRatio) {
|
|
13690
13690
|
const points = {
|
|
@@ -15073,10 +15073,10 @@ function rotated(point, center, angle) {
|
|
|
15073
15073
|
}
|
|
15074
15074
|
var isOlderPart = (act, req) => req > act || act.length > req.length && act.slice(0, req.length) === req;
|
|
15075
15075
|
var EPSILON = .001;
|
|
15076
|
-
var clamp$
|
|
15076
|
+
var clamp$2 = (x, from, to) => Math.min(to, Math.max(from, x));
|
|
15077
15077
|
var inLimit = (limit, hitSize) => limit.value >= limit.start - hitSize && limit.value <= limit.end + hitSize;
|
|
15078
15078
|
function clampAll(obj, from, to) {
|
|
15079
|
-
for (const key of Object.keys(obj)) obj[key] = clamp$
|
|
15079
|
+
for (const key of Object.keys(obj)) obj[key] = clamp$2(obj[key], from, to);
|
|
15080
15080
|
return obj;
|
|
15081
15081
|
}
|
|
15082
15082
|
function inPointRange(point, center, radius, hitSize) {
|
|
@@ -15117,7 +15117,7 @@ function requireVersion(pkg, min, ver, strict = true) {
|
|
|
15117
15117
|
}
|
|
15118
15118
|
var isPercentString = (s) => typeof s === "string" && s.endsWith("%");
|
|
15119
15119
|
var toPercent = (s) => parseFloat(s) / 100;
|
|
15120
|
-
var toPositivePercent = (s) => clamp$
|
|
15120
|
+
var toPositivePercent = (s) => clamp$2(toPercent(s), 0, 1);
|
|
15121
15121
|
var boxAppering = (x, y) => ({
|
|
15122
15122
|
x,
|
|
15123
15123
|
y,
|
|
@@ -15499,8 +15499,8 @@ function applyLabelContent(ctx, { x, y }, labels, { fonts, colors }) {
|
|
|
15499
15499
|
});
|
|
15500
15500
|
}
|
|
15501
15501
|
function getOpacity(value, elementValue) {
|
|
15502
|
-
const opacity = isNumber$
|
|
15503
|
-
return isNumber$
|
|
15502
|
+
const opacity = isNumber$1(value) ? value : elementValue;
|
|
15503
|
+
return isNumber$1(opacity) ? clamp$2(opacity, 0, 1) : 1;
|
|
15504
15504
|
}
|
|
15505
15505
|
var positions = [
|
|
15506
15506
|
"left",
|
|
@@ -16834,7 +16834,7 @@ function calculateTAdjust(lineSize, sizes, label, space) {
|
|
|
16834
16834
|
const lineH = lineSize.h * space.dy;
|
|
16835
16835
|
const x = lineW > 0 && (labelSize.w / 2 + padding.left - space.x) / lineW;
|
|
16836
16836
|
const y = lineH > 0 && (labelSize.h / 2 + padding.top - space.y) / lineH;
|
|
16837
|
-
return clamp$
|
|
16837
|
+
return clamp$2(Math.max(x, y), 0, .25);
|
|
16838
16838
|
}
|
|
16839
16839
|
function spaceAround(properties, chartArea) {
|
|
16840
16840
|
const { x, x2, y, y2 } = properties;
|
|
@@ -17595,7 +17595,6 @@ const BORDER_COLOR = "rgba(0,0,0,0.1)";
|
|
|
17595
17595
|
const ANNOTATION_DASH = [10, 2];
|
|
17596
17596
|
const DEFAULT_FONT_FAMILY = "\"Roobert\", \"Noto Sans\", sans-serif";
|
|
17597
17597
|
const DEFAULT_COLOR = "hsl(60, 10.34482759%, 12.5%)";
|
|
17598
|
-
const TRANSPARENT = "transparent";
|
|
17599
17598
|
const LOGARITHMIC_STEPS = [
|
|
17600
17599
|
1,
|
|
17601
17600
|
10,
|
|
@@ -19393,329 +19392,505 @@ function addTransparency(input, alpha, out = "rgb") {
|
|
|
19393
19392
|
const c = color.alpha(a);
|
|
19394
19393
|
return out === "hex" ? c.toHex() : c.toRgbString();
|
|
19395
19394
|
}
|
|
19395
|
+
var DEFAULT_FONT_SIZE = 12;
|
|
19396
|
+
var DEFAULT_PADDING = 5;
|
|
19397
|
+
var DEFAULT_MARGIN = 8;
|
|
19398
|
+
var DEFAULT_LABEL_GAP = 8;
|
|
19399
|
+
var DEFAULT_MIN_CONNECTOR_LENGTH = 14;
|
|
19400
|
+
var DEFAULT_HORIZONTAL_OFFSET = 18;
|
|
19401
|
+
var DEFAULT_VERTICAL_OFFSET = -18;
|
|
19402
|
+
var DEFAULT_ROW_GAP = 22;
|
|
19403
|
+
var DEFAULT_ITEM_GAP = 8;
|
|
19404
|
+
var DEFAULT_OVERLAP_ONLY_ITEM_GAP = 14;
|
|
19405
|
+
var DEFAULT_SIDE_SPREAD_STEP = 12;
|
|
19406
|
+
var DEFAULT_SIDE_SPREAD_MAX = 48;
|
|
19407
|
+
var clamp$1 = (value, min, max) => {
|
|
19408
|
+
if (Number.isNaN(value)) return min;
|
|
19409
|
+
if (min > max) return min;
|
|
19410
|
+
return Math.min(Math.max(value, min), max);
|
|
19411
|
+
};
|
|
19412
|
+
var getChartFromCtx$1 = (ctx) => {
|
|
19413
|
+
return ctx?.chart?.chart ?? ctx?.chart;
|
|
19414
|
+
};
|
|
19396
19415
|
var getXScale = (chart, axisId) => {
|
|
19397
19416
|
if (axisId && chart?.scales?.[axisId]) return chart.scales[axisId];
|
|
19398
19417
|
if (chart?.scales?.x) return chart.scales.x;
|
|
19399
|
-
const key = Object.keys(chart?.scales ?? {})?.find((
|
|
19418
|
+
const key = Object.keys(chart?.scales ?? {})?.find((item) => {
|
|
19419
|
+
return item?.toLowerCase()?.includes("x");
|
|
19420
|
+
});
|
|
19400
19421
|
return key ? chart?.scales?.[key] : void 0;
|
|
19401
19422
|
};
|
|
19402
19423
|
var getYScale = (chart, axisId) => {
|
|
19403
19424
|
if (axisId && chart?.scales?.[axisId]) return chart.scales[axisId];
|
|
19404
19425
|
if (chart?.scales?.y) return chart.scales.y;
|
|
19405
|
-
const key = Object.keys(chart?.scales ?? {})?.find((
|
|
19426
|
+
const key = Object.keys(chart?.scales ?? {})?.find((item) => {
|
|
19427
|
+
return item?.toLowerCase()?.includes("y");
|
|
19428
|
+
});
|
|
19406
19429
|
return key ? chart?.scales?.[key] : void 0;
|
|
19407
19430
|
};
|
|
19408
|
-
var
|
|
19409
|
-
|
|
19431
|
+
var resolveFontSize = (font) => {
|
|
19432
|
+
if (typeof font === "string") {
|
|
19433
|
+
const match = font.match(/(\d+(?:\.\d+)?)px/);
|
|
19434
|
+
return match ? Number(match[1]) : DEFAULT_FONT_SIZE;
|
|
19435
|
+
}
|
|
19436
|
+
if (font && typeof font === "object" && "size" in font) {
|
|
19437
|
+
const size = Number(font.size);
|
|
19438
|
+
return Number.isFinite(size) ? size : DEFAULT_FONT_SIZE;
|
|
19439
|
+
}
|
|
19440
|
+
return DEFAULT_FONT_SIZE;
|
|
19410
19441
|
};
|
|
19411
|
-
var
|
|
19412
|
-
|
|
19442
|
+
var resolvePadding = (padding) => {
|
|
19443
|
+
if (typeof padding === "number") return {
|
|
19444
|
+
top: padding,
|
|
19445
|
+
right: padding,
|
|
19446
|
+
bottom: padding,
|
|
19447
|
+
left: padding
|
|
19448
|
+
};
|
|
19449
|
+
if (padding && typeof padding === "object") {
|
|
19450
|
+
const typedPadding = padding;
|
|
19451
|
+
return {
|
|
19452
|
+
top: Number(typedPadding.top ?? DEFAULT_PADDING),
|
|
19453
|
+
right: Number(typedPadding.right ?? DEFAULT_PADDING),
|
|
19454
|
+
bottom: Number(typedPadding.bottom ?? DEFAULT_PADDING),
|
|
19455
|
+
left: Number(typedPadding.left ?? DEFAULT_PADDING)
|
|
19456
|
+
};
|
|
19457
|
+
}
|
|
19458
|
+
return {
|
|
19459
|
+
top: DEFAULT_PADDING,
|
|
19460
|
+
right: DEFAULT_PADDING,
|
|
19461
|
+
bottom: DEFAULT_PADDING,
|
|
19462
|
+
left: DEFAULT_PADDING
|
|
19463
|
+
};
|
|
19464
|
+
};
|
|
19465
|
+
var estimateLabelSize = (chart, annotation, calloutCfg) => {
|
|
19466
|
+
const content = `${annotation?.label ?? ""}`;
|
|
19467
|
+
const fontSize = resolveFontSize(calloutCfg?.font);
|
|
19468
|
+
const padding = resolvePadding(calloutCfg?.padding);
|
|
19469
|
+
const lines = content.split("\n");
|
|
19470
|
+
const fallbackWidth = Math.max(...lines.map((line) => line.length), 0) * fontSize * .62;
|
|
19471
|
+
let measuredWidth = fallbackWidth;
|
|
19472
|
+
if (chart?.ctx) {
|
|
19473
|
+
chart.ctx.save();
|
|
19474
|
+
chart.ctx.font = typeof calloutCfg?.font === "string" ? calloutCfg.font : `${fontSize}px sans-serif`;
|
|
19475
|
+
measuredWidth = Math.max(...lines.map((line) => chart.ctx.measureText(line).width), fallbackWidth);
|
|
19476
|
+
chart.ctx.restore();
|
|
19477
|
+
}
|
|
19478
|
+
return {
|
|
19479
|
+
width: measuredWidth + padding.left + padding.right,
|
|
19480
|
+
height: lines.length * fontSize + padding.top + padding.bottom
|
|
19481
|
+
};
|
|
19482
|
+
};
|
|
19483
|
+
var getAxisId = (annotation, axis) => {
|
|
19484
|
+
const axisScaleId = axis === "x" ? annotation?.xScaleID : annotation?.yScaleID;
|
|
19485
|
+
if (axisScaleId) return axisScaleId;
|
|
19486
|
+
if (annotation?.annotationAxis?.startsWith(axis)) return annotation.annotationAxis;
|
|
19487
|
+
};
|
|
19488
|
+
var getAnchorPixel = (chart, annotation, axis, area) => {
|
|
19489
|
+
const scale = axis === "x" ? getXScale(chart, getAxisId(annotation, "x")) : getYScale(chart, getAxisId(annotation, "y"));
|
|
19490
|
+
const directValue = axis === "x" ? annotation?.xValue : annotation?.yValue;
|
|
19491
|
+
if (typeof directValue === "number" && scale) return scale.getPixelForValue(directValue);
|
|
19492
|
+
const minKey = axis === "x" ? "xMin" : "yMin";
|
|
19493
|
+
const maxKey = axis === "x" ? "xMax" : "yMax";
|
|
19494
|
+
const minValue = annotation?.[minKey];
|
|
19495
|
+
const maxValue = annotation?.[maxKey];
|
|
19496
|
+
if (typeof minValue === "number" && typeof maxValue === "number" && scale) return (scale.getPixelForValue(minValue) + scale.getPixelForValue(maxValue)) / 2;
|
|
19497
|
+
if (typeof minValue === "number" && scale) return scale.getPixelForValue(minValue);
|
|
19498
|
+
if (typeof maxValue === "number" && scale) return scale.getPixelForValue(maxValue);
|
|
19499
|
+
return axis === "x" ? (area.left + area.right) / 2 : (area.top + area.bottom) / 2;
|
|
19500
|
+
};
|
|
19501
|
+
var hasAxisAnchor = (annotation, axis) => {
|
|
19502
|
+
if (axis === "x") return typeof annotation?.xValue === "number" || typeof annotation?.xMin === "number" || typeof annotation?.xMax === "number" || annotation?.type === "box" || annotation?.type === "label" || annotation?.type === "ellipse";
|
|
19503
|
+
return typeof annotation?.yValue === "number" || typeof annotation?.yMin === "number" || typeof annotation?.yMax === "number" || annotation?.type === "box" || annotation?.type === "label" || annotation?.type === "ellipse";
|
|
19504
|
+
};
|
|
19505
|
+
var getBoxHalfWidth = (chart, area, annotation) => {
|
|
19506
|
+
const xScale = getXScale(chart, getAxisId(annotation, "x"));
|
|
19507
|
+
if (xScale && typeof annotation?.xMin === "number" && typeof annotation?.xMax === "number") return Math.abs(xScale.getPixelForValue(annotation.xMax) - xScale.getPixelForValue(annotation.xMin)) / 2;
|
|
19508
|
+
if (annotation?.type === "box") return (area.right - area.left) / 2;
|
|
19509
|
+
return annotation?.radius ?? 0;
|
|
19510
|
+
};
|
|
19511
|
+
var getBoxHalfHeight = (chart, annotation) => {
|
|
19512
|
+
const yScale = getYScale(chart, getAxisId(annotation, "y"));
|
|
19513
|
+
if (yScale && typeof annotation?.yMin === "number" && typeof annotation?.yMax === "number") return Math.abs(yScale.getPixelForValue(annotation.yMax) - yScale.getPixelForValue(annotation.yMin)) / 2;
|
|
19514
|
+
return annotation?.radius ?? 0;
|
|
19515
|
+
};
|
|
19516
|
+
var getReferencePoint$1 = (chart, area, annotation) => {
|
|
19517
|
+
const anchorX = getAnchorPixel(chart, annotation, "x", area);
|
|
19518
|
+
const anchorY = getAnchorPixel(chart, annotation, "y", area);
|
|
19519
|
+
const halfWidth = getBoxHalfWidth(chart, area, annotation);
|
|
19520
|
+
const halfHeight = getBoxHalfHeight(chart, annotation);
|
|
19521
|
+
const labelOffsetPx = annotation?.labelOffsetPx ?? 14;
|
|
19522
|
+
const xAdjust = annotation?.labelConfig?.xAdjust ?? 0;
|
|
19523
|
+
const yAdjust = annotation?.labelConfig?.yAdjust ?? 0;
|
|
19524
|
+
const position = annotation?.labelConfig?.position;
|
|
19525
|
+
let x = anchorX;
|
|
19526
|
+
let y = anchorY;
|
|
19527
|
+
let side = anchorX >= (area.left + area.right) / 2 ? "right" : "left";
|
|
19528
|
+
switch (position) {
|
|
19529
|
+
case Position.Left:
|
|
19530
|
+
x -= Math.max(halfWidth, annotation?.radius ?? 0) + labelOffsetPx;
|
|
19531
|
+
side = "left";
|
|
19532
|
+
break;
|
|
19533
|
+
case Position.Right:
|
|
19534
|
+
x += Math.max(halfWidth, annotation?.radius ?? 0) + labelOffsetPx;
|
|
19535
|
+
side = "right";
|
|
19536
|
+
break;
|
|
19537
|
+
case Position.TopLeft:
|
|
19538
|
+
x -= halfWidth;
|
|
19539
|
+
y -= halfHeight;
|
|
19540
|
+
side = "left";
|
|
19541
|
+
break;
|
|
19542
|
+
case Position.TopRight:
|
|
19543
|
+
x += halfWidth;
|
|
19544
|
+
y -= halfHeight;
|
|
19545
|
+
side = "right";
|
|
19546
|
+
break;
|
|
19547
|
+
case Position.BottomLeft:
|
|
19548
|
+
x -= halfWidth;
|
|
19549
|
+
y += halfHeight;
|
|
19550
|
+
side = "left";
|
|
19551
|
+
break;
|
|
19552
|
+
case Position.BottomRight:
|
|
19553
|
+
x += halfWidth;
|
|
19554
|
+
y += halfHeight;
|
|
19555
|
+
side = "right";
|
|
19556
|
+
break;
|
|
19557
|
+
case Position.Bottom:
|
|
19558
|
+
y += Math.max(halfHeight, annotation?.radius ?? 0) + labelOffsetPx;
|
|
19559
|
+
break;
|
|
19560
|
+
case Position.Top:
|
|
19561
|
+
default:
|
|
19562
|
+
y -= Math.max(halfHeight, annotation?.radius ?? 0) + labelOffsetPx;
|
|
19563
|
+
break;
|
|
19564
|
+
}
|
|
19565
|
+
return {
|
|
19566
|
+
x: x + xAdjust,
|
|
19567
|
+
y: y + yAdjust,
|
|
19568
|
+
side
|
|
19569
|
+
};
|
|
19413
19570
|
};
|
|
19414
|
-
var
|
|
19415
|
-
|
|
19571
|
+
var getOriginalLabelRect = (chart, area, annotation, index) => {
|
|
19572
|
+
const size = estimateLabelSize(chart, annotation, annotation?.labelConfig?.callout ?? {});
|
|
19573
|
+
const reference = getReferencePoint$1(chart, area, annotation);
|
|
19574
|
+
const direction = reference.side === "right" ? 1 : -1;
|
|
19575
|
+
const centerX = reference.x + direction * (size.width / 2);
|
|
19576
|
+
const centerY = reference.y;
|
|
19577
|
+
return {
|
|
19578
|
+
id: `callout-annotation-${index}`,
|
|
19579
|
+
side: reference.side,
|
|
19580
|
+
left: centerX - size.width / 2,
|
|
19581
|
+
right: centerX + size.width / 2,
|
|
19582
|
+
top: centerY - size.height / 2,
|
|
19583
|
+
bottom: centerY + size.height / 2
|
|
19584
|
+
};
|
|
19416
19585
|
};
|
|
19417
|
-
var
|
|
19418
|
-
return
|
|
19586
|
+
var isRectOverlapping = (left, right) => {
|
|
19587
|
+
return !(left.right <= right.left || right.right <= left.left || left.bottom <= right.top || right.bottom <= left.top);
|
|
19419
19588
|
};
|
|
19420
|
-
var
|
|
19421
|
-
|
|
19589
|
+
var getOverlappingCalloutIds = (chart) => {
|
|
19590
|
+
const area = chart?.chartArea;
|
|
19591
|
+
const annotationsData = (chart?.options)?.annotations?.annotationsData ?? [];
|
|
19592
|
+
if (!chart || !area) return /* @__PURE__ */ new Set();
|
|
19593
|
+
const rects = annotationsData.flatMap((annotation, index) => {
|
|
19594
|
+
const calloutCfg = annotation?.labelConfig?.callout ?? {};
|
|
19595
|
+
if (!calloutCfg?.enabled || !calloutCfg?.onlyWhenOverlapping) return [];
|
|
19596
|
+
return [getOriginalLabelRect(chart, area, annotation, index)];
|
|
19597
|
+
});
|
|
19598
|
+
const overlappingIds = /* @__PURE__ */ new Set();
|
|
19599
|
+
rects.forEach((rect, index) => {
|
|
19600
|
+
rects.slice(index + 1).forEach((otherRect) => {
|
|
19601
|
+
if (rect.side !== otherRect.side) return;
|
|
19602
|
+
if (!isRectOverlapping(rect, otherRect)) return;
|
|
19603
|
+
overlappingIds.add(rect.id);
|
|
19604
|
+
overlappingIds.add(otherRect.id);
|
|
19605
|
+
});
|
|
19606
|
+
});
|
|
19607
|
+
return overlappingIds;
|
|
19608
|
+
};
|
|
19609
|
+
var getOccupiedOriginalLabelRects = (chart, area, overlappingIds) => {
|
|
19610
|
+
return ((chart?.options)?.annotations?.annotationsData ?? []).flatMap((annotation, index) => {
|
|
19611
|
+
const calloutCfg = annotation?.labelConfig?.callout ?? {};
|
|
19612
|
+
const id = `callout-annotation-${index}`;
|
|
19613
|
+
if (!calloutCfg?.enabled || !calloutCfg?.onlyWhenOverlapping) return [];
|
|
19614
|
+
if (overlappingIds.has(id)) return [];
|
|
19615
|
+
return [getOriginalLabelRect(chart, area, annotation, index)];
|
|
19616
|
+
});
|
|
19422
19617
|
};
|
|
19423
|
-
|
|
19424
|
-
|
|
19425
|
-
|
|
19426
|
-
if (
|
|
19427
|
-
|
|
19618
|
+
const isCalloutOverlapping = (ctx, refAnnotation, index) => {
|
|
19619
|
+
const chart = getChartFromCtx$1(ctx);
|
|
19620
|
+
if (!(refAnnotation?.labelConfig?.callout ?? {})?.onlyWhenOverlapping) return true;
|
|
19621
|
+
if (!chart?.chartArea) return false;
|
|
19622
|
+
return getOverlappingCalloutIds(chart).has(`callout-annotation-${index}`);
|
|
19623
|
+
};
|
|
19624
|
+
var getPreferredX = (chart, area, annotation, calloutCfg, width) => {
|
|
19625
|
+
const xScale = getXScale(chart, getAxisId(annotation, "x"));
|
|
19626
|
+
const explicitXValue = typeof calloutCfg?.xValue === "number" ? calloutCfg.xValue : void 0;
|
|
19627
|
+
if (typeof explicitXValue === "number" && xScale) return xScale.getPixelForValue(explicitXValue);
|
|
19628
|
+
const margin = calloutCfg?.margin ?? DEFAULT_MARGIN;
|
|
19629
|
+
const halfWidth = width / 2;
|
|
19630
|
+
const reference = getReferencePoint$1(chart, area, annotation);
|
|
19631
|
+
const direction = reference.side === "right" ? 1 : -1;
|
|
19632
|
+
const gap = calloutCfg?.gapPx ?? DEFAULT_LABEL_GAP;
|
|
19633
|
+
const minConnectorLength = calloutCfg?.minConnectorLengthPx ?? DEFAULT_MIN_CONNECTOR_LENGTH;
|
|
19634
|
+
return clamp$1(reference.x + direction * (halfWidth + gap + minConnectorLength), area.left + margin + halfWidth, area.right - margin - halfWidth);
|
|
19635
|
+
};
|
|
19636
|
+
var getPreferredY = (chart, area, annotation, calloutCfg, index) => {
|
|
19637
|
+
const yScale = getYScale(chart, getAxisId(annotation, "y"));
|
|
19638
|
+
const explicitYValue = typeof calloutCfg?.yValue === "number" ? calloutCfg.yValue : void 0;
|
|
19639
|
+
if (typeof explicitYValue === "number" && yScale) return yScale.getPixelForValue(explicitYValue);
|
|
19640
|
+
const reference = getReferencePoint$1(chart, area, annotation);
|
|
19641
|
+
const hasCustomOffset = typeof calloutCfg?.yAdjust === "number";
|
|
19642
|
+
const row = Math.floor(index / 3);
|
|
19643
|
+
const dy = hasCustomOffset ? 0 : DEFAULT_VERTICAL_OFFSET - row * DEFAULT_ROW_GAP;
|
|
19644
|
+
return reference.y + dy;
|
|
19645
|
+
};
|
|
19646
|
+
var getCalloutItems = (chart, area) => {
|
|
19647
|
+
const overlappingIds = getOverlappingCalloutIds(chart);
|
|
19648
|
+
return ((chart?.options)?.annotations?.annotationsData ?? []).flatMap((annotation, index) => {
|
|
19649
|
+
const calloutCfg = annotation?.labelConfig?.callout ?? {};
|
|
19650
|
+
const id = `callout-annotation-${index}`;
|
|
19651
|
+
if (!calloutCfg?.enabled) return [];
|
|
19652
|
+
if (calloutCfg?.onlyWhenOverlapping && !overlappingIds.has(id)) return [];
|
|
19653
|
+
const size = estimateLabelSize(chart, annotation, calloutCfg);
|
|
19654
|
+
const xScale = getXScale(chart, getAxisId(annotation, "x"));
|
|
19655
|
+
const yScale = getYScale(chart, getAxisId(annotation, "y"));
|
|
19656
|
+
const reference = getReferencePoint$1(chart, area, annotation);
|
|
19657
|
+
const preferredX = getPreferredX(chart, area, annotation, calloutCfg, size.width);
|
|
19658
|
+
const preferredY = getPreferredY(chart, area, annotation, calloutCfg, index);
|
|
19659
|
+
const hasStoredX = typeof calloutCfg?.xValue === "number" || !xScale;
|
|
19660
|
+
const hasStoredY = typeof calloutCfg?.yValue === "number" || !yScale;
|
|
19661
|
+
const side = reference.side;
|
|
19662
|
+
const margin = calloutCfg?.margin ?? DEFAULT_MARGIN;
|
|
19663
|
+
return [{
|
|
19664
|
+
annotation,
|
|
19665
|
+
calloutCfg,
|
|
19666
|
+
id,
|
|
19667
|
+
index,
|
|
19668
|
+
preferredX,
|
|
19669
|
+
preferredY,
|
|
19670
|
+
width: size.width,
|
|
19671
|
+
height: size.height,
|
|
19672
|
+
isFixed: hasStoredX && hasStoredY,
|
|
19673
|
+
overlapOnly: Boolean(calloutCfg?.onlyWhenOverlapping),
|
|
19674
|
+
minX: area.left + margin + size.width / 2,
|
|
19675
|
+
maxX: area.right - margin - size.width / 2,
|
|
19676
|
+
minY: area.top + margin + size.height / 2,
|
|
19677
|
+
maxY: area.bottom - margin - size.height / 2,
|
|
19678
|
+
side
|
|
19679
|
+
}];
|
|
19680
|
+
});
|
|
19428
19681
|
};
|
|
19429
|
-
var
|
|
19430
|
-
|
|
19431
|
-
|
|
19432
|
-
|
|
19433
|
-
|
|
19434
|
-
|
|
19435
|
-
|
|
19436
|
-
|
|
19437
|
-
|
|
19438
|
-
return xScale.getValueForPixel((area.left + area.right) / 2);
|
|
19439
|
-
};
|
|
19440
|
-
var resolveAnchorY = (chart, refAnnotation) => {
|
|
19441
|
-
if (isNumber$1(refAnnotation?.yValue)) return refAnnotation.yValue;
|
|
19442
|
-
if (isNumber$1(refAnnotation?.yMin) && isNumber$1(refAnnotation?.yMax)) return (refAnnotation.yMin + refAnnotation.yMax) / 2;
|
|
19443
|
-
const axisValue = getAxisAlignedValue(refAnnotation, "y");
|
|
19444
|
-
if (isNumber$1(axisValue)) return axisValue;
|
|
19445
|
-
if (!chart) return 0;
|
|
19446
|
-
const yScale = resolveYScale(chart, refAnnotation);
|
|
19447
|
-
const area = chart.chartArea;
|
|
19448
|
-
if (!yScale || !area) return 0;
|
|
19449
|
-
return yScale.getValueForPixel((area.top + area.bottom) / 2);
|
|
19682
|
+
var hasVerticalOverlap = (items) => {
|
|
19683
|
+
const sorted = [...items].sort((left, right) => left.preferredY - right.preferredY);
|
|
19684
|
+
for (let index = 1; index < sorted.length; index += 1) {
|
|
19685
|
+
const previous = sorted[index - 1];
|
|
19686
|
+
const current = sorted[index];
|
|
19687
|
+
const gap = previous.height / 2 + current.height / 2 + DEFAULT_ITEM_GAP;
|
|
19688
|
+
if (current.preferredY - previous.preferredY < gap) return true;
|
|
19689
|
+
}
|
|
19690
|
+
return false;
|
|
19450
19691
|
};
|
|
19451
|
-
var
|
|
19452
|
-
|
|
19453
|
-
|
|
19454
|
-
|
|
19455
|
-
|
|
19456
|
-
|
|
19457
|
-
|
|
19458
|
-
|
|
19459
|
-
|
|
19692
|
+
var overlapsOccupiedRect = (centerY, height, occupiedRects) => {
|
|
19693
|
+
const top = centerY - height / 2;
|
|
19694
|
+
const bottom = centerY + height / 2;
|
|
19695
|
+
return occupiedRects.find((rect) => !(bottom <= rect.top || top >= rect.bottom));
|
|
19696
|
+
};
|
|
19697
|
+
var getLayoutGap = (item) => {
|
|
19698
|
+
return item.overlapOnly ? DEFAULT_OVERLAP_ONLY_ITEM_GAP : DEFAULT_ITEM_GAP;
|
|
19699
|
+
};
|
|
19700
|
+
var layoutSide = (items, occupiedRects = []) => {
|
|
19701
|
+
const sorted = [...items].sort((left, right) => left.preferredY - right.preferredY);
|
|
19702
|
+
const result = /* @__PURE__ */ new Map();
|
|
19703
|
+
if (!sorted.filter((item) => !item.isFixed).length) {
|
|
19704
|
+
sorted.forEach((item) => {
|
|
19705
|
+
result.set(item.id, {
|
|
19706
|
+
xValue: item.preferredX,
|
|
19707
|
+
yValue: item.preferredY
|
|
19708
|
+
});
|
|
19709
|
+
});
|
|
19710
|
+
return result;
|
|
19460
19711
|
}
|
|
19712
|
+
const shouldReflow = sorted.some((item) => !item.overlapOnly) || hasVerticalOverlap(sorted);
|
|
19713
|
+
sorted.forEach((item) => {
|
|
19714
|
+
result.set(item.id, {
|
|
19715
|
+
xValue: item.preferredX,
|
|
19716
|
+
yValue: clamp$1(item.preferredY, item.minY, item.maxY)
|
|
19717
|
+
});
|
|
19718
|
+
});
|
|
19719
|
+
if (!shouldReflow) return result;
|
|
19720
|
+
let previousBottom = Number.NEGATIVE_INFINITY;
|
|
19721
|
+
sorted.forEach((item) => {
|
|
19722
|
+
if (item.isFixed) {
|
|
19723
|
+
const yValue = clamp$1(item.preferredY, item.minY, item.maxY);
|
|
19724
|
+
result.set(item.id, {
|
|
19725
|
+
xValue: item.preferredX,
|
|
19726
|
+
yValue
|
|
19727
|
+
});
|
|
19728
|
+
previousBottom = yValue + item.height / 2;
|
|
19729
|
+
return;
|
|
19730
|
+
}
|
|
19731
|
+
const minCenter = Math.max(item.minY, previousBottom + item.height / 2 + getLayoutGap(item));
|
|
19732
|
+
let yValue = clamp$1(item.preferredY, minCenter, item.maxY);
|
|
19733
|
+
let overlappingRect = overlapsOccupiedRect(yValue, item.height, occupiedRects);
|
|
19734
|
+
while (overlappingRect) {
|
|
19735
|
+
yValue = clamp$1(overlappingRect.bottom + getLayoutGap(item) + item.height / 2, item.minY, item.maxY);
|
|
19736
|
+
overlappingRect = overlapsOccupiedRect(yValue, item.height, occupiedRects);
|
|
19737
|
+
}
|
|
19738
|
+
result.set(item.id, {
|
|
19739
|
+
xValue: item.preferredX,
|
|
19740
|
+
yValue
|
|
19741
|
+
});
|
|
19742
|
+
previousBottom = yValue + item.height / 2;
|
|
19743
|
+
});
|
|
19744
|
+
let nextTop = Number.POSITIVE_INFINITY;
|
|
19745
|
+
[...sorted].reverse().forEach((item) => {
|
|
19746
|
+
const current = result.get(item.id);
|
|
19747
|
+
if (!current) return;
|
|
19748
|
+
if (item.isFixed) {
|
|
19749
|
+
nextTop = current.yValue - item.height / 2;
|
|
19750
|
+
return;
|
|
19751
|
+
}
|
|
19752
|
+
const maxCenter = Math.min(item.maxY, nextTop - item.height / 2 - getLayoutGap(item));
|
|
19753
|
+
const yValue = clamp$1(current.yValue, item.minY, maxCenter);
|
|
19754
|
+
result.set(item.id, {
|
|
19755
|
+
...current,
|
|
19756
|
+
yValue
|
|
19757
|
+
});
|
|
19758
|
+
nextTop = yValue - item.height / 2;
|
|
19759
|
+
});
|
|
19760
|
+
const overlapOnlyMovable = sorted.filter((item) => {
|
|
19761
|
+
return item.overlapOnly && !item.isFixed;
|
|
19762
|
+
});
|
|
19763
|
+
if (overlapOnlyMovable.length > 1) {
|
|
19764
|
+
const sortedOverlapOnlyMovable = [...overlapOnlyMovable].sort((left, right) => left.preferredY - right.preferredY);
|
|
19765
|
+
const sharedOuterEdge = sortedOverlapOnlyMovable[0]?.side === "right" ? Math.max(...sortedOverlapOnlyMovable.map((item) => {
|
|
19766
|
+
return (result.get(item.id)?.xValue ?? item.preferredX) + item.width / 2;
|
|
19767
|
+
})) : Math.min(...sortedOverlapOnlyMovable.map((item) => {
|
|
19768
|
+
return (result.get(item.id)?.xValue ?? item.preferredX) - item.width / 2;
|
|
19769
|
+
}));
|
|
19770
|
+
sortedOverlapOnlyMovable.forEach((item, index) => {
|
|
19771
|
+
const current = result.get(item.id);
|
|
19772
|
+
if (!current) return;
|
|
19773
|
+
const spreadOffset = Math.min(index * DEFAULT_SIDE_SPREAD_STEP, DEFAULT_SIDE_SPREAD_MAX);
|
|
19774
|
+
const direction = item.side === "right" ? -1 : 1;
|
|
19775
|
+
const alignedXValue = item.side === "right" ? sharedOuterEdge - item.width / 2 : sharedOuterEdge + item.width / 2;
|
|
19776
|
+
result.set(item.id, {
|
|
19777
|
+
...current,
|
|
19778
|
+
xValue: clamp$1(alignedXValue + direction * spreadOffset, item.minX, item.maxX)
|
|
19779
|
+
});
|
|
19780
|
+
});
|
|
19781
|
+
return result;
|
|
19782
|
+
}
|
|
19783
|
+
sorted.forEach((item, index) => {
|
|
19784
|
+
const current = result.get(item.id);
|
|
19785
|
+
if (!current || item.isFixed) return;
|
|
19786
|
+
const spreadOffset = Math.min(index * DEFAULT_SIDE_SPREAD_STEP, DEFAULT_SIDE_SPREAD_MAX);
|
|
19787
|
+
const direction = item.side === "right" ? -1 : 1;
|
|
19788
|
+
const xValue = clamp$1(current.xValue + direction * spreadOffset, item.minX, item.maxX);
|
|
19789
|
+
result.set(item.id, {
|
|
19790
|
+
...current,
|
|
19791
|
+
xValue
|
|
19792
|
+
});
|
|
19793
|
+
});
|
|
19794
|
+
return result;
|
|
19461
19795
|
};
|
|
19462
|
-
var
|
|
19463
|
-
const
|
|
19464
|
-
if (!
|
|
19465
|
-
|
|
19466
|
-
|
|
19467
|
-
|
|
19796
|
+
var getCalloutLayoutPixels = (chart) => {
|
|
19797
|
+
const area = chart?.chartArea;
|
|
19798
|
+
if (!chart || !area) return /* @__PURE__ */ new Map();
|
|
19799
|
+
const occupiedRects = getOccupiedOriginalLabelRects(chart, area, getOverlappingCalloutIds(chart));
|
|
19800
|
+
const grouped = getCalloutItems(chart, area).map((item) => {
|
|
19801
|
+
const xValue = clamp$1(item.preferredX, item.minX, item.maxX);
|
|
19802
|
+
return {
|
|
19803
|
+
...item,
|
|
19804
|
+
preferredX: xValue
|
|
19805
|
+
};
|
|
19806
|
+
}).reduce((accumulator, item) => {
|
|
19807
|
+
accumulator[item.side].push(item);
|
|
19808
|
+
return accumulator;
|
|
19809
|
+
}, {
|
|
19810
|
+
left: [],
|
|
19811
|
+
right: []
|
|
19812
|
+
});
|
|
19813
|
+
const leftLayout = layoutSide(grouped.left, occupiedRects.filter((rect) => rect.side === "left").map((rect) => ({
|
|
19814
|
+
top: rect.top,
|
|
19815
|
+
bottom: rect.bottom
|
|
19816
|
+
})));
|
|
19817
|
+
const rightLayout = layoutSide(grouped.right, occupiedRects.filter((rect) => rect.side === "right").map((rect) => ({
|
|
19818
|
+
top: rect.top,
|
|
19819
|
+
bottom: rect.bottom
|
|
19820
|
+
})));
|
|
19821
|
+
return new Map([...leftLayout.entries(), ...rightLayout.entries()]);
|
|
19822
|
+
};
|
|
19823
|
+
var getCalloutLayout = (ctx, refAnnotation, index) => {
|
|
19824
|
+
const chart = getChartFromCtx$1(ctx);
|
|
19825
|
+
const xScale = chart ? getXScale(chart, getAxisId(refAnnotation, "x")) : void 0;
|
|
19826
|
+
const yScale = chart ? getYScale(chart, getAxisId(refAnnotation, "y")) : void 0;
|
|
19827
|
+
if (!chart || !yScale || !chart.chartArea) return null;
|
|
19828
|
+
if (!xScale && hasAxisAnchor(refAnnotation, "x")) return null;
|
|
19829
|
+
if (!xScale) return null;
|
|
19830
|
+
const layout = getCalloutLayoutPixels(chart).get(`callout-annotation-${index}`);
|
|
19831
|
+
if (!layout) return null;
|
|
19832
|
+
return {
|
|
19833
|
+
xValue: xScale.getValueForPixel(layout.xValue),
|
|
19834
|
+
yValue: yScale.getValueForPixel(layout.yValue)
|
|
19468
19835
|
};
|
|
19469
|
-
return c.__calloutLayoutState;
|
|
19470
19836
|
};
|
|
19471
19837
|
const resolveCalloutXValue = (ctx, refAnnotation, calloutCfg, index) => {
|
|
19472
|
-
const
|
|
19473
|
-
|
|
19838
|
+
const layout = getCalloutLayout(ctx, refAnnotation, index);
|
|
19839
|
+
if (layout) return layout.xValue;
|
|
19840
|
+
const chart = getChartFromCtx$1(ctx);
|
|
19841
|
+
const xVal = refAnnotation?.xValue;
|
|
19842
|
+
if (typeof xVal !== "number") return 0;
|
|
19474
19843
|
if (!chart) return xVal;
|
|
19475
|
-
const scale =
|
|
19844
|
+
const scale = getXScale(chart, getAxisId(refAnnotation, "x"));
|
|
19476
19845
|
if (!scale) return xVal;
|
|
19477
19846
|
const hasCustomOffset = typeof calloutCfg?.xAdjust === "number";
|
|
19478
|
-
const side =
|
|
19479
|
-
const dx = hasCustomOffset ? calloutCfg?.xAdjust : side *
|
|
19480
|
-
if (!isNumber$1(xVal)) return xVal;
|
|
19847
|
+
const side = index % 2 === 0 ? 1 : -1;
|
|
19848
|
+
const dx = hasCustomOffset ? calloutCfg?.xAdjust : side * DEFAULT_HORIZONTAL_OFFSET;
|
|
19481
19849
|
const basePx = scale.getPixelForValue(xVal);
|
|
19482
|
-
const cxBase = basePx + dx;
|
|
19483
19850
|
const area = chart.chartArea;
|
|
19484
|
-
|
|
19485
|
-
|
|
19486
|
-
const
|
|
19487
|
-
|
|
19488
|
-
|
|
19489
|
-
|
|
19490
|
-
adjDx += area.left + margin + halfW - cx;
|
|
19491
|
-
cx = basePx + adjDx;
|
|
19492
|
-
} else if (cx + halfW > area.right - margin) {
|
|
19493
|
-
adjDx += area.right - margin - halfW - cx;
|
|
19494
|
-
cx = basePx + adjDx;
|
|
19495
|
-
}
|
|
19496
|
-
return scale.getValueForPixel(cx);
|
|
19851
|
+
const element = ctx?.element;
|
|
19852
|
+
if (!area || !element) return scale.getValueForPixel(basePx + dx);
|
|
19853
|
+
const margin = calloutCfg?.margin ?? DEFAULT_MARGIN;
|
|
19854
|
+
const halfWidth = (element?.width ?? 0) / 2;
|
|
19855
|
+
const clampedPx = clamp$1(basePx + dx, area.left + margin + halfWidth, area.right - margin - halfWidth);
|
|
19856
|
+
return scale.getValueForPixel(clampedPx);
|
|
19497
19857
|
};
|
|
19498
19858
|
const resolveCalloutYValue = (ctx, refAnnotation, calloutCfg, index) => {
|
|
19499
|
-
const
|
|
19500
|
-
|
|
19859
|
+
const layout = getCalloutLayout(ctx, refAnnotation, index);
|
|
19860
|
+
if (layout) return layout.yValue;
|
|
19861
|
+
const chart = getChartFromCtx$1(ctx);
|
|
19862
|
+
const yVal = refAnnotation?.yValue;
|
|
19863
|
+
if (typeof yVal !== "number") return 0;
|
|
19501
19864
|
if (!chart) return yVal;
|
|
19502
|
-
const scale =
|
|
19865
|
+
const scale = getYScale(chart, getAxisId(refAnnotation, "y"));
|
|
19503
19866
|
if (!scale) return yVal;
|
|
19504
19867
|
const hasCustomOffset = typeof calloutCfg?.yAdjust === "number";
|
|
19505
|
-
const
|
|
19506
|
-
const
|
|
19507
|
-
const dy = hasCustomOffset ? calloutCfg?.yAdjust : -40 - row * 22;
|
|
19508
|
-
if (!isNumber$1(yVal)) return yVal;
|
|
19868
|
+
const row = Math.floor(index / 2);
|
|
19869
|
+
const dy = hasCustomOffset ? calloutCfg?.yAdjust : DEFAULT_VERTICAL_OFFSET - row * DEFAULT_ROW_GAP;
|
|
19509
19870
|
const basePx = scale.getPixelForValue(yVal);
|
|
19510
|
-
const laneBaseOffset = -24;
|
|
19511
|
-
let cyBase = !hasCustomOffset ? basePx + laneBaseOffset : basePx + dy;
|
|
19512
19871
|
const area = chart.chartArea;
|
|
19513
|
-
|
|
19514
|
-
|
|
19515
|
-
const
|
|
19516
|
-
const
|
|
19517
|
-
|
|
19518
|
-
|
|
19519
|
-
|
|
19520
|
-
|
|
19521
|
-
const state = getCalloutLayoutState(chart, layoutIndex);
|
|
19522
|
-
const cachedCy = state.byIndex[layoutIndex];
|
|
19523
|
-
if (isNumber$1(cachedCy)) cy = cachedCy;
|
|
19524
|
-
else {
|
|
19525
|
-
if (side < 0) {
|
|
19526
|
-
cy = Math.max(cy, state.leftLastPx + minGapPx);
|
|
19527
|
-
state.leftLastPx = cy;
|
|
19528
|
-
} else {
|
|
19529
|
-
cy = Math.max(cy, state.rightLastPx + minGapPx);
|
|
19530
|
-
state.rightLastPx = cy;
|
|
19531
|
-
}
|
|
19532
|
-
state.byIndex[layoutIndex] = cy;
|
|
19533
|
-
}
|
|
19534
|
-
}
|
|
19535
|
-
if (cy - halfH < area.top + margin) {
|
|
19536
|
-
adjDy += area.top + margin + halfH - cy;
|
|
19537
|
-
cy = basePx + adjDy;
|
|
19538
|
-
} else if (cy + halfH > area.bottom - margin) {
|
|
19539
|
-
adjDy += area.bottom - margin - halfH - cy;
|
|
19540
|
-
cy = basePx + adjDy;
|
|
19541
|
-
}
|
|
19542
|
-
return scale.getValueForPixel(cy);
|
|
19543
|
-
};
|
|
19544
|
-
var isInRange = (v, min, max) => v >= min && v <= max;
|
|
19872
|
+
const element = ctx?.element;
|
|
19873
|
+
if (!area || !element) return scale.getValueForPixel(basePx + dy);
|
|
19874
|
+
const margin = calloutCfg?.margin ?? DEFAULT_MARGIN;
|
|
19875
|
+
const halfHeight = (element?.height ?? 0) / 2;
|
|
19876
|
+
const clampedPx = clamp$1(basePx + dy, area.top + margin + halfHeight, area.bottom - margin - halfHeight);
|
|
19877
|
+
return scale.getValueForPixel(clampedPx);
|
|
19878
|
+
};
|
|
19879
|
+
var isInRange = (value, min, max) => value >= min && value <= max;
|
|
19545
19880
|
const isCalloutAnchorInChartArea = (ctx, refAnnotation, margin = 0) => {
|
|
19546
|
-
const chart = ctx
|
|
19881
|
+
const chart = getChartFromCtx$1(ctx);
|
|
19547
19882
|
const area = chart?.chartArea;
|
|
19548
19883
|
if (!chart || !area) return true;
|
|
19549
|
-
const xScale =
|
|
19550
|
-
const yScale =
|
|
19551
|
-
const
|
|
19552
|
-
const
|
|
19553
|
-
if (!xScale || !yScale) return false;
|
|
19554
|
-
if (!
|
|
19555
|
-
const x =
|
|
19556
|
-
const y =
|
|
19884
|
+
const xScale = getXScale(chart, getAxisId(refAnnotation, "x"));
|
|
19885
|
+
const yScale = getYScale(chart, getAxisId(refAnnotation, "y"));
|
|
19886
|
+
const hasXValues = hasAxisAnchor(refAnnotation, "x");
|
|
19887
|
+
const hasYValues = hasAxisAnchor(refAnnotation, "y");
|
|
19888
|
+
if (hasXValues && !xScale || hasYValues && !yScale) return false;
|
|
19889
|
+
if (!hasXValues || !hasYValues) return false;
|
|
19890
|
+
const x = getAnchorPixel(chart, refAnnotation, "x", area);
|
|
19891
|
+
const y = getAnchorPixel(chart, refAnnotation, "y", area);
|
|
19557
19892
|
return isInRange(x, area.left + margin, area.right - margin) && isInRange(y, area.top + margin, area.bottom - margin);
|
|
19558
19893
|
};
|
|
19559
|
-
const getChartFromCtx = (ctx) => {
|
|
19560
|
-
if (!ctx) return;
|
|
19561
|
-
if (ctx.chart?.persistenceId !== void 0) return ctx.chart;
|
|
19562
|
-
if (ctx.chart?.chart?.persistenceId !== void 0) return ctx.chart.chart;
|
|
19563
|
-
if (ctx.$context?.chart?.persistenceId !== void 0) return ctx.$context.chart;
|
|
19564
|
-
return ctx.chart?.chart ?? ctx.chart ?? ctx.$context?.chart;
|
|
19565
|
-
};
|
|
19566
|
-
var isFiniteNumber$1 = (value) => {
|
|
19567
|
-
return typeof value === "number" && Number.isFinite(value);
|
|
19568
|
-
};
|
|
19569
|
-
var parseFontSize = (font) => {
|
|
19570
|
-
if (!font) return 12;
|
|
19571
|
-
const match = font.match(/(\d+(?:\.\d+)?)px/);
|
|
19572
|
-
return match ? Number(match[1]) : 12;
|
|
19573
|
-
};
|
|
19574
|
-
const getScaleByAxis = (chart, axis, ann) => {
|
|
19575
|
-
const preferred = axis === "x" ? [ann?.xScaleID, ann?.annotationAxis] : [ann?.yScaleID, ann?.annotationAxis];
|
|
19576
|
-
for (const key of preferred) if (key && chart?.scales?.[key]) return chart.scales[key];
|
|
19577
|
-
if (axis === "x" && chart?.scales?.x) return chart.scales.x;
|
|
19578
|
-
if (axis === "y" && chart?.scales?.y) return chart.scales.y;
|
|
19579
|
-
const contains = axis === "x" ? "x" : "y";
|
|
19580
|
-
const key = Object.keys(chart?.scales ?? {}).find((k) => k.toLowerCase().includes(contains));
|
|
19581
|
-
return key ? chart.scales[key] : void 0;
|
|
19582
|
-
};
|
|
19583
|
-
const getAnchorValueFromData = (ann, axis) => {
|
|
19584
|
-
const value = axis === "x" ? ann?.xValue : ann?.yValue;
|
|
19585
|
-
if (isFiniteNumber$1(value)) return value;
|
|
19586
|
-
const min = axis === "x" ? ann?.xMin : ann?.yMin;
|
|
19587
|
-
const max = axis === "x" ? ann?.xMax : ann?.yMax;
|
|
19588
|
-
if (isFiniteNumber$1(min) && isFiniteNumber$1(max)) return (min + max) / 2;
|
|
19589
|
-
const annAxis = `${ann?.annotationAxis ?? ""}`.toLowerCase();
|
|
19590
|
-
if (axis === "x" && annAxis.includes("x") && isFiniteNumber$1(ann?.value)) return ann.value;
|
|
19591
|
-
if (axis === "y" && annAxis.includes("y") && isFiniteNumber$1(ann?.value)) return ann.value;
|
|
19592
|
-
};
|
|
19593
|
-
const getLabelSide = (ann) => {
|
|
19594
|
-
const p = `${ann?.labelConfig?.position ?? ""}`.toLowerCase();
|
|
19595
|
-
if (p.includes("left")) return "left";
|
|
19596
|
-
if (p.includes("right")) return "right";
|
|
19597
|
-
return "center";
|
|
19598
|
-
};
|
|
19599
|
-
const buildLikelyOverlapSet = (annotationsData) => {
|
|
19600
|
-
const points = annotationsData.map((ann, idx) => ({
|
|
19601
|
-
idx,
|
|
19602
|
-
side: getLabelSide(ann),
|
|
19603
|
-
x: getAnchorValueFromData(ann, "x"),
|
|
19604
|
-
y: getAnchorValueFromData(ann, "y"),
|
|
19605
|
-
label: ann?.label,
|
|
19606
|
-
visible: ann?.display !== false
|
|
19607
|
-
})).filter((p) => p.visible && !!p.label && isFiniteNumber$1(p.y));
|
|
19608
|
-
if (!points.length) return /* @__PURE__ */ new Set();
|
|
19609
|
-
const ys = points.map((p) => p.y);
|
|
19610
|
-
const rangeY = Math.max(...ys) - Math.min(...ys);
|
|
19611
|
-
const yThreshold = Math.max(120, rangeY * .06);
|
|
19612
|
-
const xThreshold = .35;
|
|
19613
|
-
const overlapSet = /* @__PURE__ */ new Set();
|
|
19614
|
-
for (let i = 0; i < points.length; i += 1) for (let j = i + 1; j < points.length; j += 1) {
|
|
19615
|
-
const a = points[i];
|
|
19616
|
-
const b = points[j];
|
|
19617
|
-
if (!(a.side === "center" || b.side === "center" || a.side === b.side)) continue;
|
|
19618
|
-
const xClose = !isFiniteNumber$1(a.x) || !isFiniteNumber$1(b.x) ? true : Math.abs(a.x - b.x) <= xThreshold;
|
|
19619
|
-
if (Math.abs(a.y - b.y) <= yThreshold && xClose) {
|
|
19620
|
-
overlapSet.add(a.idx);
|
|
19621
|
-
overlapSet.add(b.idx);
|
|
19622
|
-
}
|
|
19623
|
-
}
|
|
19624
|
-
return overlapSet;
|
|
19625
|
-
};
|
|
19626
|
-
const buildOverlapCalloutYMap = (annotationsData, overlapSet) => {
|
|
19627
|
-
const points = annotationsData.map((ann, idx) => ({
|
|
19628
|
-
idx,
|
|
19629
|
-
side: getLabelSide(ann),
|
|
19630
|
-
y: getAnchorValueFromData(ann, "y")
|
|
19631
|
-
})).filter((p) => overlapSet.has(p.idx) && typeof p.y === "number");
|
|
19632
|
-
const yMap = /* @__PURE__ */ new Map();
|
|
19633
|
-
if (!points.length) return yMap;
|
|
19634
|
-
const ys = points.map((p) => p.y);
|
|
19635
|
-
const minY = Math.min(...ys);
|
|
19636
|
-
const maxY = Math.max(...ys);
|
|
19637
|
-
const yRange = Math.max(maxY - minY, 1);
|
|
19638
|
-
const minGap = Math.max(130, yRange * .03);
|
|
19639
|
-
const minBound = minY - minGap * .5;
|
|
19640
|
-
const maxBound = maxY + minGap * .5;
|
|
19641
|
-
const groups = {
|
|
19642
|
-
left: [],
|
|
19643
|
-
right: []
|
|
19644
|
-
};
|
|
19645
|
-
points.forEach((p) => {
|
|
19646
|
-
if (p.side === "right") {
|
|
19647
|
-
groups.right.push({
|
|
19648
|
-
idx: p.idx,
|
|
19649
|
-
y: p.y
|
|
19650
|
-
});
|
|
19651
|
-
return;
|
|
19652
|
-
}
|
|
19653
|
-
groups.left.push({
|
|
19654
|
-
idx: p.idx,
|
|
19655
|
-
y: p.y
|
|
19656
|
-
});
|
|
19657
|
-
});
|
|
19658
|
-
Object.keys(groups).forEach((side) => {
|
|
19659
|
-
const group = groups[side].sort((a, b) => a.y - b.y);
|
|
19660
|
-
if (!group.length) return;
|
|
19661
|
-
const packed = group.map((item, i) => {
|
|
19662
|
-
return i === 0 ? item.y : Math.max(item.y, group[i - 1].y + minGap);
|
|
19663
|
-
});
|
|
19664
|
-
const overflowBottom = packed[packed.length - 1] - maxBound;
|
|
19665
|
-
if (overflowBottom > 0) for (let i = 0; i < packed.length; i += 1) packed[i] -= overflowBottom;
|
|
19666
|
-
const overflowTop = minBound - packed[0];
|
|
19667
|
-
if (overflowTop > 0) for (let i = 0; i < packed.length; i += 1) packed[i] += overflowTop;
|
|
19668
|
-
group.forEach((item, i) => {
|
|
19669
|
-
yMap.set(item.idx, packed[i]);
|
|
19670
|
-
});
|
|
19671
|
-
});
|
|
19672
|
-
return yMap;
|
|
19673
|
-
};
|
|
19674
|
-
const getOverlapCalloutXAdjust = (ann) => {
|
|
19675
|
-
const side = getLabelSide(ann);
|
|
19676
|
-
if (side === "right") return -56;
|
|
19677
|
-
if (side === "left") return 56;
|
|
19678
|
-
return 0;
|
|
19679
|
-
};
|
|
19680
|
-
const hasOverlappingLabel = (ctx, refAnnotation, index, annotationsData) => {
|
|
19681
|
-
const chart = getChartFromCtx(ctx);
|
|
19682
|
-
if (!chart) return false;
|
|
19683
|
-
const yScale = getScaleByAxis(chart, "y", refAnnotation);
|
|
19684
|
-
const xScale = getScaleByAxis(chart, "x", refAnnotation);
|
|
19685
|
-
if (!yScale || !xScale) return false;
|
|
19686
|
-
const area = chart.chartArea;
|
|
19687
|
-
if (!area) return false;
|
|
19688
|
-
const yVal = getAnchorValueFromData(refAnnotation, "y");
|
|
19689
|
-
const xVal = getAnchorValueFromData(refAnnotation, "x");
|
|
19690
|
-
if (!isFiniteNumber$1(yVal)) return false;
|
|
19691
|
-
const currentYPx = yScale.getPixelForValue(yVal);
|
|
19692
|
-
const currentXPx = isFiniteNumber$1(xVal) ? xScale.getPixelForValue(xVal) : void 0;
|
|
19693
|
-
const currentSide = getLabelSide(refAnnotation);
|
|
19694
|
-
const currentFont = refAnnotation?.labelConfig?.font;
|
|
19695
|
-
const currentHeight = parseFontSize(currentFont) + 6;
|
|
19696
|
-
const nearTop = currentYPx - currentHeight <= area.top + 2;
|
|
19697
|
-
const nearBottom = currentYPx + currentHeight >= area.bottom - 2;
|
|
19698
|
-
if (nearTop || nearBottom) return true;
|
|
19699
|
-
for (let i = 0; i < annotationsData.length; i += 1) {
|
|
19700
|
-
if (i === index) continue;
|
|
19701
|
-
const ann = annotationsData[i];
|
|
19702
|
-
if (!ann?.label || ann?.display === false) continue;
|
|
19703
|
-
const otherYScale = getScaleByAxis(chart, "y", ann);
|
|
19704
|
-
const otherXScale = getScaleByAxis(chart, "x", ann);
|
|
19705
|
-
if (!otherYScale || !otherXScale) continue;
|
|
19706
|
-
const otherYVal = getAnchorValueFromData(ann, "y");
|
|
19707
|
-
const otherXVal = getAnchorValueFromData(ann, "x");
|
|
19708
|
-
if (!isFiniteNumber$1(otherYVal)) continue;
|
|
19709
|
-
const otherYPx = otherYScale.getPixelForValue(otherYVal);
|
|
19710
|
-
const otherXPx = isFiniteNumber$1(otherXVal) ? otherXScale.getPixelForValue(otherXVal) : void 0;
|
|
19711
|
-
const otherSide = getLabelSide(ann);
|
|
19712
|
-
const otherFont = ann?.labelConfig?.font;
|
|
19713
|
-
const yThreshold = (currentHeight + (parseFontSize(otherFont) + 6)) / 2;
|
|
19714
|
-
const xClose = !isFiniteNumber$1(currentXPx) || !isFiniteNumber$1(otherXPx) ? true : Math.abs(currentXPx - otherXPx) < 160;
|
|
19715
|
-
if ((currentSide === "center" || otherSide === "center" || currentSide === otherSide) && Math.abs(currentYPx - otherYPx) < yThreshold && xClose) return true;
|
|
19716
|
-
}
|
|
19717
|
-
return false;
|
|
19718
|
-
};
|
|
19719
19894
|
var STORAGE_PREFIX = "chart_annotations";
|
|
19720
19895
|
var getStorageKey = (persistenceId) => {
|
|
19721
19896
|
return `${STORAGE_PREFIX}:${persistenceId}`;
|
|
@@ -19750,9 +19925,12 @@ const getAnnotationPosition = (persistenceId, annotationId) => {
|
|
|
19750
19925
|
if (!persistenceId) return void 0;
|
|
19751
19926
|
return readStorage(persistenceId)[annotationId];
|
|
19752
19927
|
};
|
|
19753
|
-
|
|
19754
|
-
|
|
19755
|
-
|
|
19928
|
+
const getChartFromCtx = (ctx) => {
|
|
19929
|
+
if (!ctx) return;
|
|
19930
|
+
if (ctx.chart?.persistenceId !== void 0) return ctx.chart;
|
|
19931
|
+
if (ctx.chart?.chart?.persistenceId !== void 0) return ctx.chart.chart;
|
|
19932
|
+
if (ctx.$context?.chart?.persistenceId !== void 0) return ctx.$context.chart;
|
|
19933
|
+
return ctx.chart?.chart ?? ctx.chart ?? ctx.$context?.chart;
|
|
19756
19934
|
};
|
|
19757
19935
|
var mapToBoxLikeLabelPosition = (position) => {
|
|
19758
19936
|
switch (position) {
|
|
@@ -19792,8 +19970,7 @@ var mapToBoxLikeLabelPosition = (position) => {
|
|
|
19792
19970
|
}
|
|
19793
19971
|
};
|
|
19794
19972
|
var handleLineEnter = (element, chart, annotation) => {
|
|
19795
|
-
|
|
19796
|
-
chart.canvas.style.cursor = canDrag ? CursorStyle.Pointer : CursorStyle.Initial;
|
|
19973
|
+
chart.canvas.style.cursor = CursorStyle.Pointer;
|
|
19797
19974
|
if (element.options.scaleID?.includes(AxisType.X)) {
|
|
19798
19975
|
if (element.options.label) element.options.label.xAdjust = chart.chartArea.left;
|
|
19799
19976
|
}
|
|
@@ -19802,7 +19979,7 @@ var handleLineEnter = (element, chart, annotation) => {
|
|
|
19802
19979
|
element.label.options.display = true;
|
|
19803
19980
|
element.options.label.enabled = true;
|
|
19804
19981
|
}
|
|
19805
|
-
if (
|
|
19982
|
+
if (annotation?.enableDrag) {
|
|
19806
19983
|
chart.hoveredAnnotationId = element.options.id || null;
|
|
19807
19984
|
chart.update("none");
|
|
19808
19985
|
}
|
|
@@ -19816,14 +19993,14 @@ var handleLineLeave = (element, chart, annotation) => {
|
|
|
19816
19993
|
element.label.options.display = false;
|
|
19817
19994
|
element.options.label.enabled = false;
|
|
19818
19995
|
}
|
|
19819
|
-
if (
|
|
19996
|
+
if (annotation?.enableDrag) {
|
|
19820
19997
|
chart.hoveredAnnotationId = null;
|
|
19821
19998
|
chart.update("none");
|
|
19822
19999
|
}
|
|
19823
20000
|
chart.draw();
|
|
19824
20001
|
};
|
|
19825
20002
|
var handleBoxEnter = (element, chart, annotation) => {
|
|
19826
|
-
if (
|
|
20003
|
+
if (annotation?.enableDrag) {
|
|
19827
20004
|
chart.hoveredAnnotationId = element.options.id || null;
|
|
19828
20005
|
chart.update("none");
|
|
19829
20006
|
element.options.borderWidth = BORDER_WIDTH.HOVERED;
|
|
@@ -19832,7 +20009,7 @@ var handleBoxEnter = (element, chart, annotation) => {
|
|
|
19832
20009
|
chart.draw();
|
|
19833
20010
|
};
|
|
19834
20011
|
var handleBoxLeave = (element, chart, annotation) => {
|
|
19835
|
-
if (
|
|
20012
|
+
if (annotation?.enableDrag) {
|
|
19836
20013
|
chart.hoveredAnnotationId = null;
|
|
19837
20014
|
element.options.borderWidth = BORDER_WIDTH.INITIAL;
|
|
19838
20015
|
chart.canvas.style.cursor = CursorStyle.Initial;
|
|
@@ -19841,7 +20018,7 @@ var handleBoxLeave = (element, chart, annotation) => {
|
|
|
19841
20018
|
chart.draw();
|
|
19842
20019
|
};
|
|
19843
20020
|
var handlePointEnter = (element, chart, annotation) => {
|
|
19844
|
-
if (
|
|
20021
|
+
if (annotation?.enableDrag) {
|
|
19845
20022
|
chart.hoveredAnnotationId = element.options.id || null;
|
|
19846
20023
|
chart.update("none");
|
|
19847
20024
|
element.options.borderWidth = BORDER_WIDTH.POINT_HOVERED;
|
|
@@ -19850,7 +20027,7 @@ var handlePointEnter = (element, chart, annotation) => {
|
|
|
19850
20027
|
chart.draw();
|
|
19851
20028
|
};
|
|
19852
20029
|
var handlePointLeave = (element, chart, annotation) => {
|
|
19853
|
-
if (
|
|
20030
|
+
if (annotation?.enableDrag) {
|
|
19854
20031
|
chart.hoveredAnnotationId = null;
|
|
19855
20032
|
element.options.borderWidth = BORDER_WIDTH.INITIAL;
|
|
19856
20033
|
chart.canvas.style.cursor = CursorStyle.Initial;
|
|
@@ -19859,7 +20036,7 @@ var handlePointLeave = (element, chart, annotation) => {
|
|
|
19859
20036
|
chart.draw();
|
|
19860
20037
|
};
|
|
19861
20038
|
var handleLabelEnter = (element, chart, annotation) => {
|
|
19862
|
-
if (
|
|
20039
|
+
if (annotation?.enableDrag) {
|
|
19863
20040
|
chart.hoveredAnnotationId = element.options.id || null;
|
|
19864
20041
|
chart.update("none");
|
|
19865
20042
|
chart.canvas.style.cursor = CursorStyle.Pointer;
|
|
@@ -19867,7 +20044,7 @@ var handleLabelEnter = (element, chart, annotation) => {
|
|
|
19867
20044
|
chart.draw();
|
|
19868
20045
|
};
|
|
19869
20046
|
var handleLabelLeave = (_element, chart, annotation) => {
|
|
19870
|
-
if (
|
|
20047
|
+
if (annotation?.enableDrag) {
|
|
19871
20048
|
chart.hoveredAnnotationId = null;
|
|
19872
20049
|
chart.canvas.style.cursor = CursorStyle.Initial;
|
|
19873
20050
|
chart.update("none");
|
|
@@ -19998,41 +20175,32 @@ const generateAnn = (ann, index) => {
|
|
|
19998
20175
|
displayDragCoordinates: ann?.displayDragCoordinates ?? true
|
|
19999
20176
|
};
|
|
20000
20177
|
};
|
|
20001
|
-
var getCalloutAnnotation = (refAnnotation, index
|
|
20178
|
+
var getCalloutAnnotation = (refAnnotation, index) => {
|
|
20002
20179
|
const generated = generateAnn(refAnnotation, index);
|
|
20003
20180
|
if (!generated) return [];
|
|
20004
20181
|
const { label, ...baseRest } = generated;
|
|
20005
20182
|
const baseId = baseRest.id;
|
|
20006
20183
|
const calloutCfg = refAnnotation?.labelConfig?.callout ?? {};
|
|
20007
|
-
const onlyWhenOverlapping = calloutCfg?.onlyWhenOverlapping ?? false;
|
|
20008
|
-
const hideBoxGlyphInOverlapMode = onlyWhenOverlapping && refAnnotation?.type === AnnotationType$1.BOX;
|
|
20009
|
-
const staticShouldShowCallout = likelyOverlapSet.has(index);
|
|
20010
|
-
const shouldShowCallout = (ctx) => {
|
|
20011
|
-
return !onlyWhenOverlapping || staticShouldShowCallout || calloutCfg?.useRuntimeOverlap === true && hasOverlappingLabel(ctx, refAnnotation, index, annotationsData);
|
|
20012
|
-
};
|
|
20013
|
-
const canDisplayCallout = (ctx) => {
|
|
20014
|
-
return (refAnnotation.display ?? true) && shouldShowCallout(ctx) && isCalloutAnchorInChartArea(ctx, refAnnotation, calloutCfg.margin ?? 0);
|
|
20015
|
-
};
|
|
20016
20184
|
const baseAnnotation = {
|
|
20017
20185
|
...baseRest,
|
|
20018
|
-
backgroundColor: hideBoxGlyphInOverlapMode ? TRANSPARENT : baseRest?.backgroundColor,
|
|
20019
|
-
borderWidth: hideBoxGlyphInOverlapMode ? BORDER_WIDTH.ZERO : baseRest?.borderWidth,
|
|
20020
|
-
borderColor: hideBoxGlyphInOverlapMode ? TRANSPARENT : baseRest?.borderColor,
|
|
20021
20186
|
label: {
|
|
20022
20187
|
...label,
|
|
20023
|
-
display: (ctx) =>
|
|
20188
|
+
display: (ctx) => {
|
|
20189
|
+
if (!(refAnnotation.display ?? true)) return false;
|
|
20190
|
+
if (!calloutCfg?.onlyWhenOverlapping) return false;
|
|
20191
|
+
return !isCalloutOverlapping(ctx, refAnnotation, index);
|
|
20192
|
+
}
|
|
20024
20193
|
}
|
|
20025
20194
|
};
|
|
20026
20195
|
const color = calloutCfg?.color ?? "hsl(60, 10.34482759%, 12.5%)";
|
|
20027
20196
|
const font = calloutCfg?.font ?? `12px "Roobert", "Noto Sans", sans-serif`;
|
|
20028
20197
|
const borderColor = calloutCfg?.borderColor ?? "transparent";
|
|
20029
|
-
const
|
|
20198
|
+
const strokeStyle = calloutCfg.strokeStyle ?? "rgba(120, 126, 138, 0.9)";
|
|
20030
20199
|
const lineWidth = typeof calloutCfg.lineWidth === "number" ? calloutCfg.lineWidth : 1;
|
|
20031
|
-
const startOffset = typeof calloutCfg.startOffset === "number" ? calloutCfg.startOffset :
|
|
20032
|
-
const endOffset = typeof calloutCfg.endOffset === "number" ? calloutCfg.endOffset :
|
|
20200
|
+
const startOffset = typeof calloutCfg.startOffset === "number" ? calloutCfg.startOffset : 2;
|
|
20201
|
+
const endOffset = typeof calloutCfg.endOffset === "number" ? calloutCfg.endOffset : .5;
|
|
20033
20202
|
const calloutId = `callout-annotation-${index}`;
|
|
20034
|
-
|
|
20035
|
-
const calloutAnnotation = {
|
|
20203
|
+
return [baseAnnotation, {
|
|
20036
20204
|
id: calloutId,
|
|
20037
20205
|
type: "label",
|
|
20038
20206
|
backgroundColor: "transparent",
|
|
@@ -20040,47 +20208,38 @@ var getCalloutAnnotation = (refAnnotation, index, annotationsData, likelyOverlap
|
|
|
20040
20208
|
color: (ctx) => {
|
|
20041
20209
|
const chart = getChartFromCtx(ctx);
|
|
20042
20210
|
if (!chart) return color;
|
|
20043
|
-
|
|
20044
|
-
if (!isCalloutDraggable || !isDragModeEnabled) return color;
|
|
20045
|
-
if (chart.hoveredAnnotationId === calloutId) return "#DB5B00";
|
|
20211
|
+
if (Boolean(chart?.options?.plugins?.annotationDraggerPlugin?.enabled) && chart.hoveredAnnotationId === calloutId) return "#DB5B00";
|
|
20046
20212
|
return color;
|
|
20047
20213
|
},
|
|
20048
20214
|
font,
|
|
20049
20215
|
borderColor,
|
|
20050
20216
|
borderWidth: BORDER_WIDTH.INITIAL,
|
|
20051
20217
|
padding: 5,
|
|
20052
|
-
display:
|
|
20218
|
+
display: (ctx) => {
|
|
20219
|
+
if (!(refAnnotation.display ?? true)) return false;
|
|
20220
|
+
if (!isCalloutAnchorInChartArea(ctx, refAnnotation, calloutCfg.margin ?? 0)) return false;
|
|
20221
|
+
return isCalloutOverlapping(ctx, refAnnotation, index);
|
|
20222
|
+
},
|
|
20053
20223
|
xValue: (ctx) => {
|
|
20054
20224
|
const persistenceId = getChartFromCtx(ctx)?.options?.persistenceId;
|
|
20055
20225
|
const stored = getAnnotationPosition(persistenceId, `callout-annotation-${index}`);
|
|
20056
20226
|
const explicit = typeof calloutCfg.xValue === "number" ? calloutCfg.xValue : void 0;
|
|
20057
|
-
|
|
20058
|
-
return stored?.x ?? explicit ?? resolveCalloutXValue(ctx, refAnnotation, {
|
|
20059
|
-
...calloutCfg,
|
|
20060
|
-
xAdjust: overlapCalloutAdjust,
|
|
20061
|
-
layoutIndex
|
|
20062
|
-
}, index);
|
|
20227
|
+
return stored?.x ?? explicit ?? resolveCalloutXValue(ctx, refAnnotation, calloutCfg, index);
|
|
20063
20228
|
},
|
|
20064
20229
|
yValue: (ctx) => {
|
|
20065
20230
|
const persistenceId = getChartFromCtx(ctx)?.options?.persistenceId;
|
|
20066
20231
|
const stored = getAnnotationPosition(persistenceId, `callout-annotation-${index}`);
|
|
20067
20232
|
const explicit = typeof calloutCfg.yValue === "number" ? calloutCfg.yValue : void 0;
|
|
20068
|
-
|
|
20069
|
-
const overlapCalloutYAdjust = onlyWhenOverlapping && !calloutCfg?.yAdjust ? 0 : calloutCfg?.yAdjust;
|
|
20070
|
-
return stored?.y ?? explicit ?? overlapPackedY ?? resolveCalloutYValue(ctx, refAnnotation, {
|
|
20071
|
-
...calloutCfg,
|
|
20072
|
-
yAdjust: overlapCalloutYAdjust,
|
|
20073
|
-
layoutIndex
|
|
20074
|
-
}, index);
|
|
20233
|
+
return stored?.y ?? explicit ?? resolveCalloutYValue(ctx, refAnnotation, calloutCfg, index);
|
|
20075
20234
|
},
|
|
20076
20235
|
resizable: false,
|
|
20077
20236
|
displayDragCoordinates: false,
|
|
20078
|
-
enableDrag:
|
|
20237
|
+
enableDrag: true,
|
|
20079
20238
|
enter: ({ element }, { chart }) => {
|
|
20080
|
-
return handleLabelEnter(element, chart, { enableDrag:
|
|
20239
|
+
return handleLabelEnter(element, chart, { enableDrag: Boolean(chart?.options?.plugins?.annotationDraggerPlugin?.enabled) });
|
|
20081
20240
|
},
|
|
20082
20241
|
leave: ({ element }, { chart }) => {
|
|
20083
|
-
return handleLabelLeave(element, chart, { enableDrag:
|
|
20242
|
+
return handleLabelLeave(element, chart, { enableDrag: Boolean(chart?.options?.plugins?.annotationDraggerPlugin?.enabled) });
|
|
20084
20243
|
},
|
|
20085
20244
|
onDragStart: calloutCfg?.onDragStart ? () => (coords) => {
|
|
20086
20245
|
return calloutCfg.onDragStart?.(coords, refAnnotation);
|
|
@@ -20094,58 +20253,22 @@ var getCalloutAnnotation = (refAnnotation, index, annotationsData, likelyOverlap
|
|
|
20094
20253
|
calloutConnector: {
|
|
20095
20254
|
enabled: true,
|
|
20096
20255
|
fromId: baseId,
|
|
20097
|
-
strokeStyle
|
|
20256
|
+
strokeStyle,
|
|
20098
20257
|
lineWidth,
|
|
20099
20258
|
startOffset,
|
|
20100
|
-
endOffset
|
|
20259
|
+
endOffset,
|
|
20260
|
+
anchor: {
|
|
20261
|
+
position: refAnnotation?.labelConfig?.position,
|
|
20262
|
+
xAdjust: refAnnotation?.labelConfig?.xAdjust,
|
|
20263
|
+
yAdjust: refAnnotation?.labelConfig?.yAdjust,
|
|
20264
|
+
labelOffsetPx: refAnnotation?.labelOffsetPx
|
|
20265
|
+
}
|
|
20101
20266
|
}
|
|
20102
|
-
};
|
|
20103
|
-
const anchorX = getAnchorValueFromData(refAnnotation, "x");
|
|
20104
|
-
const anchorY = getAnchorValueFromData(refAnnotation, "y");
|
|
20105
|
-
const originTickAnnotation = typeof anchorX === "number" && typeof anchorY === "number" ? {
|
|
20106
|
-
id: `callout-origin-tick-${index}`,
|
|
20107
|
-
type: "line",
|
|
20108
|
-
xMin: anchorX,
|
|
20109
|
-
xMax: (ctx) => {
|
|
20110
|
-
const chart = getChartFromCtx(ctx);
|
|
20111
|
-
const xScale = chart ? getScaleByAxis(chart, "x", refAnnotation) : null;
|
|
20112
|
-
if (!xScale) return anchorX;
|
|
20113
|
-
const px = xScale.getPixelForValue(anchorX);
|
|
20114
|
-
const tickLength = calloutCfg?.originTickLengthPx ?? 8;
|
|
20115
|
-
return xScale.getValueForPixel(px + tickLength);
|
|
20116
|
-
},
|
|
20117
|
-
yMin: anchorY,
|
|
20118
|
-
yMax: anchorY,
|
|
20119
|
-
borderColor: calloutCfg?.originTickColor ?? connectorStrokeStyle,
|
|
20120
|
-
borderWidth: calloutCfg?.originTickWidth ?? 1,
|
|
20121
|
-
borderDash: [],
|
|
20122
|
-
adjustScaleRange: false,
|
|
20123
|
-
label: {
|
|
20124
|
-
display: false,
|
|
20125
|
-
content: ""
|
|
20126
|
-
},
|
|
20127
|
-
display: (ctx) => onlyWhenOverlapping && (refAnnotation.display ?? true) && shouldShowCallout(ctx),
|
|
20128
|
-
resizable: false,
|
|
20129
|
-
displayDragCoordinates: false,
|
|
20130
|
-
enableDrag: false
|
|
20131
|
-
} : null;
|
|
20132
|
-
if (!onlyWhenOverlapping) return [baseAnnotation, calloutAnnotation];
|
|
20133
|
-
return originTickAnnotation ? [
|
|
20134
|
-
baseAnnotation,
|
|
20135
|
-
originTickAnnotation,
|
|
20136
|
-
calloutAnnotation
|
|
20137
|
-
] : [baseAnnotation, calloutAnnotation];
|
|
20267
|
+
}];
|
|
20138
20268
|
};
|
|
20139
20269
|
var generateAnnotations = (annotationsData) => {
|
|
20140
|
-
const likelyOverlapSet = buildLikelyOverlapSet(annotationsData);
|
|
20141
|
-
const overlapCalloutYMap = buildOverlapCalloutYMap(annotationsData, likelyOverlapSet);
|
|
20142
|
-
let calloutLayoutIndex = 0;
|
|
20143
20270
|
return annotationsData?.flatMap((ann, idx) => {
|
|
20144
|
-
if (ann?.labelConfig?.callout?.enabled ?? false)
|
|
20145
|
-
const annotation = getCalloutAnnotation(ann, idx, annotationsData, likelyOverlapSet, overlapCalloutYMap, calloutLayoutIndex);
|
|
20146
|
-
calloutLayoutIndex += 1;
|
|
20147
|
-
return annotation;
|
|
20148
|
-
}
|
|
20271
|
+
if (ann?.labelConfig?.callout?.enabled ?? false) return getCalloutAnnotation(ann, idx);
|
|
20149
20272
|
return generateAnn(ann, idx);
|
|
20150
20273
|
});
|
|
20151
20274
|
};
|
|
@@ -20844,52 +20967,126 @@ const annotationDraggerPlugin = {
|
|
|
20844
20967
|
}
|
|
20845
20968
|
}
|
|
20846
20969
|
};
|
|
20847
|
-
var
|
|
20848
|
-
|
|
20849
|
-
|
|
20850
|
-
return
|
|
20970
|
+
var getRectangleEdgePoint = (el, targetX, targetY, offset) => {
|
|
20971
|
+
const width = el?.width ?? 0;
|
|
20972
|
+
const height = el?.height ?? 0;
|
|
20973
|
+
if (width <= 0 || height <= 0) return {
|
|
20974
|
+
x: el.centerX,
|
|
20975
|
+
y: el.centerY
|
|
20976
|
+
};
|
|
20977
|
+
const halfWidth = width / 2;
|
|
20978
|
+
const halfHeight = height / 2;
|
|
20979
|
+
const dx = targetX - el.centerX;
|
|
20980
|
+
const dy = targetY - el.centerY;
|
|
20981
|
+
const length = Math.sqrt(dx * dx + dy * dy) || 1;
|
|
20982
|
+
const ux = dx / length;
|
|
20983
|
+
const uy = dy / length;
|
|
20984
|
+
const tx = Math.abs(ux) > 1e-6 ? halfWidth / Math.abs(ux) : Number.POSITIVE_INFINITY;
|
|
20985
|
+
const ty = Math.abs(uy) > 1e-6 ? halfHeight / Math.abs(uy) : Number.POSITIVE_INFINITY;
|
|
20986
|
+
const distance = Math.min(tx, ty) + offset;
|
|
20987
|
+
return {
|
|
20988
|
+
x: el.centerX + ux * distance,
|
|
20989
|
+
y: el.centerY + uy * distance
|
|
20990
|
+
};
|
|
20991
|
+
};
|
|
20992
|
+
var getLabelEdgePoint = (labelEl, startX, endOffset) => {
|
|
20993
|
+
const width = labelEl?.width ?? 0;
|
|
20994
|
+
const height = labelEl?.height ?? 0;
|
|
20995
|
+
if (width <= 0 || height <= 0) return {
|
|
20996
|
+
x: labelEl.centerX,
|
|
20997
|
+
y: labelEl.centerY
|
|
20998
|
+
};
|
|
20999
|
+
const halfWidth = width / 2;
|
|
21000
|
+
const direction = startX <= labelEl.centerX ? -1 : 1;
|
|
21001
|
+
return {
|
|
21002
|
+
x: labelEl.centerX + direction * (halfWidth + endOffset),
|
|
21003
|
+
y: labelEl.centerY
|
|
21004
|
+
};
|
|
21005
|
+
};
|
|
21006
|
+
var getReferencePoint = (fromEl, connector) => {
|
|
21007
|
+
const { anchor } = connector;
|
|
21008
|
+
if (!anchor) return {
|
|
21009
|
+
x: fromEl.centerX,
|
|
21010
|
+
y: fromEl.centerY
|
|
21011
|
+
};
|
|
21012
|
+
const width = fromEl?.width ?? 0;
|
|
21013
|
+
const height = fromEl?.height ?? 0;
|
|
21014
|
+
const radius = fromEl?.options?.radius ?? 0;
|
|
21015
|
+
const halfWidth = width / 2;
|
|
21016
|
+
const halfHeight = height / 2;
|
|
21017
|
+
const labelOffset = anchor?.labelOffsetPx ?? 14;
|
|
21018
|
+
const xAdjust = anchor?.xAdjust ?? 0;
|
|
21019
|
+
const yAdjust = anchor?.yAdjust ?? 0;
|
|
21020
|
+
const position = anchor?.position ?? "top";
|
|
21021
|
+
let x = fromEl.centerX;
|
|
21022
|
+
let y = fromEl.centerY;
|
|
21023
|
+
switch (position) {
|
|
21024
|
+
case "left":
|
|
21025
|
+
x -= Math.max(halfWidth, radius) + labelOffset;
|
|
21026
|
+
break;
|
|
21027
|
+
case "right":
|
|
21028
|
+
x += Math.max(halfWidth, radius) + labelOffset;
|
|
21029
|
+
break;
|
|
21030
|
+
case "bottom":
|
|
21031
|
+
y += Math.max(halfHeight, radius) + labelOffset;
|
|
21032
|
+
break;
|
|
21033
|
+
case "top-left":
|
|
21034
|
+
x -= halfWidth;
|
|
21035
|
+
y -= halfHeight;
|
|
21036
|
+
break;
|
|
21037
|
+
case "top-right":
|
|
21038
|
+
x += halfWidth;
|
|
21039
|
+
y -= halfHeight;
|
|
21040
|
+
break;
|
|
21041
|
+
case "bottom-left":
|
|
21042
|
+
x -= halfWidth;
|
|
21043
|
+
y += halfHeight;
|
|
21044
|
+
break;
|
|
21045
|
+
case "bottom-right":
|
|
21046
|
+
x += halfWidth;
|
|
21047
|
+
y += halfHeight;
|
|
21048
|
+
break;
|
|
21049
|
+
default:
|
|
21050
|
+
y -= Math.max(halfHeight, radius) + labelOffset;
|
|
21051
|
+
break;
|
|
21052
|
+
}
|
|
21053
|
+
return {
|
|
21054
|
+
x: x + xAdjust,
|
|
21055
|
+
y: y + yAdjust
|
|
21056
|
+
};
|
|
20851
21057
|
};
|
|
20852
21058
|
const computeConnectorPoints = (fromEl, labelEl, connector) => {
|
|
20853
21059
|
const x1c = fromEl?.centerX;
|
|
20854
21060
|
const y1c = fromEl?.centerY;
|
|
20855
21061
|
const cx = labelEl?.centerX;
|
|
20856
21062
|
const cy = labelEl?.centerY;
|
|
20857
|
-
const labelWidth = labelEl?.width ?? 0;
|
|
20858
|
-
const labelHeight = labelEl?.height ?? 0;
|
|
20859
21063
|
const ux = cx - x1c;
|
|
20860
21064
|
const uy = cy - y1c;
|
|
20861
21065
|
const len = Math.sqrt(ux * ux + uy * uy) || 1;
|
|
20862
21066
|
const dx = ux / len;
|
|
20863
21067
|
const dy = uy / len;
|
|
20864
|
-
const
|
|
20865
|
-
const
|
|
20866
|
-
const
|
|
20867
|
-
|
|
20868
|
-
|
|
20869
|
-
|
|
20870
|
-
|
|
20871
|
-
|
|
20872
|
-
|
|
20873
|
-
|
|
20874
|
-
|
|
20875
|
-
|
|
20876
|
-
|
|
20877
|
-
const vyn = vy / vlen;
|
|
20878
|
-
const tx = Math.abs(vxn) > 1e-6 ? hw / Math.abs(vxn) : Number.POSITIVE_INFINITY;
|
|
20879
|
-
const ty = Math.abs(vyn) > 1e-6 ? hh / Math.abs(vyn) : Number.POSITIVE_INFINITY;
|
|
20880
|
-
const total = Math.min(tx, ty) + (connector.endOffset ?? 1);
|
|
20881
|
-
endX = cx + vxn * total;
|
|
20882
|
-
endY = cy + vyn * total;
|
|
20883
|
-
} else {
|
|
20884
|
-
const endOffset = connector.endOffset ?? 1;
|
|
20885
|
-
endX = cx - dx * endOffset;
|
|
20886
|
-
endY = cy - dy * endOffset;
|
|
20887
|
-
}
|
|
21068
|
+
const startOffset = connector?.startOffset ?? 6;
|
|
21069
|
+
const isPointAnchor = typeof fromEl?.options?.radius === "number";
|
|
21070
|
+
const referencePoint = connector?.anchor && !isPointAnchor ? getReferencePoint(fromEl, connector) : isPointAnchor ? {
|
|
21071
|
+
x: x1c,
|
|
21072
|
+
y: y1c
|
|
21073
|
+
} : getRectangleEdgePoint(fromEl, cx, cy, startOffset);
|
|
21074
|
+
const endOffset = connector?.endOffset ?? 1;
|
|
21075
|
+
const end = typeof labelEl?.width === "number" && typeof labelEl?.height === "number" ? getLabelEdgePoint(labelEl, referencePoint.x, endOffset) : {
|
|
21076
|
+
x: cx - dx * endOffset,
|
|
21077
|
+
y: cy - dy * endOffset
|
|
21078
|
+
};
|
|
21079
|
+
const tickHalf = isPointAnchor ? 0 : (connector?.anchor?.tickSize ?? 8) / 2;
|
|
21080
|
+
const lineDirection = end.x >= referencePoint.x ? 1 : -1;
|
|
20888
21081
|
return {
|
|
20889
|
-
startX,
|
|
20890
|
-
startY,
|
|
20891
|
-
endX,
|
|
20892
|
-
endY
|
|
21082
|
+
startX: referencePoint.x + lineDirection * tickHalf,
|
|
21083
|
+
startY: referencePoint.y,
|
|
21084
|
+
endX: end.x,
|
|
21085
|
+
endY: end.y,
|
|
21086
|
+
tickStartX: referencePoint.x - tickHalf,
|
|
21087
|
+
tickStartY: referencePoint.y,
|
|
21088
|
+
tickEndX: referencePoint.x + tickHalf,
|
|
21089
|
+
tickEndY: referencePoint.y
|
|
20893
21090
|
};
|
|
20894
21091
|
};
|
|
20895
21092
|
const calloutConnectorPlugin = {
|
|
@@ -20910,17 +21107,24 @@ const calloutConnectorPlugin = {
|
|
|
20910
21107
|
const fromEl = elements.find((el) => el.options && el.options.id === connector.fromId);
|
|
20911
21108
|
if (!labelEl || !fromEl) return;
|
|
20912
21109
|
if (labelEl.options?.display === false) return;
|
|
20913
|
-
const { startX, startY, endX, endY } = computeConnectorPoints(fromEl, labelEl, connector) ?? {};
|
|
21110
|
+
const { startX, startY, endX, endY, tickStartX, tickStartY, tickEndX, tickEndY } = computeConnectorPoints(fromEl, labelEl, connector) ?? {};
|
|
20914
21111
|
const ctx = chart?.ctx;
|
|
21112
|
+
const strokeStyle = connector?.strokeStyle ?? "rgba(120, 126, 138, 0.9)";
|
|
20915
21113
|
ctx?.save?.();
|
|
20916
21114
|
ctx?.beginPath?.();
|
|
20917
21115
|
ctx?.moveTo?.(startX, startY);
|
|
20918
21116
|
ctx?.lineTo?.(endX, endY);
|
|
20919
21117
|
ctx.lineWidth = connector?.lineWidth ?? 1;
|
|
20920
|
-
ctx.strokeStyle =
|
|
21118
|
+
ctx.strokeStyle = strokeStyle;
|
|
20921
21119
|
if (connector?.lineDash && connector?.lineDash?.length) ctx?.setLineDash?.(connector.lineDash);
|
|
20922
21120
|
ctx.lineCap = "round";
|
|
20923
21121
|
ctx?.stroke?.();
|
|
21122
|
+
ctx?.beginPath?.();
|
|
21123
|
+
ctx?.moveTo?.(tickStartX, tickStartY);
|
|
21124
|
+
ctx?.lineTo?.(tickEndX, tickEndY);
|
|
21125
|
+
ctx.lineWidth = Math.max(connector?.lineWidth ?? 1, 1);
|
|
21126
|
+
ctx.strokeStyle = strokeStyle;
|
|
21127
|
+
ctx?.stroke?.();
|
|
20924
21128
|
ctx?.restore?.();
|
|
20925
21129
|
});
|
|
20926
21130
|
}
|