@coinbase/cds-web-visualization 3.4.0-beta.1 → 3.4.0-beta.10
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/CHANGELOG.md +47 -0
- package/dts/chart/CartesianChart.d.ts +38 -2
- package/dts/chart/CartesianChart.d.ts.map +1 -1
- package/dts/chart/Path.d.ts +27 -7
- package/dts/chart/Path.d.ts.map +1 -1
- package/dts/chart/PeriodSelector.d.ts +0 -4
- package/dts/chart/PeriodSelector.d.ts.map +1 -1
- package/dts/chart/area/Area.d.ts +54 -24
- package/dts/chart/area/Area.d.ts.map +1 -1
- package/dts/chart/area/AreaChart.d.ts +33 -6
- package/dts/chart/area/AreaChart.d.ts.map +1 -1
- package/dts/chart/area/DottedArea.d.ts +21 -44
- package/dts/chart/area/DottedArea.d.ts.map +1 -1
- package/dts/chart/area/GradientArea.d.ts +21 -12
- package/dts/chart/area/GradientArea.d.ts.map +1 -1
- package/dts/chart/area/SolidArea.d.ts +16 -1
- package/dts/chart/area/SolidArea.d.ts.map +1 -1
- package/dts/chart/axis/Axis.d.ts +92 -45
- package/dts/chart/axis/Axis.d.ts.map +1 -1
- package/dts/chart/axis/DefaultAxisTickLabel.d.ts +8 -0
- package/dts/chart/axis/DefaultAxisTickLabel.d.ts.map +1 -0
- package/dts/chart/axis/XAxis.d.ts +1 -1
- package/dts/chart/axis/XAxis.d.ts.map +1 -1
- package/dts/chart/axis/YAxis.d.ts +1 -1
- package/dts/chart/axis/YAxis.d.ts.map +1 -1
- package/dts/chart/axis/index.d.ts +1 -0
- package/dts/chart/axis/index.d.ts.map +1 -1
- package/dts/chart/bar/Bar.d.ts +16 -13
- package/dts/chart/bar/Bar.d.ts.map +1 -1
- package/dts/chart/bar/BarChart.d.ts +17 -8
- package/dts/chart/bar/BarChart.d.ts.map +1 -1
- package/dts/chart/bar/BarPlot.d.ts +2 -1
- package/dts/chart/bar/BarPlot.d.ts.map +1 -1
- package/dts/chart/bar/BarStack.d.ts +40 -48
- package/dts/chart/bar/BarStack.d.ts.map +1 -1
- package/dts/chart/bar/BarStackGroup.d.ts +1 -0
- package/dts/chart/bar/BarStackGroup.d.ts.map +1 -1
- package/dts/chart/bar/DefaultBar.d.ts.map +1 -1
- package/dts/chart/bar/DefaultBarStack.d.ts.map +1 -1
- package/dts/chart/gradient/Gradient.d.ts +35 -0
- package/dts/chart/gradient/Gradient.d.ts.map +1 -0
- package/dts/chart/gradient/index.d.ts +2 -0
- package/dts/chart/gradient/index.d.ts.map +1 -0
- package/dts/chart/index.d.ts +2 -1
- package/dts/chart/index.d.ts.map +1 -1
- package/dts/chart/line/DefaultReferenceLineLabel.d.ts +9 -0
- package/dts/chart/line/DefaultReferenceLineLabel.d.ts.map +1 -0
- package/dts/chart/line/DottedLine.d.ts +15 -3
- package/dts/chart/line/DottedLine.d.ts.map +1 -1
- package/dts/chart/line/Line.d.ts +70 -28
- package/dts/chart/line/Line.d.ts.map +1 -1
- package/dts/chart/line/LineChart.d.ts +26 -8
- package/dts/chart/line/LineChart.d.ts.map +1 -1
- package/dts/chart/line/ReferenceLine.d.ts +91 -44
- package/dts/chart/line/ReferenceLine.d.ts.map +1 -1
- package/dts/chart/line/SolidLine.d.ts +14 -3
- package/dts/chart/line/SolidLine.d.ts.map +1 -1
- package/dts/chart/line/index.d.ts +1 -1
- package/dts/chart/line/index.d.ts.map +1 -1
- package/dts/chart/point/DefaultPointLabel.d.ts +10 -0
- package/dts/chart/point/DefaultPointLabel.d.ts.map +1 -0
- package/dts/chart/point/Point.d.ts +201 -0
- package/dts/chart/point/Point.d.ts.map +1 -0
- package/dts/chart/point/index.d.ts +3 -0
- package/dts/chart/point/index.d.ts.map +1 -0
- package/dts/chart/scrubber/DefaultScrubberBeacon.d.ts +24 -0
- package/dts/chart/scrubber/DefaultScrubberBeacon.d.ts.map +1 -0
- package/dts/chart/scrubber/DefaultScrubberBeaconLabel.d.ts +12 -0
- package/dts/chart/scrubber/DefaultScrubberBeaconLabel.d.ts.map +1 -0
- package/dts/chart/scrubber/DefaultScrubberLabel.d.ts +10 -0
- package/dts/chart/scrubber/DefaultScrubberLabel.d.ts.map +1 -0
- package/dts/chart/scrubber/Scrubber.d.ts +207 -66
- package/dts/chart/scrubber/Scrubber.d.ts.map +1 -1
- package/dts/chart/scrubber/ScrubberBeaconGroup.d.ts +70 -0
- package/dts/chart/scrubber/ScrubberBeaconGroup.d.ts.map +1 -0
- package/dts/chart/scrubber/ScrubberBeaconLabelGroup.d.ts +32 -0
- package/dts/chart/scrubber/ScrubberBeaconLabelGroup.d.ts.map +1 -0
- package/dts/chart/scrubber/index.d.ts +3 -0
- package/dts/chart/scrubber/index.d.ts.map +1 -1
- package/dts/chart/text/ChartText.d.ts +46 -43
- package/dts/chart/text/ChartText.d.ts.map +1 -1
- package/dts/chart/text/{SmartChartTextGroup.d.ts → ChartTextGroup.d.ts} +9 -3
- package/dts/chart/text/ChartTextGroup.d.ts.map +1 -0
- package/dts/chart/text/index.d.ts +1 -1
- package/dts/chart/text/index.d.ts.map +1 -1
- package/dts/chart/utils/chart.d.ts +27 -7
- package/dts/chart/utils/chart.d.ts.map +1 -1
- package/dts/chart/utils/context.d.ts +6 -0
- package/dts/chart/utils/context.d.ts.map +1 -1
- package/dts/chart/utils/gradient.d.ts +104 -0
- package/dts/chart/utils/gradient.d.ts.map +1 -0
- package/dts/chart/utils/index.d.ts +4 -0
- package/dts/chart/utils/index.d.ts.map +1 -1
- package/dts/chart/utils/interpolate.d.ts +112 -0
- package/dts/chart/utils/interpolate.d.ts.map +1 -0
- package/dts/chart/utils/path.d.ts +24 -1
- package/dts/chart/utils/path.d.ts.map +1 -1
- package/dts/chart/utils/point.d.ts +29 -0
- package/dts/chart/utils/point.d.ts.map +1 -1
- package/dts/chart/utils/scrubber.d.ts +39 -0
- package/dts/chart/utils/scrubber.d.ts.map +1 -0
- package/dts/chart/utils/transition.d.ts +65 -0
- package/dts/chart/utils/transition.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveMarkerDates.d.ts.map +1 -1
- package/esm/chart/CartesianChart.js +140 -85
- package/esm/chart/Path.js +53 -47
- package/esm/chart/PeriodSelector.js +4 -18
- package/esm/chart/area/Area.js +24 -34
- package/esm/chart/area/AreaChart.js +24 -15
- package/esm/chart/area/DottedArea.js +35 -89
- package/esm/chart/area/GradientArea.js +34 -80
- package/esm/chart/area/SolidArea.js +29 -11
- package/esm/chart/axis/Axis.js +4 -25
- package/esm/chart/axis/DefaultAxisTickLabel.js +15 -0
- package/esm/chart/axis/XAxis.js +76 -52
- package/esm/chart/axis/YAxis.js +80 -49
- package/esm/chart/axis/index.js +1 -0
- package/esm/chart/bar/Bar.js +3 -1
- package/esm/chart/bar/BarChart.js +15 -32
- package/esm/chart/bar/BarPlot.js +3 -2
- package/esm/chart/bar/BarStack.js +65 -23
- package/esm/chart/bar/BarStackGroup.js +7 -17
- package/esm/chart/bar/DefaultBar.js +4 -7
- package/esm/chart/bar/DefaultBarStack.js +5 -7
- package/esm/chart/gradient/Gradient.js +104 -0
- package/esm/chart/gradient/index.js +1 -0
- package/esm/chart/index.js +2 -1
- package/esm/chart/line/DefaultReferenceLineLabel.js +81 -0
- package/esm/chart/line/DottedLine.js +38 -17
- package/esm/chart/line/Line.js +96 -70
- package/esm/chart/line/LineChart.js +18 -6
- package/esm/chart/line/ReferenceLine.js +41 -43
- package/esm/chart/line/SolidLine.js +36 -15
- package/esm/chart/line/index.js +1 -1
- package/esm/chart/{line/GradientLine.js → point/DefaultPointLabel.js} +31 -45
- package/esm/chart/point/Point.css +2 -0
- package/esm/chart/{Point.js → point/Point.js} +66 -57
- package/esm/chart/point/index.js +2 -0
- package/esm/chart/scrubber/DefaultScrubberBeacon.js +155 -0
- package/esm/chart/scrubber/{ScrubberBeaconLabel.js → DefaultScrubberBeaconLabel.js} +23 -10
- package/esm/chart/scrubber/DefaultScrubberLabel.js +30 -0
- package/esm/chart/scrubber/Scrubber.js +98 -392
- package/esm/chart/scrubber/ScrubberBeaconGroup.js +166 -0
- package/esm/chart/scrubber/ScrubberBeaconLabelGroup.js +186 -0
- package/esm/chart/scrubber/index.js +3 -1
- package/esm/chart/text/ChartText.js +13 -19
- package/esm/chart/text/{SmartChartTextGroup.js → ChartTextGroup.js} +4 -3
- package/esm/chart/text/index.js +1 -1
- package/esm/chart/utils/chart.js +29 -3
- package/esm/chart/utils/gradient.js +257 -0
- package/esm/chart/utils/index.js +4 -0
- package/esm/chart/utils/interpolate.js +644 -0
- package/esm/chart/utils/path.js +32 -9
- package/esm/chart/utils/point.js +69 -0
- package/esm/chart/utils/scrubber.js +132 -0
- package/esm/chart/utils/transition.js +111 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveMarkerDates.js +8 -4
- package/package.json +9 -9
- package/dts/chart/Point.d.ts +0 -153
- package/dts/chart/Point.d.ts.map +0 -1
- package/dts/chart/line/GradientLine.d.ts +0 -42
- package/dts/chart/line/GradientLine.d.ts.map +0 -1
- package/dts/chart/scrubber/ScrubberBeacon.d.ts +0 -93
- package/dts/chart/scrubber/ScrubberBeacon.d.ts.map +0 -1
- package/dts/chart/scrubber/ScrubberBeaconLabel.d.ts +0 -7
- package/dts/chart/scrubber/ScrubberBeaconLabel.d.ts.map +0 -1
- package/dts/chart/text/SmartChartTextGroup.d.ts.map +0 -1
- package/esm/chart/Point.css +0 -2
- package/esm/chart/scrubber/ScrubberBeacon.js +0 -195
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { forwardRef, memo, useCallback, useImperativeHandle, useMemo } from 'react';
|
|
2
|
+
import { useRefMap } from '@coinbase/cds-common/hooks/useRefMap';
|
|
3
|
+
import { useCartesianChartContext } from '../ChartProvider';
|
|
4
|
+
import { evaluateGradientAtValue, getGradientConfig, useScrubberContext } from '../utils';
|
|
5
|
+
import { DefaultScrubberBeacon } from './DefaultScrubberBeacon';
|
|
6
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
7
|
+
// Helper component to calculate beacon data for a specific series
|
|
8
|
+
const BeaconWithData = /*#__PURE__*/memo(_ref => {
|
|
9
|
+
let {
|
|
10
|
+
seriesId,
|
|
11
|
+
dataIndex,
|
|
12
|
+
dataX,
|
|
13
|
+
isIdle,
|
|
14
|
+
BeaconComponent,
|
|
15
|
+
idlePulse,
|
|
16
|
+
transitions,
|
|
17
|
+
className,
|
|
18
|
+
style,
|
|
19
|
+
testID,
|
|
20
|
+
beaconRef
|
|
21
|
+
} = _ref;
|
|
22
|
+
const {
|
|
23
|
+
getSeries,
|
|
24
|
+
getSeriesData,
|
|
25
|
+
getXScale,
|
|
26
|
+
getYScale
|
|
27
|
+
} = useCartesianChartContext();
|
|
28
|
+
const series = useMemo(() => getSeries(seriesId), [getSeries, seriesId]);
|
|
29
|
+
const sourceData = useMemo(() => getSeriesData(seriesId), [getSeriesData, seriesId]);
|
|
30
|
+
const gradient = series === null || series === void 0 ? void 0 : series.gradient;
|
|
31
|
+
|
|
32
|
+
// Get dataY from series data
|
|
33
|
+
const dataY = useMemo(() => {
|
|
34
|
+
if (sourceData && dataIndex >= 0 && dataIndex < sourceData.length) {
|
|
35
|
+
const dataValue = sourceData[dataIndex];
|
|
36
|
+
if (typeof dataValue === 'number') {
|
|
37
|
+
return dataValue;
|
|
38
|
+
} else if (Array.isArray(dataValue)) {
|
|
39
|
+
const validValues = dataValue.filter(val => val !== null);
|
|
40
|
+
if (validValues.length >= 1) {
|
|
41
|
+
return validValues[validValues.length - 1];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return undefined;
|
|
46
|
+
}, [sourceData, dataIndex]);
|
|
47
|
+
|
|
48
|
+
// Evaluate gradient color
|
|
49
|
+
const color = useMemo(() => {
|
|
50
|
+
var _series$color, _series$color2;
|
|
51
|
+
if (dataY === undefined) return (_series$color = series === null || series === void 0 ? void 0 : series.color) !== null && _series$color !== void 0 ? _series$color : 'var(--color-fgPrimary)';
|
|
52
|
+
if (gradient) {
|
|
53
|
+
const xScale = getXScale();
|
|
54
|
+
const yScale = getYScale(series === null || series === void 0 ? void 0 : series.yAxisId);
|
|
55
|
+
if (xScale && yScale) {
|
|
56
|
+
const gradientScale = gradient.axis === 'x' ? xScale : yScale;
|
|
57
|
+
const stops = getGradientConfig(gradient, xScale, yScale);
|
|
58
|
+
if (stops) {
|
|
59
|
+
var _gradient$axis;
|
|
60
|
+
const gradientAxis = (_gradient$axis = gradient.axis) !== null && _gradient$axis !== void 0 ? _gradient$axis : 'y';
|
|
61
|
+
const dataValue = gradientAxis === 'x' ? dataX : dataY;
|
|
62
|
+
const evaluatedColor = evaluateGradientAtValue(stops, dataValue, gradientScale);
|
|
63
|
+
if (evaluatedColor) {
|
|
64
|
+
return evaluatedColor;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return (_series$color2 = series === null || series === void 0 ? void 0 : series.color) !== null && _series$color2 !== void 0 ? _series$color2 : 'var(--color-fgPrimary)';
|
|
70
|
+
}, [gradient, dataX, dataY, series === null || series === void 0 ? void 0 : series.color, series === null || series === void 0 ? void 0 : series.yAxisId, getXScale, getYScale]);
|
|
71
|
+
if (dataY === undefined) return null;
|
|
72
|
+
return /*#__PURE__*/_jsx(BeaconComponent, {
|
|
73
|
+
ref: beaconRef,
|
|
74
|
+
className: className,
|
|
75
|
+
color: color,
|
|
76
|
+
dataX: dataX,
|
|
77
|
+
dataY: dataY,
|
|
78
|
+
idlePulse: idlePulse,
|
|
79
|
+
isIdle: isIdle,
|
|
80
|
+
seriesId: seriesId,
|
|
81
|
+
style: style,
|
|
82
|
+
testID: testID,
|
|
83
|
+
transitions: transitions
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
export const ScrubberBeaconGroup = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref2, ref) => {
|
|
87
|
+
let {
|
|
88
|
+
seriesIds,
|
|
89
|
+
idlePulse,
|
|
90
|
+
transitions,
|
|
91
|
+
BeaconComponent = DefaultScrubberBeacon,
|
|
92
|
+
className,
|
|
93
|
+
style,
|
|
94
|
+
testID
|
|
95
|
+
} = _ref2;
|
|
96
|
+
const ScrubberBeaconRefs = useRefMap();
|
|
97
|
+
const {
|
|
98
|
+
scrubberPosition
|
|
99
|
+
} = useScrubberContext();
|
|
100
|
+
const {
|
|
101
|
+
getXScale,
|
|
102
|
+
getXAxis,
|
|
103
|
+
dataLength,
|
|
104
|
+
series
|
|
105
|
+
} = useCartesianChartContext();
|
|
106
|
+
|
|
107
|
+
// Expose imperative handle with pulse method
|
|
108
|
+
useImperativeHandle(ref, () => ({
|
|
109
|
+
pulse: () => {
|
|
110
|
+
Object.values(ScrubberBeaconRefs.refs).forEach(beaconRef => {
|
|
111
|
+
beaconRef === null || beaconRef === void 0 || beaconRef.pulse();
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}));
|
|
115
|
+
const filteredSeries = useMemo(() => {
|
|
116
|
+
var _series$filter;
|
|
117
|
+
return (_series$filter = series === null || series === void 0 ? void 0 : series.filter(s => seriesIds.includes(s.id))) !== null && _series$filter !== void 0 ? _series$filter : [];
|
|
118
|
+
}, [series, seriesIds]);
|
|
119
|
+
const {
|
|
120
|
+
dataX,
|
|
121
|
+
dataIndex
|
|
122
|
+
} = useMemo(() => {
|
|
123
|
+
const xScale = getXScale();
|
|
124
|
+
const xAxis = getXAxis();
|
|
125
|
+
if (!xScale) return {
|
|
126
|
+
dataX: undefined,
|
|
127
|
+
dataIndex: undefined
|
|
128
|
+
};
|
|
129
|
+
const dataIndex = scrubberPosition !== null && scrubberPosition !== void 0 ? scrubberPosition : Math.max(0, dataLength - 1);
|
|
130
|
+
|
|
131
|
+
// Convert index to actual x value if axis has data
|
|
132
|
+
let dataX;
|
|
133
|
+
if (xAxis !== null && xAxis !== void 0 && xAxis.data && Array.isArray(xAxis.data) && xAxis.data[dataIndex] !== undefined) {
|
|
134
|
+
const dataValue = xAxis.data[dataIndex];
|
|
135
|
+
dataX = typeof dataValue === 'string' ? dataIndex : dataValue;
|
|
136
|
+
} else {
|
|
137
|
+
dataX = dataIndex;
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
dataX,
|
|
141
|
+
dataIndex
|
|
142
|
+
};
|
|
143
|
+
}, [getXScale, getXAxis, scrubberPosition, dataLength]);
|
|
144
|
+
const isIdle = scrubberPosition === undefined;
|
|
145
|
+
const createBeaconRef = useCallback(seriesId => {
|
|
146
|
+
return beaconRef => {
|
|
147
|
+
if (beaconRef) {
|
|
148
|
+
ScrubberBeaconRefs.registerRef(seriesId, beaconRef);
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
}, [ScrubberBeaconRefs]);
|
|
152
|
+
if (dataX === undefined || dataIndex === undefined) return null;
|
|
153
|
+
return filteredSeries.map(s => /*#__PURE__*/_jsx(BeaconWithData, {
|
|
154
|
+
BeaconComponent: BeaconComponent,
|
|
155
|
+
beaconRef: createBeaconRef(s.id),
|
|
156
|
+
className: className,
|
|
157
|
+
dataIndex: dataIndex,
|
|
158
|
+
dataX: dataX,
|
|
159
|
+
idlePulse: idlePulse,
|
|
160
|
+
isIdle: isIdle,
|
|
161
|
+
seriesId: s.id,
|
|
162
|
+
style: style,
|
|
163
|
+
testID: testID ? "".concat(testID !== null && testID !== void 0 ? testID : 'beacon', "-").concat(s.id) : undefined,
|
|
164
|
+
transitions: transitions
|
|
165
|
+
}, s.id));
|
|
166
|
+
}));
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
2
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
3
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
4
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
5
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
6
|
+
import { memo, useCallback, useMemo, useState } from 'react';
|
|
7
|
+
import { useCartesianChartContext } from '../ChartProvider';
|
|
8
|
+
import { getPointOnScale, useScrubberContext } from '../utils';
|
|
9
|
+
import { calculateLabelYPositions, getLabelPosition } from '../utils/scrubber';
|
|
10
|
+
import { DefaultScrubberBeaconLabel } from './DefaultScrubberBeaconLabel';
|
|
11
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
12
|
+
const PositionedLabel = /*#__PURE__*/memo(_ref => {
|
|
13
|
+
let {
|
|
14
|
+
index,
|
|
15
|
+
positions,
|
|
16
|
+
position,
|
|
17
|
+
label,
|
|
18
|
+
color,
|
|
19
|
+
seriesId,
|
|
20
|
+
onDimensionsChange,
|
|
21
|
+
BeaconLabelComponent,
|
|
22
|
+
labelHorizontalOffset,
|
|
23
|
+
labelFont
|
|
24
|
+
} = _ref;
|
|
25
|
+
const pos = positions[index];
|
|
26
|
+
|
|
27
|
+
// Don't render if position is null (invalid data)
|
|
28
|
+
if (!pos) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const x = pos.x;
|
|
32
|
+
const y = pos.y;
|
|
33
|
+
const dx = position === 'right' ? labelHorizontalOffset : -labelHorizontalOffset;
|
|
34
|
+
const horizontalAlignment = position === 'right' ? 'left' : 'right';
|
|
35
|
+
return /*#__PURE__*/_jsx(BeaconLabelComponent, {
|
|
36
|
+
color: color,
|
|
37
|
+
dx: dx,
|
|
38
|
+
font: labelFont,
|
|
39
|
+
horizontalAlignment: horizontalAlignment,
|
|
40
|
+
label: label,
|
|
41
|
+
onDimensionsChange: d => onDimensionsChange(seriesId, d),
|
|
42
|
+
seriesId: seriesId,
|
|
43
|
+
x: x,
|
|
44
|
+
y: y
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
export const ScrubberBeaconLabelGroup = /*#__PURE__*/memo(_ref2 => {
|
|
48
|
+
let {
|
|
49
|
+
labels,
|
|
50
|
+
labelMinGap = 4,
|
|
51
|
+
labelHorizontalOffset = 16,
|
|
52
|
+
labelFont,
|
|
53
|
+
BeaconLabelComponent = DefaultScrubberBeaconLabel
|
|
54
|
+
} = _ref2;
|
|
55
|
+
const {
|
|
56
|
+
getSeries,
|
|
57
|
+
getSeriesData,
|
|
58
|
+
getXScale,
|
|
59
|
+
getYScale,
|
|
60
|
+
getXAxis,
|
|
61
|
+
drawingArea,
|
|
62
|
+
dataLength
|
|
63
|
+
} = useCartesianChartContext();
|
|
64
|
+
const {
|
|
65
|
+
scrubberPosition
|
|
66
|
+
} = useScrubberContext();
|
|
67
|
+
const [labelDimensions, setLabelDimensions] = useState({});
|
|
68
|
+
const handleDimensionsChange = useCallback((seriesId, dimensions) => {
|
|
69
|
+
setLabelDimensions(prev => {
|
|
70
|
+
const existing = prev[seriesId];
|
|
71
|
+
if (existing && existing.width === dimensions.width && existing.height === dimensions.height) {
|
|
72
|
+
return prev;
|
|
73
|
+
}
|
|
74
|
+
return _objectSpread(_objectSpread({}, prev), {}, {
|
|
75
|
+
[seriesId]: dimensions
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
}, []);
|
|
79
|
+
const seriesInfo = useMemo(() => {
|
|
80
|
+
return labels.map(label => {
|
|
81
|
+
const series = getSeries(label.seriesId);
|
|
82
|
+
if (!series) return null;
|
|
83
|
+
const sourceData = getSeriesData(label.seriesId);
|
|
84
|
+
const yScale = getYScale(series.yAxisId);
|
|
85
|
+
return {
|
|
86
|
+
seriesId: label.seriesId,
|
|
87
|
+
sourceData,
|
|
88
|
+
yScale
|
|
89
|
+
};
|
|
90
|
+
}).filter(info => info !== null);
|
|
91
|
+
}, [labels, getSeries, getSeriesData, getYScale]);
|
|
92
|
+
const xScale = getXScale();
|
|
93
|
+
const xAxis = getXAxis();
|
|
94
|
+
const dataIndex = useMemo(() => {
|
|
95
|
+
return scrubberPosition !== null && scrubberPosition !== void 0 ? scrubberPosition : Math.max(0, dataLength - 1);
|
|
96
|
+
}, [scrubberPosition, dataLength]);
|
|
97
|
+
const dataX = useMemo(() => {
|
|
98
|
+
if (xAxis !== null && xAxis !== void 0 && xAxis.data && Array.isArray(xAxis.data) && xAxis.data[dataIndex] !== undefined) {
|
|
99
|
+
const dataValue = xAxis.data[dataIndex];
|
|
100
|
+
return typeof dataValue === 'string' ? dataIndex : dataValue;
|
|
101
|
+
}
|
|
102
|
+
return dataIndex;
|
|
103
|
+
}, [xAxis, dataIndex]);
|
|
104
|
+
const allLabelPositions = useMemo(() => {
|
|
105
|
+
if (!xScale || dataX === undefined) return [];
|
|
106
|
+
const sharedPixelX = getPointOnScale(dataX, xScale);
|
|
107
|
+
const desiredPositions = seriesInfo.map(info => {
|
|
108
|
+
let dataY;
|
|
109
|
+
if (info.yScale) {
|
|
110
|
+
if (info.sourceData && dataIndex !== undefined && dataIndex >= 0 && dataIndex < info.sourceData.length) {
|
|
111
|
+
const dataValue = info.sourceData[dataIndex];
|
|
112
|
+
if (Array.isArray(dataValue)) {
|
|
113
|
+
const validValues = dataValue.filter(val => val !== null);
|
|
114
|
+
if (validValues.length >= 1) {
|
|
115
|
+
dataY = validValues[validValues.length - 1];
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (dataY !== undefined && info.yScale) {
|
|
121
|
+
return {
|
|
122
|
+
seriesId: info.seriesId,
|
|
123
|
+
x: sharedPixelX,
|
|
124
|
+
desiredY: getPointOnScale(dataY, info.yScale)
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Return null for invalid data
|
|
129
|
+
return null;
|
|
130
|
+
});
|
|
131
|
+
const maxLabelHeight = Math.max(...Object.values(labelDimensions).map(dim => dim.height));
|
|
132
|
+
const maxLabelWidth = Math.max(...Object.values(labelDimensions).map(dim => dim.width));
|
|
133
|
+
|
|
134
|
+
// Only apply collision detection to valid positions
|
|
135
|
+
const validPositions = desiredPositions.filter(pos => pos !== null);
|
|
136
|
+
|
|
137
|
+
// Convert to LabelDimension format expected by utility
|
|
138
|
+
const dimensions = validPositions.map(pos => {
|
|
139
|
+
var _trackedDimensions$wi, _trackedDimensions$he;
|
|
140
|
+
const trackedDimensions = labelDimensions[pos.seriesId];
|
|
141
|
+
return {
|
|
142
|
+
seriesId: pos.seriesId,
|
|
143
|
+
width: (_trackedDimensions$wi = trackedDimensions === null || trackedDimensions === void 0 ? void 0 : trackedDimensions.width) !== null && _trackedDimensions$wi !== void 0 ? _trackedDimensions$wi : maxLabelWidth,
|
|
144
|
+
height: (_trackedDimensions$he = trackedDimensions === null || trackedDimensions === void 0 ? void 0 : trackedDimensions.height) !== null && _trackedDimensions$he !== void 0 ? _trackedDimensions$he : maxLabelHeight,
|
|
145
|
+
preferredX: pos.x,
|
|
146
|
+
preferredY: pos.desiredY
|
|
147
|
+
};
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
// Calculate Y positions with collision resolution for valid positions only
|
|
151
|
+
const yPositions = calculateLabelYPositions(dimensions, drawingArea, maxLabelHeight, labelMinGap);
|
|
152
|
+
|
|
153
|
+
// Return all positions (including null ones)
|
|
154
|
+
return desiredPositions.map(pos => {
|
|
155
|
+
var _yPositions$get;
|
|
156
|
+
if (!pos) return null;
|
|
157
|
+
return {
|
|
158
|
+
seriesId: pos.seriesId,
|
|
159
|
+
x: pos.x,
|
|
160
|
+
y: (_yPositions$get = yPositions.get(pos.seriesId)) !== null && _yPositions$get !== void 0 ? _yPositions$get : pos.desiredY
|
|
161
|
+
};
|
|
162
|
+
});
|
|
163
|
+
}, [seriesInfo, dataIndex, dataX, xScale, labelDimensions, drawingArea, labelMinGap]);
|
|
164
|
+
const currentPosition = useMemo(() => {
|
|
165
|
+
if (!xScale || dataX === undefined) return 'right';
|
|
166
|
+
const pixelX = getPointOnScale(dataX, xScale);
|
|
167
|
+
const maxWidth = Math.max(...Object.values(labelDimensions).map(dim => dim.width));
|
|
168
|
+
return getLabelPosition(pixelX, maxWidth, drawingArea, labelHorizontalOffset);
|
|
169
|
+
}, [dataX, xScale, labelDimensions, drawingArea, labelHorizontalOffset]);
|
|
170
|
+
return seriesInfo.map((info, index) => {
|
|
171
|
+
const labelInfo = labels.find(label => label.seriesId === info.seriesId);
|
|
172
|
+
if (!labelInfo) return;
|
|
173
|
+
return /*#__PURE__*/_jsx(PositionedLabel, {
|
|
174
|
+
BeaconLabelComponent: BeaconLabelComponent,
|
|
175
|
+
color: labelInfo.color,
|
|
176
|
+
index: index,
|
|
177
|
+
label: labelInfo.label,
|
|
178
|
+
labelFont: labelFont,
|
|
179
|
+
labelHorizontalOffset: labelHorizontalOffset,
|
|
180
|
+
onDimensionsChange: handleDimensionsChange,
|
|
181
|
+
position: currentPosition,
|
|
182
|
+
positions: allLabelPositions,
|
|
183
|
+
seriesId: info.seriesId
|
|
184
|
+
}, info.seriesId);
|
|
185
|
+
});
|
|
186
|
+
});
|
|
@@ -67,9 +67,9 @@ export const ChartText = /*#__PURE__*/memo(_ref => {
|
|
|
67
67
|
fontFamily,
|
|
68
68
|
fontSize,
|
|
69
69
|
fontWeight,
|
|
70
|
-
|
|
70
|
+
elevated,
|
|
71
71
|
color = 'var(--color-fgMuted)',
|
|
72
|
-
background =
|
|
72
|
+
background = elevated ? 'var(--color-bg)' : 'transparent',
|
|
73
73
|
borderRadius,
|
|
74
74
|
inset: insetInput,
|
|
75
75
|
onDimensionsChange,
|
|
@@ -112,7 +112,7 @@ export const ChartText = /*#__PURE__*/memo(_ref => {
|
|
|
112
112
|
};
|
|
113
113
|
}
|
|
114
114
|
const parentBounds = bounds !== null && bounds !== void 0 ? bounds : fullChartBounds;
|
|
115
|
-
if (!
|
|
115
|
+
if (!backgroundRectDimensions || !parentBounds || parentBounds.width <= 0 || parentBounds.height <= 0) {
|
|
116
116
|
return {
|
|
117
117
|
x: 0,
|
|
118
118
|
y: 0
|
|
@@ -120,25 +120,21 @@ export const ChartText = /*#__PURE__*/memo(_ref => {
|
|
|
120
120
|
}
|
|
121
121
|
let x = 0;
|
|
122
122
|
let y = 0;
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
if (
|
|
126
|
-
x = parentBounds.x -
|
|
127
|
-
} else if (textBBox.x + textBBox.width > parentBounds.x + parentBounds.width) {
|
|
128
|
-
x = parentBounds.x + parentBounds.width - (textBBox.x + textBBox.width); // negative = shift left
|
|
123
|
+
if (backgroundRectDimensions.x < parentBounds.x) {
|
|
124
|
+
x = parentBounds.x - backgroundRectDimensions.x; // positive = shift right
|
|
125
|
+
} else if (backgroundRectDimensions.x + backgroundRectDimensions.width > parentBounds.x + parentBounds.width) {
|
|
126
|
+
x = parentBounds.x + parentBounds.width - (backgroundRectDimensions.x + backgroundRectDimensions.width); // negative = shift left
|
|
129
127
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
if (
|
|
133
|
-
y = parentBounds.y -
|
|
134
|
-
} else if (textBBox.y + textBBox.height > parentBounds.y + parentBounds.height) {
|
|
135
|
-
y = parentBounds.y + parentBounds.height - (textBBox.y + textBBox.height); // negative = shift up
|
|
128
|
+
if (backgroundRectDimensions.y < parentBounds.y) {
|
|
129
|
+
y = parentBounds.y - backgroundRectDimensions.y; // positive = shift down
|
|
130
|
+
} else if (backgroundRectDimensions.y + backgroundRectDimensions.height > parentBounds.y + parentBounds.height) {
|
|
131
|
+
y = parentBounds.y + parentBounds.height - (backgroundRectDimensions.y + backgroundRectDimensions.height); // negative = shift up
|
|
136
132
|
}
|
|
137
133
|
return {
|
|
138
134
|
x,
|
|
139
135
|
y
|
|
140
136
|
};
|
|
141
|
-
}, [
|
|
137
|
+
}, [backgroundRectDimensions, fullChartBounds, bounds, disableRepositioning]);
|
|
142
138
|
|
|
143
139
|
// Compose the final reported rect including any overflow translation applied
|
|
144
140
|
const reportedRect = useMemo(() => {
|
|
@@ -150,8 +146,6 @@ export const ChartText = /*#__PURE__*/memo(_ref => {
|
|
|
150
146
|
height: backgroundRectDimensions.height
|
|
151
147
|
};
|
|
152
148
|
}, [backgroundRectDimensions, overflowAmount.x, overflowAmount.y]);
|
|
153
|
-
|
|
154
|
-
// send latest calculated dimensions (adjusted for translation) to parent
|
|
155
149
|
useEffect(() => {
|
|
156
150
|
if (onDimensionsChange && reportedRect !== null) {
|
|
157
151
|
onDimensionsChange(reportedRect);
|
|
@@ -203,7 +197,7 @@ export const ChartText = /*#__PURE__*/memo(_ref => {
|
|
|
203
197
|
as: "rect",
|
|
204
198
|
className: classNames === null || classNames === void 0 ? void 0 : classNames.backgroundRect,
|
|
205
199
|
fill: background,
|
|
206
|
-
filter:
|
|
200
|
+
filter: elevated ? 'drop-shadow(var(--shadow-elevation1))' : undefined,
|
|
207
201
|
height: backgroundRectDimensions === null || backgroundRectDimensions === void 0 ? void 0 : backgroundRectDimensions.height,
|
|
208
202
|
rx: borderRadius,
|
|
209
203
|
ry: borderRadius,
|
|
@@ -36,12 +36,13 @@ const EPSILON_PX = 0.5;
|
|
|
36
36
|
*
|
|
37
37
|
* The component focuses solely on overlap prevention logic for better separation of concerns.
|
|
38
38
|
*/
|
|
39
|
-
export const
|
|
39
|
+
export const ChartTextGroup = /*#__PURE__*/memo(_ref => {
|
|
40
40
|
let {
|
|
41
41
|
labels,
|
|
42
42
|
minGap = 8,
|
|
43
43
|
prioritizeEndLabels = true,
|
|
44
|
-
chartTextProps
|
|
44
|
+
chartTextProps,
|
|
45
|
+
LabelComponent = ChartText
|
|
45
46
|
} = _ref;
|
|
46
47
|
const [boundingBoxes, setBoundingBoxes] = useState(new Map());
|
|
47
48
|
const _ref2 = chartTextProps !== null && chartTextProps !== void 0 ? chartTextProps : {},
|
|
@@ -213,7 +214,7 @@ export const SmartChartTextGroup = /*#__PURE__*/memo(_ref => {
|
|
|
213
214
|
display: 'none'
|
|
214
215
|
} : {})
|
|
215
216
|
};
|
|
216
|
-
return /*#__PURE__*/_jsx(
|
|
217
|
+
return /*#__PURE__*/_jsx(LabelComponent, _objectSpread(_objectSpread(_objectSpread({
|
|
217
218
|
x: labelData.x,
|
|
218
219
|
y: labelData.y
|
|
219
220
|
}, restChartTextProps), labelData.chartTextProps), {}, {
|
package/esm/chart/text/index.js
CHANGED
package/esm/chart/utils/chart.js
CHANGED
|
@@ -19,13 +19,13 @@ export const getChartDomain = (series, min, max) => {
|
|
|
19
19
|
return domain;
|
|
20
20
|
}
|
|
21
21
|
if (series.length > 0) {
|
|
22
|
-
const
|
|
22
|
+
const dataLength = Math.max(...series.map(s => {
|
|
23
23
|
var _s$data;
|
|
24
24
|
return ((_s$data = s.data) === null || _s$data === void 0 ? void 0 : _s$data.length) || 0;
|
|
25
25
|
}));
|
|
26
|
-
if (
|
|
26
|
+
if (dataLength > 0) {
|
|
27
27
|
if (domain.min === undefined) domain.min = 0;
|
|
28
|
-
if (domain.max === undefined) domain.max =
|
|
28
|
+
if (domain.max === undefined) domain.max = dataLength - 1;
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
return domain;
|
|
@@ -111,6 +111,32 @@ export const getStackedSeriesData = series => {
|
|
|
111
111
|
return stackedDataMap;
|
|
112
112
|
};
|
|
113
113
|
|
|
114
|
+
/**
|
|
115
|
+
* Extracts line data values from series data that may contain tuples.
|
|
116
|
+
* For tuple data [[baseline, value]], extracts the last value.
|
|
117
|
+
* For numeric data [value], returns as-is.
|
|
118
|
+
*
|
|
119
|
+
* @param data - Array of numbers, tuples, or null values
|
|
120
|
+
* @returns Array of numbers or null values
|
|
121
|
+
*/
|
|
122
|
+
export const getLineData = data => {
|
|
123
|
+
if (!data) return [];
|
|
124
|
+
|
|
125
|
+
// Check if this is tuple data by finding first non-null entry
|
|
126
|
+
const firstNonNull = data.find(d => d !== null);
|
|
127
|
+
if (Array.isArray(firstNonNull)) {
|
|
128
|
+
return data.map(d => {
|
|
129
|
+
var _d$at;
|
|
130
|
+
if (d === null) return null;
|
|
131
|
+
if (Array.isArray(d)) return (_d$at = d.at(-1)) !== null && _d$at !== void 0 ? _d$at : null;
|
|
132
|
+
return d;
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Already numeric data
|
|
137
|
+
return data;
|
|
138
|
+
};
|
|
139
|
+
|
|
114
140
|
/**
|
|
115
141
|
* Calculates the range of a chart from series data.
|
|
116
142
|
* Range represents the range of y-values from the data.
|