@coinbase/cds-mobile-visualization 3.4.0-beta.2 → 3.4.0-beta.20
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 +122 -0
- package/dts/chart/CartesianChart.d.ts +92 -34
- package/dts/chart/CartesianChart.d.ts.map +1 -1
- package/dts/chart/ChartContextBridge.d.ts +28 -0
- package/dts/chart/ChartContextBridge.d.ts.map +1 -0
- package/dts/chart/ChartProvider.d.ts +3 -0
- package/dts/chart/ChartProvider.d.ts.map +1 -1
- package/dts/chart/Path.d.ts +97 -32
- package/dts/chart/Path.d.ts.map +1 -1
- package/dts/chart/PeriodSelector.d.ts +6 -13
- package/dts/chart/PeriodSelector.d.ts.map +1 -1
- package/dts/chart/area/Area.d.ts +39 -28
- package/dts/chart/area/Area.d.ts.map +1 -1
- package/dts/chart/area/AreaChart.d.ts +51 -10
- package/dts/chart/area/AreaChart.d.ts.map +1 -1
- package/dts/chart/area/DottedArea.d.ts +21 -2
- package/dts/chart/area/DottedArea.d.ts.map +1 -1
- package/dts/chart/area/GradientArea.d.ts +19 -13
- package/dts/chart/area/GradientArea.d.ts.map +1 -1
- package/dts/chart/area/SolidArea.d.ts +17 -2
- package/dts/chart/area/SolidArea.d.ts.map +1 -1
- package/dts/chart/axis/Axis.d.ts +86 -118
- 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 +2 -2
- 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 +49 -12
- package/dts/chart/bar/Bar.d.ts.map +1 -1
- package/dts/chart/bar/BarChart.d.ts +40 -19
- package/dts/chart/bar/BarChart.d.ts.map +1 -1
- package/dts/chart/bar/BarPlot.d.ts +3 -1
- package/dts/chart/bar/BarPlot.d.ts.map +1 -1
- package/dts/chart/bar/BarStack.d.ts +41 -46
- package/dts/chart/bar/BarStack.d.ts.map +1 -1
- package/dts/chart/bar/BarStackGroup.d.ts +2 -0
- package/dts/chart/bar/BarStackGroup.d.ts.map +1 -1
- package/dts/chart/bar/DefaultBar.d.ts +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 +25 -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 +4 -1
- package/dts/chart/index.d.ts.map +1 -1
- package/dts/chart/legend/DefaultLegendEntry.d.ts +5 -0
- package/dts/chart/legend/DefaultLegendEntry.d.ts.map +1 -0
- package/dts/chart/legend/DefaultLegendShape.d.ts +5 -0
- package/dts/chart/legend/DefaultLegendShape.d.ts.map +1 -0
- package/dts/chart/legend/Legend.d.ts +168 -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/DefaultReferenceLineLabel.d.ts +9 -0
- package/dts/chart/line/DefaultReferenceLineLabel.d.ts.map +1 -0
- package/dts/chart/line/DottedLine.d.ts +13 -5
- package/dts/chart/line/DottedLine.d.ts.map +1 -1
- package/dts/chart/line/Line.d.ts +61 -27
- package/dts/chart/line/Line.d.ts.map +1 -1
- package/dts/chart/line/LineChart.d.ts +43 -9
- package/dts/chart/line/LineChart.d.ts.map +1 -1
- package/dts/chart/line/ReferenceLine.d.ts +68 -20
- package/dts/chart/line/ReferenceLine.d.ts.map +1 -1
- package/dts/chart/line/SolidLine.d.ts +8 -5
- 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 +136 -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 +38 -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 +11 -0
- package/dts/chart/scrubber/DefaultScrubberLabel.d.ts.map +1 -0
- package/dts/chart/scrubber/Scrubber.d.ts +230 -42
- package/dts/chart/scrubber/Scrubber.d.ts.map +1 -1
- package/dts/chart/scrubber/ScrubberBeaconGroup.d.ts +54 -0
- package/dts/chart/scrubber/ScrubberBeaconGroup.d.ts.map +1 -0
- package/dts/chart/scrubber/ScrubberBeaconLabelGroup.d.ts +46 -0
- package/dts/chart/scrubber/ScrubberBeaconLabelGroup.d.ts.map +1 -0
- package/dts/chart/scrubber/ScrubberProvider.d.ts +6 -3
- package/dts/chart/scrubber/ScrubberProvider.d.ts.map +1 -1
- 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 +151 -77
- 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/axis.d.ts +25 -1
- package/dts/chart/utils/axis.d.ts.map +1 -1
- package/dts/chart/utils/bar.d.ts +34 -0
- package/dts/chart/utils/bar.d.ts.map +1 -1
- package/dts/chart/utils/chart.d.ts +52 -7
- package/dts/chart/utils/chart.d.ts.map +1 -1
- package/dts/chart/utils/context.d.ts +28 -7
- package/dts/chart/utils/context.d.ts.map +1 -1
- package/dts/chart/utils/gradient.d.ts +117 -0
- package/dts/chart/utils/gradient.d.ts.map +1 -0
- package/dts/chart/utils/index.d.ts +3 -0
- package/dts/chart/utils/index.d.ts.map +1 -1
- package/dts/chart/utils/path.d.ts +59 -0
- package/dts/chart/utils/path.d.ts.map +1 -1
- package/dts/chart/utils/point.d.ts +71 -7
- package/dts/chart/utils/point.d.ts.map +1 -1
- package/dts/chart/utils/scale.d.ts +102 -0
- package/dts/chart/utils/scale.d.ts.map +1 -1
- package/dts/chart/utils/scrubber.d.ts +40 -0
- package/dts/chart/utils/scrubber.d.ts.map +1 -0
- package/dts/chart/utils/transition.d.ts +178 -0
- package/dts/chart/utils/transition.d.ts.map +1 -0
- package/esm/chart/CartesianChart.js +199 -75
- package/esm/chart/ChartContextBridge.js +159 -0
- package/esm/chart/ChartProvider.js +2 -2
- package/esm/chart/Path.js +200 -114
- package/esm/chart/PeriodSelector.js +7 -3
- package/esm/chart/__stories__/CartesianChart.stories.js +307 -134
- package/esm/chart/__stories__/ChartTransitions.stories.js +629 -0
- package/esm/chart/__stories__/PeriodSelector.stories.js +201 -75
- package/esm/chart/area/Area.js +27 -35
- package/esm/chart/area/AreaChart.js +17 -12
- package/esm/chart/area/DottedArea.js +64 -108
- package/esm/chart/area/GradientArea.js +37 -91
- package/esm/chart/area/SolidArea.js +24 -8
- package/esm/chart/area/__stories__/AreaChart.stories.js +1 -1
- package/esm/chart/axis/Axis.js +5 -39
- package/esm/chart/axis/DefaultAxisTickLabel.js +11 -0
- package/esm/chart/axis/XAxis.js +148 -66
- package/esm/chart/axis/YAxis.js +149 -65
- package/esm/chart/axis/__stories__/Axis.stories.js +259 -1
- package/esm/chart/axis/index.js +1 -0
- package/esm/chart/bar/Bar.js +7 -1
- package/esm/chart/bar/BarChart.js +17 -37
- package/esm/chart/bar/BarPlot.js +43 -35
- package/esm/chart/bar/BarStack.js +84 -37
- package/esm/chart/bar/BarStackGroup.js +7 -17
- package/esm/chart/bar/DefaultBar.js +29 -51
- package/esm/chart/bar/DefaultBarStack.js +34 -58
- package/esm/chart/bar/__stories__/BarChart.stories.js +948 -88
- package/esm/chart/gradient/Gradient.js +53 -0
- package/esm/chart/gradient/index.js +1 -0
- package/esm/chart/index.js +4 -1
- package/esm/chart/legend/DefaultLegendEntry.js +42 -0
- package/esm/chart/legend/DefaultLegendShape.js +64 -0
- package/esm/chart/legend/Legend.js +59 -0
- package/esm/chart/legend/__stories__/Legend.stories.js +574 -0
- package/esm/chart/legend/index.js +3 -0
- package/esm/chart/line/DefaultReferenceLineLabel.js +66 -0
- package/esm/chart/line/DottedLine.js +31 -14
- package/esm/chart/line/Line.js +96 -68
- package/esm/chart/line/LineChart.js +21 -14
- package/esm/chart/line/ReferenceLine.js +80 -63
- package/esm/chart/line/SolidLine.js +27 -10
- package/esm/chart/line/__stories__/LineChart.stories.js +1748 -2048
- package/esm/chart/line/__stories__/ReferenceLine.stories.js +177 -28
- package/esm/chart/line/index.js +1 -1
- package/esm/chart/point/DefaultPointLabel.js +39 -0
- package/esm/chart/point/Point.js +186 -0
- package/esm/chart/point/index.js +2 -0
- package/esm/chart/scrubber/DefaultScrubberBeacon.js +180 -0
- package/esm/chart/scrubber/DefaultScrubberBeaconLabel.js +43 -0
- package/esm/chart/scrubber/DefaultScrubberLabel.js +28 -0
- package/esm/chart/scrubber/Scrubber.js +130 -144
- package/esm/chart/scrubber/ScrubberBeaconGroup.js +165 -0
- package/esm/chart/scrubber/ScrubberBeaconLabelGroup.js +208 -0
- package/esm/chart/scrubber/ScrubberProvider.js +46 -54
- package/esm/chart/scrubber/__stories__/Scrubber.stories.js +760 -0
- package/esm/chart/scrubber/index.js +3 -1
- package/esm/chart/text/ChartText.js +242 -174
- package/esm/chart/text/{SmartChartTextGroup.js → ChartTextGroup.js} +6 -5
- package/esm/chart/text/index.js +1 -1
- package/esm/chart/utils/axis.js +47 -31
- package/esm/chart/utils/bar.js +43 -0
- package/esm/chart/utils/chart.js +57 -3
- package/esm/chart/utils/gradient.js +305 -0
- package/esm/chart/utils/index.js +3 -0
- package/esm/chart/utils/path.js +84 -8
- package/esm/chart/utils/point.js +171 -17
- package/esm/chart/utils/scale.js +242 -2
- package/esm/chart/utils/scrubber.js +146 -0
- package/esm/chart/utils/transition.js +220 -0
- package/esm/sparkline/__figma__/Sparkline.figma.js +1 -1
- package/esm/sparkline/__stories__/Sparkline.stories.js +11 -7
- package/esm/sparkline/__stories__/SparklineGradient.stories.js +7 -4
- package/esm/sparkline/sparkline-interactive/__figma__/SparklineInteractive.figma.js +1 -1
- package/esm/sparkline/sparkline-interactive/__stories__/SparklineInteractive.stories.js +51 -26
- package/esm/sparkline/sparkline-interactive-header/__figma__/SparklineInteractiveHeader.figma.js +1 -1
- package/esm/sparkline/sparkline-interactive-header/__stories__/SparklineInteractiveHeader.stories.js +17 -9
- package/package.json +15 -10
- package/dts/chart/Point.d.ts +0 -103
- package/dts/chart/Point.d.ts.map +0 -1
- package/dts/chart/line/GradientLine.d.ts +0 -45
- package/dts/chart/line/GradientLine.d.ts.map +0 -1
- package/dts/chart/scrubber/ScrubberBeacon.d.ts +0 -75
- package/dts/chart/scrubber/ScrubberBeacon.d.ts.map +0 -1
- package/dts/chart/text/SmartChartTextGroup.d.ts.map +0 -1
- package/esm/chart/Point.js +0 -111
- package/esm/chart/__stories__/Chart.stories.js +0 -79
- package/esm/chart/line/GradientLine.js +0 -62
- package/esm/chart/scrubber/ScrubberBeacon.js +0 -199
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
|
|
2
|
+
import { memo, useCallback, useMemo, useState } from 'react';
|
|
3
|
+
import { useAnimatedReaction, useDerivedValue, useSharedValue } from 'react-native-reanimated';
|
|
4
|
+
import { useCartesianChartContext } from '../ChartProvider';
|
|
5
|
+
import { applySerializableScale, unwrapAnimatedValue, useScrubberContext } from '../utils';
|
|
6
|
+
import { calculateLabelYPositions, getLabelPosition } from '../utils/scrubber';
|
|
7
|
+
import { buildTransition, defaultTransition, getTransition } from '../utils/transition';
|
|
8
|
+
import { DefaultScrubberBeaconLabel } from './DefaultScrubberBeaconLabel';
|
|
9
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
10
|
+
const PositionedLabel = /*#__PURE__*/memo(_ref => {
|
|
11
|
+
let {
|
|
12
|
+
index,
|
|
13
|
+
positions,
|
|
14
|
+
position,
|
|
15
|
+
isIdle,
|
|
16
|
+
updateTransition,
|
|
17
|
+
label,
|
|
18
|
+
color,
|
|
19
|
+
seriesId,
|
|
20
|
+
onDimensionsChange,
|
|
21
|
+
BeaconLabelComponent,
|
|
22
|
+
labelHorizontalOffset,
|
|
23
|
+
labelFont
|
|
24
|
+
} = _ref;
|
|
25
|
+
const opacity = useDerivedValue(() => positions.value[index] !== null ? 1 : 0, [positions, index]);
|
|
26
|
+
const x = useDerivedValue(() => {
|
|
27
|
+
var _positions$value$inde, _positions$value$inde2;
|
|
28
|
+
return (_positions$value$inde = (_positions$value$inde2 = positions.value[index]) == null ? void 0 : _positions$value$inde2.x) != null ? _positions$value$inde : 0;
|
|
29
|
+
}, [positions, index]);
|
|
30
|
+
const targetY = useDerivedValue(() => {
|
|
31
|
+
var _positions$value$inde3, _positions$value$inde4;
|
|
32
|
+
return (_positions$value$inde3 = (_positions$value$inde4 = positions.value[index]) == null ? void 0 : _positions$value$inde4.y) != null ? _positions$value$inde3 : 0;
|
|
33
|
+
}, [positions, index]);
|
|
34
|
+
const animatedY = useSharedValue(0);
|
|
35
|
+
useAnimatedReaction(() => ({
|
|
36
|
+
y: targetY.value,
|
|
37
|
+
idle: unwrapAnimatedValue(isIdle)
|
|
38
|
+
}), (current, previous) => {
|
|
39
|
+
if (previous === null || !previous.idle || !current.idle) {
|
|
40
|
+
animatedY.value = current.y;
|
|
41
|
+
} else {
|
|
42
|
+
animatedY.value = buildTransition(current.y, updateTransition);
|
|
43
|
+
}
|
|
44
|
+
}, [updateTransition]);
|
|
45
|
+
const dx = useDerivedValue(() => {
|
|
46
|
+
return position.value === 'right' ? labelHorizontalOffset : -labelHorizontalOffset;
|
|
47
|
+
}, [position, labelHorizontalOffset]);
|
|
48
|
+
const horizontalAlignment = useDerivedValue(() => position.value === 'right' ? 'left' : 'right', [position]);
|
|
49
|
+
return /*#__PURE__*/_jsx(BeaconLabelComponent, {
|
|
50
|
+
color: color,
|
|
51
|
+
dx: dx,
|
|
52
|
+
font: labelFont,
|
|
53
|
+
horizontalAlignment: horizontalAlignment,
|
|
54
|
+
label: label,
|
|
55
|
+
onDimensionsChange: d => onDimensionsChange(seriesId, d),
|
|
56
|
+
opacity: opacity,
|
|
57
|
+
seriesId: seriesId,
|
|
58
|
+
x: x,
|
|
59
|
+
y: animatedY
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
export const ScrubberBeaconLabelGroup = /*#__PURE__*/memo(_ref2 => {
|
|
63
|
+
let {
|
|
64
|
+
labels,
|
|
65
|
+
labelMinGap = 4,
|
|
66
|
+
labelHorizontalOffset = 16,
|
|
67
|
+
labelFont,
|
|
68
|
+
labelPreferredSide = 'right',
|
|
69
|
+
BeaconLabelComponent = DefaultScrubberBeaconLabel,
|
|
70
|
+
transitions
|
|
71
|
+
} = _ref2;
|
|
72
|
+
const {
|
|
73
|
+
getSeries,
|
|
74
|
+
getSeriesData,
|
|
75
|
+
getXSerializableScale,
|
|
76
|
+
getYSerializableScale,
|
|
77
|
+
getXAxis,
|
|
78
|
+
drawingArea,
|
|
79
|
+
dataLength,
|
|
80
|
+
animate
|
|
81
|
+
} = useCartesianChartContext();
|
|
82
|
+
const {
|
|
83
|
+
scrubberPosition
|
|
84
|
+
} = useScrubberContext();
|
|
85
|
+
const isIdle = useDerivedValue(() => {
|
|
86
|
+
return scrubberPosition.value === undefined;
|
|
87
|
+
}, [scrubberPosition]);
|
|
88
|
+
const updateTransition = useMemo(() => getTransition(transitions == null ? void 0 : transitions.update, animate, defaultTransition), [transitions == null ? void 0 : transitions.update, animate]);
|
|
89
|
+
const [labelDimensions, setLabelDimensions] = useState({});
|
|
90
|
+
const handleDimensionsChange = useCallback((id, dimensions) => {
|
|
91
|
+
setLabelDimensions(prev => {
|
|
92
|
+
const existing = prev[id];
|
|
93
|
+
if (existing && existing.width === dimensions.width && existing.height === dimensions.height) {
|
|
94
|
+
return prev;
|
|
95
|
+
}
|
|
96
|
+
return _extends({}, prev, {
|
|
97
|
+
[id]: dimensions
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
}, []);
|
|
101
|
+
const seriesInfo = useMemo(() => {
|
|
102
|
+
return labels.map(label => {
|
|
103
|
+
const series = getSeries(label.seriesId);
|
|
104
|
+
if (!series) return null;
|
|
105
|
+
const sourceData = getSeriesData(label.seriesId);
|
|
106
|
+
const yScale = getYSerializableScale(series.yAxisId);
|
|
107
|
+
return {
|
|
108
|
+
seriesId: label.seriesId,
|
|
109
|
+
sourceData,
|
|
110
|
+
yScale
|
|
111
|
+
};
|
|
112
|
+
}).filter(info => info !== null);
|
|
113
|
+
}, [labels, getSeries, getSeriesData, getYSerializableScale]);
|
|
114
|
+
const xScale = getXSerializableScale();
|
|
115
|
+
const xAxis = getXAxis();
|
|
116
|
+
const dataIndex = useDerivedValue(() => {
|
|
117
|
+
var _scrubberPosition$val;
|
|
118
|
+
return (_scrubberPosition$val = scrubberPosition.value) != null ? _scrubberPosition$val : Math.max(0, dataLength - 1);
|
|
119
|
+
}, [scrubberPosition, dataLength]);
|
|
120
|
+
const dataX = useDerivedValue(() => {
|
|
121
|
+
if (xAxis != null && xAxis.data && Array.isArray(xAxis.data) && xAxis.data[dataIndex.value] !== undefined) {
|
|
122
|
+
const dataValue = xAxis.data[dataIndex.value];
|
|
123
|
+
return typeof dataValue === 'string' ? dataIndex.value : dataValue;
|
|
124
|
+
}
|
|
125
|
+
return dataIndex.value;
|
|
126
|
+
}, [xAxis, dataIndex]);
|
|
127
|
+
const allLabelPositions = useDerivedValue(() => {
|
|
128
|
+
const sharedPixelX = dataX.value !== undefined && xScale ? applySerializableScale(dataX.value, xScale) : 0;
|
|
129
|
+
const desiredPositions = seriesInfo.map(info => {
|
|
130
|
+
let dataY;
|
|
131
|
+
if (xScale && info.yScale) {
|
|
132
|
+
if (info.sourceData && dataIndex.value !== undefined && dataIndex.value >= 0 && dataIndex.value < info.sourceData.length) {
|
|
133
|
+
const dataValue = info.sourceData[dataIndex.value];
|
|
134
|
+
if (Array.isArray(dataValue)) {
|
|
135
|
+
const validValues = dataValue.filter(val => val !== null);
|
|
136
|
+
if (validValues.length >= 1) {
|
|
137
|
+
dataY = validValues[validValues.length - 1];
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
if (dataY !== undefined && info.yScale) {
|
|
143
|
+
return {
|
|
144
|
+
seriesId: info.seriesId,
|
|
145
|
+
x: sharedPixelX,
|
|
146
|
+
desiredY: applySerializableScale(dataY, info.yScale)
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Return null for invalid data
|
|
151
|
+
return null;
|
|
152
|
+
});
|
|
153
|
+
const maxLabelHeight = Math.max(...Object.values(labelDimensions).map(dim => dim.height));
|
|
154
|
+
const maxLabelWidth = Math.max(...Object.values(labelDimensions).map(dim => dim.width));
|
|
155
|
+
const validPositions = desiredPositions.filter(pos => pos !== null);
|
|
156
|
+
|
|
157
|
+
// Convert to LabelDimension format expected by utility
|
|
158
|
+
const dimensions = validPositions.map(pos => {
|
|
159
|
+
var _trackedDimensions$wi, _trackedDimensions$he;
|
|
160
|
+
const trackedDimensions = labelDimensions[pos.seriesId];
|
|
161
|
+
return {
|
|
162
|
+
seriesId: pos.seriesId,
|
|
163
|
+
width: (_trackedDimensions$wi = trackedDimensions == null ? void 0 : trackedDimensions.width) != null ? _trackedDimensions$wi : maxLabelWidth,
|
|
164
|
+
height: (_trackedDimensions$he = trackedDimensions == null ? void 0 : trackedDimensions.height) != null ? _trackedDimensions$he : maxLabelHeight,
|
|
165
|
+
preferredX: pos.x,
|
|
166
|
+
preferredY: pos.desiredY
|
|
167
|
+
};
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
// Calculate Y positions with collision resolution for valid positions only
|
|
171
|
+
const yPositions = calculateLabelYPositions(dimensions, drawingArea, maxLabelHeight, labelMinGap);
|
|
172
|
+
|
|
173
|
+
// Return all positions (including null ones)
|
|
174
|
+
return desiredPositions.map(pos => {
|
|
175
|
+
var _yPositions$get;
|
|
176
|
+
if (!pos) return null;
|
|
177
|
+
return {
|
|
178
|
+
seriesId: pos.seriesId,
|
|
179
|
+
x: pos.x,
|
|
180
|
+
y: (_yPositions$get = yPositions.get(pos.seriesId)) != null ? _yPositions$get : pos.desiredY
|
|
181
|
+
};
|
|
182
|
+
});
|
|
183
|
+
}, [seriesInfo, dataIndex, dataX, xScale, labelDimensions, labelMinGap]);
|
|
184
|
+
const currentPosition = useDerivedValue(() => {
|
|
185
|
+
const pixelX = dataX.value !== undefined && xScale ? applySerializableScale(dataX.value, xScale) : 0;
|
|
186
|
+
const maxWidth = Math.max(...Object.values(labelDimensions).map(dim => dim.width));
|
|
187
|
+
const position = getLabelPosition(pixelX, maxWidth, drawingArea, labelHorizontalOffset, labelPreferredSide);
|
|
188
|
+
return position;
|
|
189
|
+
}, [dataX, xScale, labelDimensions, drawingArea, labelHorizontalOffset, labelPreferredSide]);
|
|
190
|
+
return seriesInfo.map((info, index) => {
|
|
191
|
+
const labelInfo = labels.find(label => label.seriesId === info.seriesId);
|
|
192
|
+
if (!labelInfo) return;
|
|
193
|
+
return /*#__PURE__*/_jsx(PositionedLabel, {
|
|
194
|
+
BeaconLabelComponent: BeaconLabelComponent,
|
|
195
|
+
color: labelInfo.color,
|
|
196
|
+
index: index,
|
|
197
|
+
isIdle: isIdle,
|
|
198
|
+
label: labelInfo.label,
|
|
199
|
+
labelFont: labelFont,
|
|
200
|
+
labelHorizontalOffset: labelHorizontalOffset,
|
|
201
|
+
onDimensionsChange: handleDimensionsChange,
|
|
202
|
+
position: currentPosition,
|
|
203
|
+
positions: allLabelPositions,
|
|
204
|
+
seriesId: info.seriesId,
|
|
205
|
+
updateTransition: updateTransition
|
|
206
|
+
}, info.seriesId);
|
|
207
|
+
});
|
|
208
|
+
});
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import React, { useCallback, useMemo
|
|
1
|
+
import React, { useCallback, useMemo } from 'react';
|
|
2
2
|
import { Platform } from 'react-native';
|
|
3
3
|
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
|
|
4
|
-
import { runOnJS } from 'react-native-reanimated';
|
|
4
|
+
import { runOnJS, useAnimatedReaction, useSharedValue } from 'react-native-reanimated';
|
|
5
5
|
import { Haptics } from '@coinbase/cds-mobile/utils/haptics';
|
|
6
6
|
import { useCartesianChartContext } from '../ChartProvider';
|
|
7
|
-
import {
|
|
7
|
+
import { invertSerializableScale, ScrubberContext } from '../utils';
|
|
8
|
+
import { getPointOnSerializableScale } from '../utils/point';
|
|
8
9
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
9
10
|
/**
|
|
10
11
|
* A component which encapsulates the ScrubberContext.
|
|
@@ -22,25 +23,25 @@ export const ScrubberProvider = _ref => {
|
|
|
22
23
|
throw new Error('ScrubberProvider must be used within a ChartContext');
|
|
23
24
|
}
|
|
24
25
|
const {
|
|
25
|
-
|
|
26
|
-
getXAxis
|
|
27
|
-
series
|
|
26
|
+
getXSerializableScale,
|
|
27
|
+
getXAxis
|
|
28
28
|
} = chartContext;
|
|
29
|
-
const
|
|
29
|
+
const scrubberPosition = useSharedValue(undefined);
|
|
30
|
+
const xAxis = useMemo(() => getXAxis(), [getXAxis]);
|
|
31
|
+
const xScale = useMemo(() => getXSerializableScale(), [getXSerializableScale]);
|
|
30
32
|
const getDataIndexFromX = useCallback(touchX => {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
'worklet';
|
|
34
|
+
|
|
33
35
|
if (!xScale || !xAxis) return 0;
|
|
34
|
-
if (
|
|
35
|
-
|
|
36
|
-
const
|
|
37
|
-
const bandwidth = (_xScale$bandwidth = xScale.bandwidth == null ? void 0 : xScale.bandwidth()) != null ? _xScale$bandwidth : 0;
|
|
36
|
+
if (xScale.type === 'band') {
|
|
37
|
+
const [domainMin, domainMax] = xScale.domain;
|
|
38
|
+
const categoryCount = domainMax - domainMin + 1;
|
|
38
39
|
let closestIndex = 0;
|
|
39
40
|
let closestDistance = Infinity;
|
|
40
|
-
for (let i = 0; i <
|
|
41
|
-
const xPos =
|
|
41
|
+
for (let i = 0; i < categoryCount; i++) {
|
|
42
|
+
const xPos = getPointOnSerializableScale(i, xScale);
|
|
42
43
|
if (xPos !== undefined) {
|
|
43
|
-
const distance = Math.abs(touchX -
|
|
44
|
+
const distance = Math.abs(touchX - xPos);
|
|
44
45
|
if (distance < closestDistance) {
|
|
45
46
|
closestDistance = distance;
|
|
46
47
|
closestIndex = i;
|
|
@@ -58,7 +59,7 @@ export const ScrubberProvider = _ref => {
|
|
|
58
59
|
let closestDistance = Infinity;
|
|
59
60
|
for (let i = 0; i < numericData.length; i++) {
|
|
60
61
|
const xValue = numericData[i];
|
|
61
|
-
const xPos =
|
|
62
|
+
const xPos = getPointOnSerializableScale(xValue, xScale);
|
|
62
63
|
if (xPos !== undefined) {
|
|
63
64
|
const distance = Math.abs(touchX - xPos);
|
|
64
65
|
if (distance < closestDistance) {
|
|
@@ -70,62 +71,53 @@ export const ScrubberProvider = _ref => {
|
|
|
70
71
|
return closestIndex;
|
|
71
72
|
} else {
|
|
72
73
|
var _domain$min, _domain$max;
|
|
73
|
-
const xValue =
|
|
74
|
+
const xValue = invertSerializableScale(touchX, xScale);
|
|
74
75
|
const dataIndex = Math.round(xValue);
|
|
75
76
|
const domain = xAxis.domain;
|
|
76
77
|
return Math.max((_domain$min = domain.min) != null ? _domain$min : 0, Math.min(dataIndex, (_domain$max = domain.max) != null ? _domain$max : 0));
|
|
77
78
|
}
|
|
78
79
|
}
|
|
79
|
-
}, [
|
|
80
|
-
const
|
|
81
|
-
if (!enableScrubbing || !series || series.length === 0) return;
|
|
82
|
-
const dataIndex = getDataIndexFromX(x);
|
|
83
|
-
if (dataIndex !== scrubberPosition) {
|
|
84
|
-
setScrubberPosition(dataIndex);
|
|
85
|
-
onScrubberPositionChange == null || onScrubberPositionChange(dataIndex);
|
|
86
|
-
}
|
|
87
|
-
}, [enableScrubbing, series, getDataIndexFromX, scrubberPosition, onScrubberPositionChange]);
|
|
88
|
-
const handleInteractionEnd = useCallback(() => {
|
|
89
|
-
if (!enableScrubbing) return;
|
|
90
|
-
setScrubberPosition(undefined);
|
|
91
|
-
onScrubberPositionChange == null || onScrubberPositionChange(undefined);
|
|
92
|
-
}, [enableScrubbing, onScrubberPositionChange]);
|
|
93
|
-
|
|
94
|
-
// Gesture handler callbacks
|
|
95
|
-
const handleOnStartJsThread = useCallback(() => {
|
|
80
|
+
}, [xAxis, xScale]);
|
|
81
|
+
const handleStartEndHaptics = useCallback(() => {
|
|
96
82
|
void Haptics.lightImpact();
|
|
97
|
-
// Could add onScrubStart callback here if needed
|
|
98
83
|
}, []);
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
void Haptics.lightImpact();
|
|
107
|
-
handleOnEndOrCancelledJsThread();
|
|
108
|
-
}, [handleOnEndOrCancelledJsThread]);
|
|
84
|
+
useAnimatedReaction(() => scrubberPosition.value, (currentValue, previousValue) => {
|
|
85
|
+
// Confirm changes here and inside of our gesture handler before calling JS thread
|
|
86
|
+
// To prevent any rerenders
|
|
87
|
+
if (onScrubberPositionChange !== undefined && currentValue !== previousValue) {
|
|
88
|
+
runOnJS(onScrubberPositionChange)(currentValue);
|
|
89
|
+
}
|
|
90
|
+
}, [onScrubberPositionChange]);
|
|
109
91
|
|
|
110
92
|
// Create the long press pan gesture
|
|
111
93
|
const longPressGesture = useMemo(() => Gesture.Pan().activateAfterLongPress(110).shouldCancelWhenOutside(!allowOverflowGestures).onStart(function onStart(event) {
|
|
112
|
-
runOnJS(
|
|
94
|
+
runOnJS(handleStartEndHaptics)();
|
|
113
95
|
|
|
114
96
|
// Android does not trigger onUpdate when the gesture starts. This achieves consistent behavior across both iOS and Android
|
|
115
97
|
if (Platform.OS === 'android') {
|
|
116
|
-
|
|
98
|
+
const newScrubberPosition = getDataIndexFromX(event.x);
|
|
99
|
+
if (newScrubberPosition !== scrubberPosition.value) {
|
|
100
|
+
scrubberPosition.value = newScrubberPosition;
|
|
101
|
+
}
|
|
117
102
|
}
|
|
118
103
|
}).onUpdate(function onUpdate(event) {
|
|
119
|
-
|
|
104
|
+
const newScrubberPosition = getDataIndexFromX(event.x);
|
|
105
|
+
if (newScrubberPosition !== scrubberPosition.value) {
|
|
106
|
+
scrubberPosition.value = newScrubberPosition;
|
|
107
|
+
}
|
|
120
108
|
}).onEnd(function onEnd() {
|
|
121
|
-
|
|
109
|
+
if (enableScrubbing) {
|
|
110
|
+
runOnJS(handleStartEndHaptics)();
|
|
111
|
+
scrubberPosition.value = undefined;
|
|
112
|
+
}
|
|
122
113
|
}).onTouchesCancelled(function onTouchesCancelled() {
|
|
123
|
-
|
|
124
|
-
|
|
114
|
+
if (enableScrubbing) {
|
|
115
|
+
scrubberPosition.value = undefined;
|
|
116
|
+
}
|
|
117
|
+
}), [allowOverflowGestures, handleStartEndHaptics, getDataIndexFromX, scrubberPosition, enableScrubbing]);
|
|
125
118
|
const contextValue = useMemo(() => ({
|
|
126
119
|
enableScrubbing: !!enableScrubbing,
|
|
127
|
-
scrubberPosition
|
|
128
|
-
onScrubberPositionChange: setScrubberPosition
|
|
120
|
+
scrubberPosition
|
|
129
121
|
}), [enableScrubbing, scrubberPosition]);
|
|
130
122
|
const content = /*#__PURE__*/_jsx(ScrubberContext.Provider, {
|
|
131
123
|
value: contextValue,
|