@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
|
@@ -2,9 +2,17 @@ function _extends() { return _extends = Object.assign ? Object.assign.bind() : f
|
|
|
2
2
|
import React, { memo, useMemo } from 'react';
|
|
3
3
|
import { useTheme } from '@coinbase/cds-mobile/hooks/useTheme';
|
|
4
4
|
import { useCartesianChartContext } from '../ChartProvider';
|
|
5
|
+
import { evaluateGradientAtValue, getGradientStops } from '../utils/gradient';
|
|
6
|
+
import { convertToSerializableScale } from '../utils/scale';
|
|
5
7
|
import { Bar } from './Bar';
|
|
6
8
|
import { DefaultBarStack } from './DefaultBarStack';
|
|
7
9
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
10
|
+
const EPSILON = 1e-4;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Extended series type that includes bar-specific properties.
|
|
14
|
+
*/
|
|
15
|
+
|
|
8
16
|
/**
|
|
9
17
|
* BarStack component that renders a single stack of bars at a specific category index.
|
|
10
18
|
* Handles the stacking logic for bars within a single category.
|
|
@@ -26,14 +34,18 @@ export const BarStack = /*#__PURE__*/memo(_ref => {
|
|
|
26
34
|
stackGap,
|
|
27
35
|
barMinSize,
|
|
28
36
|
stackMinSize,
|
|
29
|
-
roundBaseline
|
|
37
|
+
roundBaseline,
|
|
38
|
+
transitions,
|
|
39
|
+
transition
|
|
30
40
|
} = _ref;
|
|
31
41
|
const theme = useTheme();
|
|
32
42
|
const {
|
|
33
43
|
getSeriesData,
|
|
34
|
-
getXAxis
|
|
44
|
+
getXAxis,
|
|
45
|
+
getXScale
|
|
35
46
|
} = useCartesianChartContext();
|
|
36
47
|
const xAxis = getXAxis();
|
|
48
|
+
const xScale = getXScale();
|
|
37
49
|
const baseline = useMemo(() => {
|
|
38
50
|
var _yScale;
|
|
39
51
|
const domain = yScale.domain();
|
|
@@ -42,6 +54,25 @@ export const BarStack = /*#__PURE__*/memo(_ref => {
|
|
|
42
54
|
const baseline = (_yScale = yScale(baselineValue)) != null ? _yScale : rect.y + rect.height;
|
|
43
55
|
return Math.max(rect.y, Math.min(baseline, rect.y + rect.height));
|
|
44
56
|
}, [rect.height, rect.y, yScale]);
|
|
57
|
+
const seriesGradients = useMemo(() => {
|
|
58
|
+
return series.map(s => {
|
|
59
|
+
if (!s.gradient || !xScale || !yScale) return;
|
|
60
|
+
const gradientScale = s.gradient.axis === 'x' ? xScale : yScale;
|
|
61
|
+
const serializableScale = convertToSerializableScale(gradientScale);
|
|
62
|
+
if (!serializableScale) return;
|
|
63
|
+
const domain = {
|
|
64
|
+
min: serializableScale.domain[0],
|
|
65
|
+
max: serializableScale.domain[1]
|
|
66
|
+
};
|
|
67
|
+
const stops = getGradientStops(s.gradient.stops, domain);
|
|
68
|
+
return {
|
|
69
|
+
seriesId: s.id,
|
|
70
|
+
gradient: s.gradient,
|
|
71
|
+
scale: serializableScale,
|
|
72
|
+
stops
|
|
73
|
+
};
|
|
74
|
+
});
|
|
75
|
+
}, [series, xScale, yScale]);
|
|
45
76
|
|
|
46
77
|
// Calculate bars for this specific category
|
|
47
78
|
const {
|
|
@@ -98,6 +129,24 @@ export const BarStack = /*#__PURE__*/memo(_ref => {
|
|
|
98
129
|
// Update stack bounds
|
|
99
130
|
minY = Math.min(minY, y);
|
|
100
131
|
maxY = Math.max(maxY, y + height);
|
|
132
|
+
|
|
133
|
+
// Determine fill color, respecting gradient if present
|
|
134
|
+
let barFill = s.color || theme.color.fgPrimary;
|
|
135
|
+
|
|
136
|
+
// Evaluate gradient if provided (using precomputed stops)
|
|
137
|
+
const seriesGradientConfig = seriesGradients.find(g => (g == null ? void 0 : g.seriesId) === s.id);
|
|
138
|
+
if (seriesGradientConfig) {
|
|
139
|
+
var _seriesGradientConfig;
|
|
140
|
+
const axis = (_seriesGradientConfig = seriesGradientConfig.gradient.axis) != null ? _seriesGradientConfig : 'y';
|
|
141
|
+
// For x-axis gradient, use the categoryIndex
|
|
142
|
+
// For y-axis gradient, use the actual data value
|
|
143
|
+
const dataValue = axis === 'x' ? categoryIndex : top;
|
|
144
|
+
const evaluatedColor = evaluateGradientAtValue(seriesGradientConfig.stops, dataValue, seriesGradientConfig.scale);
|
|
145
|
+
if (evaluatedColor) {
|
|
146
|
+
// Only apply gradient color if fill is not explicitly set
|
|
147
|
+
barFill = evaluatedColor;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
101
150
|
allBars.push({
|
|
102
151
|
seriesId: s.id,
|
|
103
152
|
x,
|
|
@@ -106,15 +155,11 @@ export const BarStack = /*#__PURE__*/memo(_ref => {
|
|
|
106
155
|
height,
|
|
107
156
|
dataY: value,
|
|
108
157
|
// Store the actual data value
|
|
109
|
-
|
|
158
|
+
fill: barFill,
|
|
159
|
+
// Check if the bar should be rounded based on the baseline, with an epsilon to handle floating-point rounding
|
|
160
|
+
roundTop: roundBaseline || Math.abs(barTop - baseline) >= EPSILON,
|
|
161
|
+
roundBottom: roundBaseline || Math.abs(barBottom - baseline) >= EPSILON,
|
|
110
162
|
BarComponent: s.BarComponent,
|
|
111
|
-
fill: s.fill || s.color || theme.color.fgPrimary,
|
|
112
|
-
fillOpacity: s.fillOpacity,
|
|
113
|
-
stroke: s.stroke,
|
|
114
|
-
strokeWidth: s.strokeWidth,
|
|
115
|
-
// Pass context data for custom components
|
|
116
|
-
roundTop: roundBaseline || barTop !== baseline,
|
|
117
|
-
roundBottom: roundBaseline || barBottom !== baseline,
|
|
118
163
|
shouldApplyGap
|
|
119
164
|
});
|
|
120
165
|
});
|
|
@@ -200,8 +245,7 @@ export const BarStack = /*#__PURE__*/memo(_ref => {
|
|
|
200
245
|
if (bar.height < barMinSize) {
|
|
201
246
|
var _yScale4, _yScale5, _yScale6, _yScale7;
|
|
202
247
|
const heightIncrease = barMinSize - bar.height;
|
|
203
|
-
const bottom =
|
|
204
|
-
const top = 0;
|
|
248
|
+
const [bottom, top] = bar.dataY.sort((a, b) => a - b);
|
|
205
249
|
|
|
206
250
|
// Determine how to expand the bar
|
|
207
251
|
let newBottom = bottom;
|
|
@@ -344,8 +388,7 @@ export const BarStack = /*#__PURE__*/memo(_ref => {
|
|
|
344
388
|
|
|
345
389
|
const bar = allBars[0];
|
|
346
390
|
const heightIncrease = stackMinSize - bar.height;
|
|
347
|
-
const bottom =
|
|
348
|
-
const top = 0;
|
|
391
|
+
const [bottom, top] = bar.dataY.sort((a, b) => a - b);
|
|
349
392
|
|
|
350
393
|
// Determine how to expand the bar (same logic as barMinSize)
|
|
351
394
|
let newBottom = bottom;
|
|
@@ -474,37 +517,41 @@ export const BarStack = /*#__PURE__*/memo(_ref => {
|
|
|
474
517
|
bars: allBars,
|
|
475
518
|
stackRect: stackBounds
|
|
476
519
|
};
|
|
477
|
-
}, [series, x, width, getSeriesData, categoryIndex, roundBaseline, baseline, stackGap, barMinSize, stackMinSize, yScale, theme.color.fgPrimary]);
|
|
520
|
+
}, [series, x, width, getSeriesData, categoryIndex, roundBaseline, baseline, stackGap, barMinSize, stackMinSize, yScale, seriesGradients, theme.color.fgPrimary]);
|
|
478
521
|
const xData = xAxis != null && xAxis.data && Array.isArray(xAxis.data) && typeof xAxis.data[0] === 'number' ? xAxis.data : undefined;
|
|
479
522
|
const dataX = xData ? xData[categoryIndex] : categoryIndex;
|
|
480
|
-
const barElements = bars.map((bar, index) => {
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
});
|
|
500
|
-
|
|
501
|
-
|
|
523
|
+
const barElements = bars.map((bar, index) => /*#__PURE__*/_jsx(Bar, {
|
|
524
|
+
BarComponent: bar.BarComponent || defaultBarComponent,
|
|
525
|
+
borderRadius: borderRadius,
|
|
526
|
+
dataX: dataX,
|
|
527
|
+
dataY: bar.dataY,
|
|
528
|
+
fill: bar.fill,
|
|
529
|
+
fillOpacity: defaultFillOpacity,
|
|
530
|
+
height: bar.height,
|
|
531
|
+
originY: baseline,
|
|
532
|
+
roundBottom: bar.roundBottom,
|
|
533
|
+
roundTop: bar.roundTop,
|
|
534
|
+
seriesId: bar.seriesId,
|
|
535
|
+
stroke: defaultStroke,
|
|
536
|
+
strokeWidth: defaultStrokeWidth,
|
|
537
|
+
transition: transition,
|
|
538
|
+
transitions: transitions,
|
|
539
|
+
width: bar.width,
|
|
540
|
+
x: bar.x,
|
|
541
|
+
y: bar.y
|
|
542
|
+
}, bar.seriesId + "-" + categoryIndex + "-" + index));
|
|
543
|
+
|
|
544
|
+
// Check if the bar should be rounded based on the baseline, with an epsilon to handle floating-point rounding
|
|
545
|
+
const stackRoundBottom = roundBaseline || Math.abs(stackRect.y + stackRect.height - baseline) >= EPSILON;
|
|
546
|
+
const stackRoundTop = roundBaseline || Math.abs(stackRect.y - baseline) >= EPSILON;
|
|
502
547
|
return /*#__PURE__*/_jsx(BarStackComponent, {
|
|
503
548
|
borderRadius: borderRadius,
|
|
504
549
|
categoryIndex: categoryIndex,
|
|
505
550
|
height: stackRect.height,
|
|
506
551
|
roundBottom: stackRoundBottom,
|
|
507
552
|
roundTop: stackRoundTop,
|
|
553
|
+
transition: transition,
|
|
554
|
+
transitions: transitions,
|
|
508
555
|
width: stackRect.width,
|
|
509
556
|
x: stackRect.x,
|
|
510
557
|
y: stackRect.y,
|
|
@@ -19,26 +19,15 @@ export const BarStackGroup = /*#__PURE__*/memo(_ref => {
|
|
|
19
19
|
} = _ref,
|
|
20
20
|
props = _objectWithoutPropertiesLoose(_ref, _excluded);
|
|
21
21
|
const {
|
|
22
|
-
getSeriesData,
|
|
23
22
|
getXScale,
|
|
24
23
|
getYScale,
|
|
25
|
-
drawingArea
|
|
24
|
+
drawingArea,
|
|
25
|
+
dataLength
|
|
26
26
|
} = useCartesianChartContext();
|
|
27
27
|
const xScale = getXScale();
|
|
28
28
|
const yScale = getYScale(yAxisId);
|
|
29
|
-
const maxDataLength = useMemo(() => {
|
|
30
|
-
if (!series || series.length === 0) return 0;
|
|
31
|
-
let maxLength = 0;
|
|
32
|
-
series.forEach(s => {
|
|
33
|
-
const data = getSeriesData(s.id);
|
|
34
|
-
if (data && data.length > maxLength) {
|
|
35
|
-
maxLength = data.length;
|
|
36
|
-
}
|
|
37
|
-
});
|
|
38
|
-
return maxLength;
|
|
39
|
-
}, [series, getSeriesData]);
|
|
40
29
|
const stackConfigs = useMemo(() => {
|
|
41
|
-
if (!xScale || !yScale || !drawingArea ||
|
|
30
|
+
if (!xScale || !yScale || !drawingArea || dataLength === 0) return [];
|
|
42
31
|
if (!isCategoricalScale(xScale)) {
|
|
43
32
|
return [];
|
|
44
33
|
}
|
|
@@ -51,7 +40,8 @@ export const BarStackGroup = /*#__PURE__*/memo(_ref => {
|
|
|
51
40
|
const configs = [];
|
|
52
41
|
|
|
53
42
|
// Calculate position for each category
|
|
54
|
-
|
|
43
|
+
// todo: look at using xDomain for this instead of dataLength
|
|
44
|
+
for (let categoryIndex = 0; categoryIndex < dataLength; categoryIndex++) {
|
|
55
45
|
// Get x position for this category
|
|
56
46
|
const categoryX = xScale(categoryIndex);
|
|
57
47
|
if (categoryX !== undefined) {
|
|
@@ -65,9 +55,9 @@ export const BarStackGroup = /*#__PURE__*/memo(_ref => {
|
|
|
65
55
|
}
|
|
66
56
|
}
|
|
67
57
|
return configs;
|
|
68
|
-
}, [xScale, yScale, drawingArea,
|
|
58
|
+
}, [xScale, yScale, drawingArea, dataLength, stackIndex, totalStacks, barPadding]);
|
|
69
59
|
if (xScale && !isCategoricalScale(xScale)) {
|
|
70
|
-
throw new Error('BarStackGroup requires a band scale for x-axis. See https://cds.coinbase.com/components/
|
|
60
|
+
throw new Error('BarStackGroup requires a band scale for x-axis. See https://cds.coinbase.com/components/charts/XAxis/#scale-type');
|
|
71
61
|
}
|
|
72
62
|
if (!yScale || !drawingArea || stackConfigs.length === 0) return;
|
|
73
63
|
return stackConfigs.map(_ref2 => {
|
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
import { memo,
|
|
2
|
-
import { runOnJS, useAnimatedReaction, useSharedValue, withTiming } from 'react-native-reanimated';
|
|
3
|
-
import { Path } from 'react-native-svg';
|
|
4
|
-
import { usePreviousValue } from '@coinbase/cds-common/hooks/usePreviousValue';
|
|
1
|
+
import { memo, useMemo } from 'react';
|
|
5
2
|
import { useTheme } from '@coinbase/cds-mobile/hooks/useTheme';
|
|
6
|
-
import * as interpolate from 'd3-interpolate-path';
|
|
7
3
|
import { useCartesianChartContext } from '../ChartProvider';
|
|
8
|
-
import {
|
|
4
|
+
import { Path } from '../Path';
|
|
5
|
+
import { defaultBarEnterTransition, getBarPath, withStaggerDelayTransition } from '../utils';
|
|
6
|
+
import { defaultTransition, getTransition } from '../utils/transition';
|
|
9
7
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
10
8
|
/**
|
|
11
|
-
* Default bar component that renders a solid bar with animation.
|
|
9
|
+
* Default bar component that renders a solid bar with animation support.
|
|
12
10
|
*/
|
|
13
11
|
export const DefaultBar = /*#__PURE__*/memo(_ref => {
|
|
14
12
|
let {
|
|
@@ -16,63 +14,43 @@ export const DefaultBar = /*#__PURE__*/memo(_ref => {
|
|
|
16
14
|
y,
|
|
17
15
|
width,
|
|
18
16
|
height,
|
|
19
|
-
borderRadius,
|
|
17
|
+
borderRadius = 4,
|
|
20
18
|
roundTop,
|
|
21
19
|
roundBottom,
|
|
22
20
|
d,
|
|
23
21
|
fill,
|
|
24
22
|
fillOpacity = 1,
|
|
25
23
|
stroke,
|
|
26
|
-
strokeWidth
|
|
24
|
+
strokeWidth,
|
|
25
|
+
originY,
|
|
26
|
+
transitions,
|
|
27
|
+
transition
|
|
27
28
|
} = _ref;
|
|
28
|
-
const pathRef = useRef(null);
|
|
29
29
|
const {
|
|
30
|
-
animate
|
|
30
|
+
animate,
|
|
31
|
+
drawingArea
|
|
31
32
|
} = useCartesianChartContext();
|
|
32
33
|
const theme = useTheme();
|
|
33
|
-
const animationProgress = useSharedValue(0);
|
|
34
|
-
const targetPath = useMemo(() => {
|
|
35
|
-
return d || getBarPath(x, y, width, height, borderRadius != null ? borderRadius : 0, roundTop != null ? roundTop : true, roundBottom != null ? roundBottom : true);
|
|
36
|
-
}, [d, x, y, width, height, borderRadius, roundTop, roundBottom]);
|
|
37
|
-
const previousPath = usePreviousValue(targetPath);
|
|
38
|
-
const fromPath = useMemo(() => {
|
|
39
|
-
if (!animate) return targetPath;
|
|
40
|
-
return previousPath || targetPath;
|
|
41
|
-
}, [animate, previousPath, targetPath]);
|
|
42
|
-
const pathInterpolator = useMemo(() => interpolate.interpolatePath(fromPath, targetPath), [fromPath, targetPath]);
|
|
43
|
-
const updatePath = useCallback(progress => {
|
|
44
|
-
var _pathRef$current;
|
|
45
|
-
const val = Number(progress.toFixed(4));
|
|
46
|
-
(_pathRef$current = pathRef.current) == null || _pathRef$current.setNativeProps({
|
|
47
|
-
d: pathInterpolator(val)
|
|
48
|
-
});
|
|
49
|
-
}, [pathInterpolator]);
|
|
50
34
|
const defaultFill = fill || theme.color.fgPrimary;
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
if (!animate) {
|
|
59
|
-
pathRef.current.setNativeProps({
|
|
60
|
-
d: targetPath
|
|
61
|
-
});
|
|
62
|
-
animationProgress.value = 1;
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
animationProgress.value = 0;
|
|
66
|
-
animationProgress.value = withTiming(1, {
|
|
67
|
-
duration: 200
|
|
68
|
-
});
|
|
69
|
-
}, [animate, animationProgress, targetPath]);
|
|
35
|
+
const normalizedX = useMemo(() => drawingArea.width > 0 ? (x - drawingArea.x) / drawingArea.width : 0, [x, drawingArea.x, drawingArea.width]);
|
|
36
|
+
const enterTransition = useMemo(() => withStaggerDelayTransition(getTransition(transitions == null ? void 0 : transitions.enter, animate, defaultBarEnterTransition), normalizedX), [transitions == null ? void 0 : transitions.enter, animate, normalizedX]);
|
|
37
|
+
const updateTransition = useMemo(() => withStaggerDelayTransition(getTransition((transitions == null ? void 0 : transitions.update) !== undefined ? transitions.update : transition, animate, defaultTransition), normalizedX), [transitions == null ? void 0 : transitions.update, transition, animate, normalizedX]);
|
|
38
|
+
const initialPath = useMemo(() => {
|
|
39
|
+
const baselineY = originY != null ? originY : y + height;
|
|
40
|
+
return getBarPath(x, baselineY, width, 1, borderRadius, !!roundTop, !!roundBottom);
|
|
41
|
+
}, [x, originY, y, height, width, borderRadius, roundTop, roundBottom]);
|
|
70
42
|
return /*#__PURE__*/_jsx(Path, {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
43
|
+
animate: animate,
|
|
44
|
+
clipPath: null,
|
|
45
|
+
d: d,
|
|
46
|
+
fill: stroke ? 'none' : defaultFill,
|
|
74
47
|
fillOpacity: fillOpacity,
|
|
48
|
+
initialPath: initialPath,
|
|
75
49
|
stroke: stroke,
|
|
76
|
-
strokeWidth: strokeWidth
|
|
50
|
+
strokeWidth: strokeWidth,
|
|
51
|
+
transitions: {
|
|
52
|
+
enter: enterTransition,
|
|
53
|
+
update: updateTransition
|
|
54
|
+
}
|
|
77
55
|
});
|
|
78
56
|
});
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { memo,
|
|
2
|
-
import {
|
|
3
|
-
import { ClipPath, Defs, G, Path } from 'react-native-svg';
|
|
4
|
-
import { usePreviousValue } from '@coinbase/cds-common/hooks/usePreviousValue';
|
|
5
|
-
import * as interpolate from 'd3-interpolate-path';
|
|
1
|
+
import { memo, useMemo } from 'react';
|
|
2
|
+
import { Group } from '@shopify/react-native-skia';
|
|
6
3
|
import { useCartesianChartContext } from '../ChartProvider';
|
|
7
4
|
import { getBarPath } from '../utils';
|
|
8
|
-
import {
|
|
5
|
+
import { defaultBarEnterTransition, withStaggerDelayTransition } from '../utils/bar';
|
|
6
|
+
import { defaultTransition, getTransition, usePathTransition } from '../utils/transition';
|
|
7
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
9
8
|
/**
|
|
10
9
|
* Default stack component that renders children in a group with animated clip path.
|
|
11
10
|
*/
|
|
@@ -19,64 +18,41 @@ export const DefaultBarStack = /*#__PURE__*/memo(_ref => {
|
|
|
19
18
|
borderRadius = 4,
|
|
20
19
|
roundTop = true,
|
|
21
20
|
roundBottom = true,
|
|
22
|
-
yOrigin
|
|
21
|
+
yOrigin,
|
|
22
|
+
transitions,
|
|
23
|
+
transition
|
|
23
24
|
} = _ref;
|
|
24
|
-
const pathRef = useRef(null);
|
|
25
25
|
const {
|
|
26
|
-
animate
|
|
26
|
+
animate,
|
|
27
|
+
drawingArea
|
|
27
28
|
} = useCartesianChartContext();
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const
|
|
29
|
+
|
|
30
|
+
// Compute normalized x position for stagger delay calculation
|
|
31
|
+
const normalizedX = useMemo(() => drawingArea.width > 0 ? (x - drawingArea.x) / drawingArea.width : 0, [x, drawingArea.x, drawingArea.width]);
|
|
32
|
+
const enterTransition = useMemo(() => withStaggerDelayTransition(getTransition(transitions == null ? void 0 : transitions.enter, animate, defaultBarEnterTransition), normalizedX), [animate, transitions == null ? void 0 : transitions.enter, normalizedX]);
|
|
33
|
+
const updateTransition = useMemo(() => withStaggerDelayTransition(getTransition((transitions == null ? void 0 : transitions.update) !== undefined ? transitions.update : transition, animate, defaultTransition), normalizedX), [animate, transitions == null ? void 0 : transitions.update, transition, normalizedX]);
|
|
34
|
+
|
|
35
|
+
// Generate target clip path (full bar)
|
|
36
|
+
const targetPath = useMemo(() => {
|
|
31
37
|
return getBarPath(x, y, width, height, borderRadius, roundTop, roundBottom);
|
|
32
38
|
}, [x, y, width, height, borderRadius, roundTop, roundBottom]);
|
|
33
|
-
const previousClipPath = usePreviousValue(targetClipPath);
|
|
34
|
-
const initialClipPath = useMemo(() => {
|
|
35
|
-
return getBarPath(x, yOrigin != null ? yOrigin : y + height, width, 1, borderRadius, roundTop, roundBottom);
|
|
36
|
-
}, [x, yOrigin, y, height, width, borderRadius, roundTop, roundBottom]);
|
|
37
|
-
const fromClipPath = useMemo(() => {
|
|
38
|
-
if (!animate) return targetClipPath;
|
|
39
|
-
return previousClipPath || initialClipPath;
|
|
40
|
-
}, [animate, previousClipPath, initialClipPath, targetClipPath]);
|
|
41
|
-
const clipPathInterpolator = useMemo(() => interpolate.interpolatePath(fromClipPath, targetClipPath), [fromClipPath, targetClipPath]);
|
|
42
|
-
const updateClipPath = useCallback(progress => {
|
|
43
|
-
var _pathRef$current;
|
|
44
|
-
const val = Number(progress.toFixed(4));
|
|
45
|
-
(_pathRef$current = pathRef.current) == null || _pathRef$current.setNativeProps({
|
|
46
|
-
d: clipPathInterpolator(val)
|
|
47
|
-
});
|
|
48
|
-
}, [clipPathInterpolator]);
|
|
49
|
-
useAnimatedReaction(() => animationProgress.value, progress => {
|
|
50
|
-
'worklet';
|
|
51
39
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
40
|
+
// Initial clip path for entry animation (bar at baseline with minimal height)
|
|
41
|
+
const initialPath = useMemo(() => {
|
|
42
|
+
const baselineY = yOrigin != null ? yOrigin : y + height;
|
|
43
|
+
return getBarPath(x, baselineY, width, 1, borderRadius, roundTop, roundBottom);
|
|
44
|
+
}, [x, yOrigin, y, height, width, borderRadius, roundTop, roundBottom]);
|
|
45
|
+
const animatedClipPath = usePathTransition({
|
|
46
|
+
currentPath: targetPath,
|
|
47
|
+
initialPath,
|
|
48
|
+
transitions: {
|
|
49
|
+
enter: enterTransition,
|
|
50
|
+
update: updateTransition
|
|
62
51
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
69
|
-
children: [/*#__PURE__*/_jsx(Defs, {
|
|
70
|
-
children: /*#__PURE__*/_jsx(ClipPath, {
|
|
71
|
-
id: clipPathId,
|
|
72
|
-
children: /*#__PURE__*/_jsx(Path, {
|
|
73
|
-
ref: pathRef,
|
|
74
|
-
d: fromClipPath
|
|
75
|
-
})
|
|
76
|
-
})
|
|
77
|
-
}), /*#__PURE__*/_jsx(G, {
|
|
78
|
-
clipPath: "url(#" + clipPathId + ")",
|
|
79
|
-
children: children
|
|
80
|
-
})]
|
|
52
|
+
});
|
|
53
|
+
const clipPath = animate ? animatedClipPath : targetPath;
|
|
54
|
+
return /*#__PURE__*/_jsx(Group, {
|
|
55
|
+
clip: clipPath,
|
|
56
|
+
children: children
|
|
81
57
|
});
|
|
82
58
|
});
|