@coinbase/cds-web-visualization 3.4.0-beta.9 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +126 -0
- package/dts/chart/CartesianChart.d.ts +40 -4
- package/dts/chart/CartesianChart.d.ts.map +1 -1
- package/dts/chart/ChartProvider.d.ts +3 -0
- package/dts/chart/ChartProvider.d.ts.map +1 -1
- package/dts/chart/Path.d.ts +51 -12
- package/dts/chart/Path.d.ts.map +1 -1
- package/dts/chart/PeriodSelector.d.ts +25 -4
- package/dts/chart/PeriodSelector.d.ts.map +1 -1
- package/dts/chart/area/Area.d.ts +13 -11
- package/dts/chart/area/Area.d.ts.map +1 -1
- package/dts/chart/area/AreaChart.d.ts +18 -5
- package/dts/chart/area/AreaChart.d.ts.map +1 -1
- package/dts/chart/area/DottedArea.d.ts.map +1 -1
- package/dts/chart/area/GradientArea.d.ts.map +1 -1
- package/dts/chart/area/SolidArea.d.ts.map +1 -1
- package/dts/chart/axis/Axis.d.ts +29 -29
- package/dts/chart/axis/Axis.d.ts.map +1 -1
- package/dts/chart/axis/XAxis.d.ts +6 -0
- package/dts/chart/axis/XAxis.d.ts.map +1 -1
- package/dts/chart/axis/YAxis.d.ts +2 -1
- package/dts/chart/axis/YAxis.d.ts.map +1 -1
- package/dts/chart/bar/Bar.d.ts +51 -51
- package/dts/chart/bar/Bar.d.ts.map +1 -1
- package/dts/chart/bar/BarChart.d.ts +29 -6
- 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 +58 -20
- package/dts/chart/bar/BarStack.d.ts.map +1 -1
- package/dts/chart/bar/BarStackGroup.d.ts +2 -1
- 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 +7 -0
- package/dts/chart/gradient/Gradient.d.ts.map +1 -1
- package/dts/chart/index.d.ts +1 -0
- package/dts/chart/index.d.ts.map +1 -1
- package/dts/chart/legend/DefaultLegendEntry.d.ts +21 -0
- package/dts/chart/legend/DefaultLegendEntry.d.ts.map +1 -0
- package/dts/chart/legend/DefaultLegendShape.d.ts +7 -0
- package/dts/chart/legend/DefaultLegendShape.d.ts.map +1 -0
- package/dts/chart/legend/Legend.d.ts +169 -0
- package/dts/chart/legend/Legend.d.ts.map +1 -0
- package/dts/chart/legend/index.d.ts +4 -0
- package/dts/chart/legend/index.d.ts.map +1 -0
- package/dts/chart/line/DottedLine.d.ts.map +1 -1
- package/dts/chart/line/Line.d.ts +45 -24
- package/dts/chart/line/Line.d.ts.map +1 -1
- package/dts/chart/line/LineChart.d.ts +5 -3
- package/dts/chart/line/LineChart.d.ts.map +1 -1
- package/dts/chart/line/ReferenceLine.d.ts +9 -0
- package/dts/chart/line/ReferenceLine.d.ts.map +1 -1
- package/dts/chart/line/SolidLine.d.ts.map +1 -1
- package/dts/chart/point/Point.d.ts +26 -2
- package/dts/chart/point/Point.d.ts.map +1 -1
- package/dts/chart/scrubber/DefaultScrubberBeacon.d.ts +34 -17
- package/dts/chart/scrubber/DefaultScrubberBeacon.d.ts.map +1 -1
- package/dts/chart/scrubber/DefaultScrubberBeaconLabel.d.ts.map +1 -1
- package/dts/chart/scrubber/DefaultScrubberLabel.d.ts +2 -1
- package/dts/chart/scrubber/DefaultScrubberLabel.d.ts.map +1 -1
- package/dts/chart/scrubber/Scrubber.d.ts +148 -46
- package/dts/chart/scrubber/Scrubber.d.ts.map +1 -1
- package/dts/chart/scrubber/ScrubberBeaconGroup.d.ts +10 -0
- package/dts/chart/scrubber/ScrubberBeaconGroup.d.ts.map +1 -1
- package/dts/chart/scrubber/ScrubberBeaconLabelGroup.d.ts +25 -1
- package/dts/chart/scrubber/ScrubberBeaconLabelGroup.d.ts.map +1 -1
- package/dts/chart/scrubber/ScrubberProvider.d.ts.map +1 -1
- package/dts/chart/text/ChartText.d.ts.map +1 -1
- package/dts/chart/utils/axis.d.ts +48 -9
- package/dts/chart/utils/axis.d.ts.map +1 -1
- package/dts/chart/utils/bar.d.ts +188 -0
- package/dts/chart/utils/bar.d.ts.map +1 -1
- package/dts/chart/utils/chart.d.ts +32 -0
- package/dts/chart/utils/chart.d.ts.map +1 -1
- package/dts/chart/utils/context.d.ts +20 -4
- package/dts/chart/utils/context.d.ts.map +1 -1
- package/dts/chart/utils/gradient.d.ts +3 -1
- package/dts/chart/utils/gradient.d.ts.map +1 -1
- package/dts/chart/utils/path.d.ts +26 -0
- package/dts/chart/utils/path.d.ts.map +1 -1
- package/dts/chart/utils/point.d.ts +18 -7
- package/dts/chart/utils/point.d.ts.map +1 -1
- package/dts/chart/utils/scale.d.ts +11 -0
- package/dts/chart/utils/scale.d.ts.map +1 -1
- package/dts/chart/utils/scrubber.d.ts +2 -1
- package/dts/chart/utils/scrubber.d.ts.map +1 -1
- package/dts/chart/utils/transition.d.ts +50 -14
- package/dts/chart/utils/transition.d.ts.map +1 -1
- package/dts/sparkline/Sparkline.d.ts +2 -1
- package/dts/sparkline/Sparkline.d.ts.map +1 -1
- package/dts/sparkline/SparklineArea.d.ts +2 -1
- package/dts/sparkline/SparklineArea.d.ts.map +1 -1
- package/dts/sparkline/SparklineGradient.d.ts +2 -1
- package/dts/sparkline/SparklineGradient.d.ts.map +1 -1
- package/dts/sparkline/sparkline-interactive/SparklineInteractive.d.ts +2 -1
- package/dts/sparkline/sparkline-interactive/SparklineInteractive.d.ts.map +1 -1
- package/esm/chart/CartesianChart.js +154 -90
- package/esm/chart/ChartProvider.js +2 -2
- package/esm/chart/Path.js +35 -19
- package/esm/chart/PeriodSelector.js +33 -15
- package/esm/chart/area/Area.js +21 -9
- package/esm/chart/area/AreaChart.js +28 -25
- package/esm/chart/area/DottedArea.js +18 -9
- package/esm/chart/area/GradientArea.js +16 -8
- package/esm/chart/area/SolidArea.js +8 -3
- package/esm/chart/axis/Axis.js +3 -17
- package/esm/chart/axis/XAxis.js +153 -50
- package/esm/chart/axis/YAxis.js +146 -36
- package/esm/chart/bar/Bar.js +16 -8
- package/esm/chart/bar/BarChart.js +38 -33
- package/esm/chart/bar/BarPlot.js +20 -25
- package/esm/chart/bar/BarStack.js +109 -505
- package/esm/chart/bar/BarStackGroup.js +36 -27
- package/esm/chart/bar/DefaultBar.js +34 -26
- package/esm/chart/bar/DefaultBarStack.js +31 -18
- package/esm/chart/gradient/Gradient.js +3 -2
- package/esm/chart/index.js +1 -0
- package/esm/chart/legend/DefaultLegendEntry.css +1 -0
- package/esm/chart/legend/DefaultLegendEntry.js +50 -0
- package/esm/chart/legend/DefaultLegendShape.css +5 -0
- package/esm/chart/legend/DefaultLegendShape.js +47 -0
- package/esm/chart/legend/Legend.js +76 -0
- package/esm/chart/legend/index.js +3 -0
- package/esm/chart/line/DottedLine.js +7 -2
- package/esm/chart/line/Line.js +41 -42
- package/esm/chart/line/LineChart.js +18 -13
- package/esm/chart/line/ReferenceLine.js +6 -2
- package/esm/chart/line/SolidLine.js +8 -3
- package/esm/chart/point/Point.js +41 -24
- package/esm/chart/scrubber/DefaultScrubberBeacon.js +64 -65
- package/esm/chart/scrubber/DefaultScrubberBeaconLabel.js +25 -14
- package/esm/chart/scrubber/DefaultScrubberLabel.js +26 -8
- package/esm/chart/scrubber/Scrubber.js +54 -43
- package/esm/chart/scrubber/ScrubberBeaconGroup.js +60 -35
- package/esm/chart/scrubber/ScrubberBeaconLabelGroup.js +31 -8
- package/esm/chart/scrubber/ScrubberProvider.js +44 -39
- package/esm/chart/text/ChartText.js +3 -2
- package/esm/chart/utils/axis.js +90 -43
- package/esm/chart/utils/bar.js +863 -0
- package/esm/chart/utils/chart.js +34 -7
- package/esm/chart/utils/context.js +7 -0
- package/esm/chart/utils/gradient.js +6 -4
- package/esm/chart/utils/path.js +88 -61
- package/esm/chart/utils/point.js +57 -30
- package/esm/chart/utils/scale.js +13 -2
- package/esm/chart/utils/scrubber.js +9 -4
- package/esm/chart/utils/transition.js +68 -41
- package/esm/sparkline/Sparkline.js +2 -1
- package/esm/sparkline/SparklineArea.js +2 -1
- package/esm/sparkline/SparklineGradient.js +2 -1
- package/esm/sparkline/__figma__/Sparkline.figma.js +1 -1
- package/esm/sparkline/sparkline-interactive/SparklineInteractive.js +2 -1
- package/esm/sparkline/sparkline-interactive/__figma__/SparklineInteractive.figma.js +1 -1
- package/esm/sparkline/sparkline-interactive-header/__figma__/SparklineInteractiveHeader.figma.js +1 -1
- package/package.json +8 -7
|
@@ -9,34 +9,39 @@ const BeaconWithData = /*#__PURE__*/memo(_ref => {
|
|
|
9
9
|
let {
|
|
10
10
|
seriesId,
|
|
11
11
|
dataIndex,
|
|
12
|
-
|
|
12
|
+
dataIndexValue,
|
|
13
13
|
isIdle,
|
|
14
14
|
BeaconComponent,
|
|
15
15
|
idlePulse,
|
|
16
|
+
animate,
|
|
16
17
|
transitions,
|
|
17
18
|
className,
|
|
18
19
|
style,
|
|
19
20
|
testID,
|
|
20
|
-
beaconRef
|
|
21
|
+
beaconRef,
|
|
22
|
+
stroke
|
|
21
23
|
} = _ref;
|
|
22
24
|
const {
|
|
25
|
+
layout,
|
|
23
26
|
getSeries,
|
|
24
27
|
getSeriesData,
|
|
25
28
|
getXScale,
|
|
26
|
-
getYScale
|
|
29
|
+
getYScale,
|
|
30
|
+
getXAxis,
|
|
31
|
+
getYAxis
|
|
27
32
|
} = useCartesianChartContext();
|
|
28
33
|
const series = useMemo(() => getSeries(seriesId), [getSeries, seriesId]);
|
|
29
34
|
const sourceData = useMemo(() => getSeriesData(seriesId), [getSeriesData, seriesId]);
|
|
30
35
|
const gradient = series === null || series === void 0 ? void 0 : series.gradient;
|
|
31
36
|
|
|
32
|
-
// Get
|
|
33
|
-
const
|
|
37
|
+
// Get dataValue from series data
|
|
38
|
+
const dataValue = useMemo(() => {
|
|
34
39
|
if (sourceData && dataIndex >= 0 && dataIndex < sourceData.length) {
|
|
35
|
-
const
|
|
36
|
-
if (typeof
|
|
37
|
-
return
|
|
38
|
-
} else if (Array.isArray(
|
|
39
|
-
const validValues =
|
|
40
|
+
const value = sourceData[dataIndex];
|
|
41
|
+
if (typeof value === 'number') {
|
|
42
|
+
return value;
|
|
43
|
+
} else if (Array.isArray(value)) {
|
|
44
|
+
const validValues = value.filter(val => val !== null);
|
|
40
45
|
if (validValues.length >= 1) {
|
|
41
46
|
return validValues[validValues.length - 1];
|
|
42
47
|
}
|
|
@@ -48,18 +53,27 @@ const BeaconWithData = /*#__PURE__*/memo(_ref => {
|
|
|
48
53
|
// Evaluate gradient color
|
|
49
54
|
const color = useMemo(() => {
|
|
50
55
|
var _series$color, _series$color2;
|
|
51
|
-
if (
|
|
56
|
+
if (dataValue === undefined) return (_series$color = series === null || series === void 0 ? void 0 : series.color) !== null && _series$color !== void 0 ? _series$color : 'var(--color-fgPrimary)';
|
|
52
57
|
if (gradient) {
|
|
53
|
-
const xScale = getXScale();
|
|
58
|
+
const xScale = getXScale(series === null || series === void 0 ? void 0 : series.xAxisId);
|
|
54
59
|
const yScale = getYScale(series === null || series === void 0 ? void 0 : series.yAxisId);
|
|
55
60
|
if (xScale && yScale) {
|
|
61
|
+
const categoryAxisIsX = layout !== 'horizontal';
|
|
56
62
|
const gradientScale = gradient.axis === 'x' ? xScale : yScale;
|
|
57
63
|
const stops = getGradientConfig(gradient, xScale, yScale);
|
|
58
64
|
if (stops) {
|
|
59
65
|
var _gradient$axis;
|
|
60
66
|
const gradientAxis = (_gradient$axis = gradient.axis) !== null && _gradient$axis !== void 0 ? _gradient$axis : 'y';
|
|
61
|
-
|
|
62
|
-
|
|
67
|
+
// Determine the correct data value to evaluate against based on gradient axis and layout
|
|
68
|
+
let evalValue;
|
|
69
|
+
if (gradientAxis === 'x') {
|
|
70
|
+
// X-axis gradient: In vertical it's the index, in horizontal it's the value.
|
|
71
|
+
evalValue = categoryAxisIsX ? dataIndexValue : dataValue;
|
|
72
|
+
} else {
|
|
73
|
+
// Y-axis gradient: In vertical it's the value, in horizontal it's the index.
|
|
74
|
+
evalValue = categoryAxisIsX ? dataValue : dataIndexValue;
|
|
75
|
+
}
|
|
76
|
+
const evaluatedColor = evaluateGradientAtValue(stops, evalValue, gradientScale);
|
|
63
77
|
if (evaluatedColor) {
|
|
64
78
|
return evaluatedColor;
|
|
65
79
|
}
|
|
@@ -67,17 +81,20 @@ const BeaconWithData = /*#__PURE__*/memo(_ref => {
|
|
|
67
81
|
}
|
|
68
82
|
}
|
|
69
83
|
return (_series$color2 = series === null || series === void 0 ? void 0 : series.color) !== null && _series$color2 !== void 0 ? _series$color2 : 'var(--color-fgPrimary)';
|
|
70
|
-
}, [gradient,
|
|
71
|
-
if (
|
|
84
|
+
}, [gradient, dataIndexValue, dataValue, series === null || series === void 0 ? void 0 : series.color, series === null || series === void 0 ? void 0 : series.xAxisId, series === null || series === void 0 ? void 0 : series.yAxisId, getXScale, getYScale, layout]);
|
|
85
|
+
if (dataValue === undefined) return null;
|
|
86
|
+
const categoryAxisIsX = layout !== 'horizontal';
|
|
72
87
|
return /*#__PURE__*/_jsx(BeaconComponent, {
|
|
73
88
|
ref: beaconRef,
|
|
89
|
+
animate: animate,
|
|
74
90
|
className: className,
|
|
75
91
|
color: color,
|
|
76
|
-
dataX:
|
|
77
|
-
dataY:
|
|
92
|
+
dataX: categoryAxisIsX ? dataIndexValue : dataValue,
|
|
93
|
+
dataY: categoryAxisIsX ? dataValue : dataIndexValue,
|
|
78
94
|
idlePulse: idlePulse,
|
|
79
95
|
isIdle: isIdle,
|
|
80
96
|
seriesId: seriesId,
|
|
97
|
+
stroke: stroke,
|
|
81
98
|
style: style,
|
|
82
99
|
testID: testID,
|
|
83
100
|
transitions: transitions
|
|
@@ -91,17 +108,22 @@ export const ScrubberBeaconGroup = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_r
|
|
|
91
108
|
BeaconComponent = DefaultScrubberBeacon,
|
|
92
109
|
className,
|
|
93
110
|
style,
|
|
94
|
-
testID
|
|
111
|
+
testID,
|
|
112
|
+
stroke
|
|
95
113
|
} = _ref2;
|
|
96
114
|
const ScrubberBeaconRefs = useRefMap();
|
|
97
115
|
const {
|
|
98
116
|
scrubberPosition
|
|
99
117
|
} = useScrubberContext();
|
|
100
118
|
const {
|
|
119
|
+
layout,
|
|
101
120
|
getXScale,
|
|
121
|
+
getYScale,
|
|
102
122
|
getXAxis,
|
|
123
|
+
getYAxis,
|
|
103
124
|
dataLength,
|
|
104
|
-
series
|
|
125
|
+
series,
|
|
126
|
+
animate
|
|
105
127
|
} = useCartesianChartContext();
|
|
106
128
|
|
|
107
129
|
// Expose imperative handle with pulse method
|
|
@@ -117,30 +139,31 @@ export const ScrubberBeaconGroup = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_r
|
|
|
117
139
|
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
140
|
}, [series, seriesIds]);
|
|
119
141
|
const {
|
|
120
|
-
|
|
142
|
+
dataIndexValue,
|
|
121
143
|
dataIndex
|
|
122
144
|
} = useMemo(() => {
|
|
123
|
-
const
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
145
|
+
const categoryAxisIsX = layout !== 'horizontal';
|
|
146
|
+
const indexScale = categoryAxisIsX ? getXScale() : getYScale();
|
|
147
|
+
const indexAxis = categoryAxisIsX ? getXAxis() : getYAxis();
|
|
148
|
+
if (!indexScale) return {
|
|
149
|
+
dataIndexValue: undefined,
|
|
127
150
|
dataIndex: undefined
|
|
128
151
|
};
|
|
129
152
|
const dataIndex = scrubberPosition !== null && scrubberPosition !== void 0 ? scrubberPosition : Math.max(0, dataLength - 1);
|
|
130
153
|
|
|
131
|
-
// Convert index to actual
|
|
132
|
-
let
|
|
133
|
-
if (
|
|
134
|
-
const
|
|
135
|
-
|
|
154
|
+
// Convert index to actual data value if axis has data
|
|
155
|
+
let dataIndexValue;
|
|
156
|
+
if (indexAxis !== null && indexAxis !== void 0 && indexAxis.data && Array.isArray(indexAxis.data) && indexAxis.data[dataIndex] !== undefined) {
|
|
157
|
+
const val = indexAxis.data[dataIndex];
|
|
158
|
+
dataIndexValue = typeof val === 'string' ? dataIndex : val;
|
|
136
159
|
} else {
|
|
137
|
-
|
|
160
|
+
dataIndexValue = dataIndex;
|
|
138
161
|
}
|
|
139
162
|
return {
|
|
140
|
-
|
|
163
|
+
dataIndexValue,
|
|
141
164
|
dataIndex
|
|
142
165
|
};
|
|
143
|
-
}, [getXScale, getXAxis, scrubberPosition, dataLength]);
|
|
166
|
+
}, [getXScale, getYScale, getXAxis, getYAxis, scrubberPosition, dataLength, layout]);
|
|
144
167
|
const isIdle = scrubberPosition === undefined;
|
|
145
168
|
const createBeaconRef = useCallback(seriesId => {
|
|
146
169
|
return beaconRef => {
|
|
@@ -149,16 +172,18 @@ export const ScrubberBeaconGroup = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_r
|
|
|
149
172
|
}
|
|
150
173
|
};
|
|
151
174
|
}, [ScrubberBeaconRefs]);
|
|
152
|
-
if (
|
|
175
|
+
if (dataIndexValue === undefined || dataIndex === undefined) return null;
|
|
153
176
|
return filteredSeries.map(s => /*#__PURE__*/_jsx(BeaconWithData, {
|
|
154
177
|
BeaconComponent: BeaconComponent,
|
|
178
|
+
animate: animate,
|
|
155
179
|
beaconRef: createBeaconRef(s.id),
|
|
156
180
|
className: className,
|
|
157
181
|
dataIndex: dataIndex,
|
|
158
|
-
|
|
182
|
+
dataIndexValue: dataIndexValue,
|
|
159
183
|
idlePulse: idlePulse,
|
|
160
184
|
isIdle: isIdle,
|
|
161
185
|
seriesId: s.id,
|
|
186
|
+
stroke: stroke,
|
|
162
187
|
style: style,
|
|
163
188
|
testID: testID ? "".concat(testID !== null && testID !== void 0 ? testID : 'beacon', "-").concat(s.id) : undefined,
|
|
164
189
|
transitions: transitions
|
|
@@ -4,8 +4,9 @@ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object
|
|
|
4
4
|
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
5
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
6
|
import { memo, useCallback, useMemo, useState } from 'react';
|
|
7
|
+
import { usePreviousValue } from '@coinbase/cds-common/hooks/usePreviousValue';
|
|
7
8
|
import { useCartesianChartContext } from '../ChartProvider';
|
|
8
|
-
import { getPointOnScale, useScrubberContext } from '../utils';
|
|
9
|
+
import { defaultTransition, getPointOnScale, getTransition, instantTransition, useScrubberContext } from '../utils';
|
|
9
10
|
import { calculateLabelYPositions, getLabelPosition } from '../utils/scrubber';
|
|
10
11
|
import { DefaultScrubberBeaconLabel } from './DefaultScrubberBeaconLabel';
|
|
11
12
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
@@ -20,7 +21,10 @@ const PositionedLabel = /*#__PURE__*/memo(_ref => {
|
|
|
20
21
|
onDimensionsChange,
|
|
21
22
|
BeaconLabelComponent,
|
|
22
23
|
labelHorizontalOffset,
|
|
23
|
-
labelFont
|
|
24
|
+
labelFont,
|
|
25
|
+
updateTransition,
|
|
26
|
+
className,
|
|
27
|
+
style
|
|
24
28
|
} = _ref;
|
|
25
29
|
const pos = positions[index];
|
|
26
30
|
|
|
@@ -33,6 +37,7 @@ const PositionedLabel = /*#__PURE__*/memo(_ref => {
|
|
|
33
37
|
const dx = position === 'right' ? labelHorizontalOffset : -labelHorizontalOffset;
|
|
34
38
|
const horizontalAlignment = position === 'right' ? 'left' : 'right';
|
|
35
39
|
return /*#__PURE__*/_jsx(BeaconLabelComponent, {
|
|
40
|
+
className: className,
|
|
36
41
|
color: color,
|
|
37
42
|
dx: dx,
|
|
38
43
|
font: labelFont,
|
|
@@ -40,6 +45,8 @@ const PositionedLabel = /*#__PURE__*/memo(_ref => {
|
|
|
40
45
|
label: label,
|
|
41
46
|
onDimensionsChange: d => onDimensionsChange(seriesId, d),
|
|
42
47
|
seriesId: seriesId,
|
|
48
|
+
style: style,
|
|
49
|
+
transition: updateTransition !== null && updateTransition !== void 0 ? updateTransition : instantTransition,
|
|
43
50
|
x: x,
|
|
44
51
|
y: y
|
|
45
52
|
});
|
|
@@ -50,7 +57,11 @@ export const ScrubberBeaconLabelGroup = /*#__PURE__*/memo(_ref2 => {
|
|
|
50
57
|
labelMinGap = 4,
|
|
51
58
|
labelHorizontalOffset = 16,
|
|
52
59
|
labelFont,
|
|
53
|
-
|
|
60
|
+
labelPreferredSide = 'right',
|
|
61
|
+
BeaconLabelComponent = DefaultScrubberBeaconLabel,
|
|
62
|
+
transitions,
|
|
63
|
+
className,
|
|
64
|
+
style
|
|
54
65
|
} = _ref2;
|
|
55
66
|
const {
|
|
56
67
|
getSeries,
|
|
@@ -59,11 +70,20 @@ export const ScrubberBeaconLabelGroup = /*#__PURE__*/memo(_ref2 => {
|
|
|
59
70
|
getYScale,
|
|
60
71
|
getXAxis,
|
|
61
72
|
drawingArea,
|
|
62
|
-
dataLength
|
|
73
|
+
dataLength,
|
|
74
|
+
animate
|
|
63
75
|
} = useCartesianChartContext();
|
|
64
76
|
const {
|
|
65
77
|
scrubberPosition
|
|
66
78
|
} = useScrubberContext();
|
|
79
|
+
const isIdle = scrubberPosition === undefined;
|
|
80
|
+
const prevIsIdle = usePreviousValue(isIdle);
|
|
81
|
+
const isIdleTransition = prevIsIdle !== undefined && isIdle !== prevIsIdle;
|
|
82
|
+
const updateTransition = useMemo(() => {
|
|
83
|
+
if (isIdleTransition) return instantTransition;
|
|
84
|
+
if (!isIdle) return instantTransition;
|
|
85
|
+
return getTransition(transitions === null || transitions === void 0 ? void 0 : transitions.update, animate, defaultTransition);
|
|
86
|
+
}, [transitions === null || transitions === void 0 ? void 0 : transitions.update, isIdle, animate, isIdleTransition]);
|
|
67
87
|
const [labelDimensions, setLabelDimensions] = useState({});
|
|
68
88
|
const handleDimensionsChange = useCallback((seriesId, dimensions) => {
|
|
69
89
|
setLabelDimensions(prev => {
|
|
@@ -162,16 +182,17 @@ export const ScrubberBeaconLabelGroup = /*#__PURE__*/memo(_ref2 => {
|
|
|
162
182
|
});
|
|
163
183
|
}, [seriesInfo, dataIndex, dataX, xScale, labelDimensions, drawingArea, labelMinGap]);
|
|
164
184
|
const currentPosition = useMemo(() => {
|
|
165
|
-
if (!xScale || dataX === undefined) return
|
|
185
|
+
if (!xScale || dataX === undefined) return labelPreferredSide;
|
|
166
186
|
const pixelX = getPointOnScale(dataX, xScale);
|
|
167
187
|
const maxWidth = Math.max(...Object.values(labelDimensions).map(dim => dim.width));
|
|
168
|
-
return getLabelPosition(pixelX, maxWidth, drawingArea, labelHorizontalOffset);
|
|
169
|
-
}, [dataX, xScale, labelDimensions, drawingArea, labelHorizontalOffset]);
|
|
188
|
+
return getLabelPosition(pixelX, maxWidth, drawingArea, labelHorizontalOffset, labelPreferredSide);
|
|
189
|
+
}, [dataX, xScale, labelDimensions, drawingArea, labelHorizontalOffset, labelPreferredSide]);
|
|
170
190
|
return seriesInfo.map((info, index) => {
|
|
171
191
|
const labelInfo = labels.find(label => label.seriesId === info.seriesId);
|
|
172
192
|
if (!labelInfo) return;
|
|
173
193
|
return /*#__PURE__*/_jsx(PositionedLabel, {
|
|
174
194
|
BeaconLabelComponent: BeaconLabelComponent,
|
|
195
|
+
className: className,
|
|
175
196
|
color: labelInfo.color,
|
|
176
197
|
index: index,
|
|
177
198
|
label: labelInfo.label,
|
|
@@ -180,7 +201,9 @@ export const ScrubberBeaconLabelGroup = /*#__PURE__*/memo(_ref2 => {
|
|
|
180
201
|
onDimensionsChange: handleDimensionsChange,
|
|
181
202
|
position: currentPosition,
|
|
182
203
|
positions: allLabelPositions,
|
|
183
|
-
seriesId: info.seriesId
|
|
204
|
+
seriesId: info.seriesId,
|
|
205
|
+
style: style,
|
|
206
|
+
updateTransition: updateTransition
|
|
184
207
|
}, info.seriesId);
|
|
185
208
|
});
|
|
186
209
|
});
|
|
@@ -18,25 +18,29 @@ export const ScrubberProvider = _ref => {
|
|
|
18
18
|
throw new Error('ScrubberProvider must be used within a ChartContext');
|
|
19
19
|
}
|
|
20
20
|
const {
|
|
21
|
+
layout,
|
|
21
22
|
getXScale,
|
|
23
|
+
getYScale,
|
|
22
24
|
getXAxis,
|
|
25
|
+
getYAxis,
|
|
23
26
|
series
|
|
24
27
|
} = chartContext;
|
|
25
28
|
const [scrubberPosition, setScrubberPosition] = useState(undefined);
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
if (
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const
|
|
29
|
+
const getDataIndexFromPosition = useCallback(mousePosition => {
|
|
30
|
+
const categoryAxisIsX = layout !== 'horizontal';
|
|
31
|
+
const categoryScale = categoryAxisIsX ? getXScale() : getYScale();
|
|
32
|
+
const categoryAxis = categoryAxisIsX ? getXAxis() : getYAxis();
|
|
33
|
+
if (!categoryScale || !categoryAxis) return 0;
|
|
34
|
+
if (isCategoricalScale(categoryScale)) {
|
|
35
|
+
var _ref2, _categoryScale$domain, _categoryScale$domain2, _categoryScale$bandwi, _categoryScale$bandwi2;
|
|
36
|
+
const categories = (_ref2 = (_categoryScale$domain = (_categoryScale$domain2 = categoryScale.domain) === null || _categoryScale$domain2 === void 0 ? void 0 : _categoryScale$domain2.call(categoryScale)) !== null && _categoryScale$domain !== void 0 ? _categoryScale$domain : categoryAxis.data) !== null && _ref2 !== void 0 ? _ref2 : [];
|
|
37
|
+
const bandwidth = (_categoryScale$bandwi = (_categoryScale$bandwi2 = categoryScale.bandwidth) === null || _categoryScale$bandwi2 === void 0 ? void 0 : _categoryScale$bandwi2.call(categoryScale)) !== null && _categoryScale$bandwi !== void 0 ? _categoryScale$bandwi : 0;
|
|
34
38
|
let closestIndex = 0;
|
|
35
39
|
let closestDistance = Infinity;
|
|
36
40
|
for (let i = 0; i < categories.length; i++) {
|
|
37
|
-
const
|
|
38
|
-
if (
|
|
39
|
-
const distance = Math.abs(
|
|
41
|
+
const pos = categoryScale(i);
|
|
42
|
+
if (pos !== undefined) {
|
|
43
|
+
const distance = Math.abs(mousePosition - (pos + bandwidth / 2));
|
|
40
44
|
if (distance < closestDistance) {
|
|
41
45
|
closestDistance = distance;
|
|
42
46
|
closestIndex = i;
|
|
@@ -46,17 +50,17 @@ export const ScrubberProvider = _ref => {
|
|
|
46
50
|
return closestIndex;
|
|
47
51
|
} else {
|
|
48
52
|
// For numeric scales with axis data, find the nearest data point
|
|
49
|
-
const axisData =
|
|
53
|
+
const axisData = categoryAxis.data;
|
|
50
54
|
if (axisData && Array.isArray(axisData) && typeof axisData[0] === 'number') {
|
|
51
55
|
// We have numeric axis data - find the closest data point
|
|
52
56
|
const numericData = axisData;
|
|
53
57
|
let closestIndex = 0;
|
|
54
58
|
let closestDistance = Infinity;
|
|
55
59
|
for (let i = 0; i < numericData.length; i++) {
|
|
56
|
-
const
|
|
57
|
-
const
|
|
58
|
-
if (
|
|
59
|
-
const distance = Math.abs(
|
|
60
|
+
const dataValue = numericData[i];
|
|
61
|
+
const pos = categoryScale(dataValue);
|
|
62
|
+
if (pos !== undefined) {
|
|
63
|
+
const distance = Math.abs(mousePosition - pos);
|
|
60
64
|
if (distance < closestDistance) {
|
|
61
65
|
closestDistance = distance;
|
|
62
66
|
closestIndex = i;
|
|
@@ -66,26 +70,26 @@ export const ScrubberProvider = _ref => {
|
|
|
66
70
|
return closestIndex;
|
|
67
71
|
} else {
|
|
68
72
|
var _domain$min, _domain$max;
|
|
69
|
-
const
|
|
70
|
-
const
|
|
71
|
-
const domain =
|
|
72
|
-
return Math.max((_domain$min = domain.min) !== null && _domain$min !== void 0 ? _domain$min : 0, Math.min(
|
|
73
|
+
const dataValue = categoryScale.invert(mousePosition);
|
|
74
|
+
const dataIndexVal = Math.round(dataValue);
|
|
75
|
+
const domain = categoryAxis.domain;
|
|
76
|
+
return Math.max((_domain$min = domain.min) !== null && _domain$min !== void 0 ? _domain$min : 0, Math.min(dataIndexVal, (_domain$max = domain.max) !== null && _domain$max !== void 0 ? _domain$max : 0));
|
|
73
77
|
}
|
|
74
78
|
}
|
|
75
|
-
}, [getXScale, getXAxis]);
|
|
76
|
-
const handlePointerMove = useCallback((clientX, target) => {
|
|
79
|
+
}, [layout, getXScale, getYScale, getXAxis, getYAxis]);
|
|
80
|
+
const handlePointerMove = useCallback((clientX, clientY, target) => {
|
|
77
81
|
if (!enableScrubbing || !series || series.length === 0) return;
|
|
78
82
|
const rect = target.getBoundingClientRect();
|
|
79
|
-
const
|
|
80
|
-
const dataIndex =
|
|
83
|
+
const position = layout === 'horizontal' ? clientY - rect.top : clientX - rect.left;
|
|
84
|
+
const dataIndex = getDataIndexFromPosition(position);
|
|
81
85
|
if (dataIndex !== scrubberPosition) {
|
|
82
86
|
setScrubberPosition(dataIndex);
|
|
83
87
|
onScrubberPositionChange === null || onScrubberPositionChange === void 0 || onScrubberPositionChange(dataIndex);
|
|
84
88
|
}
|
|
85
|
-
}, [enableScrubbing, series,
|
|
89
|
+
}, [enableScrubbing, series, layout, getDataIndexFromPosition, scrubberPosition, onScrubberPositionChange]);
|
|
86
90
|
const handleMouseMove = useCallback(event => {
|
|
87
91
|
const target = event.currentTarget;
|
|
88
|
-
handlePointerMove(event.clientX, target);
|
|
92
|
+
handlePointerMove(event.clientX, event.clientY, target);
|
|
89
93
|
}, [handlePointerMove]);
|
|
90
94
|
const handleTouchMove = useCallback(event => {
|
|
91
95
|
if (!event.touches.length) return;
|
|
@@ -93,14 +97,14 @@ export const ScrubberProvider = _ref => {
|
|
|
93
97
|
event.preventDefault();
|
|
94
98
|
const touch = event.touches[0];
|
|
95
99
|
const target = event.currentTarget;
|
|
96
|
-
handlePointerMove(touch.clientX, target);
|
|
100
|
+
handlePointerMove(touch.clientX, touch.clientY, target);
|
|
97
101
|
}, [handlePointerMove]);
|
|
98
102
|
const handleTouchStart = useCallback(event => {
|
|
99
103
|
if (!enableScrubbing || !event.touches.length) return;
|
|
100
104
|
// Handle initial touch
|
|
101
105
|
const touch = event.touches[0];
|
|
102
106
|
const target = event.currentTarget;
|
|
103
|
-
handlePointerMove(touch.clientX, target);
|
|
107
|
+
handlePointerMove(touch.clientX, touch.clientY, target);
|
|
104
108
|
}, [enableScrubbing, handlePointerMove]);
|
|
105
109
|
const handlePointerLeave = useCallback(() => {
|
|
106
110
|
if (!enableScrubbing) return;
|
|
@@ -111,25 +115,26 @@ export const ScrubberProvider = _ref => {
|
|
|
111
115
|
const handleTouchEnd = handlePointerLeave;
|
|
112
116
|
const handleKeyDown = useCallback(event => {
|
|
113
117
|
if (!enableScrubbing) return;
|
|
114
|
-
const
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
|
|
118
|
+
const categoryAxisIsX = layout !== 'horizontal';
|
|
119
|
+
const categoryScale = categoryAxisIsX ? getXScale() : getYScale();
|
|
120
|
+
const categoryAxis = categoryAxisIsX ? getXAxis() : getYAxis();
|
|
121
|
+
if (!categoryScale || !categoryAxis) return;
|
|
122
|
+
const isBand = isCategoricalScale(categoryScale);
|
|
118
123
|
|
|
119
124
|
// Determine the actual data indices we can navigate to
|
|
120
125
|
let minIndex;
|
|
121
126
|
let maxIndex;
|
|
122
127
|
let dataPoints;
|
|
123
128
|
if (isBand) {
|
|
124
|
-
var _ref3,
|
|
129
|
+
var _ref3, _categoryScale$domain3, _categoryScale$domain4;
|
|
125
130
|
// For categorical scales, use the categories
|
|
126
|
-
const categories = (_ref3 = (
|
|
131
|
+
const categories = (_ref3 = (_categoryScale$domain3 = (_categoryScale$domain4 = categoryScale.domain) === null || _categoryScale$domain4 === void 0 ? void 0 : _categoryScale$domain4.call(categoryScale)) !== null && _categoryScale$domain3 !== void 0 ? _categoryScale$domain3 : categoryAxis.data) !== null && _ref3 !== void 0 ? _ref3 : [];
|
|
127
132
|
minIndex = 0;
|
|
128
133
|
maxIndex = Math.max(0, categories.length - 1);
|
|
129
134
|
dataPoints = categories.length;
|
|
130
135
|
} else {
|
|
131
136
|
// For numeric scales, check if we have specific data points
|
|
132
|
-
const axisData =
|
|
137
|
+
const axisData = categoryAxis.data;
|
|
133
138
|
if (axisData && Array.isArray(axisData)) {
|
|
134
139
|
// We have specific data points - use their indices
|
|
135
140
|
minIndex = 0;
|
|
@@ -138,7 +143,7 @@ export const ScrubberProvider = _ref => {
|
|
|
138
143
|
} else {
|
|
139
144
|
var _domain$min2, _domain$max2;
|
|
140
145
|
// Fall back to domain-based navigation for continuous scales without specific data
|
|
141
|
-
const domain =
|
|
146
|
+
const domain = categoryAxis.domain;
|
|
142
147
|
minIndex = (_domain$min2 = domain.min) !== null && _domain$min2 !== void 0 ? _domain$min2 : 0;
|
|
143
148
|
maxIndex = (_domain$max2 = domain.max) !== null && _domain$max2 !== void 0 ? _domain$max2 : 0;
|
|
144
149
|
dataPoints = maxIndex - minIndex + 1;
|
|
@@ -152,11 +157,11 @@ export const ScrubberProvider = _ref => {
|
|
|
152
157
|
const stepSize = multiSkip ? Math.min(10, Math.max(1, Math.floor(dataRange * 0.1))) : 1;
|
|
153
158
|
let newIndex;
|
|
154
159
|
switch (event.key) {
|
|
155
|
-
case 'ArrowLeft':
|
|
160
|
+
case categoryAxisIsX ? 'ArrowLeft' : 'ArrowUp':
|
|
156
161
|
event.preventDefault();
|
|
157
162
|
newIndex = Math.max(minIndex, currentIndex - stepSize);
|
|
158
163
|
break;
|
|
159
|
-
case 'ArrowRight':
|
|
164
|
+
case categoryAxisIsX ? 'ArrowRight' : 'ArrowDown':
|
|
160
165
|
event.preventDefault();
|
|
161
166
|
newIndex = Math.min(maxIndex, currentIndex + stepSize);
|
|
162
167
|
break;
|
|
@@ -180,7 +185,7 @@ export const ScrubberProvider = _ref => {
|
|
|
180
185
|
setScrubberPosition(newIndex);
|
|
181
186
|
onScrubberPositionChange === null || onScrubberPositionChange === void 0 || onScrubberPositionChange(newIndex);
|
|
182
187
|
}
|
|
183
|
-
}, [enableScrubbing, getXScale, getXAxis, scrubberPosition, onScrubberPositionChange]);
|
|
188
|
+
}, [enableScrubbing, layout, getXScale, getYScale, getXAxis, getYAxis, scrubberPosition, onScrubberPositionChange]);
|
|
184
189
|
const handleBlur = useCallback(() => {
|
|
185
190
|
if (!enableScrubbing || scrubberPosition === undefined) return;
|
|
186
191
|
setScrubberPosition(undefined);
|
|
@@ -10,6 +10,7 @@ import { Text } from '@coinbase/cds-web/typography';
|
|
|
10
10
|
import { m as motion } from 'framer-motion';
|
|
11
11
|
import { useCartesianChartContext } from '../ChartProvider';
|
|
12
12
|
import { getChartInset } from '../utils';
|
|
13
|
+
import { accessoryFadeTransitionDuration } from '../utils/transition';
|
|
13
14
|
|
|
14
15
|
/**
|
|
15
16
|
* The supported content types for ChartText.
|
|
@@ -69,7 +70,7 @@ export const ChartText = /*#__PURE__*/memo(_ref => {
|
|
|
69
70
|
fontWeight,
|
|
70
71
|
elevated,
|
|
71
72
|
color = 'var(--color-fgMuted)',
|
|
72
|
-
background = elevated ? 'var(--color-
|
|
73
|
+
background = elevated ? 'var(--color-bgElevation1)' : 'transparent',
|
|
73
74
|
borderRadius,
|
|
74
75
|
inset: insetInput,
|
|
75
76
|
onDimensionsChange,
|
|
@@ -190,7 +191,7 @@ export const ChartText = /*#__PURE__*/memo(_ref => {
|
|
|
190
191
|
opacity: isDimensionsReady ? 1 : 0
|
|
191
192
|
},
|
|
192
193
|
transition: animate ? {
|
|
193
|
-
duration:
|
|
194
|
+
duration: accessoryFadeTransitionDuration,
|
|
194
195
|
ease: 'easeOut'
|
|
195
196
|
} : undefined,
|
|
196
197
|
children: [/*#__PURE__*/_jsx(Box, {
|