@oliasoft-open-source/charts-library 5.10.0-beta-3 → 5.10.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/index.d.ts +66 -97
- package/dist/index.js +848 -876
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14364,7 +14364,7 @@ function isZoomingOrPanning(chart) {
|
|
|
14364
14364
|
const state = getState(chart);
|
|
14365
14365
|
return state.panning || state.dragging;
|
|
14366
14366
|
}
|
|
14367
|
-
var clamp$
|
|
14367
|
+
var clamp$3 = (x, from, to) => Math.min(to, Math.max(from, x));
|
|
14368
14368
|
function removeHandler(chart, type) {
|
|
14369
14369
|
const { handlers } = getState(chart);
|
|
14370
14370
|
const handler = handlers[type];
|
|
@@ -14450,8 +14450,8 @@ function applyAspectRatio({ begin, end }, aspectRatio) {
|
|
|
14450
14450
|
end.y = begin.y + height;
|
|
14451
14451
|
}
|
|
14452
14452
|
function applyMinMaxProps(rect, chartArea, points, { min, max, prop }) {
|
|
14453
|
-
rect[min] = clamp$
|
|
14454
|
-
rect[max] = clamp$
|
|
14453
|
+
rect[min] = clamp$3(Math.min(points.begin[prop], points.end[prop]), chartArea[min], chartArea[max]);
|
|
14454
|
+
rect[max] = clamp$3(Math.max(points.begin[prop], points.end[prop]), chartArea[min], chartArea[max]);
|
|
14455
14455
|
}
|
|
14456
14456
|
function getRelativePoints(chart, pointEvents, maintainAspectRatio) {
|
|
14457
14457
|
const points = {
|
|
@@ -15889,7 +15889,7 @@ var isOlderPart = (act, req) => req > act || act.length > req.length && act.slic
|
|
|
15889
15889
|
* @typedef { import('../../types/element').AnnotationElement } AnnotationElement
|
|
15890
15890
|
*/
|
|
15891
15891
|
var EPSILON = .001;
|
|
15892
|
-
var clamp$
|
|
15892
|
+
var clamp$2 = (x, from, to) => Math.min(to, Math.max(from, x));
|
|
15893
15893
|
/**
|
|
15894
15894
|
* @param {{value: number, start: number, end: number}} limit
|
|
15895
15895
|
* @param {number} hitSize
|
|
@@ -15903,7 +15903,7 @@ var inLimit = (limit, hitSize) => limit.value >= limit.start - hitSize && limit.
|
|
|
15903
15903
|
* @returns {Object}
|
|
15904
15904
|
*/
|
|
15905
15905
|
function clampAll(obj, from, to) {
|
|
15906
|
-
for (const key of Object.keys(obj)) obj[key] = clamp$
|
|
15906
|
+
for (const key of Object.keys(obj)) obj[key] = clamp$2(obj[key], from, to);
|
|
15907
15907
|
return obj;
|
|
15908
15908
|
}
|
|
15909
15909
|
/**
|
|
@@ -15977,7 +15977,7 @@ function requireVersion(pkg, min, ver, strict = true) {
|
|
|
15977
15977
|
}
|
|
15978
15978
|
var isPercentString = (s) => typeof s === "string" && s.endsWith("%");
|
|
15979
15979
|
var toPercent = (s) => parseFloat(s) / 100;
|
|
15980
|
-
var toPositivePercent = (s) => clamp$
|
|
15980
|
+
var toPositivePercent = (s) => clamp$2(toPercent(s), 0, 1);
|
|
15981
15981
|
var boxAppering = (x, y) => ({
|
|
15982
15982
|
x,
|
|
15983
15983
|
y,
|
|
@@ -16472,7 +16472,7 @@ function applyLabelContent(ctx, { x, y }, labels, { fonts, colors }) {
|
|
|
16472
16472
|
}
|
|
16473
16473
|
function getOpacity(value, elementValue) {
|
|
16474
16474
|
const opacity = isNumber$1(value) ? value : elementValue;
|
|
16475
|
-
return isNumber$1(opacity) ? clamp$
|
|
16475
|
+
return isNumber$1(opacity) ? clamp$2(opacity, 0, 1) : 1;
|
|
16476
16476
|
}
|
|
16477
16477
|
var positions = [
|
|
16478
16478
|
"left",
|
|
@@ -17912,7 +17912,7 @@ function calculateTAdjust(lineSize, sizes, label, space) {
|
|
|
17912
17912
|
const lineH = lineSize.h * space.dy;
|
|
17913
17913
|
const x = lineW > 0 && (labelSize.w / 2 + padding.left - space.x) / lineW;
|
|
17914
17914
|
const y = lineH > 0 && (labelSize.h / 2 + padding.top - space.y) / lineH;
|
|
17915
|
-
return clamp$
|
|
17915
|
+
return clamp$2(Math.max(x, y), 0, .25);
|
|
17916
17916
|
}
|
|
17917
17917
|
function spaceAround(properties, chartArea) {
|
|
17918
17918
|
const { x, x2, y, y2 } = properties;
|
|
@@ -18839,7 +18839,7 @@ var BORDER_WIDTH = {
|
|
|
18839
18839
|
var BORDER_COLOR = "rgba(0,0,0,0.1)";
|
|
18840
18840
|
var ANNOTATION_DASH = [10, 2];
|
|
18841
18841
|
var DEFAULT_FONT_FAMILY = "\"Roobert\", \"Noto Sans\", sans-serif";
|
|
18842
|
-
var DEFAULT_COLOR
|
|
18842
|
+
var DEFAULT_COLOR = "hsl(60, 10.34482759%, 12.5%)";
|
|
18843
18843
|
var LOGARITHMIC_STEPS = [
|
|
18844
18844
|
1,
|
|
18845
18845
|
10,
|
|
@@ -19024,7 +19024,7 @@ var getChartFileName = (axes) => {
|
|
|
19024
19024
|
var setDefaultTheme = () => {
|
|
19025
19025
|
defaults$1.font.size = 12;
|
|
19026
19026
|
defaults$1.font.family = DEFAULT_FONT_FAMILY;
|
|
19027
|
-
defaults$1.color = DEFAULT_COLOR
|
|
19027
|
+
defaults$1.color = DEFAULT_COLOR;
|
|
19028
19028
|
defaults$1.borderColor = BORDER_COLOR;
|
|
19029
19029
|
};
|
|
19030
19030
|
var isEmptyString = (value) => value === "";
|
|
@@ -20190,33 +20190,20 @@ var defaultAnnotations$2 = (annotations) => ({
|
|
|
20190
20190
|
controlAnnotation: annotationConfig?.controlAnnotation ?? false,
|
|
20191
20191
|
enableDragAnnotation: annotationConfig?.enableDragAnnotation ?? false,
|
|
20192
20192
|
enableCalloutAnnotation: annotationConfig?.enableCalloutAnnotation ?? false,
|
|
20193
|
-
|
|
20194
|
-
enabled: annotationConfig?.
|
|
20195
|
-
itemGapPx: annotationConfig?.
|
|
20196
|
-
edgePaddingPx: annotationConfig?.
|
|
20197
|
-
|
|
20198
|
-
|
|
20199
|
-
|
|
20200
|
-
|
|
20201
|
-
|
|
20202
|
-
|
|
20203
|
-
|
|
20204
|
-
|
|
20205
|
-
|
|
20206
|
-
|
|
20207
|
-
yValue: annotationConfig?.lineMarkersAnnotation?.yValue,
|
|
20208
|
-
yStartValue: annotationConfig?.lineMarkersAnnotation?.yStartValue,
|
|
20209
|
-
yEndValue: annotationConfig?.lineMarkersAnnotation?.yEndValue,
|
|
20210
|
-
xStartValue: annotationConfig?.lineMarkersAnnotation?.xStartValue,
|
|
20211
|
-
xEndValue: annotationConfig?.lineMarkersAnnotation?.xEndValue,
|
|
20212
|
-
lengthPx: annotationConfig?.lineMarkersAnnotation?.lengthPx,
|
|
20213
|
-
color: annotationConfig?.lineMarkersAnnotation?.color ?? "rgba(20,20,20,0.9)",
|
|
20214
|
-
opacity: annotationConfig?.lineMarkersAnnotation?.opacity ?? 1,
|
|
20215
|
-
lineWidth: annotationConfig?.lineMarkersAnnotation?.lineWidth ?? 1,
|
|
20216
|
-
lineDash: annotationConfig?.lineMarkersAnnotation?.lineDash ?? [],
|
|
20217
|
-
startTick: annotationConfig?.lineMarkersAnnotation?.startTick,
|
|
20218
|
-
endTick: annotationConfig?.lineMarkersAnnotation?.endTick,
|
|
20219
|
-
items: annotationConfig?.lineMarkersAnnotation?.items ?? []
|
|
20193
|
+
verticalMarkersAnnotation: {
|
|
20194
|
+
enabled: annotationConfig?.verticalMarkersAnnotation?.enabled ?? false,
|
|
20195
|
+
itemGapPx: annotationConfig?.verticalMarkersAnnotation?.itemGapPx ?? 4,
|
|
20196
|
+
edgePaddingPx: annotationConfig?.verticalMarkersAnnotation?.edgePaddingPx ?? 8,
|
|
20197
|
+
stickToEdge: annotationConfig?.verticalMarkersAnnotation?.stickToEdge ?? true,
|
|
20198
|
+
stickSide: annotationConfig?.verticalMarkersAnnotation?.stickSide ?? "right",
|
|
20199
|
+
reverse: annotationConfig?.verticalMarkersAnnotation?.reverse ?? false,
|
|
20200
|
+
xValue: annotationConfig?.verticalMarkersAnnotation?.xValue,
|
|
20201
|
+
yStartValue: annotationConfig?.verticalMarkersAnnotation?.yStartValue,
|
|
20202
|
+
color: annotationConfig?.verticalMarkersAnnotation?.color ?? "rgba(20,20,20,0.9)",
|
|
20203
|
+
opacity: annotationConfig?.verticalMarkersAnnotation?.opacity ?? 1,
|
|
20204
|
+
lineWidth: annotationConfig?.verticalMarkersAnnotation?.lineWidth ?? 1,
|
|
20205
|
+
lineDash: annotationConfig?.verticalMarkersAnnotation?.lineDash ?? [],
|
|
20206
|
+
items: annotationConfig?.verticalMarkersAnnotation?.items ?? []
|
|
20220
20207
|
},
|
|
20221
20208
|
annotationsData: defaultAnnotationsData$2(Array.isArray(annotations) ? annotations : annotations?.annotationsData)
|
|
20222
20209
|
};
|
|
@@ -20892,87 +20879,590 @@ function addTransparency(input, alpha, out = "rgb") {
|
|
|
20892
20879
|
}
|
|
20893
20880
|
//#endregion
|
|
20894
20881
|
//#region src/components/common/helpers/callout-helpers/callout-helpers.ts
|
|
20882
|
+
var DEFAULT_FONT_SIZE = 12;
|
|
20883
|
+
var DEFAULT_PADDING = 5;
|
|
20884
|
+
var DEFAULT_MARGIN = 8;
|
|
20885
|
+
var DEFAULT_LABEL_GAP = 8;
|
|
20886
|
+
var DEFAULT_MIN_CONNECTOR_LENGTH = 14;
|
|
20887
|
+
var DEFAULT_HORIZONTAL_OFFSET = 18;
|
|
20888
|
+
var DEFAULT_VERTICAL_OFFSET = -18;
|
|
20889
|
+
var DEFAULT_ROW_GAP = 22;
|
|
20890
|
+
var DEFAULT_ITEM_GAP = 8;
|
|
20891
|
+
var DEFAULT_OVERLAP_ONLY_ITEM_GAP = 14;
|
|
20892
|
+
var DEFAULT_LANE_GAP = 12;
|
|
20893
|
+
var clamp$1 = (value, min, max) => {
|
|
20894
|
+
if (Number.isNaN(value)) return min;
|
|
20895
|
+
if (min > max) return min;
|
|
20896
|
+
return Math.min(Math.max(value, min), max);
|
|
20897
|
+
};
|
|
20898
|
+
var clampRelaxed = (value, min, max) => {
|
|
20899
|
+
if (min <= max) return clamp$1(value, min, max);
|
|
20900
|
+
if (value < max) return max;
|
|
20901
|
+
if (value > min) return min;
|
|
20902
|
+
return value;
|
|
20903
|
+
};
|
|
20904
|
+
var getNumericValue = (value, fallback = 0) => {
|
|
20905
|
+
return typeof value === "number" ? value : fallback;
|
|
20906
|
+
};
|
|
20907
|
+
var getCalloutCfg = (annotation) => {
|
|
20908
|
+
return annotation?.labelConfig?.callout ?? {};
|
|
20909
|
+
};
|
|
20910
|
+
var getChartFromCtx$1 = (ctx) => {
|
|
20911
|
+
return ctx?.chart?.chart ?? ctx?.chart;
|
|
20912
|
+
};
|
|
20895
20913
|
var getXScale = (chart, axisId) => {
|
|
20896
20914
|
if (axisId && chart?.scales?.[axisId]) return chart.scales[axisId];
|
|
20897
20915
|
if (chart?.scales?.x) return chart.scales.x;
|
|
20898
|
-
const key = Object.keys(chart?.scales ?? {})?.find((
|
|
20916
|
+
const key = Object.keys(chart?.scales ?? {})?.find((item) => {
|
|
20917
|
+
return item?.toLowerCase()?.includes("x");
|
|
20918
|
+
});
|
|
20899
20919
|
return key ? chart?.scales?.[key] : void 0;
|
|
20900
20920
|
};
|
|
20901
20921
|
var getYScale = (chart, axisId) => {
|
|
20902
20922
|
if (axisId && chart?.scales?.[axisId]) return chart.scales[axisId];
|
|
20903
20923
|
if (chart?.scales?.y) return chart.scales.y;
|
|
20904
|
-
const key = Object.keys(chart?.scales ?? {})?.find((
|
|
20924
|
+
const key = Object.keys(chart?.scales ?? {})?.find((item) => {
|
|
20925
|
+
return item?.toLowerCase()?.includes("y");
|
|
20926
|
+
});
|
|
20905
20927
|
return key ? chart?.scales?.[key] : void 0;
|
|
20906
20928
|
};
|
|
20929
|
+
var resolveFontSize = (font) => {
|
|
20930
|
+
if (typeof font === "string") {
|
|
20931
|
+
const match = font.match(/(\d+(?:\.\d+)?)px/);
|
|
20932
|
+
return match ? Number(match[1]) : DEFAULT_FONT_SIZE;
|
|
20933
|
+
}
|
|
20934
|
+
if (font && typeof font === "object" && "size" in font) {
|
|
20935
|
+
const size = Number(font.size);
|
|
20936
|
+
return Number.isFinite(size) ? size : DEFAULT_FONT_SIZE;
|
|
20937
|
+
}
|
|
20938
|
+
return DEFAULT_FONT_SIZE;
|
|
20939
|
+
};
|
|
20940
|
+
var resolvePadding = (padding) => {
|
|
20941
|
+
if (typeof padding === "number") return {
|
|
20942
|
+
top: padding,
|
|
20943
|
+
right: padding,
|
|
20944
|
+
bottom: padding,
|
|
20945
|
+
left: padding
|
|
20946
|
+
};
|
|
20947
|
+
if (padding && typeof padding === "object") {
|
|
20948
|
+
const typedPadding = padding;
|
|
20949
|
+
return {
|
|
20950
|
+
top: Number(typedPadding.top ?? DEFAULT_PADDING),
|
|
20951
|
+
right: Number(typedPadding.right ?? DEFAULT_PADDING),
|
|
20952
|
+
bottom: Number(typedPadding.bottom ?? DEFAULT_PADDING),
|
|
20953
|
+
left: Number(typedPadding.left ?? DEFAULT_PADDING)
|
|
20954
|
+
};
|
|
20955
|
+
}
|
|
20956
|
+
return {
|
|
20957
|
+
top: DEFAULT_PADDING,
|
|
20958
|
+
right: DEFAULT_PADDING,
|
|
20959
|
+
bottom: DEFAULT_PADDING,
|
|
20960
|
+
left: DEFAULT_PADDING
|
|
20961
|
+
};
|
|
20962
|
+
};
|
|
20963
|
+
var estimateLabelSize = (chart, annotation, calloutCfg) => {
|
|
20964
|
+
const content = `${annotation?.label ?? ""}`;
|
|
20965
|
+
const fontSize = resolveFontSize(calloutCfg?.font);
|
|
20966
|
+
const padding = resolvePadding(calloutCfg?.padding);
|
|
20967
|
+
const lines = content.split("\n");
|
|
20968
|
+
const fallbackWidth = Math.max(...lines.map((line) => line.length), 0) * fontSize * .62;
|
|
20969
|
+
let measuredWidth = fallbackWidth;
|
|
20970
|
+
if (chart?.ctx) {
|
|
20971
|
+
chart.ctx.save();
|
|
20972
|
+
chart.ctx.font = typeof calloutCfg?.font === "string" ? calloutCfg.font : `${fontSize}px sans-serif`;
|
|
20973
|
+
measuredWidth = Math.max(...lines.map((line) => chart.ctx.measureText(line).width), fallbackWidth);
|
|
20974
|
+
chart.ctx.restore();
|
|
20975
|
+
}
|
|
20976
|
+
return {
|
|
20977
|
+
width: measuredWidth + padding.left + padding.right,
|
|
20978
|
+
height: lines.length * fontSize + padding.top + padding.bottom
|
|
20979
|
+
};
|
|
20980
|
+
};
|
|
20981
|
+
var getAxisId = (annotation, axis) => {
|
|
20982
|
+
const axisScaleId = axis === "x" ? annotation?.xScaleID : annotation?.yScaleID;
|
|
20983
|
+
if (axisScaleId) return axisScaleId;
|
|
20984
|
+
if (annotation?.annotationAxis?.startsWith(axis)) return annotation.annotationAxis;
|
|
20985
|
+
};
|
|
20986
|
+
var getAnchorPixel = (chart, annotation, axis, area) => {
|
|
20987
|
+
const scale = axis === "x" ? getXScale(chart, getAxisId(annotation, "x")) : getYScale(chart, getAxisId(annotation, "y"));
|
|
20988
|
+
const directValue = axis === "x" ? annotation?.xValue : annotation?.yValue;
|
|
20989
|
+
if (typeof directValue === "number" && scale) return scale.getPixelForValue(directValue);
|
|
20990
|
+
const minKey = axis === "x" ? "xMin" : "yMin";
|
|
20991
|
+
const maxKey = axis === "x" ? "xMax" : "yMax";
|
|
20992
|
+
const minValue = annotation?.[minKey];
|
|
20993
|
+
const maxValue = annotation?.[maxKey];
|
|
20994
|
+
if (typeof minValue === "number" && typeof maxValue === "number" && scale) return (scale.getPixelForValue(minValue) + scale.getPixelForValue(maxValue)) / 2;
|
|
20995
|
+
if (typeof minValue === "number" && scale) return scale.getPixelForValue(minValue);
|
|
20996
|
+
if (typeof maxValue === "number" && scale) return scale.getPixelForValue(maxValue);
|
|
20997
|
+
return axis === "x" ? (area.left + area.right) / 2 : (area.top + area.bottom) / 2;
|
|
20998
|
+
};
|
|
20999
|
+
var hasAxisAnchor = (annotation, axis) => {
|
|
21000
|
+
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";
|
|
21001
|
+
return typeof annotation?.yValue === "number" || typeof annotation?.yMin === "number" || typeof annotation?.yMax === "number" || annotation?.type === "box" || annotation?.type === "label" || annotation?.type === "ellipse";
|
|
21002
|
+
};
|
|
21003
|
+
var getBoxHalfWidth = (chart, area, annotation) => {
|
|
21004
|
+
const xScale = getXScale(chart, getAxisId(annotation, "x"));
|
|
21005
|
+
if (xScale && typeof annotation?.xMin === "number" && typeof annotation?.xMax === "number") return Math.abs(xScale.getPixelForValue(annotation.xMax) - xScale.getPixelForValue(annotation.xMin)) / 2;
|
|
21006
|
+
if (annotation?.type === "box") return (area.right - area.left) / 2;
|
|
21007
|
+
return annotation?.radius ?? 0;
|
|
21008
|
+
};
|
|
21009
|
+
var getBoxHalfHeight = (chart, annotation) => {
|
|
21010
|
+
const yScale = getYScale(chart, getAxisId(annotation, "y"));
|
|
21011
|
+
if (yScale && typeof annotation?.yMin === "number" && typeof annotation?.yMax === "number") return Math.abs(yScale.getPixelForValue(annotation.yMax) - yScale.getPixelForValue(annotation.yMin)) / 2;
|
|
21012
|
+
return annotation?.radius ?? 0;
|
|
21013
|
+
};
|
|
21014
|
+
var getReferencePoint$1 = (chart, area, annotation) => {
|
|
21015
|
+
const anchorX = getAnchorPixel(chart, annotation, "x", area);
|
|
21016
|
+
const anchorY = getAnchorPixel(chart, annotation, "y", area);
|
|
21017
|
+
const halfWidth = getBoxHalfWidth(chart, area, annotation);
|
|
21018
|
+
const halfHeight = getBoxHalfHeight(chart, annotation);
|
|
21019
|
+
const labelOffsetPx = getNumericValue(annotation?.labelOffsetPx, 14);
|
|
21020
|
+
const xAdjust = getNumericValue(annotation?.labelConfig?.xAdjust, 0);
|
|
21021
|
+
const yAdjust = getNumericValue(annotation?.labelConfig?.yAdjust, 0);
|
|
21022
|
+
const position = annotation?.labelConfig?.position;
|
|
21023
|
+
let x = anchorX;
|
|
21024
|
+
let y = anchorY;
|
|
21025
|
+
let side = anchorX >= (area.left + area.right) / 2 ? "right" : "left";
|
|
21026
|
+
switch (position) {
|
|
21027
|
+
case Position.Left:
|
|
21028
|
+
x -= Math.max(halfWidth, annotation?.radius ?? 0) + labelOffsetPx;
|
|
21029
|
+
side = "left";
|
|
21030
|
+
break;
|
|
21031
|
+
case Position.Right:
|
|
21032
|
+
x += Math.max(halfWidth, annotation?.radius ?? 0) + labelOffsetPx;
|
|
21033
|
+
side = "right";
|
|
21034
|
+
break;
|
|
21035
|
+
case Position.TopLeft:
|
|
21036
|
+
x -= halfWidth;
|
|
21037
|
+
y -= halfHeight;
|
|
21038
|
+
side = "left";
|
|
21039
|
+
break;
|
|
21040
|
+
case Position.TopRight:
|
|
21041
|
+
x += halfWidth;
|
|
21042
|
+
y -= halfHeight;
|
|
21043
|
+
side = "right";
|
|
21044
|
+
break;
|
|
21045
|
+
case Position.BottomLeft:
|
|
21046
|
+
x -= halfWidth;
|
|
21047
|
+
y += halfHeight;
|
|
21048
|
+
side = "left";
|
|
21049
|
+
break;
|
|
21050
|
+
case Position.BottomRight:
|
|
21051
|
+
x += halfWidth;
|
|
21052
|
+
y += halfHeight;
|
|
21053
|
+
side = "right";
|
|
21054
|
+
break;
|
|
21055
|
+
case Position.Bottom:
|
|
21056
|
+
y += Math.max(halfHeight, annotation?.radius ?? 0) + labelOffsetPx;
|
|
21057
|
+
break;
|
|
21058
|
+
case Position.Top:
|
|
21059
|
+
default:
|
|
21060
|
+
y -= Math.max(halfHeight, annotation?.radius ?? 0) + labelOffsetPx;
|
|
21061
|
+
break;
|
|
21062
|
+
}
|
|
21063
|
+
return {
|
|
21064
|
+
x: x + xAdjust,
|
|
21065
|
+
y: y + yAdjust,
|
|
21066
|
+
side
|
|
21067
|
+
};
|
|
21068
|
+
};
|
|
21069
|
+
var getOriginalLabelRect = (chart, area, annotation, index) => {
|
|
21070
|
+
const size = estimateLabelSize(chart, annotation, getCalloutCfg(annotation));
|
|
21071
|
+
const reference = getReferencePoint$1(chart, area, annotation);
|
|
21072
|
+
const direction = reference.side === "right" ? 1 : -1;
|
|
21073
|
+
const centerX = reference.x + direction * (size.width / 2);
|
|
21074
|
+
const centerY = reference.y;
|
|
21075
|
+
return {
|
|
21076
|
+
id: `callout-annotation-${index}`,
|
|
21077
|
+
side: reference.side,
|
|
21078
|
+
left: centerX - size.width / 2,
|
|
21079
|
+
right: centerX + size.width / 2,
|
|
21080
|
+
top: centerY - size.height / 2,
|
|
21081
|
+
bottom: centerY + size.height / 2
|
|
21082
|
+
};
|
|
21083
|
+
};
|
|
21084
|
+
var isRectOverlapping = (left, right) => {
|
|
21085
|
+
return !(left.right <= right.left || right.right <= left.left || left.bottom <= right.top || right.bottom <= left.top);
|
|
21086
|
+
};
|
|
21087
|
+
var getOverlappingCalloutIds = (chart) => {
|
|
21088
|
+
const area = chart?.chartArea;
|
|
21089
|
+
const annotationsData = (chart?.options)?.annotations?.annotationsData ?? [];
|
|
21090
|
+
if (!chart || !area) return /* @__PURE__ */ new Set();
|
|
21091
|
+
const rects = annotationsData.flatMap((annotation, index) => {
|
|
21092
|
+
const calloutCfg = getCalloutCfg(annotation);
|
|
21093
|
+
if (!calloutCfg?.enabled || !calloutCfg?.onlyWhenOverlapping) return [];
|
|
21094
|
+
return [getOriginalLabelRect(chart, area, annotation, index)];
|
|
21095
|
+
});
|
|
21096
|
+
const overlappingIds = /* @__PURE__ */ new Set();
|
|
21097
|
+
rects.forEach((rect, index) => {
|
|
21098
|
+
rects.slice(index + 1).forEach((otherRect) => {
|
|
21099
|
+
if (rect.side !== otherRect.side) return;
|
|
21100
|
+
if (!isRectOverlapping(rect, otherRect)) return;
|
|
21101
|
+
overlappingIds.add(rect.id);
|
|
21102
|
+
overlappingIds.add(otherRect.id);
|
|
21103
|
+
});
|
|
21104
|
+
});
|
|
21105
|
+
return overlappingIds;
|
|
21106
|
+
};
|
|
21107
|
+
var isCalloutOverlapping = (ctx, refAnnotation, index) => {
|
|
21108
|
+
const chart = getChartFromCtx$1(ctx);
|
|
21109
|
+
if (!getCalloutCfg(refAnnotation)?.onlyWhenOverlapping) return true;
|
|
21110
|
+
if (!chart?.chartArea) return false;
|
|
21111
|
+
return getOverlappingCalloutIds(chart).has(`callout-annotation-${index}`);
|
|
21112
|
+
};
|
|
21113
|
+
var getPreferredX = (chart, area, annotation, calloutCfg, width) => {
|
|
21114
|
+
const xScale = getXScale(chart, getAxisId(annotation, "x"));
|
|
21115
|
+
const explicitXValue = typeof calloutCfg?.xValue === "number" ? calloutCfg.xValue : void 0;
|
|
21116
|
+
if (typeof explicitXValue === "number" && xScale) return xScale.getPixelForValue(explicitXValue);
|
|
21117
|
+
const margin = getNumericValue(calloutCfg?.margin, DEFAULT_MARGIN);
|
|
21118
|
+
const halfWidth = width / 2;
|
|
21119
|
+
const reference = getReferencePoint$1(chart, area, annotation);
|
|
21120
|
+
const direction = reference.side === "right" ? 1 : -1;
|
|
21121
|
+
const gap = getNumericValue(calloutCfg?.gapPx, DEFAULT_LABEL_GAP);
|
|
21122
|
+
const minConnectorLength = getNumericValue(calloutCfg?.minConnectorLengthPx, DEFAULT_MIN_CONNECTOR_LENGTH);
|
|
21123
|
+
return clamp$1(reference.x + direction * (halfWidth + gap + minConnectorLength), area.left + margin + halfWidth, area.right - margin - halfWidth);
|
|
21124
|
+
};
|
|
21125
|
+
var getPreferredY = (chart, area, annotation, calloutCfg) => {
|
|
21126
|
+
const yScale = getYScale(chart, getAxisId(annotation, "y"));
|
|
21127
|
+
const explicitYValue = typeof calloutCfg?.yValue === "number" ? calloutCfg.yValue : void 0;
|
|
21128
|
+
if (typeof explicitYValue === "number" && yScale) return yScale.getPixelForValue(explicitYValue);
|
|
21129
|
+
const reference = getReferencePoint$1(chart, area, annotation);
|
|
21130
|
+
const dy = typeof calloutCfg?.yAdjust === "number" ? 0 : DEFAULT_VERTICAL_OFFSET;
|
|
21131
|
+
return reference.y + dy;
|
|
21132
|
+
};
|
|
21133
|
+
var getCalloutItems = (chart, area) => {
|
|
21134
|
+
const overlappingIds = getOverlappingCalloutIds(chart);
|
|
21135
|
+
return ((chart?.options)?.annotations?.annotationsData ?? []).flatMap((annotation, index) => {
|
|
21136
|
+
const calloutCfg = getCalloutCfg(annotation);
|
|
21137
|
+
const id = `callout-annotation-${index}`;
|
|
21138
|
+
if (!calloutCfg?.enabled) return [];
|
|
21139
|
+
const size = estimateLabelSize(chart, annotation, calloutCfg);
|
|
21140
|
+
const xScale = getXScale(chart, getAxisId(annotation, "x"));
|
|
21141
|
+
const yScale = getYScale(chart, getAxisId(annotation, "y"));
|
|
21142
|
+
const reference = getReferencePoint$1(chart, area, annotation);
|
|
21143
|
+
const preferredX = getPreferredX(chart, area, annotation, calloutCfg, size.width);
|
|
21144
|
+
const preferredY = getPreferredY(chart, area, annotation, calloutCfg);
|
|
21145
|
+
const hasStoredX = typeof calloutCfg?.xValue === "number" || !xScale;
|
|
21146
|
+
const hasStoredY = typeof calloutCfg?.yValue === "number" || !yScale;
|
|
21147
|
+
const side = reference.side;
|
|
21148
|
+
const margin = getNumericValue(calloutCfg?.margin, DEFAULT_MARGIN);
|
|
21149
|
+
return [{
|
|
21150
|
+
annotation,
|
|
21151
|
+
calloutCfg,
|
|
21152
|
+
id,
|
|
21153
|
+
index,
|
|
21154
|
+
anchorY: reference.y,
|
|
21155
|
+
preferredX,
|
|
21156
|
+
preferredY,
|
|
21157
|
+
width: size.width,
|
|
21158
|
+
height: size.height,
|
|
21159
|
+
isFixed: hasStoredX && hasStoredY,
|
|
21160
|
+
isOverlapping: overlappingIds.has(id),
|
|
21161
|
+
overlapOnly: Boolean(calloutCfg?.onlyWhenOverlapping),
|
|
21162
|
+
minX: area.left + margin + size.width / 2,
|
|
21163
|
+
maxX: area.right - margin - size.width / 2,
|
|
21164
|
+
minY: area.top + margin + size.height / 2,
|
|
21165
|
+
maxY: area.bottom - margin - size.height / 2,
|
|
21166
|
+
side
|
|
21167
|
+
}];
|
|
21168
|
+
});
|
|
21169
|
+
};
|
|
21170
|
+
var hasVerticalOverlap = (items) => {
|
|
21171
|
+
const sorted = [...items].sort((left, right) => left.preferredY - right.preferredY);
|
|
21172
|
+
for (let index = 1; index < sorted.length; index += 1) {
|
|
21173
|
+
const previous = sorted[index - 1];
|
|
21174
|
+
const current = sorted[index];
|
|
21175
|
+
const gap = previous.height / 2 + current.height / 2 + DEFAULT_ITEM_GAP;
|
|
21176
|
+
if (current.preferredY - previous.preferredY < gap) return true;
|
|
21177
|
+
}
|
|
21178
|
+
return false;
|
|
21179
|
+
};
|
|
21180
|
+
var overlapsOccupiedRect = (centerY, height, occupiedRects) => {
|
|
21181
|
+
const top = centerY - height / 2;
|
|
21182
|
+
const bottom = centerY + height / 2;
|
|
21183
|
+
return occupiedRects.find((rect) => !(bottom <= rect.top || top >= rect.bottom));
|
|
21184
|
+
};
|
|
21185
|
+
var getLayoutGap = (item) => {
|
|
21186
|
+
return item.overlapOnly ? DEFAULT_OVERLAP_ONLY_ITEM_GAP : DEFAULT_ITEM_GAP;
|
|
21187
|
+
};
|
|
21188
|
+
var getLayoutOrderY = (item) => {
|
|
21189
|
+
return item.isFixed ? item.preferredY : item.anchorY;
|
|
21190
|
+
};
|
|
21191
|
+
var intervalsOverlap = (top, bottom, otherTop, otherBottom) => {
|
|
21192
|
+
return !(bottom <= otherTop || top >= otherBottom);
|
|
21193
|
+
};
|
|
21194
|
+
var assignLabelColumns = (items, layout) => {
|
|
21195
|
+
const columns = [];
|
|
21196
|
+
const hasPrimaryColumn = items.some((item) => {
|
|
21197
|
+
return !item.overlapOnly || !item.isOverlapping;
|
|
21198
|
+
});
|
|
21199
|
+
[...items].sort((left, right) => getLayoutOrderY(left) - getLayoutOrderY(right)).forEach((item) => {
|
|
21200
|
+
const current = layout.get(item.id);
|
|
21201
|
+
if (!current) return;
|
|
21202
|
+
const top = current.yValue - item.height / 2 - getLayoutGap(item) / 2;
|
|
21203
|
+
const bottom = current.yValue + item.height / 2 + getLayoutGap(item) / 2;
|
|
21204
|
+
let columnIndex = hasPrimaryColumn && item.overlapOnly && item.isOverlapping ? 1 : 0;
|
|
21205
|
+
while (true) {
|
|
21206
|
+
if (!(columns[columnIndex] ?? []).some((placed) => {
|
|
21207
|
+
return intervalsOverlap(top, bottom, placed.top, placed.bottom);
|
|
21208
|
+
})) {
|
|
21209
|
+
if (!columns[columnIndex]) columns[columnIndex] = [];
|
|
21210
|
+
columns[columnIndex].push({
|
|
21211
|
+
id: item.id,
|
|
21212
|
+
top,
|
|
21213
|
+
bottom,
|
|
21214
|
+
width: item.width
|
|
21215
|
+
});
|
|
21216
|
+
break;
|
|
21217
|
+
}
|
|
21218
|
+
columnIndex += 1;
|
|
21219
|
+
}
|
|
21220
|
+
});
|
|
21221
|
+
return columns;
|
|
21222
|
+
};
|
|
21223
|
+
var applyLaneLayout = (items, layout, occupiedRects) => {
|
|
21224
|
+
if (items.length <= 1) return;
|
|
21225
|
+
const side = items[0]?.side;
|
|
21226
|
+
const columns = assignLabelColumns(items, layout);
|
|
21227
|
+
const getCurrentRect = (item) => {
|
|
21228
|
+
const centerX = layout.get(item.id)?.xValue ?? item.preferredX;
|
|
21229
|
+
return {
|
|
21230
|
+
left: centerX - item.width / 2,
|
|
21231
|
+
right: centerX + item.width / 2
|
|
21232
|
+
};
|
|
21233
|
+
};
|
|
21234
|
+
const referenceItems = items.filter((item) => {
|
|
21235
|
+
return columns[0]?.some((placed) => placed.id === item.id);
|
|
21236
|
+
});
|
|
21237
|
+
const referenceRects = referenceItems.length ? referenceItems : items;
|
|
21238
|
+
const baseEdge = side === "right" ? occupiedRects.length ? Math.min(...occupiedRects.map((rect) => rect.left)) - DEFAULT_LANE_GAP : Math.min(...referenceRects.map((item) => getCurrentRect(item).left)) : occupiedRects.length ? Math.max(...occupiedRects.map((rect) => rect.right)) + DEFAULT_LANE_GAP : Math.max(...referenceRects.map((item) => getCurrentRect(item).right));
|
|
21239
|
+
columns.forEach((column, columnIndex) => {
|
|
21240
|
+
const columnWidth = Math.max(...column.map((placed) => placed.width));
|
|
21241
|
+
column?.forEach((placed) => {
|
|
21242
|
+
const item = items.find((candidate) => candidate.id === placed.id);
|
|
21243
|
+
const current = layout.get(placed.id);
|
|
21244
|
+
if (!item || !current) return;
|
|
21245
|
+
const xValue = side === "right" ? baseEdge - columnIndex * (columnWidth + DEFAULT_LANE_GAP) - item.width / 2 : baseEdge + columnIndex * (columnWidth + DEFAULT_LANE_GAP) + item.width / 2;
|
|
21246
|
+
layout.set(placed.id, {
|
|
21247
|
+
...current,
|
|
21248
|
+
xValue: clamp$1(xValue, item.minX, item.maxX)
|
|
21249
|
+
});
|
|
21250
|
+
});
|
|
21251
|
+
});
|
|
21252
|
+
};
|
|
21253
|
+
var getOrderBounds = (item, occupiedRects) => {
|
|
21254
|
+
const previousRect = [...occupiedRects].filter((rect) => rect.centerY <= item.anchorY).at(-1);
|
|
21255
|
+
const nextRect = occupiedRects.find((rect) => rect.centerY >= item.anchorY);
|
|
21256
|
+
const gap = getLayoutGap(item);
|
|
21257
|
+
return {
|
|
21258
|
+
minCenter: previousRect ? previousRect.bottom + gap + item.height / 2 : item.minY,
|
|
21259
|
+
maxCenter: nextRect ? nextRect.top - gap - item.height / 2 : item.maxY
|
|
21260
|
+
};
|
|
21261
|
+
};
|
|
21262
|
+
var layoutSide = (items, occupiedRects = []) => {
|
|
21263
|
+
const sortedOccupiedRects = [...occupiedRects].sort((left, right) => left.centerY - right.centerY);
|
|
21264
|
+
const sorted = [...items].sort((left, right) => getLayoutOrderY(left) - getLayoutOrderY(right));
|
|
21265
|
+
const result = /* @__PURE__ */ new Map();
|
|
21266
|
+
if (!sorted.filter((item) => !item.isFixed).length) {
|
|
21267
|
+
sorted.forEach((item) => {
|
|
21268
|
+
result.set(item.id, {
|
|
21269
|
+
xValue: item.preferredX,
|
|
21270
|
+
yValue: item.preferredY
|
|
21271
|
+
});
|
|
21272
|
+
});
|
|
21273
|
+
return result;
|
|
21274
|
+
}
|
|
21275
|
+
const shouldReflow = sorted.some((item) => !item.overlapOnly) || hasVerticalOverlap(sorted);
|
|
21276
|
+
sorted.forEach((item) => {
|
|
21277
|
+
result.set(item.id, {
|
|
21278
|
+
xValue: item.preferredX,
|
|
21279
|
+
yValue: clamp$1(item.preferredY, item.minY, item.maxY)
|
|
21280
|
+
});
|
|
21281
|
+
});
|
|
21282
|
+
if (!shouldReflow) return result;
|
|
21283
|
+
let previousBottom = Number.NEGATIVE_INFINITY;
|
|
21284
|
+
sorted.forEach((item) => {
|
|
21285
|
+
if (item.isFixed) {
|
|
21286
|
+
const yValue = clamp$1(item.preferredY, item.minY, item.maxY);
|
|
21287
|
+
result.set(item.id, {
|
|
21288
|
+
xValue: item.preferredX,
|
|
21289
|
+
yValue
|
|
21290
|
+
});
|
|
21291
|
+
previousBottom = yValue + item.height / 2;
|
|
21292
|
+
return;
|
|
21293
|
+
}
|
|
21294
|
+
const orderBounds = getOrderBounds(item, sortedOccupiedRects);
|
|
21295
|
+
const maxCenter = Math.min(item.maxY, orderBounds.maxCenter);
|
|
21296
|
+
const minCenter = Math.max(item.minY, orderBounds.minCenter, previousBottom + item.height / 2 + getLayoutGap(item));
|
|
21297
|
+
let yValue = clampRelaxed(item.preferredY, minCenter, maxCenter);
|
|
21298
|
+
let overlappingRect = overlapsOccupiedRect(yValue, item.height, sortedOccupiedRects);
|
|
21299
|
+
while (overlappingRect) {
|
|
21300
|
+
const nextCandidate = overlappingRect.bottom + getLayoutGap(item) + item.height / 2;
|
|
21301
|
+
if (nextCandidate === yValue) break;
|
|
21302
|
+
yValue = clampRelaxed(nextCandidate, minCenter, maxCenter);
|
|
21303
|
+
overlappingRect = overlapsOccupiedRect(yValue, item.height, sortedOccupiedRects);
|
|
21304
|
+
}
|
|
21305
|
+
result.set(item.id, {
|
|
21306
|
+
xValue: item.preferredX,
|
|
21307
|
+
yValue
|
|
21308
|
+
});
|
|
21309
|
+
previousBottom = yValue + item.height / 2;
|
|
21310
|
+
});
|
|
21311
|
+
let nextTop = Number.POSITIVE_INFINITY;
|
|
21312
|
+
[...sorted].reverse().forEach((item) => {
|
|
21313
|
+
const current = result.get(item.id);
|
|
21314
|
+
if (!current) return;
|
|
21315
|
+
if (item.isFixed) {
|
|
21316
|
+
nextTop = current.yValue - item.height / 2;
|
|
21317
|
+
return;
|
|
21318
|
+
}
|
|
21319
|
+
const orderBounds = getOrderBounds(item, sortedOccupiedRects);
|
|
21320
|
+
const maxCenter = Math.min(item.maxY, orderBounds.maxCenter, nextTop - item.height / 2 - getLayoutGap(item));
|
|
21321
|
+
const minCenter = Math.max(item.minY, orderBounds.minCenter);
|
|
21322
|
+
const yValue = clampRelaxed(current.yValue, minCenter, maxCenter);
|
|
21323
|
+
result.set(item.id, {
|
|
21324
|
+
...current,
|
|
21325
|
+
yValue
|
|
21326
|
+
});
|
|
21327
|
+
nextTop = yValue - item.height / 2;
|
|
21328
|
+
});
|
|
21329
|
+
previousBottom = Number.NEGATIVE_INFINITY;
|
|
21330
|
+
sorted.forEach((item) => {
|
|
21331
|
+
const current = result.get(item.id);
|
|
21332
|
+
if (!current) return;
|
|
21333
|
+
if (item.isFixed) {
|
|
21334
|
+
previousBottom = current.yValue + item.height / 2;
|
|
21335
|
+
return;
|
|
21336
|
+
}
|
|
21337
|
+
const orderBounds = getOrderBounds(item, sortedOccupiedRects);
|
|
21338
|
+
const maxCenter = Math.min(item.maxY, orderBounds.maxCenter);
|
|
21339
|
+
const minCenter = Math.max(item.minY, orderBounds.minCenter, previousBottom + item.height / 2 + getLayoutGap(item));
|
|
21340
|
+
const yValue = clampRelaxed(current.yValue, minCenter, maxCenter);
|
|
21341
|
+
result.set(item.id, {
|
|
21342
|
+
...current,
|
|
21343
|
+
yValue
|
|
21344
|
+
});
|
|
21345
|
+
previousBottom = yValue + item.height / 2;
|
|
21346
|
+
});
|
|
21347
|
+
if (sorted.some((item) => item.overlapOnly)) {
|
|
21348
|
+
const untouchedPrimary = sorted.filter((item) => {
|
|
21349
|
+
return !item.isFixed && item.overlapOnly && !item.isOverlapping;
|
|
21350
|
+
});
|
|
21351
|
+
const secondaryMovable = sorted.filter((item) => {
|
|
21352
|
+
return !item.isFixed && item.overlapOnly && item.isOverlapping;
|
|
21353
|
+
});
|
|
21354
|
+
untouchedPrimary.forEach((item) => {
|
|
21355
|
+
result.set(item.id, {
|
|
21356
|
+
xValue: item.preferredX,
|
|
21357
|
+
yValue: clamp$1(item.preferredY, item.minY, item.maxY)
|
|
21358
|
+
});
|
|
21359
|
+
});
|
|
21360
|
+
if (secondaryMovable.length) applyLaneLayout(secondaryMovable, result, untouchedPrimary.map((item) => {
|
|
21361
|
+
const current = result.get(item.id);
|
|
21362
|
+
const centerX = current?.xValue ?? item.preferredX;
|
|
21363
|
+
const centerY = current?.yValue ?? item.preferredY;
|
|
21364
|
+
return {
|
|
21365
|
+
top: centerY - item.height / 2,
|
|
21366
|
+
bottom: centerY + item.height / 2,
|
|
21367
|
+
centerY,
|
|
21368
|
+
left: centerX - item.width / 2,
|
|
21369
|
+
right: centerX + item.width / 2
|
|
21370
|
+
};
|
|
21371
|
+
}));
|
|
21372
|
+
return result;
|
|
21373
|
+
}
|
|
21374
|
+
applyLaneLayout(sorted.filter((item) => !item.isFixed), result, []);
|
|
21375
|
+
return result;
|
|
21376
|
+
};
|
|
21377
|
+
var getCalloutLayoutPixels = (chart) => {
|
|
21378
|
+
const area = chart?.chartArea;
|
|
21379
|
+
if (!chart || !area) return /* @__PURE__ */ new Map();
|
|
21380
|
+
const grouped = getCalloutItems(chart, area).map((item) => {
|
|
21381
|
+
const xValue = clamp$1(item.preferredX, item.minX, item.maxX);
|
|
21382
|
+
return {
|
|
21383
|
+
...item,
|
|
21384
|
+
preferredX: xValue
|
|
21385
|
+
};
|
|
21386
|
+
}).reduce((accumulator, item) => {
|
|
21387
|
+
accumulator[item.side].push(item);
|
|
21388
|
+
return accumulator;
|
|
21389
|
+
}, {
|
|
21390
|
+
left: [],
|
|
21391
|
+
right: []
|
|
21392
|
+
});
|
|
21393
|
+
const leftLayout = layoutSide(grouped.left, []);
|
|
21394
|
+
const rightLayout = layoutSide(grouped.right, []);
|
|
21395
|
+
return new Map([...leftLayout.entries(), ...rightLayout.entries()]);
|
|
21396
|
+
};
|
|
21397
|
+
var getCalloutLayout = (ctx, refAnnotation, index) => {
|
|
21398
|
+
const chart = getChartFromCtx$1(ctx);
|
|
21399
|
+
const xScale = chart ? getXScale(chart, getAxisId(refAnnotation, "x")) : void 0;
|
|
21400
|
+
const yScale = chart ? getYScale(chart, getAxisId(refAnnotation, "y")) : void 0;
|
|
21401
|
+
if (!chart || !yScale || !chart.chartArea) return null;
|
|
21402
|
+
if (!xScale && hasAxisAnchor(refAnnotation, "x")) return null;
|
|
21403
|
+
if (!xScale) return null;
|
|
21404
|
+
const layout = getCalloutLayoutPixels(chart).get(`callout-annotation-${index}`);
|
|
21405
|
+
if (!layout) return null;
|
|
21406
|
+
return {
|
|
21407
|
+
xValue: xScale.getValueForPixel(layout.xValue),
|
|
21408
|
+
yValue: yScale.getValueForPixel(layout.yValue)
|
|
21409
|
+
};
|
|
21410
|
+
};
|
|
20907
21411
|
var resolveCalloutXValue = (ctx, refAnnotation, calloutCfg, index) => {
|
|
20908
|
-
const
|
|
21412
|
+
const layout = getCalloutLayout(ctx, refAnnotation, index);
|
|
21413
|
+
if (layout) return layout.xValue;
|
|
21414
|
+
const chart = getChartFromCtx$1(ctx);
|
|
20909
21415
|
const xVal = refAnnotation?.xValue;
|
|
20910
21416
|
if (typeof xVal !== "number") return 0;
|
|
20911
21417
|
if (!chart) return xVal;
|
|
20912
|
-
const scale = getXScale(chart, refAnnotation
|
|
21418
|
+
const scale = getXScale(chart, getAxisId(refAnnotation, "x"));
|
|
20913
21419
|
if (!scale) return xVal;
|
|
20914
21420
|
const hasCustomOffset = typeof calloutCfg?.xAdjust === "number";
|
|
20915
21421
|
const side = index % 2 === 0 ? 1 : -1;
|
|
20916
|
-
const dx = hasCustomOffset ? calloutCfg?.xAdjust : side *
|
|
21422
|
+
const dx = hasCustomOffset ? calloutCfg?.xAdjust : side * DEFAULT_HORIZONTAL_OFFSET;
|
|
20917
21423
|
const basePx = scale.getPixelForValue(xVal);
|
|
20918
|
-
const cxBase = basePx + dx;
|
|
20919
21424
|
const area = chart.chartArea;
|
|
20920
|
-
const
|
|
20921
|
-
if (!area || !
|
|
20922
|
-
const margin = calloutCfg?.margin
|
|
20923
|
-
const
|
|
20924
|
-
|
|
20925
|
-
|
|
20926
|
-
if (cx - halfW < area.left + margin) {
|
|
20927
|
-
adjDx += area.left + margin + halfW - cx;
|
|
20928
|
-
cx = basePx + adjDx;
|
|
20929
|
-
} else if (cx + halfW > area.right - margin) {
|
|
20930
|
-
adjDx += area.right - margin - halfW - cx;
|
|
20931
|
-
cx = basePx + adjDx;
|
|
20932
|
-
}
|
|
20933
|
-
return scale.getValueForPixel(cx);
|
|
21425
|
+
const element = ctx?.element;
|
|
21426
|
+
if (!area || !element) return scale.getValueForPixel(basePx + dx);
|
|
21427
|
+
const margin = getNumericValue(calloutCfg?.margin, DEFAULT_MARGIN);
|
|
21428
|
+
const halfWidth = (element?.width ?? 0) / 2;
|
|
21429
|
+
const clampedPx = clamp$1(basePx + dx, area.left + margin + halfWidth, area.right - margin - halfWidth);
|
|
21430
|
+
return scale.getValueForPixel(clampedPx);
|
|
20934
21431
|
};
|
|
20935
21432
|
var resolveCalloutYValue = (ctx, refAnnotation, calloutCfg, index) => {
|
|
20936
|
-
const
|
|
20937
|
-
|
|
21433
|
+
const layout = getCalloutLayout(ctx, refAnnotation, index);
|
|
21434
|
+
if (layout) return layout.yValue;
|
|
21435
|
+
const chart = getChartFromCtx$1(ctx);
|
|
21436
|
+
const yVal = refAnnotation?.yValue;
|
|
20938
21437
|
if (typeof yVal !== "number") return 0;
|
|
20939
21438
|
if (!chart) return yVal;
|
|
20940
|
-
const scale = getYScale(chart, refAnnotation
|
|
21439
|
+
const scale = getYScale(chart, getAxisId(refAnnotation, "y"));
|
|
20941
21440
|
if (!scale) return yVal;
|
|
20942
21441
|
const hasCustomOffset = typeof calloutCfg?.yAdjust === "number";
|
|
20943
21442
|
const row = Math.floor(index / 2);
|
|
20944
|
-
const dy = hasCustomOffset ? calloutCfg?.yAdjust :
|
|
21443
|
+
const dy = hasCustomOffset ? calloutCfg?.yAdjust : DEFAULT_VERTICAL_OFFSET - row * DEFAULT_ROW_GAP;
|
|
20945
21444
|
const basePx = scale.getPixelForValue(yVal);
|
|
20946
|
-
const cyBase = basePx + dy;
|
|
20947
21445
|
const area = chart.chartArea;
|
|
20948
|
-
const
|
|
20949
|
-
if (!area || !
|
|
20950
|
-
const margin = calloutCfg?.margin
|
|
20951
|
-
const
|
|
20952
|
-
|
|
20953
|
-
|
|
20954
|
-
|
|
20955
|
-
|
|
20956
|
-
cy = basePx + adjDy;
|
|
20957
|
-
} else if (cy + halfH > area.bottom - margin) {
|
|
20958
|
-
adjDy += area.bottom - margin - halfH - cy;
|
|
20959
|
-
cy = basePx + adjDy;
|
|
20960
|
-
}
|
|
20961
|
-
return scale.getValueForPixel(cy);
|
|
20962
|
-
};
|
|
20963
|
-
var isInRange = (v, min, max) => v >= min && v <= max;
|
|
21446
|
+
const element = ctx?.element;
|
|
21447
|
+
if (!area || !element) return scale.getValueForPixel(basePx + dy);
|
|
21448
|
+
const margin = getNumericValue(calloutCfg?.margin, DEFAULT_MARGIN);
|
|
21449
|
+
const halfHeight = (element?.height ?? 0) / 2;
|
|
21450
|
+
const clampedPx = clamp$1(basePx + dy, area.top + margin + halfHeight, area.bottom - margin - halfHeight);
|
|
21451
|
+
return scale.getValueForPixel(clampedPx);
|
|
21452
|
+
};
|
|
21453
|
+
var isInRange = (value, min, max) => value >= min && value <= max;
|
|
20964
21454
|
var isCalloutAnchorInChartArea = (ctx, refAnnotation, margin = 0) => {
|
|
20965
|
-
const chart = ctx
|
|
21455
|
+
const chart = getChartFromCtx$1(ctx);
|
|
20966
21456
|
const area = chart?.chartArea;
|
|
20967
21457
|
if (!chart || !area) return true;
|
|
20968
|
-
const xScale = getXScale(chart, refAnnotation
|
|
20969
|
-
const yScale = getYScale(chart, refAnnotation
|
|
20970
|
-
const
|
|
20971
|
-
const
|
|
20972
|
-
if (!xScale || !yScale) return false;
|
|
20973
|
-
if (
|
|
20974
|
-
const x =
|
|
20975
|
-
const y =
|
|
21458
|
+
const xScale = getXScale(chart, getAxisId(refAnnotation, "x"));
|
|
21459
|
+
const yScale = getYScale(chart, getAxisId(refAnnotation, "y"));
|
|
21460
|
+
const hasXValues = hasAxisAnchor(refAnnotation, "x");
|
|
21461
|
+
const hasYValues = hasAxisAnchor(refAnnotation, "y");
|
|
21462
|
+
if (hasXValues && !xScale || hasYValues && !yScale) return false;
|
|
21463
|
+
if (!hasXValues || !hasYValues) return false;
|
|
21464
|
+
const x = getAnchorPixel(chart, refAnnotation, "x", area);
|
|
21465
|
+
const y = getAnchorPixel(chart, refAnnotation, "y", area);
|
|
20976
21466
|
return isInRange(x, area.left + margin, area.right - margin) && isInRange(y, area.top + margin, area.bottom - margin);
|
|
20977
21467
|
};
|
|
20978
21468
|
//#endregion
|
|
@@ -21273,7 +21763,10 @@ var getCalloutAnnotation = (refAnnotation, index) => {
|
|
|
21273
21763
|
const calloutCfg = refAnnotation?.labelConfig?.callout ?? {};
|
|
21274
21764
|
const baseAnnotation = {
|
|
21275
21765
|
...baseRest,
|
|
21276
|
-
label: {
|
|
21766
|
+
label: {
|
|
21767
|
+
...label,
|
|
21768
|
+
display: () => false
|
|
21769
|
+
}
|
|
21277
21770
|
};
|
|
21278
21771
|
const color = calloutCfg?.color ?? "hsl(60, 10.34482759%, 12.5%)";
|
|
21279
21772
|
const font = calloutCfg?.font ?? `12px "Roobert", "Noto Sans", sans-serif`;
|
|
@@ -21281,10 +21774,10 @@ var getCalloutAnnotation = (refAnnotation, index) => {
|
|
|
21281
21774
|
const onCalloutDragStart = typeof calloutCfg?.onDragStart === "function" ? calloutCfg.onDragStart : void 0;
|
|
21282
21775
|
const onCalloutDrag = typeof calloutCfg?.onDrag === "function" ? calloutCfg.onDrag : void 0;
|
|
21283
21776
|
const onCalloutDragEnd = typeof calloutCfg?.onDragEnd === "function" ? calloutCfg.onDragEnd : void 0;
|
|
21284
|
-
const strokeStyle = calloutCfg.strokeStyle ??
|
|
21777
|
+
const strokeStyle = calloutCfg.strokeStyle ?? "rgba(120, 126, 138, 0.9)";
|
|
21285
21778
|
const lineWidth = typeof calloutCfg.lineWidth === "number" ? calloutCfg.lineWidth : 1;
|
|
21286
|
-
const startOffset = typeof calloutCfg.startOffset === "number" ? calloutCfg.startOffset :
|
|
21287
|
-
const endOffset = typeof calloutCfg.endOffset === "number" ? calloutCfg.endOffset :
|
|
21779
|
+
const startOffset = typeof calloutCfg.startOffset === "number" ? calloutCfg.startOffset : 2;
|
|
21780
|
+
const endOffset = typeof calloutCfg.endOffset === "number" ? calloutCfg.endOffset : .5;
|
|
21288
21781
|
const calloutId = `callout-annotation-${index}`;
|
|
21289
21782
|
return [baseAnnotation, {
|
|
21290
21783
|
id: calloutId,
|
|
@@ -21294,14 +21787,18 @@ var getCalloutAnnotation = (refAnnotation, index) => {
|
|
|
21294
21787
|
color: (ctx) => {
|
|
21295
21788
|
const chart = getChartFromCtx(ctx);
|
|
21296
21789
|
if (!chart) return color;
|
|
21297
|
-
if (chart.hoveredAnnotationId === calloutId) return "#DB5B00";
|
|
21790
|
+
if (Boolean(chart?.options?.plugins?.annotationDraggerPlugin?.enabled) && chart.hoveredAnnotationId === calloutId) return "#DB5B00";
|
|
21298
21791
|
return color;
|
|
21299
21792
|
},
|
|
21300
21793
|
font,
|
|
21301
21794
|
borderColor,
|
|
21302
21795
|
borderWidth: BORDER_WIDTH.INITIAL,
|
|
21303
21796
|
padding: 5,
|
|
21304
|
-
display: (ctx) =>
|
|
21797
|
+
display: (ctx) => {
|
|
21798
|
+
if (!(refAnnotation.display ?? true)) return false;
|
|
21799
|
+
if (!isCalloutAnchorInChartArea(ctx, refAnnotation, calloutCfg.margin ?? 0)) return false;
|
|
21800
|
+
return true;
|
|
21801
|
+
},
|
|
21305
21802
|
xValue: (ctx) => {
|
|
21306
21803
|
const persistenceId = getChartFromCtx(ctx)?.options?.persistenceId;
|
|
21307
21804
|
const stored = getAnnotationPosition(persistenceId, `callout-annotation-${index}`);
|
|
@@ -21318,10 +21815,10 @@ var getCalloutAnnotation = (refAnnotation, index) => {
|
|
|
21318
21815
|
displayDragCoordinates: false,
|
|
21319
21816
|
enableDrag: true,
|
|
21320
21817
|
enter: ({ element }, { chart }) => {
|
|
21321
|
-
return handleLabelEnter(element, chart, { enableDrag:
|
|
21818
|
+
return handleLabelEnter(element, chart, { enableDrag: Boolean(chart?.options?.plugins?.annotationDraggerPlugin?.enabled) });
|
|
21322
21819
|
},
|
|
21323
21820
|
leave: ({ element }, { chart }) => {
|
|
21324
|
-
return handleLabelLeave(element, chart, { enableDrag:
|
|
21821
|
+
return handleLabelLeave(element, chart, { enableDrag: Boolean(chart?.options?.plugins?.annotationDraggerPlugin?.enabled) });
|
|
21325
21822
|
},
|
|
21326
21823
|
onDragStart: onCalloutDragStart ? () => (coords) => {
|
|
21327
21824
|
return onCalloutDragStart(coords, refAnnotation);
|
|
@@ -21333,12 +21830,21 @@ var getCalloutAnnotation = (refAnnotation, index) => {
|
|
|
21333
21830
|
return onCalloutDragEnd(coords, refAnnotation);
|
|
21334
21831
|
} : void 0,
|
|
21335
21832
|
calloutConnector: {
|
|
21336
|
-
enabled:
|
|
21833
|
+
enabled: ({ chart }) => {
|
|
21834
|
+
if (!calloutCfg?.onlyWhenOverlapping) return true;
|
|
21835
|
+
return isCalloutOverlapping({ chart }, refAnnotation, index);
|
|
21836
|
+
},
|
|
21337
21837
|
fromId: baseId,
|
|
21338
21838
|
strokeStyle,
|
|
21339
21839
|
lineWidth,
|
|
21340
21840
|
startOffset,
|
|
21341
|
-
endOffset
|
|
21841
|
+
endOffset,
|
|
21842
|
+
anchor: {
|
|
21843
|
+
position: refAnnotation?.labelConfig?.position,
|
|
21844
|
+
xAdjust: refAnnotation?.labelConfig?.xAdjust,
|
|
21845
|
+
yAdjust: refAnnotation?.labelConfig?.yAdjust,
|
|
21846
|
+
labelOffsetPx: refAnnotation?.labelOffsetPx
|
|
21847
|
+
}
|
|
21342
21848
|
}
|
|
21343
21849
|
}];
|
|
21344
21850
|
};
|
|
@@ -21519,11 +22025,6 @@ var useChartOptions = ({ chartRef, state, options, dispatch, generatedDatasets,
|
|
|
21519
22025
|
state
|
|
21520
22026
|
]);
|
|
21521
22027
|
const dragData = useMemo(() => enableDragPoints && getDraggableData(options), [enableDragPoints, options]);
|
|
21522
|
-
const onChartHover = useMemo(() => onHover(hoveredPoint, setHoveredPoint, generatedDatasets), [
|
|
21523
|
-
generatedDatasets,
|
|
21524
|
-
hoveredPoint,
|
|
21525
|
-
onHover
|
|
21526
|
-
]);
|
|
21527
22028
|
const panOptions = useMemo(() => ({
|
|
21528
22029
|
enabled: panEnabled,
|
|
21529
22030
|
mode: PanZoomMode.XY,
|
|
@@ -21554,13 +22055,13 @@ var useChartOptions = ({ chartRef, state, options, dispatch, generatedDatasets,
|
|
|
21554
22055
|
updateAxesRangesFromChart,
|
|
21555
22056
|
zoomEnabled
|
|
21556
22057
|
]);
|
|
21557
|
-
const
|
|
21558
|
-
const
|
|
21559
|
-
const plugins = {
|
|
22058
|
+
const verticalMarkersAnnotation = options?.annotations?.verticalMarkersAnnotation ?? {};
|
|
22059
|
+
const verticalMarkersPluginEnabled = Boolean(options?.plugins?.verticalMarkersPlugin?.enabled ?? verticalMarkersAnnotation?.enabled);
|
|
22060
|
+
const plugins = useMemo(() => ({
|
|
21560
22061
|
datalabels,
|
|
21561
22062
|
annotationDraggerPlugin: { enabled: state?.enableDragAnnotation },
|
|
21562
22063
|
calloutConnectorPlugin: { enableCalloutAnnotation: options?.annotations.enableCalloutAnnotation },
|
|
21563
|
-
|
|
22064
|
+
verticalMarkersPlugin: { enabled: verticalMarkersPluginEnabled },
|
|
21564
22065
|
annotation: toAnnotationObject(annotation),
|
|
21565
22066
|
zoom: {
|
|
21566
22067
|
pan: panOptions,
|
|
@@ -21585,7 +22086,32 @@ var useChartOptions = ({ chartRef, state, options, dispatch, generatedDatasets,
|
|
|
21585
22086
|
lineHeight
|
|
21586
22087
|
},
|
|
21587
22088
|
...dragData
|
|
21588
|
-
}
|
|
22089
|
+
}), [
|
|
22090
|
+
annotation,
|
|
22091
|
+
customLegendPlugin,
|
|
22092
|
+
datalabels,
|
|
22093
|
+
dragData,
|
|
22094
|
+
fontSize,
|
|
22095
|
+
legend,
|
|
22096
|
+
lineHeight,
|
|
22097
|
+
maxWidth,
|
|
22098
|
+
options?.annotations.enableCalloutAnnotation,
|
|
22099
|
+
panOptions,
|
|
22100
|
+
position,
|
|
22101
|
+
showLabel,
|
|
22102
|
+
state?.enableDragAnnotation,
|
|
22103
|
+
text,
|
|
22104
|
+
tooltip,
|
|
22105
|
+
verticalMarkersPluginEnabled,
|
|
22106
|
+
xOffset,
|
|
22107
|
+
yOffset,
|
|
22108
|
+
zoomOptions
|
|
22109
|
+
]);
|
|
22110
|
+
const onChartHover = useMemo(() => onHover(hoveredPoint, setHoveredPoint, generatedDatasets), [
|
|
22111
|
+
generatedDatasets,
|
|
22112
|
+
hoveredPoint,
|
|
22113
|
+
onHover
|
|
22114
|
+
]);
|
|
21589
22115
|
return useMemo(() => ({
|
|
21590
22116
|
persistenceId,
|
|
21591
22117
|
layout: { padding: layoutPadding },
|
|
@@ -21613,6 +22139,7 @@ var useChartOptions = ({ chartRef, state, options, dispatch, generatedDatasets,
|
|
|
21613
22139
|
layoutPadding,
|
|
21614
22140
|
lineEnabled,
|
|
21615
22141
|
onAnimationComplete,
|
|
22142
|
+
onChartHover,
|
|
21616
22143
|
options?.annotations,
|
|
21617
22144
|
options?.chartStyling?.maintainAspectRatio,
|
|
21618
22145
|
options?.chartStyling?.performanceMode,
|
|
@@ -22138,52 +22665,126 @@ var annotationDraggerPlugin = {
|
|
|
22138
22665
|
};
|
|
22139
22666
|
//#endregion
|
|
22140
22667
|
//#region src/components/line-chart/plugins/callout-plugin/helpers.ts
|
|
22141
|
-
var
|
|
22142
|
-
|
|
22143
|
-
|
|
22144
|
-
return
|
|
22668
|
+
var getRectangleEdgePoint = (el, targetX, targetY, offset) => {
|
|
22669
|
+
const width = el?.width ?? 0;
|
|
22670
|
+
const height = el?.height ?? 0;
|
|
22671
|
+
if (width <= 0 || height <= 0) return {
|
|
22672
|
+
x: el.centerX,
|
|
22673
|
+
y: el.centerY
|
|
22674
|
+
};
|
|
22675
|
+
const halfWidth = width / 2;
|
|
22676
|
+
const halfHeight = height / 2;
|
|
22677
|
+
const dx = targetX - el.centerX;
|
|
22678
|
+
const dy = targetY - el.centerY;
|
|
22679
|
+
const length = Math.sqrt(dx * dx + dy * dy) || 1;
|
|
22680
|
+
const ux = dx / length;
|
|
22681
|
+
const uy = dy / length;
|
|
22682
|
+
const tx = Math.abs(ux) > 1e-6 ? halfWidth / Math.abs(ux) : Number.POSITIVE_INFINITY;
|
|
22683
|
+
const ty = Math.abs(uy) > 1e-6 ? halfHeight / Math.abs(uy) : Number.POSITIVE_INFINITY;
|
|
22684
|
+
const distance = Math.min(tx, ty) + offset;
|
|
22685
|
+
return {
|
|
22686
|
+
x: el.centerX + ux * distance,
|
|
22687
|
+
y: el.centerY + uy * distance
|
|
22688
|
+
};
|
|
22689
|
+
};
|
|
22690
|
+
var getLabelEdgePoint = (labelEl, startX, endOffset) => {
|
|
22691
|
+
const width = labelEl?.width ?? 0;
|
|
22692
|
+
const height = labelEl?.height ?? 0;
|
|
22693
|
+
if (width <= 0 || height <= 0) return {
|
|
22694
|
+
x: labelEl.centerX,
|
|
22695
|
+
y: labelEl.centerY
|
|
22696
|
+
};
|
|
22697
|
+
const halfWidth = width / 2;
|
|
22698
|
+
const direction = startX <= labelEl.centerX ? -1 : 1;
|
|
22699
|
+
return {
|
|
22700
|
+
x: labelEl.centerX + direction * (halfWidth + endOffset),
|
|
22701
|
+
y: labelEl.centerY
|
|
22702
|
+
};
|
|
22703
|
+
};
|
|
22704
|
+
var getReferencePoint = (fromEl, connector) => {
|
|
22705
|
+
const { anchor } = connector;
|
|
22706
|
+
if (!anchor) return {
|
|
22707
|
+
x: fromEl.centerX,
|
|
22708
|
+
y: fromEl.centerY
|
|
22709
|
+
};
|
|
22710
|
+
const width = fromEl?.width ?? 0;
|
|
22711
|
+
const height = fromEl?.height ?? 0;
|
|
22712
|
+
const radius = fromEl?.options?.radius ?? 0;
|
|
22713
|
+
const halfWidth = width / 2;
|
|
22714
|
+
const halfHeight = height / 2;
|
|
22715
|
+
const labelOffset = anchor?.labelOffsetPx ?? 14;
|
|
22716
|
+
const xAdjust = anchor?.xAdjust ?? 0;
|
|
22717
|
+
const yAdjust = anchor?.yAdjust ?? 0;
|
|
22718
|
+
const position = anchor?.position ?? "top";
|
|
22719
|
+
let x = fromEl.centerX;
|
|
22720
|
+
let y = fromEl.centerY;
|
|
22721
|
+
switch (position) {
|
|
22722
|
+
case "left":
|
|
22723
|
+
x -= Math.max(halfWidth, radius) + labelOffset;
|
|
22724
|
+
break;
|
|
22725
|
+
case "right":
|
|
22726
|
+
x += Math.max(halfWidth, radius) + labelOffset;
|
|
22727
|
+
break;
|
|
22728
|
+
case "bottom":
|
|
22729
|
+
y += Math.max(halfHeight, radius) + labelOffset;
|
|
22730
|
+
break;
|
|
22731
|
+
case "top-left":
|
|
22732
|
+
x -= halfWidth;
|
|
22733
|
+
y -= halfHeight;
|
|
22734
|
+
break;
|
|
22735
|
+
case "top-right":
|
|
22736
|
+
x += halfWidth;
|
|
22737
|
+
y -= halfHeight;
|
|
22738
|
+
break;
|
|
22739
|
+
case "bottom-left":
|
|
22740
|
+
x -= halfWidth;
|
|
22741
|
+
y += halfHeight;
|
|
22742
|
+
break;
|
|
22743
|
+
case "bottom-right":
|
|
22744
|
+
x += halfWidth;
|
|
22745
|
+
y += halfHeight;
|
|
22746
|
+
break;
|
|
22747
|
+
default:
|
|
22748
|
+
y -= Math.max(halfHeight, radius) + labelOffset;
|
|
22749
|
+
break;
|
|
22750
|
+
}
|
|
22751
|
+
return {
|
|
22752
|
+
x: x + xAdjust,
|
|
22753
|
+
y: y + yAdjust
|
|
22754
|
+
};
|
|
22145
22755
|
};
|
|
22146
22756
|
var computeConnectorPoints = (fromEl, labelEl, connector) => {
|
|
22147
22757
|
const x1c = fromEl?.centerX;
|
|
22148
22758
|
const y1c = fromEl?.centerY;
|
|
22149
22759
|
const cx = labelEl?.centerX;
|
|
22150
22760
|
const cy = labelEl?.centerY;
|
|
22151
|
-
const labelWidth = labelEl?.width ?? 0;
|
|
22152
|
-
const labelHeight = labelEl?.height ?? 0;
|
|
22153
22761
|
const ux = cx - x1c;
|
|
22154
22762
|
const uy = cy - y1c;
|
|
22155
22763
|
const len = Math.sqrt(ux * ux + uy * uy) || 1;
|
|
22156
22764
|
const dx = ux / len;
|
|
22157
22765
|
const dy = uy / len;
|
|
22158
|
-
const
|
|
22159
|
-
const
|
|
22160
|
-
const
|
|
22161
|
-
|
|
22162
|
-
|
|
22163
|
-
|
|
22164
|
-
|
|
22165
|
-
|
|
22166
|
-
|
|
22167
|
-
|
|
22168
|
-
|
|
22169
|
-
|
|
22170
|
-
|
|
22171
|
-
const vyn = vy / vlen;
|
|
22172
|
-
const tx = Math.abs(vxn) > 1e-6 ? hw / Math.abs(vxn) : Number.POSITIVE_INFINITY;
|
|
22173
|
-
const ty = Math.abs(vyn) > 1e-6 ? hh / Math.abs(vyn) : Number.POSITIVE_INFINITY;
|
|
22174
|
-
const total = Math.min(tx, ty) + (connector.endOffset ?? 1);
|
|
22175
|
-
endX = cx + vxn * total;
|
|
22176
|
-
endY = cy + vyn * total;
|
|
22177
|
-
} else {
|
|
22178
|
-
const endOffset = connector.endOffset ?? 1;
|
|
22179
|
-
endX = cx - dx * endOffset;
|
|
22180
|
-
endY = cy - dy * endOffset;
|
|
22181
|
-
}
|
|
22766
|
+
const startOffset = connector?.startOffset ?? 6;
|
|
22767
|
+
const isPointAnchor = typeof fromEl?.options?.radius === "number";
|
|
22768
|
+
const referencePoint = connector?.anchor && !isPointAnchor ? getReferencePoint(fromEl, connector) : isPointAnchor ? {
|
|
22769
|
+
x: x1c,
|
|
22770
|
+
y: y1c
|
|
22771
|
+
} : getRectangleEdgePoint(fromEl, cx, cy, startOffset);
|
|
22772
|
+
const endOffset = connector?.endOffset ?? 1;
|
|
22773
|
+
const end = typeof labelEl?.width === "number" && typeof labelEl?.height === "number" ? getLabelEdgePoint(labelEl, referencePoint.x, endOffset) : {
|
|
22774
|
+
x: cx - dx * endOffset,
|
|
22775
|
+
y: cy - dy * endOffset
|
|
22776
|
+
};
|
|
22777
|
+
const tickHalf = isPointAnchor ? 0 : (connector?.anchor?.tickSize ?? 8) / 2;
|
|
22778
|
+
const lineDirection = end.x >= referencePoint.x ? 1 : -1;
|
|
22182
22779
|
return {
|
|
22183
|
-
startX,
|
|
22184
|
-
startY,
|
|
22185
|
-
endX,
|
|
22186
|
-
endY
|
|
22780
|
+
startX: referencePoint.x + lineDirection * tickHalf,
|
|
22781
|
+
startY: referencePoint.y,
|
|
22782
|
+
endX: end.x,
|
|
22783
|
+
endY: end.y,
|
|
22784
|
+
tickStartX: referencePoint.x - tickHalf,
|
|
22785
|
+
tickStartY: referencePoint.y,
|
|
22786
|
+
tickEndX: referencePoint.x + tickHalf,
|
|
22787
|
+
tickEndY: referencePoint.y
|
|
22187
22788
|
};
|
|
22188
22789
|
};
|
|
22189
22790
|
//#endregion
|
|
@@ -22201,54 +22802,41 @@ var calloutConnectorPlugin = {
|
|
|
22201
22802
|
if (!raw) return;
|
|
22202
22803
|
(Array.isArray(raw) ? raw : Object.values(raw)).forEach((opt) => {
|
|
22203
22804
|
const connector = opt?.calloutConnector;
|
|
22204
|
-
if (!connector || !
|
|
22805
|
+
if (!connector || !opt?.id) return;
|
|
22205
22806
|
const labelEl = elements.find((el) => el.options && el.options.id === opt.id);
|
|
22206
22807
|
const fromEl = elements.find((el) => el.options && el.options.id === connector.fromId);
|
|
22207
22808
|
if (!labelEl || !fromEl) return;
|
|
22208
22809
|
if (labelEl.options?.display === false) return;
|
|
22209
|
-
|
|
22810
|
+
if (!(typeof connector.enabled === "function" ? connector.enabled({
|
|
22811
|
+
chart,
|
|
22812
|
+
labelEl,
|
|
22813
|
+
fromEl,
|
|
22814
|
+
option: opt
|
|
22815
|
+
}) : connector.enabled !== false)) return;
|
|
22816
|
+
const { startX, startY, endX, endY, tickStartX, tickStartY, tickEndX, tickEndY } = computeConnectorPoints(fromEl, labelEl, connector) ?? {};
|
|
22210
22817
|
const ctx = chart?.ctx;
|
|
22818
|
+
const strokeStyle = connector?.strokeStyle ?? "rgba(120, 126, 138, 0.9)";
|
|
22211
22819
|
ctx?.save?.();
|
|
22212
22820
|
ctx?.beginPath?.();
|
|
22213
22821
|
ctx?.moveTo?.(startX, startY);
|
|
22214
22822
|
ctx?.lineTo?.(endX, endY);
|
|
22215
22823
|
ctx.lineWidth = connector?.lineWidth ?? 1;
|
|
22216
|
-
ctx.strokeStyle =
|
|
22824
|
+
ctx.strokeStyle = strokeStyle;
|
|
22217
22825
|
if (connector?.lineDash && connector?.lineDash?.length) ctx?.setLineDash?.(connector.lineDash);
|
|
22218
22826
|
ctx.lineCap = "round";
|
|
22219
22827
|
ctx?.stroke?.();
|
|
22828
|
+
ctx?.beginPath?.();
|
|
22829
|
+
ctx?.moveTo?.(tickStartX, tickStartY);
|
|
22830
|
+
ctx?.lineTo?.(tickEndX, tickEndY);
|
|
22831
|
+
ctx.lineWidth = Math.max(connector?.lineWidth ?? 1, 1);
|
|
22832
|
+
ctx.strokeStyle = strokeStyle;
|
|
22833
|
+
ctx?.stroke?.();
|
|
22220
22834
|
ctx?.restore?.();
|
|
22221
22835
|
});
|
|
22222
22836
|
}
|
|
22223
22837
|
};
|
|
22224
22838
|
//#endregion
|
|
22225
|
-
//#region src/components/line-chart/plugins/
|
|
22226
|
-
var LineMarkerSide = /* @__PURE__ */ function(LineMarkerSide) {
|
|
22227
|
-
LineMarkerSide["Left"] = "left";
|
|
22228
|
-
LineMarkerSide["Right"] = "right";
|
|
22229
|
-
return LineMarkerSide;
|
|
22230
|
-
}({});
|
|
22231
|
-
var LineMarkerDirection = /* @__PURE__ */ function(LineMarkerDirection) {
|
|
22232
|
-
LineMarkerDirection["Vertical"] = "vertical";
|
|
22233
|
-
LineMarkerDirection["Horizontal"] = "horizontal";
|
|
22234
|
-
return LineMarkerDirection;
|
|
22235
|
-
}({});
|
|
22236
|
-
var LineMarkerLabelPosition = /* @__PURE__ */ function(LineMarkerLabelPosition) {
|
|
22237
|
-
LineMarkerLabelPosition["Left"] = "left";
|
|
22238
|
-
LineMarkerLabelPosition["Right"] = "right";
|
|
22239
|
-
LineMarkerLabelPosition["Top"] = "top";
|
|
22240
|
-
LineMarkerLabelPosition["Bottom"] = "bottom";
|
|
22241
|
-
LineMarkerLabelPosition["OnLine"] = "onLine";
|
|
22242
|
-
return LineMarkerLabelPosition;
|
|
22243
|
-
}({});
|
|
22244
|
-
var LineMarkerTextAlign = /* @__PURE__ */ function(LineMarkerTextAlign) {
|
|
22245
|
-
LineMarkerTextAlign["Left"] = "left";
|
|
22246
|
-
LineMarkerTextAlign["Right"] = "right";
|
|
22247
|
-
LineMarkerTextAlign["Center"] = "center";
|
|
22248
|
-
return LineMarkerTextAlign;
|
|
22249
|
-
}({});
|
|
22250
|
-
//#endregion
|
|
22251
|
-
//#region src/components/line-chart/plugins/line-markers-plugin/utils.ts
|
|
22839
|
+
//#region src/components/line-chart/plugins/vertical-markers-plugin/utils.ts
|
|
22252
22840
|
var isFiniteNumber = (v) => {
|
|
22253
22841
|
return isNumber(v) && Number.isFinite(v);
|
|
22254
22842
|
};
|
|
@@ -22274,336 +22862,68 @@ var clamp = (v, min, max) => {
|
|
|
22274
22862
|
var crispLinePx = (v) => {
|
|
22275
22863
|
return Math.round(v) + .5;
|
|
22276
22864
|
};
|
|
22277
|
-
var toLines = (label) => {
|
|
22278
|
-
if (!label) return [];
|
|
22279
|
-
return isArray(label) ? label : [label];
|
|
22280
|
-
};
|
|
22281
|
-
var lineHeightPx = (font) => {
|
|
22282
|
-
const match = /(\d+)\s*px/i.exec(font);
|
|
22283
|
-
const size = match ? Number(match[1]) : 12;
|
|
22284
|
-
return Math.max(10, Math.round(size * 1.2));
|
|
22285
|
-
};
|
|
22286
|
-
var clusterByXDistance = (labels, clusterXPx) => {
|
|
22287
|
-
if (!labels.length) return [];
|
|
22288
|
-
const sorted = [...labels].sort((a, b) => a.x - b.x);
|
|
22289
|
-
const clusters = [];
|
|
22290
|
-
let current = [sorted[0]];
|
|
22291
|
-
for (let i = 1; i < sorted.length; i += 1) {
|
|
22292
|
-
const prev = sorted[i - 1];
|
|
22293
|
-
const currentItem = sorted[i];
|
|
22294
|
-
if (Math.abs(currentItem.x - prev.x) <= clusterXPx) {
|
|
22295
|
-
current.push(currentItem);
|
|
22296
|
-
continue;
|
|
22297
|
-
}
|
|
22298
|
-
clusters.push(current);
|
|
22299
|
-
current = [currentItem];
|
|
22300
|
-
}
|
|
22301
|
-
clusters.push(current);
|
|
22302
|
-
return clusters;
|
|
22303
|
-
};
|
|
22304
|
-
var resolveCluster = ({ labels, chartTop, chartBottom, gapPx }) => {
|
|
22305
|
-
const sorted = [...labels].sort((a, b) => a.y - b.y);
|
|
22306
|
-
if (!sorted.length) return {};
|
|
22307
|
-
const placed = sorted.map((item) => ({
|
|
22308
|
-
...item,
|
|
22309
|
-
placedY: item.y
|
|
22310
|
-
}));
|
|
22311
|
-
for (let i = 1; i < placed.length; i += 1) {
|
|
22312
|
-
const prev = placed[i - 1];
|
|
22313
|
-
const curr = placed[i];
|
|
22314
|
-
const prevBottom = prev.placedY + prev.height / 2;
|
|
22315
|
-
const currTop = curr.placedY - curr.height / 2;
|
|
22316
|
-
const overlap = prevBottom + gapPx - currTop;
|
|
22317
|
-
if (overlap > 0) curr.placedY += overlap;
|
|
22318
|
-
}
|
|
22319
|
-
const last = placed[placed.length - 1];
|
|
22320
|
-
const overflowBottom = last.placedY + last.height / 2 - chartBottom;
|
|
22321
|
-
if (overflowBottom > 0) placed.forEach((item) => {
|
|
22322
|
-
item.placedY -= overflowBottom;
|
|
22323
|
-
});
|
|
22324
|
-
const first = placed[0];
|
|
22325
|
-
const overflowTop = chartTop - (first.placedY - first.height / 2);
|
|
22326
|
-
if (overflowTop > 0) placed.forEach((item) => {
|
|
22327
|
-
item.placedY += overflowTop;
|
|
22328
|
-
});
|
|
22329
|
-
return placed.reduce((acc, item) => {
|
|
22330
|
-
acc[item.id] = clamp(item.placedY, chartTop, chartBottom);
|
|
22331
|
-
return acc;
|
|
22332
|
-
}, {});
|
|
22333
|
-
};
|
|
22334
|
-
var resolveLabelCollisions = ({ labels, chartTop, chartBottom, clusterXPx, gapPx }) => {
|
|
22335
|
-
const result = {};
|
|
22336
|
-
[LineMarkerSide.Left, LineMarkerSide.Right].forEach((side) => {
|
|
22337
|
-
clusterByXDistance(labels.filter((label) => label.side === side), clusterXPx).forEach((cluster) => {
|
|
22338
|
-
Object.assign(result, resolveCluster({
|
|
22339
|
-
labels: cluster,
|
|
22340
|
-
chartTop,
|
|
22341
|
-
chartBottom,
|
|
22342
|
-
gapPx
|
|
22343
|
-
}));
|
|
22344
|
-
});
|
|
22345
|
-
});
|
|
22346
|
-
return result;
|
|
22347
|
-
};
|
|
22348
22865
|
//#endregion
|
|
22349
|
-
//#region src/components/line-chart/plugins/
|
|
22350
|
-
var
|
|
22866
|
+
//#region src/components/line-chart/plugins/vertical-markers-plugin/draw.ts
|
|
22867
|
+
var drawVerticalLine = ({ chart, xPx, y1, y2, color, opacity, lineWidth, lineDash }) => {
|
|
22351
22868
|
const { ctx } = chart ?? {};
|
|
22352
|
-
const
|
|
22353
|
-
const endX = crispLinePx(x2);
|
|
22354
|
-
const startY = crispLinePx(y1);
|
|
22355
|
-
const endY = crispLinePx(y2);
|
|
22869
|
+
const x = crispLinePx(xPx);
|
|
22356
22870
|
ctx?.save?.();
|
|
22357
22871
|
ctx.globalAlpha = opacity;
|
|
22358
22872
|
ctx?.beginPath?.();
|
|
22359
22873
|
ctx.lineWidth = lineWidth;
|
|
22360
22874
|
ctx.strokeStyle = color;
|
|
22361
22875
|
ctx?.setLineDash?.(lineDash);
|
|
22362
|
-
ctx.lineCap = "
|
|
22363
|
-
ctx?.moveTo?.(
|
|
22364
|
-
ctx?.lineTo?.(
|
|
22876
|
+
ctx.lineCap = "round";
|
|
22877
|
+
ctx?.moveTo?.(x, y1);
|
|
22878
|
+
ctx?.lineTo?.(x, y2);
|
|
22365
22879
|
ctx?.stroke?.();
|
|
22366
22880
|
ctx?.restore?.();
|
|
22367
|
-
return
|
|
22368
|
-
x1: startX,
|
|
22369
|
-
y1: startY,
|
|
22370
|
-
x2: endX,
|
|
22371
|
-
y2: endY
|
|
22372
|
-
};
|
|
22373
|
-
};
|
|
22374
|
-
var isWithin = (value, min, max) => {
|
|
22375
|
-
return value >= min && value <= max;
|
|
22376
|
-
};
|
|
22377
|
-
var isTickElementInsideByDirection = (args) => {
|
|
22378
|
-
const { direction, chartArea, box } = args;
|
|
22379
|
-
if (direction === LineMarkerDirection.Vertical) return box.top >= chartArea.top && box.bottom <= chartArea.bottom;
|
|
22380
|
-
return box.left >= chartArea.left && box.right <= chartArea.right;
|
|
22381
|
-
};
|
|
22382
|
-
var resolveDefaultLabelPosition = (args) => {
|
|
22383
|
-
const { direction, side } = args;
|
|
22384
|
-
if (direction === LineMarkerDirection.Vertical) return side === LineMarkerSide.Left ? LineMarkerLabelPosition.Right : LineMarkerLabelPosition.Left;
|
|
22385
|
-
return side === LineMarkerSide.Left ? LineMarkerLabelPosition.Right : LineMarkerLabelPosition.Left;
|
|
22386
|
-
};
|
|
22387
|
-
var getLabelAnchor = (args) => {
|
|
22388
|
-
const { x, y, direction, labelOffset, bootSize, labelPosition } = args;
|
|
22389
|
-
const distance = bootSize + labelOffset;
|
|
22390
|
-
if (direction === LineMarkerDirection.Horizontal) switch (labelPosition) {
|
|
22391
|
-
case LineMarkerLabelPosition.Left: return {
|
|
22392
|
-
x: x - distance,
|
|
22393
|
-
y,
|
|
22394
|
-
textAlign: LineMarkerTextAlign.Right
|
|
22395
|
-
};
|
|
22396
|
-
case LineMarkerLabelPosition.Right: return {
|
|
22397
|
-
x: x + distance,
|
|
22398
|
-
y,
|
|
22399
|
-
textAlign: LineMarkerTextAlign.Left
|
|
22400
|
-
};
|
|
22401
|
-
case LineMarkerLabelPosition.Top: return {
|
|
22402
|
-
x,
|
|
22403
|
-
y: y - distance,
|
|
22404
|
-
textAlign: LineMarkerTextAlign.Center
|
|
22405
|
-
};
|
|
22406
|
-
case LineMarkerLabelPosition.Bottom: return {
|
|
22407
|
-
x,
|
|
22408
|
-
y: y + distance,
|
|
22409
|
-
textAlign: LineMarkerTextAlign.Center
|
|
22410
|
-
};
|
|
22411
|
-
case LineMarkerLabelPosition.OnLine: return {
|
|
22412
|
-
x,
|
|
22413
|
-
y,
|
|
22414
|
-
textAlign: LineMarkerTextAlign.Center
|
|
22415
|
-
};
|
|
22416
|
-
default: return {
|
|
22417
|
-
x,
|
|
22418
|
-
y,
|
|
22419
|
-
textAlign: LineMarkerTextAlign.Center
|
|
22420
|
-
};
|
|
22421
|
-
}
|
|
22422
|
-
switch (labelPosition) {
|
|
22423
|
-
case LineMarkerLabelPosition.Left: return {
|
|
22424
|
-
x: x - distance,
|
|
22425
|
-
y,
|
|
22426
|
-
textAlign: LineMarkerTextAlign.Right
|
|
22427
|
-
};
|
|
22428
|
-
case LineMarkerLabelPosition.Right: return {
|
|
22429
|
-
x: x + distance,
|
|
22430
|
-
y,
|
|
22431
|
-
textAlign: LineMarkerTextAlign.Left
|
|
22432
|
-
};
|
|
22433
|
-
case LineMarkerLabelPosition.Top: return {
|
|
22434
|
-
x,
|
|
22435
|
-
y: y - distance,
|
|
22436
|
-
textAlign: LineMarkerTextAlign.Center
|
|
22437
|
-
};
|
|
22438
|
-
case LineMarkerLabelPosition.Bottom: return {
|
|
22439
|
-
x,
|
|
22440
|
-
y: y + distance,
|
|
22441
|
-
textAlign: LineMarkerTextAlign.Center
|
|
22442
|
-
};
|
|
22443
|
-
case LineMarkerLabelPosition.OnLine: return {
|
|
22444
|
-
x,
|
|
22445
|
-
y,
|
|
22446
|
-
textAlign: LineMarkerTextAlign.Center
|
|
22447
|
-
};
|
|
22448
|
-
default: return {
|
|
22449
|
-
x,
|
|
22450
|
-
y,
|
|
22451
|
-
textAlign: LineMarkerTextAlign.Center
|
|
22452
|
-
};
|
|
22453
|
-
}
|
|
22454
|
-
};
|
|
22455
|
-
var getLineTextBox = (args) => {
|
|
22456
|
-
const { textAlign, x, y, width, lineHeight } = args;
|
|
22457
|
-
return {
|
|
22458
|
-
left: textAlign === LineMarkerTextAlign.Right ? x - width : textAlign === LineMarkerTextAlign.Center ? x - width / 2 : x,
|
|
22459
|
-
right: textAlign === LineMarkerTextAlign.Right ? x : textAlign === LineMarkerTextAlign.Center ? x + width / 2 : x + width,
|
|
22460
|
-
top: y - lineHeight / 2,
|
|
22461
|
-
bottom: y + lineHeight / 2
|
|
22462
|
-
};
|
|
22463
|
-
};
|
|
22464
|
-
var getOppositeLabelPosition = (position) => {
|
|
22465
|
-
switch (position) {
|
|
22466
|
-
case LineMarkerLabelPosition.Left: return LineMarkerLabelPosition.Right;
|
|
22467
|
-
case LineMarkerLabelPosition.Right: return LineMarkerLabelPosition.Left;
|
|
22468
|
-
case LineMarkerLabelPosition.Top: return LineMarkerLabelPosition.Bottom;
|
|
22469
|
-
case LineMarkerLabelPosition.Bottom: return LineMarkerLabelPosition.Top;
|
|
22470
|
-
default: return LineMarkerLabelPosition.OnLine;
|
|
22471
|
-
}
|
|
22881
|
+
return x;
|
|
22472
22882
|
};
|
|
22473
22883
|
var drawTick = (args) => {
|
|
22474
|
-
const { ctx, x, y, side, tick, defaultColor, defaultFont
|
|
22475
|
-
const direction = args?.direction ?? LineMarkerDirection.Vertical;
|
|
22884
|
+
const { ctx, x, y, side, tick, defaultColor, defaultFont } = args ?? {};
|
|
22476
22885
|
const reverse = Boolean(args?.reverse);
|
|
22477
|
-
const labelY = args?.labelY ?? y;
|
|
22478
|
-
const bootEnabled = tick?.enabled ?? true;
|
|
22479
|
-
const hasLabel = Array.isArray(tick?.label) ? tick.label.length > 0 : Boolean(tick?.label);
|
|
22480
|
-
if (!bootEnabled && !hasLabel) return;
|
|
22481
22886
|
const color = tick?.color ?? defaultColor;
|
|
22482
22887
|
const font = tick?.font ?? defaultFont;
|
|
22483
22888
|
const labelOffset = tick?.labelOffsetPx ?? 6;
|
|
22484
|
-
const bootSize =
|
|
22485
|
-
const dir = side ===
|
|
22486
|
-
const xTickEnd =
|
|
22487
|
-
const yTickEnd = crispLinePx(y);
|
|
22889
|
+
const bootSize = 6;
|
|
22890
|
+
const dir = side === "left" ? 1 : -1;
|
|
22891
|
+
const xTickEnd = x;
|
|
22488
22892
|
ctx?.save?.();
|
|
22489
22893
|
ctx.strokeStyle = color;
|
|
22490
22894
|
ctx.fillStyle = color;
|
|
22491
22895
|
ctx.lineWidth = 1;
|
|
22492
|
-
const xOuter =
|
|
22493
|
-
|
|
22494
|
-
|
|
22495
|
-
|
|
22496
|
-
|
|
22497
|
-
|
|
22498
|
-
|
|
22499
|
-
top: Math.min(yTickEnd, yOuter, yThird),
|
|
22500
|
-
bottom: Math.max(yTickEnd, yOuter, yThird)
|
|
22501
|
-
};
|
|
22502
|
-
const canDrawBoot = (direction === LineMarkerDirection.Vertical ? isWithin(yTickEnd, chartArea.top, chartArea.bottom) : isWithin(xTickEnd, chartArea.left, chartArea.right)) && isTickElementInsideByDirection({
|
|
22503
|
-
direction,
|
|
22504
|
-
chartArea,
|
|
22505
|
-
box: bootBounds
|
|
22506
|
-
});
|
|
22507
|
-
if (bootEnabled && canDrawBoot) {
|
|
22508
|
-
ctx?.beginPath?.();
|
|
22509
|
-
ctx?.moveTo?.(xTickEnd, yTickEnd);
|
|
22510
|
-
ctx?.lineTo?.(xOuter, yOuter);
|
|
22511
|
-
ctx?.lineTo?.(xThird, yThird);
|
|
22512
|
-
ctx?.closePath?.();
|
|
22513
|
-
ctx?.fill?.();
|
|
22514
|
-
}
|
|
22896
|
+
const xOuter = xTickEnd + dir * bootSize;
|
|
22897
|
+
ctx?.beginPath?.();
|
|
22898
|
+
ctx?.moveTo?.(xTickEnd, y);
|
|
22899
|
+
ctx?.lineTo?.(xOuter, y);
|
|
22900
|
+
ctx?.lineTo?.(xTickEnd, reverse ? y + bootSize : y - bootSize);
|
|
22901
|
+
ctx?.closePath?.();
|
|
22902
|
+
ctx?.fill?.();
|
|
22515
22903
|
const label = tick.label;
|
|
22516
22904
|
if (label) {
|
|
22517
22905
|
ctx.font = font;
|
|
22518
22906
|
ctx.textBaseline = "middle";
|
|
22519
|
-
|
|
22520
|
-
|
|
22521
|
-
|
|
22522
|
-
|
|
22523
|
-
|
|
22524
|
-
|
|
22525
|
-
|
|
22526
|
-
LineMarkerLabelPosition.Top,
|
|
22527
|
-
LineMarkerLabelPosition.Bottom,
|
|
22528
|
-
LineMarkerLabelPosition.OnLine
|
|
22529
|
-
].filter((value, index, arr) => arr.indexOf(value) === index);
|
|
22530
|
-
for (const labelPosition of fallbackPositions) {
|
|
22531
|
-
const anchor = getLabelAnchor({
|
|
22532
|
-
x: xTickEnd,
|
|
22533
|
-
y: labelY,
|
|
22534
|
-
direction,
|
|
22535
|
-
labelOffset,
|
|
22536
|
-
bootSize,
|
|
22537
|
-
labelPosition
|
|
22538
|
-
});
|
|
22539
|
-
const labelTextAlign = anchor.textAlign;
|
|
22540
|
-
ctx.textAlign = labelTextAlign;
|
|
22541
|
-
if (Array.isArray(label)) {
|
|
22542
|
-
const lineH = lineHeightPx(font);
|
|
22543
|
-
const startY = anchor.y - (label.length - 1) * lineH / 2;
|
|
22544
|
-
const metrics = label.map((line, i) => {
|
|
22545
|
-
const text = String(line);
|
|
22546
|
-
const width = ctx.measureText(text).width;
|
|
22547
|
-
const yLine = startY + i * lineH;
|
|
22548
|
-
return {
|
|
22549
|
-
text,
|
|
22550
|
-
yLine,
|
|
22551
|
-
box: getLineTextBox({
|
|
22552
|
-
textAlign: labelTextAlign,
|
|
22553
|
-
x: anchor.x,
|
|
22554
|
-
y: yLine,
|
|
22555
|
-
width,
|
|
22556
|
-
lineHeight: lineH
|
|
22557
|
-
})
|
|
22558
|
-
};
|
|
22559
|
-
});
|
|
22560
|
-
if (!metrics.every((lineData) => isTickElementInsideByDirection({
|
|
22561
|
-
direction,
|
|
22562
|
-
chartArea,
|
|
22563
|
-
box: lineData.box
|
|
22564
|
-
}))) continue;
|
|
22565
|
-
metrics.forEach((lineData) => ctx?.fillText?.(lineData.text, anchor.x, lineData.yLine));
|
|
22566
|
-
break;
|
|
22567
|
-
} else {
|
|
22568
|
-
const text = String(label);
|
|
22569
|
-
const width = ctx.measureText(text).width;
|
|
22570
|
-
const lineH = lineHeightPx(font);
|
|
22571
|
-
if (!isTickElementInsideByDirection({
|
|
22572
|
-
direction,
|
|
22573
|
-
chartArea,
|
|
22574
|
-
box: getLineTextBox({
|
|
22575
|
-
textAlign: labelTextAlign,
|
|
22576
|
-
x: anchor.x,
|
|
22577
|
-
y: anchor.y,
|
|
22578
|
-
width,
|
|
22579
|
-
lineHeight: lineH
|
|
22580
|
-
})
|
|
22581
|
-
})) continue;
|
|
22582
|
-
ctx?.fillText?.(text, anchor.x, anchor.y);
|
|
22583
|
-
break;
|
|
22584
|
-
}
|
|
22585
|
-
}
|
|
22907
|
+
ctx.textAlign = side === "left" ? "left" : "right";
|
|
22908
|
+
const tx = xOuter + dir * labelOffset;
|
|
22909
|
+
if (Array.isArray(label)) {
|
|
22910
|
+
const lineH = 12;
|
|
22911
|
+
const startY = y - (label.length - 1) * lineH / 2;
|
|
22912
|
+
label?.forEach((line, i) => ctx?.fillText?.(String(line), tx, startY + i * lineH));
|
|
22913
|
+
} else ctx?.fillText?.(String(label), tx, y);
|
|
22586
22914
|
}
|
|
22587
22915
|
ctx?.restore?.();
|
|
22588
22916
|
};
|
|
22589
|
-
var getTickLabelHeight = (tick, defaultFont) => {
|
|
22590
|
-
const lines = toLines(tick?.label);
|
|
22591
|
-
if (!lines.length) return 0;
|
|
22592
|
-
const lineHeight = lineHeightPx(tick?.font ?? defaultFont);
|
|
22593
|
-
return lines.length * lineHeight;
|
|
22594
|
-
};
|
|
22595
22917
|
//#endregion
|
|
22596
|
-
//#region src/components/line-chart/plugins/
|
|
22597
|
-
var DEFAULT_FONT = "12px sans-serif";
|
|
22598
|
-
var DEFAULT_COLOR = "rgba(20,20,20,0.9)";
|
|
22918
|
+
//#region src/components/line-chart/plugins/vertical-markers-plugin/vertical-markers-plugin.ts
|
|
22599
22919
|
var readPluginEnable = (chart) => {
|
|
22600
|
-
const {
|
|
22601
|
-
return asObject(
|
|
22920
|
+
const { verticalMarkersPlugin } = chart?.options?.plugins ?? {};
|
|
22921
|
+
return asObject(verticalMarkersPlugin)?.enabled === true;
|
|
22602
22922
|
};
|
|
22603
22923
|
var readAnnotationConfig = (chart) => {
|
|
22604
22924
|
const optionsWithAnnotations = chart?.options;
|
|
22605
22925
|
const configWithAnnotations = chart?.config?.options;
|
|
22606
|
-
return asObject(configWithAnnotations?.annotations?.
|
|
22926
|
+
return asObject(configWithAnnotations?.annotations?.verticalMarkersAnnotation) ?? asObject(optionsWithAnnotations?.annotations?.verticalMarkersAnnotation);
|
|
22607
22927
|
};
|
|
22608
22928
|
var readOwnBoolean = (obj, key) => {
|
|
22609
22929
|
if (!obj || typeof obj !== "object") return void 0;
|
|
@@ -22611,242 +22931,39 @@ var readOwnBoolean = (obj, key) => {
|
|
|
22611
22931
|
if (!descriptor || !("value" in descriptor)) return void 0;
|
|
22612
22932
|
return typeof descriptor?.value === "boolean" ? descriptor?.value : void 0;
|
|
22613
22933
|
};
|
|
22614
|
-
var
|
|
22615
|
-
return item?.direction ?? global?.lineDirection ?? LineMarkerDirection.Vertical;
|
|
22616
|
-
};
|
|
22617
|
-
var resolveSide = (item, global) => {
|
|
22618
|
-
return item?.stickSide ?? global?.stickSide ?? LineMarkerSide.Right;
|
|
22619
|
-
};
|
|
22620
|
-
var getEdgeX = (chartArea, side, edgePaddingPx) => {
|
|
22621
|
-
return clamp(side === LineMarkerSide.Left ? chartArea?.left + edgePaddingPx : chartArea?.right - edgePaddingPx, chartArea?.left, chartArea?.right);
|
|
22622
|
-
};
|
|
22623
|
-
var computeVerticalXPxBase = (args) => {
|
|
22934
|
+
var computeXPxBase = (args) => {
|
|
22624
22935
|
const { chart, chartArea, item, global } = args ?? {};
|
|
22625
22936
|
const stickToEdge = item?.stickToEdge ?? global?.stickToEdge ?? true;
|
|
22626
|
-
const
|
|
22937
|
+
const stickSide = item?.stickSide ?? global?.stickSide ?? "right";
|
|
22627
22938
|
const edgePaddingPx = global?.edgePaddingPx ?? 0;
|
|
22628
22939
|
const xValue = item?.xValue ?? global?.xValue;
|
|
22629
22940
|
if (isFiniteNumber(xValue)) return getPixelForValueSafe(resolveScale(chart, item?.xScaleID, "x"), xValue);
|
|
22630
|
-
if (stickToEdge) return
|
|
22941
|
+
if (stickToEdge) return clamp(stickSide === "left" ? chartArea?.left + edgePaddingPx : chartArea?.right - edgePaddingPx, chartArea?.left, chartArea?.right);
|
|
22631
22942
|
};
|
|
22632
|
-
var
|
|
22633
|
-
const { chart, chartArea, item, global
|
|
22943
|
+
var computeYSpan = (args) => {
|
|
22944
|
+
const { chart, chartArea, item, global } = args ?? {};
|
|
22634
22945
|
const yScale = resolveScale(chart, item?.yScaleID, "y");
|
|
22635
22946
|
if (!yScale) return void 0;
|
|
22636
|
-
const reverse = readOwnBoolean(item, "reverse") ?? readOwnBoolean(global, "reverse") ?? false;
|
|
22637
22947
|
const yStartValue = item?.yStartValue ?? global?.yStartValue;
|
|
22638
|
-
const
|
|
22639
|
-
|
|
22640
|
-
|
|
22641
|
-
const
|
|
22642
|
-
const
|
|
22643
|
-
const y2InArea = y2Raw >= chartArea?.top && y2Raw <= chartArea?.bottom;
|
|
22644
|
-
const y2 = clamp(y2Raw, chartArea?.top, chartArea?.bottom);
|
|
22645
|
-
return {
|
|
22646
|
-
x1: xPx,
|
|
22647
|
-
y1: clamp(y1, chartArea?.top, chartArea?.bottom),
|
|
22648
|
-
x2: xPx,
|
|
22649
|
-
y2,
|
|
22650
|
-
startInArea: y1InArea,
|
|
22651
|
-
endInArea: y2InArea,
|
|
22652
|
-
axisInArea: xPx >= chartArea.left && xPx <= chartArea.right,
|
|
22653
|
-
side: resolveSide(item, global),
|
|
22654
|
-
direction: LineMarkerDirection.Vertical
|
|
22655
|
-
};
|
|
22656
|
-
};
|
|
22657
|
-
var resolveHorizontalSpan = (args) => {
|
|
22658
|
-
const { chart, chartArea, item, global, side, groupAnchorXPx, previousGroupItemXPx } = args ?? {};
|
|
22659
|
-
const xScale = resolveScale(chart, item?.xScaleID, "x");
|
|
22660
|
-
if (!xScale) return void 0;
|
|
22661
|
-
const stickToEdge = item?.stickToEdge ?? global?.stickToEdge ?? true;
|
|
22662
|
-
const stickToGroup = item?.stickToGroup ?? global?.stickToGroup ?? false;
|
|
22663
|
-
const edgePaddingPx = global?.edgePaddingPx ?? 0;
|
|
22664
|
-
const dirIntoChart = side === LineMarkerSide.Left ? 1 : -1;
|
|
22665
|
-
const fixedLengthPx = item?.lengthPx ?? global?.lengthPx ?? global?.horizontalLineLengthPx;
|
|
22666
|
-
const edgeX = getEdgeX(chartArea, side, edgePaddingPx);
|
|
22667
|
-
const xStartValue = item?.xStartValue ?? global?.xStartValue;
|
|
22668
|
-
const xEndValue = item?.xEndValue ?? global?.xEndValue;
|
|
22669
|
-
const xValue = item?.xValue ?? global?.xValue;
|
|
22670
|
-
const xStartPxRaw = isFiniteNumber(xStartValue) ? xScale.getPixelForValue(xStartValue) : void 0;
|
|
22671
|
-
const xEndPxRaw = isFiniteNumber(xEndValue) ? xScale.getPixelForValue(xEndValue) : void 0;
|
|
22672
|
-
const xStartPx = isFiniteNumber(xStartPxRaw) ? clamp(xStartPxRaw, chartArea?.left, chartArea?.right) : void 0;
|
|
22673
|
-
const xEndPx = isFiniteNumber(xEndPxRaw) ? clamp(xEndPxRaw, chartArea?.left, chartArea?.right) : void 0;
|
|
22674
|
-
if (stickToEdge && stickToGroup && isFiniteNumber(groupAnchorXPx)) {
|
|
22675
|
-
const groupXRaw = groupAnchorXPx;
|
|
22676
|
-
if (groupXRaw < chartArea.left || groupXRaw > chartArea.right) return;
|
|
22677
|
-
const groupX = clamp(groupXRaw, chartArea?.left, chartArea?.right);
|
|
22678
|
-
const edgeX = side === LineMarkerSide.Left ? chartArea.left : chartArea.right;
|
|
22679
|
-
const x2Raw = isFiniteNumber(fixedLengthPx) ? edgeX + dirIntoChart * fixedLengthPx : groupX;
|
|
22680
|
-
return {
|
|
22681
|
-
x1: edgeX,
|
|
22682
|
-
x2: clamp(x2Raw, chartArea?.left, chartArea?.right),
|
|
22683
|
-
startInArea: edgeX >= chartArea.left && edgeX <= chartArea.right,
|
|
22684
|
-
endInArea: isFiniteNumber(fixedLengthPx) ? x2Raw >= chartArea.left && x2Raw <= chartArea.right : groupX >= chartArea.left && groupX <= chartArea.right
|
|
22685
|
-
};
|
|
22686
|
-
}
|
|
22687
|
-
if (!stickToEdge && stickToGroup && isFiniteNumber(fixedLengthPx)) {
|
|
22688
|
-
const rawAnchor = previousGroupItemXPx ?? (isFiniteNumber(groupAnchorXPx) ? groupAnchorXPx : void 0);
|
|
22689
|
-
if (!isFiniteNumber(rawAnchor)) return void 0;
|
|
22690
|
-
const anchorX = clamp(rawAnchor, chartArea?.left, chartArea?.right);
|
|
22691
|
-
const x2Raw = anchorX + dirIntoChart * fixedLengthPx;
|
|
22692
|
-
return {
|
|
22693
|
-
x1: anchorX,
|
|
22694
|
-
x2: clamp(x2Raw, chartArea?.left, chartArea?.right),
|
|
22695
|
-
startInArea: rawAnchor >= chartArea.left && rawAnchor <= chartArea.right,
|
|
22696
|
-
endInArea: x2Raw >= chartArea.left && x2Raw <= chartArea.right
|
|
22697
|
-
};
|
|
22698
|
-
}
|
|
22699
|
-
if (isFiniteNumber(xStartPx) && isFiniteNumber(xEndPx)) {
|
|
22700
|
-
const startRaw = xStartPxRaw;
|
|
22701
|
-
const endRaw = xEndPxRaw;
|
|
22702
|
-
if (!isFiniteNumber(startRaw) || !isFiniteNumber(endRaw)) return void 0;
|
|
22703
|
-
return {
|
|
22704
|
-
x1: xStartPx,
|
|
22705
|
-
x2: xEndPx,
|
|
22706
|
-
startInArea: startRaw >= chartArea.left && startRaw <= chartArea.right,
|
|
22707
|
-
endInArea: endRaw >= chartArea.left && endRaw <= chartArea.right
|
|
22708
|
-
};
|
|
22709
|
-
}
|
|
22710
|
-
if (isFiniteNumber(xStartPx) && isFiniteNumber(fixedLengthPx)) {
|
|
22711
|
-
const x2Raw = xStartPx + dirIntoChart * fixedLengthPx;
|
|
22712
|
-
return {
|
|
22713
|
-
x1: xStartPx,
|
|
22714
|
-
x2: clamp(x2Raw, chartArea?.left, chartArea?.right),
|
|
22715
|
-
startInArea: xStartPx >= chartArea.left && xStartPx <= chartArea.right,
|
|
22716
|
-
endInArea: x2Raw >= chartArea.left && x2Raw <= chartArea.right
|
|
22717
|
-
};
|
|
22718
|
-
}
|
|
22719
|
-
if (isFiniteNumber(xEndPx) && isFiniteNumber(fixedLengthPx)) {
|
|
22720
|
-
const x1Raw = xEndPx - dirIntoChart * fixedLengthPx;
|
|
22721
|
-
return {
|
|
22722
|
-
x1: clamp(x1Raw, chartArea?.left, chartArea?.right),
|
|
22723
|
-
x2: xEndPx,
|
|
22724
|
-
startInArea: x1Raw >= chartArea.left && x1Raw <= chartArea.right,
|
|
22725
|
-
endInArea: xEndPx >= chartArea.left && xEndPx <= chartArea.right
|
|
22726
|
-
};
|
|
22727
|
-
}
|
|
22728
|
-
const xValuePxRaw = isFiniteNumber(xValue) ? xScale.getPixelForValue(xValue) : void 0;
|
|
22729
|
-
if (isFiniteNumber(xValuePxRaw) && isFiniteNumber(fixedLengthPx)) {
|
|
22730
|
-
const xAnchor = clamp(xValuePxRaw, chartArea?.left, chartArea?.right);
|
|
22731
|
-
const x2Raw = xAnchor + dirIntoChart * fixedLengthPx;
|
|
22732
|
-
return {
|
|
22733
|
-
x1: xAnchor,
|
|
22734
|
-
x2: clamp(x2Raw, chartArea?.left, chartArea?.right),
|
|
22735
|
-
startInArea: xValuePxRaw >= chartArea.left && xValuePxRaw <= chartArea.right,
|
|
22736
|
-
endInArea: x2Raw >= chartArea.left && x2Raw <= chartArea.right
|
|
22737
|
-
};
|
|
22738
|
-
}
|
|
22739
|
-
if (stickToEdge && isFiniteNumber(fixedLengthPx)) {
|
|
22740
|
-
const x2Raw = edgeX + dirIntoChart * fixedLengthPx;
|
|
22741
|
-
return {
|
|
22742
|
-
x1: edgeX,
|
|
22743
|
-
x2: clamp(x2Raw, chartArea?.left, chartArea?.right),
|
|
22744
|
-
startInArea: edgeX >= chartArea.left && edgeX <= chartArea.right,
|
|
22745
|
-
endInArea: x2Raw >= chartArea.left && x2Raw <= chartArea.right
|
|
22746
|
-
};
|
|
22747
|
-
}
|
|
22748
|
-
};
|
|
22749
|
-
var computeHorizontalLineGeometry = (args) => {
|
|
22750
|
-
const { chart, chartArea, item, global, groupAnchorXPx, previousGroupItemXPx } = args ?? {};
|
|
22751
|
-
const yScale = resolveScale(chart, item?.yScaleID, "y");
|
|
22752
|
-
if (!yScale) return void 0;
|
|
22753
|
-
const yValue = item?.yValue ?? item?.value ?? global?.yValue;
|
|
22754
|
-
if (!isFiniteNumber(yValue)) return void 0;
|
|
22755
|
-
const side = resolveSide(item, global);
|
|
22756
|
-
const span = resolveHorizontalSpan({
|
|
22757
|
-
chart,
|
|
22758
|
-
chartArea,
|
|
22759
|
-
item,
|
|
22760
|
-
global,
|
|
22761
|
-
side,
|
|
22762
|
-
groupAnchorXPx,
|
|
22763
|
-
previousGroupItemXPx
|
|
22764
|
-
});
|
|
22765
|
-
if (!span) return void 0;
|
|
22766
|
-
const yPxRaw = yScale.getPixelForValue(yValue);
|
|
22767
|
-
const yPx = clamp(yPxRaw, chartArea?.top, chartArea?.bottom);
|
|
22768
|
-
const yInArea = yPxRaw >= chartArea.top && yPxRaw <= chartArea.bottom;
|
|
22769
|
-
return {
|
|
22770
|
-
x1: span.x1,
|
|
22771
|
-
y1: yPx,
|
|
22772
|
-
x2: span.x2,
|
|
22773
|
-
y2: yPx,
|
|
22774
|
-
startInArea: span.startInArea && yInArea,
|
|
22775
|
-
endInArea: span.endInArea && yInArea,
|
|
22776
|
-
axisInArea: yInArea,
|
|
22777
|
-
side,
|
|
22778
|
-
direction: LineMarkerDirection.Horizontal
|
|
22779
|
-
};
|
|
22780
|
-
};
|
|
22781
|
-
var resolveTick = (args) => {
|
|
22782
|
-
const { globalTick, itemTick, defaultEnabled } = args;
|
|
22783
|
-
return {
|
|
22784
|
-
enabled: itemTick?.enabled ?? globalTick?.enabled ?? defaultEnabled,
|
|
22785
|
-
label: itemTick?.label ?? globalTick?.label,
|
|
22786
|
-
color: itemTick?.color ?? globalTick?.color,
|
|
22787
|
-
font: itemTick?.font ?? globalTick?.font,
|
|
22788
|
-
labelOffsetPx: itemTick?.labelOffsetPx ?? globalTick?.labelOffsetPx,
|
|
22789
|
-
labelPosition: itemTick?.labelPosition ?? globalTick?.labelPosition,
|
|
22790
|
-
reverse: itemTick?.reverse ?? globalTick?.reverse,
|
|
22791
|
-
side: itemTick?.side ?? globalTick?.side,
|
|
22792
|
-
sizePx: itemTick?.sizePx ?? globalTick?.sizePx
|
|
22793
|
-
};
|
|
22794
|
-
};
|
|
22795
|
-
var hasTickLabel = (tick) => {
|
|
22796
|
-
const label = tick?.label;
|
|
22797
|
-
if (Array.isArray(label)) return label.length > 0;
|
|
22798
|
-
return Boolean(label);
|
|
22799
|
-
};
|
|
22800
|
-
var toExtraGeometry = (args) => {
|
|
22801
|
-
const { chart, chartArea, item, extra, xBase, defaultSide } = args;
|
|
22802
|
-
const yScale = resolveScale(chart, extra?.yScaleID ?? item?.yScaleID, "y");
|
|
22803
|
-
if (!yScale) return void 0;
|
|
22804
|
-
const yValue = extra?.yValue ?? extra?.value;
|
|
22805
|
-
if (!isFiniteNumber(yValue)) return void 0;
|
|
22806
|
-
const lengthPx = extra?.lengthPx;
|
|
22807
|
-
if (!isFiniteNumber(lengthPx) || lengthPx <= 0) return void 0;
|
|
22808
|
-
const side = extra?.side ?? defaultSide;
|
|
22809
|
-
const dirIntoChart = side === LineMarkerSide.Left ? 1 : -1;
|
|
22810
|
-
const yPxRaw = yScale.getPixelForValue(yValue);
|
|
22811
|
-
const yPx = clamp(yPxRaw, chartArea?.top, chartArea?.bottom);
|
|
22812
|
-
const x2Raw = xBase + dirIntoChart * lengthPx;
|
|
22813
|
-
return {
|
|
22814
|
-
x1: xBase,
|
|
22815
|
-
y1: yPx,
|
|
22816
|
-
x2: clamp(x2Raw, chartArea?.left, chartArea?.right),
|
|
22817
|
-
y2: yPx,
|
|
22818
|
-
startInArea: xBase >= chartArea.left && xBase <= chartArea.right,
|
|
22819
|
-
endInArea: x2Raw >= chartArea.left && x2Raw <= chartArea.right,
|
|
22820
|
-
axisInArea: yPxRaw >= chartArea.top && yPxRaw <= chartArea.bottom,
|
|
22821
|
-
side,
|
|
22822
|
-
direction: LineMarkerDirection.Horizontal
|
|
22823
|
-
};
|
|
22824
|
-
};
|
|
22825
|
-
var getLineStyle = (item, global) => {
|
|
22826
|
-
const color = item?.color ?? global?.color ?? DEFAULT_COLOR;
|
|
22827
|
-
const opacity = item?.opacity ?? global?.opacity ?? 1;
|
|
22828
|
-
const lineWidth = item?.lineWidth ?? global?.lineWidth ?? 1;
|
|
22829
|
-
const lineDash = asArray(item?.lineDash ?? global?.lineDash);
|
|
22830
|
-
if (!color || !isFiniteNumber(opacity) || !isFiniteNumber(lineWidth)) return;
|
|
22948
|
+
const reverse = readOwnBoolean(item, "reverse") ?? readOwnBoolean(global, "reverse") ?? false;
|
|
22949
|
+
const itemValue = item?.value;
|
|
22950
|
+
if (!isFiniteNumber(itemValue)) return void 0;
|
|
22951
|
+
const yStartPx = isFiniteNumber(yStartValue) ? clamp(yScale.getPixelForValue(yStartValue), chartArea?.top, chartArea?.bottom) : reverse ? chartArea?.bottom : chartArea?.top;
|
|
22952
|
+
const yEndPxRaw = clamp(yScale.getPixelForValue(itemValue), chartArea?.top, chartArea?.bottom);
|
|
22831
22953
|
return {
|
|
22832
|
-
|
|
22833
|
-
|
|
22834
|
-
|
|
22835
|
-
|
|
22954
|
+
yStartPx,
|
|
22955
|
+
yEndPx: reverse ? Math.min(yStartPx, yEndPxRaw) : Math.max(yStartPx, yEndPxRaw),
|
|
22956
|
+
endTick: {
|
|
22957
|
+
label: item.label,
|
|
22958
|
+
color: item.color,
|
|
22959
|
+
font: item.font,
|
|
22960
|
+
labelOffsetPx: item.labelOffsetPx
|
|
22961
|
+
},
|
|
22962
|
+
reverse
|
|
22836
22963
|
};
|
|
22837
22964
|
};
|
|
22838
|
-
var
|
|
22839
|
-
|
|
22840
|
-
return geometry.y2 < geometry.y1;
|
|
22841
|
-
};
|
|
22842
|
-
var hasVisibleLineSegment = (args) => {
|
|
22843
|
-
const { geometry } = args;
|
|
22844
|
-
const epsilon = .5;
|
|
22845
|
-
if (geometry.direction === LineMarkerDirection.Horizontal) return geometry.axisInArea && Math.abs(geometry.x2 - geometry.x1) > epsilon;
|
|
22846
|
-
return geometry.axisInArea && Math.abs(geometry.y2 - geometry.y1) > epsilon;
|
|
22847
|
-
};
|
|
22848
|
-
var lineMarkersPlugin = {
|
|
22849
|
-
id: "lineMarkers",
|
|
22965
|
+
var verticalMarkersPlugin = {
|
|
22966
|
+
id: "verticalMarkers",
|
|
22850
22967
|
afterDraw: (chart) => {
|
|
22851
22968
|
if (!readPluginEnable(chart)) return;
|
|
22852
22969
|
const cfg = readAnnotationConfig(chart);
|
|
@@ -22857,195 +22974,50 @@ var lineMarkersPlugin = {
|
|
|
22857
22974
|
const items = asArray(cfg?.items);
|
|
22858
22975
|
if (!items.length) return;
|
|
22859
22976
|
const itemGapPx = cfg?.itemGapPx ?? 0;
|
|
22860
|
-
const
|
|
22861
|
-
|
|
22862
|
-
|
|
22863
|
-
let groupedVerticalIndexBySide = {};
|
|
22864
|
-
let groupedAnchorBySide = {};
|
|
22865
|
-
let previousGroupedHorizontalEndBySide = {};
|
|
22866
|
-
items.forEach((item, itemIndex) => {
|
|
22977
|
+
const globalStickSide = cfg?.stickSide ?? "right";
|
|
22978
|
+
let visibleIndex = 0;
|
|
22979
|
+
items?.forEach((item) => {
|
|
22867
22980
|
if (!item || item?.display === false) return;
|
|
22868
|
-
const
|
|
22869
|
-
|
|
22870
|
-
|
|
22871
|
-
|
|
22872
|
-
|
|
22873
|
-
if (direction === LineMarkerDirection.Vertical) {
|
|
22874
|
-
const baseXPx = computeVerticalXPxBase({
|
|
22875
|
-
chart,
|
|
22876
|
-
chartArea,
|
|
22877
|
-
item,
|
|
22878
|
-
global: cfg
|
|
22879
|
-
});
|
|
22880
|
-
if (!isFiniteNumber(baseXPx)) return;
|
|
22881
|
-
const stickToEdge = item?.stickToEdge ?? cfg?.stickToEdge ?? true;
|
|
22882
|
-
const hasExplicitXValue = isFiniteNumber(item?.xValue ?? cfg?.xValue);
|
|
22883
|
-
const isGroupedVertical = stickToEdge && !hasExplicitXValue;
|
|
22884
|
-
const dirIntoChart = side === LineMarkerSide.Left ? 1 : -1;
|
|
22885
|
-
const groupedVerticalIndex = groupedVerticalIndexBySide[side] ?? 0;
|
|
22886
|
-
const groupOffsetPx = item?.groupOffsetPx ?? 0;
|
|
22887
|
-
geometry = computeVerticalLineGeometry({
|
|
22888
|
-
chart,
|
|
22889
|
-
chartArea,
|
|
22890
|
-
item,
|
|
22891
|
-
global: cfg,
|
|
22892
|
-
xPx: isGroupedVertical ? baseXPx + dirIntoChart * groupedVerticalIndex * itemGapPx + dirIntoChart * groupOffsetPx : baseXPx
|
|
22893
|
-
});
|
|
22894
|
-
if (geometry && isGroupedVertical) {
|
|
22895
|
-
groupedVerticalIndexBySide[side] = groupedVerticalIndex + 1;
|
|
22896
|
-
const prevAnchor = groupedAnchorBySide[side];
|
|
22897
|
-
groupedAnchorBySide[side] = isFiniteNumber(prevAnchor) ? side === LineMarkerSide.Left ? Math.min(prevAnchor, geometry.x1) : Math.max(prevAnchor, geometry.x1) : geometry.x1;
|
|
22898
|
-
}
|
|
22899
|
-
} else {
|
|
22900
|
-
const stickToGroup = item?.stickToGroup ?? cfg?.stickToGroup ?? false;
|
|
22901
|
-
geometry = computeHorizontalLineGeometry({
|
|
22902
|
-
chart,
|
|
22903
|
-
chartArea,
|
|
22904
|
-
item,
|
|
22905
|
-
global: cfg,
|
|
22906
|
-
groupAnchorXPx: (() => {
|
|
22907
|
-
const anchor = groupedAnchorBySide[side];
|
|
22908
|
-
if (!isFiniteNumber(anchor)) return void 0;
|
|
22909
|
-
return clamp(anchor, chartArea?.left, chartArea?.right);
|
|
22910
|
-
})(),
|
|
22911
|
-
previousGroupItemXPx: (() => {
|
|
22912
|
-
const prev = previousGroupedHorizontalEndBySide[side];
|
|
22913
|
-
if (!isFiniteNumber(prev)) return void 0;
|
|
22914
|
-
return clamp(prev, chartArea?.left, chartArea?.right);
|
|
22915
|
-
})()
|
|
22916
|
-
});
|
|
22917
|
-
if (geometry && stickToGroup) previousGroupedHorizontalEndBySide[side] = geometry.x2;
|
|
22918
|
-
}
|
|
22919
|
-
if (!geometry) return;
|
|
22920
|
-
if (!hasVisibleLineSegment({ geometry })) return;
|
|
22921
|
-
lineTasks.push({
|
|
22922
|
-
geometry,
|
|
22923
|
-
style
|
|
22924
|
-
});
|
|
22925
|
-
const lineReverse = getLineReverse(geometry);
|
|
22926
|
-
const lineStart = {
|
|
22927
|
-
x: geometry.x1,
|
|
22928
|
-
y: geometry.y1
|
|
22929
|
-
};
|
|
22930
|
-
const lineEnd = {
|
|
22931
|
-
x: geometry.x2,
|
|
22932
|
-
y: geometry.y2
|
|
22933
|
-
};
|
|
22934
|
-
const startTick = resolveTick({
|
|
22935
|
-
globalTick: cfg?.startTick,
|
|
22936
|
-
itemTick: item?.startTick,
|
|
22937
|
-
defaultEnabled: false
|
|
22938
|
-
});
|
|
22939
|
-
const endTick = resolveTick({
|
|
22940
|
-
globalTick: cfg?.endTick,
|
|
22941
|
-
itemTick: item?.endTick,
|
|
22942
|
-
defaultEnabled: direction === LineMarkerDirection.Vertical
|
|
22943
|
-
});
|
|
22944
|
-
const resolvedStartSide = startTick?.side ?? side;
|
|
22945
|
-
const resolvedEndSide = endTick?.side ?? side;
|
|
22946
|
-
if ((startTick?.enabled || hasTickLabel(startTick)) && geometry.startInArea) tickTasks.push({
|
|
22947
|
-
id: `${item?.id ?? `item-${itemIndex}`}-start`,
|
|
22948
|
-
x: lineStart.x,
|
|
22949
|
-
y: lineStart.y,
|
|
22950
|
-
side: resolvedStartSide,
|
|
22951
|
-
direction: geometry.direction,
|
|
22952
|
-
reverse: startTick?.reverse ?? !lineReverse,
|
|
22953
|
-
tick: startTick,
|
|
22954
|
-
defaultColor: style.color,
|
|
22955
|
-
defaultFont: DEFAULT_FONT
|
|
22956
|
-
});
|
|
22957
|
-
if ((endTick?.enabled || hasTickLabel(endTick)) && geometry.endInArea) tickTasks.push({
|
|
22958
|
-
id: `${item?.id ?? `item-${itemIndex}`}-end`,
|
|
22959
|
-
x: lineEnd.x,
|
|
22960
|
-
y: lineEnd.y,
|
|
22961
|
-
side: resolvedEndSide,
|
|
22962
|
-
direction: geometry.direction,
|
|
22963
|
-
reverse: endTick?.reverse ?? lineReverse,
|
|
22964
|
-
tick: endTick,
|
|
22965
|
-
defaultColor: style.color,
|
|
22966
|
-
defaultFont: DEFAULT_FONT
|
|
22967
|
-
});
|
|
22968
|
-
if (direction !== LineMarkerDirection.Vertical) return;
|
|
22969
|
-
asArray(item?.extras).forEach((extra, extraIndex) => {
|
|
22970
|
-
if (!extra || extra?.display === false) return;
|
|
22971
|
-
const extraGeometry = toExtraGeometry({
|
|
22972
|
-
chart,
|
|
22973
|
-
chartArea,
|
|
22974
|
-
item,
|
|
22975
|
-
extra,
|
|
22976
|
-
xBase: geometry.x1,
|
|
22977
|
-
defaultSide: side
|
|
22978
|
-
});
|
|
22979
|
-
if (!extraGeometry) return;
|
|
22980
|
-
const extraStyle = getLineStyle(extra, cfg);
|
|
22981
|
-
if (!extraStyle) return;
|
|
22982
|
-
lineTasks.push({
|
|
22983
|
-
geometry: extraGeometry,
|
|
22984
|
-
style: extraStyle
|
|
22985
|
-
});
|
|
22986
|
-
const extraTick = resolveTick({
|
|
22987
|
-
itemTick: extra?.tick,
|
|
22988
|
-
defaultEnabled: false
|
|
22989
|
-
});
|
|
22990
|
-
if (!extraTick?.enabled && !hasTickLabel(extraTick) || !extraGeometry.endInArea) return;
|
|
22991
|
-
const extraReverse = extraTick?.reverse ?? readOwnBoolean(extra, "reverse") ?? false;
|
|
22992
|
-
tickTasks.push({
|
|
22993
|
-
id: `${item?.id ?? `item-${itemIndex}`}-extra-${extra?.id ?? extraIndex}`,
|
|
22994
|
-
x: extraGeometry.x2,
|
|
22995
|
-
y: extraGeometry.y2,
|
|
22996
|
-
side: extraTick?.side ?? extraGeometry.side ?? defaultSide,
|
|
22997
|
-
direction: LineMarkerDirection.Horizontal,
|
|
22998
|
-
reverse: extraReverse,
|
|
22999
|
-
tick: extraTick,
|
|
23000
|
-
defaultColor: extraStyle.color,
|
|
23001
|
-
defaultFont: DEFAULT_FONT
|
|
23002
|
-
});
|
|
22981
|
+
const baseXPx = computeXPxBase({
|
|
22982
|
+
chart,
|
|
22983
|
+
chartArea,
|
|
22984
|
+
item,
|
|
22985
|
+
global: cfg
|
|
23003
22986
|
});
|
|
23004
|
-
|
|
23005
|
-
|
|
23006
|
-
|
|
22987
|
+
if (!isFiniteNumber(baseXPx)) return;
|
|
22988
|
+
const side = item?.stickSide ?? globalStickSide;
|
|
22989
|
+
const xPx = baseXPx + (side === "left" ? 1 : -1) * visibleIndex * itemGapPx;
|
|
22990
|
+
visibleIndex += 1;
|
|
22991
|
+
const ySpan = computeYSpan({
|
|
23007
22992
|
chart,
|
|
23008
|
-
|
|
23009
|
-
|
|
23010
|
-
|
|
23011
|
-
y2: geometry.y2,
|
|
23012
|
-
color: style.color,
|
|
23013
|
-
opacity: style.opacity,
|
|
23014
|
-
lineWidth: style.lineWidth,
|
|
23015
|
-
lineDash: style.lineDash
|
|
22993
|
+
chartArea,
|
|
22994
|
+
item,
|
|
22995
|
+
global: cfg
|
|
23016
22996
|
});
|
|
23017
|
-
|
|
23018
|
-
|
|
23019
|
-
|
|
23020
|
-
|
|
23021
|
-
|
|
23022
|
-
|
|
23023
|
-
return task?.tick?.enabled !== false && isFiniteNumber(getTickLabelHeight(task.tick, task.defaultFont)) && getTickLabelHeight(task.tick, task.defaultFont) > 0;
|
|
23024
|
-
}).map((task) => ({
|
|
23025
|
-
id: task.id,
|
|
23026
|
-
side: task.side,
|
|
23027
|
-
x: task.x,
|
|
23028
|
-
y: task.y,
|
|
23029
|
-
height: getTickLabelHeight(task.tick, task.defaultFont)
|
|
23030
|
-
})),
|
|
23031
|
-
chartTop: chartArea.top,
|
|
23032
|
-
chartBottom: chartArea.bottom,
|
|
23033
|
-
clusterXPx: labelCollisionClusterXPx,
|
|
23034
|
-
gapPx: labelCollisionPx
|
|
23035
|
-
}) : {};
|
|
23036
|
-
tickTasks.forEach((task) => {
|
|
22997
|
+
if (!ySpan) return;
|
|
22998
|
+
const color = item?.color ?? cfg?.color;
|
|
22999
|
+
const opacity = item?.opacity ?? cfg?.opacity;
|
|
23000
|
+
const lineWidth = item?.lineWidth ?? cfg?.lineWidth;
|
|
23001
|
+
const lineDash = asArray(item?.lineDash ?? cfg?.lineDash);
|
|
23002
|
+
if (!color || !isFiniteNumber(opacity) || !isFiniteNumber(lineWidth)) return;
|
|
23037
23003
|
drawTick({
|
|
23038
23004
|
ctx,
|
|
23039
|
-
|
|
23040
|
-
|
|
23041
|
-
|
|
23042
|
-
|
|
23043
|
-
|
|
23044
|
-
|
|
23045
|
-
|
|
23046
|
-
|
|
23047
|
-
|
|
23048
|
-
|
|
23005
|
+
x: drawVerticalLine({
|
|
23006
|
+
chart,
|
|
23007
|
+
xPx,
|
|
23008
|
+
y1: ySpan?.yStartPx,
|
|
23009
|
+
y2: ySpan?.yEndPx,
|
|
23010
|
+
color,
|
|
23011
|
+
opacity,
|
|
23012
|
+
lineWidth,
|
|
23013
|
+
lineDash
|
|
23014
|
+
}),
|
|
23015
|
+
y: ySpan?.yEndPx,
|
|
23016
|
+
side,
|
|
23017
|
+
reverse: ySpan?.reverse,
|
|
23018
|
+
tick: ySpan?.endTick,
|
|
23019
|
+
defaultColor: color,
|
|
23020
|
+
defaultFont: "12px sans-serif"
|
|
23049
23021
|
});
|
|
23050
23022
|
});
|
|
23051
23023
|
}
|
|
@@ -23517,7 +23489,7 @@ var Legend = ({ chartRef, legendConfig }) => {
|
|
|
23517
23489
|
};
|
|
23518
23490
|
//#endregion
|
|
23519
23491
|
//#region src/components/line-chart/line-chart.tsx
|
|
23520
|
-
Chart$1.register(LinearScale, PointElement, LineElement, CategoryScale, LogarithmicScale, plugin_legend, plugin_tooltip, plugin_title, index, plugin$1, plugin, annotation, chartAreaTextPlugin, annotationDraggerPlugin, ellipsisAnnotationPlugin, calloutConnectorPlugin,
|
|
23492
|
+
Chart$1.register(LinearScale, PointElement, LineElement, CategoryScale, LogarithmicScale, plugin_legend, plugin_tooltip, plugin_title, index, plugin$1, plugin, annotation, chartAreaTextPlugin, annotationDraggerPlugin, ellipsisAnnotationPlugin, calloutConnectorPlugin, verticalMarkersPlugin);
|
|
23521
23493
|
var LineChart = (props) => {
|
|
23522
23494
|
setDefaultTheme();
|
|
23523
23495
|
const chartRef = useRef(null);
|