@coinbase/cds-mobile-visualization 3.4.0-beta.5 → 3.4.0-beta.6
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 +9 -0
- package/dts/chart/CartesianChart.d.ts +57 -33
- 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/Path.d.ts +77 -34
- package/dts/chart/Path.d.ts.map +1 -1
- package/dts/chart/PeriodSelector.d.ts +1 -1
- package/dts/chart/PeriodSelector.d.ts.map +1 -1
- package/dts/chart/area/Area.d.ts +42 -27
- 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 +68 -78
- 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 +16 -13
- package/dts/chart/bar/Bar.d.ts.map +1 -1
- package/dts/chart/bar/BarChart.d.ts +36 -20
- 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 +39 -48
- package/dts/chart/bar/BarStack.d.ts.map +1 -1
- package/dts/chart/bar/BarStackGroup.d.ts +1 -0
- package/dts/chart/bar/BarStackGroup.d.ts.map +1 -1
- package/dts/chart/bar/DefaultBar.d.ts +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 +3 -1
- package/dts/chart/index.d.ts.map +1 -1
- package/dts/chart/line/DefaultReferenceLineLabel.d.ts +9 -0
- package/dts/chart/line/DefaultReferenceLineLabel.d.ts.map +1 -0
- package/dts/chart/line/DottedLine.d.ts +13 -5
- package/dts/chart/line/DottedLine.d.ts.map +1 -1
- package/dts/chart/line/Line.d.ts +62 -25
- 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 +65 -22
- 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 +120 -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 +8 -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 +168 -41
- package/dts/chart/scrubber/Scrubber.d.ts.map +1 -1
- package/dts/chart/scrubber/ScrubberBeaconGroup.d.ts +44 -0
- package/dts/chart/scrubber/ScrubberBeaconGroup.d.ts.map +1 -0
- package/dts/chart/scrubber/ScrubberBeaconLabelGroup.d.ts +31 -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/chart.d.ts +34 -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 +53 -0
- package/dts/chart/utils/path.d.ts.map +1 -1
- package/dts/chart/utils/point.d.ts +60 -1
- package/dts/chart/utils/point.d.ts.map +1 -1
- package/dts/chart/utils/scale.d.ts +91 -0
- package/dts/chart/utils/scale.d.ts.map +1 -1
- package/dts/chart/utils/scrubber.d.ts +39 -0
- package/dts/chart/utils/scrubber.d.ts.map +1 -0
- package/dts/chart/utils/transition.d.ts +140 -0
- package/dts/chart/utils/transition.d.ts.map +1 -0
- package/esm/chart/CartesianChart.js +164 -70
- package/esm/chart/ChartContextBridge.js +148 -0
- package/esm/chart/Path.js +196 -113
- package/esm/chart/PeriodSelector.js +1 -1
- package/esm/chart/__stories__/CartesianChart.stories.js +371 -129
- package/esm/chart/__stories__/Chart.stories.js +2 -4
- package/esm/chart/area/Area.js +25 -35
- package/esm/chart/area/AreaChart.js +17 -12
- package/esm/chart/area/DottedArea.js +61 -109
- package/esm/chart/area/GradientArea.js +35 -91
- package/esm/chart/area/SolidArea.js +22 -8
- package/esm/chart/area/__stories__/AreaChart.stories.js +1 -1
- package/esm/chart/axis/Axis.js +2 -0
- package/esm/chart/axis/DefaultAxisTickLabel.js +11 -0
- package/esm/chart/axis/XAxis.js +62 -56
- package/esm/chart/axis/YAxis.js +58 -52
- package/esm/chart/axis/__stories__/Axis.stories.js +0 -1
- package/esm/chart/axis/index.js +1 -0
- package/esm/chart/bar/Bar.js +3 -1
- package/esm/chart/bar/BarChart.js +15 -37
- package/esm/chart/bar/BarPlot.js +41 -35
- package/esm/chart/bar/BarStack.js +75 -38
- package/esm/chart/bar/BarStackGroup.js +6 -16
- package/esm/chart/bar/DefaultBar.js +26 -48
- package/esm/chart/bar/DefaultBarStack.js +23 -58
- package/esm/chart/bar/__stories__/BarChart.stories.js +463 -77
- package/esm/chart/gradient/Gradient.js +53 -0
- package/esm/chart/gradient/index.js +1 -0
- package/esm/chart/index.js +3 -1
- package/esm/chart/line/DefaultReferenceLineLabel.js +66 -0
- package/esm/chart/line/DottedLine.js +29 -14
- package/esm/chart/line/Line.js +106 -67
- package/esm/chart/line/LineChart.js +20 -14
- package/esm/chart/line/ReferenceLine.js +73 -62
- package/esm/chart/line/SolidLine.js +25 -10
- package/esm/chart/line/__stories__/LineChart.stories.js +2098 -1975
- package/esm/chart/line/__stories__/ReferenceLine.stories.js +83 -28
- package/esm/chart/line/index.js +1 -1
- package/esm/chart/point/DefaultPointLabel.js +39 -0
- package/esm/chart/point/Point.js +188 -0
- package/esm/chart/point/index.js +2 -0
- package/esm/chart/scrubber/DefaultScrubberBeacon.js +179 -0
- package/esm/chart/scrubber/DefaultScrubberBeaconLabel.js +43 -0
- package/esm/chart/scrubber/DefaultScrubberLabel.js +28 -0
- package/esm/chart/scrubber/Scrubber.js +130 -148
- package/esm/chart/scrubber/ScrubberBeaconGroup.js +161 -0
- package/esm/chart/scrubber/ScrubberBeaconLabelGroup.js +185 -0
- package/esm/chart/scrubber/ScrubberProvider.js +46 -54
- 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/chart.js +44 -3
- package/esm/chart/utils/gradient.js +305 -0
- package/esm/chart/utils/index.js +3 -0
- package/esm/chart/utils/path.js +76 -8
- package/esm/chart/utils/point.js +116 -5
- package/esm/chart/utils/scale.js +230 -1
- package/esm/chart/utils/scrubber.js +139 -0
- package/esm/chart/utils/transition.js +221 -0
- package/package.json +7 -5
- 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/line/GradientLine.js +0 -62
- package/esm/chart/scrubber/ScrubberBeacon.js +0 -199
|
@@ -1,40 +1,63 @@
|
|
|
1
|
-
const _excluded = ["series", "animate", "enableScrubbing", "xAxis", "yAxis", "inset", "onScrubberPositionChange", "
|
|
1
|
+
const _excluded = ["series", "children", "animate", "enableScrubbing", "xAxis", "yAxis", "inset", "onScrubberPositionChange", "width", "height", "style", "styles", "allowOverflowGestures", "fontFamilies", "fontProvider", "collapsable"];
|
|
2
2
|
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); }
|
|
3
3
|
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
|
|
4
4
|
import React, { forwardRef, memo, useCallback, useMemo } from 'react';
|
|
5
|
-
import { Svg } from 'react-native-svg';
|
|
6
5
|
import { useLayout } from '@coinbase/cds-mobile/hooks/useLayout';
|
|
7
6
|
import { Box } from '@coinbase/cds-mobile/layout';
|
|
7
|
+
import { Canvas, Skia } from '@shopify/react-native-skia';
|
|
8
8
|
import { ScrubberProvider } from './scrubber/ScrubberProvider';
|
|
9
|
+
import { convertToSerializableScale } from './utils/scale';
|
|
10
|
+
import { useChartContextBridge } from './ChartContextBridge';
|
|
9
11
|
import { CartesianChartProvider } from './ChartProvider';
|
|
10
12
|
import { defaultAxisId, defaultChartInset, getAxisConfig, getAxisDomain, getAxisRange, getAxisScale, getChartInset, getStackedSeriesData as calculateStackedSeriesData, useTotalAxisPadding } from './utils';
|
|
11
13
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
12
|
-
|
|
14
|
+
const ChartCanvas = /*#__PURE__*/memo(_ref => {
|
|
15
|
+
let {
|
|
16
|
+
children,
|
|
17
|
+
style
|
|
18
|
+
} = _ref;
|
|
19
|
+
const ContextBridge = useChartContextBridge();
|
|
20
|
+
return /*#__PURE__*/_jsx(Canvas, {
|
|
21
|
+
style: [{
|
|
22
|
+
width: '100%',
|
|
23
|
+
height: '100%'
|
|
24
|
+
}, style],
|
|
25
|
+
children: /*#__PURE__*/_jsx(ContextBridge, {
|
|
26
|
+
children: children
|
|
27
|
+
})
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
export const CartesianChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref2, ref) => {
|
|
13
31
|
let {
|
|
14
32
|
series,
|
|
33
|
+
children,
|
|
15
34
|
animate = true,
|
|
16
35
|
enableScrubbing,
|
|
17
|
-
xAxis:
|
|
18
|
-
yAxis:
|
|
19
|
-
inset
|
|
36
|
+
xAxis: xAxisConfigProp,
|
|
37
|
+
yAxis: yAxisConfigProp,
|
|
38
|
+
inset,
|
|
20
39
|
onScrubberPositionChange,
|
|
21
|
-
children,
|
|
22
40
|
width = '100%',
|
|
23
41
|
height = '100%',
|
|
24
42
|
style,
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
43
|
+
styles,
|
|
44
|
+
allowOverflowGestures,
|
|
45
|
+
fontFamilies,
|
|
46
|
+
fontProvider: fontProviderProp,
|
|
47
|
+
// React Native will collapse views by default when only used
|
|
48
|
+
// to group children, which interferes with gesture-handler
|
|
49
|
+
// https://docs.swmansion.com/react-native-gesture-handler/docs/gestures/gesture-detector/#:~:text=%7B%0A%20%20return%20%3C-,View,-collapsable%3D%7B
|
|
50
|
+
collapsable = false
|
|
51
|
+
} = _ref2,
|
|
52
|
+
props = _objectWithoutPropertiesLoose(_ref2, _excluded);
|
|
28
53
|
const [containerLayout, onContainerLayout] = useLayout();
|
|
29
|
-
const chartWidth =
|
|
30
|
-
const chartHeight =
|
|
31
|
-
const
|
|
32
|
-
return getChartInset(insetInput, defaultChartInset);
|
|
33
|
-
}, [insetInput]);
|
|
54
|
+
const chartWidth = containerLayout.width;
|
|
55
|
+
const chartHeight = containerLayout.height;
|
|
56
|
+
const calculatedInset = useMemo(() => getChartInset(inset, defaultChartInset), [inset]);
|
|
34
57
|
|
|
35
58
|
// there can only be one x axis but the helper function always returns an array
|
|
36
|
-
const xAxisConfig = useMemo(() => getAxisConfig('x',
|
|
37
|
-
const yAxisConfig = useMemo(() => getAxisConfig('y',
|
|
59
|
+
const xAxisConfig = useMemo(() => getAxisConfig('x', xAxisConfigProp)[0], [xAxisConfigProp]);
|
|
60
|
+
const yAxisConfig = useMemo(() => getAxisConfig('y', yAxisConfigProp), [yAxisConfigProp]);
|
|
38
61
|
const {
|
|
39
62
|
renderedAxes,
|
|
40
63
|
registerAxis,
|
|
@@ -42,11 +65,11 @@ export const CartesianChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, r
|
|
|
42
65
|
axisPadding
|
|
43
66
|
} = useTotalAxisPadding();
|
|
44
67
|
const totalInset = useMemo(() => ({
|
|
45
|
-
top:
|
|
46
|
-
right:
|
|
47
|
-
bottom:
|
|
48
|
-
left:
|
|
49
|
-
}), [
|
|
68
|
+
top: calculatedInset.top + axisPadding.top,
|
|
69
|
+
right: calculatedInset.right + axisPadding.right,
|
|
70
|
+
bottom: calculatedInset.bottom + axisPadding.bottom,
|
|
71
|
+
left: calculatedInset.left + axisPadding.left
|
|
72
|
+
}), [calculatedInset, axisPadding]);
|
|
50
73
|
const chartRect = useMemo(() => {
|
|
51
74
|
if (chartWidth <= 0 || chartHeight <= 0) return {
|
|
52
75
|
x: 0,
|
|
@@ -63,8 +86,14 @@ export const CartesianChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, r
|
|
|
63
86
|
height: availableHeight > 0 ? availableHeight : 0
|
|
64
87
|
};
|
|
65
88
|
}, [chartHeight, chartWidth, totalInset]);
|
|
66
|
-
const
|
|
67
|
-
|
|
89
|
+
const {
|
|
90
|
+
xAxis,
|
|
91
|
+
xScale
|
|
92
|
+
} = useMemo(() => {
|
|
93
|
+
if (!chartRect || chartRect.width <= 0 || chartRect.height <= 0) return {
|
|
94
|
+
xAxis: undefined,
|
|
95
|
+
xScale: undefined
|
|
96
|
+
};
|
|
68
97
|
const domain = getAxisDomain(xAxisConfig, series != null ? series : [], 'x');
|
|
69
98
|
const range = getAxisRange(xAxisConfig, chartRect, 'x');
|
|
70
99
|
const axisConfig = {
|
|
@@ -75,11 +104,47 @@ export const CartesianChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, r
|
|
|
75
104
|
categoryPadding: xAxisConfig.categoryPadding,
|
|
76
105
|
domainLimit: xAxisConfig.domainLimit
|
|
77
106
|
};
|
|
78
|
-
|
|
107
|
+
|
|
108
|
+
// Create the scale
|
|
109
|
+
const scale = getAxisScale({
|
|
110
|
+
config: axisConfig,
|
|
111
|
+
type: 'x',
|
|
112
|
+
range: axisConfig.range,
|
|
113
|
+
dataDomain: axisConfig.domain
|
|
114
|
+
});
|
|
115
|
+
if (!scale) return {
|
|
116
|
+
xAxis: undefined,
|
|
117
|
+
xScale: undefined
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
// Update axis config with actual scale domain (after .nice() or other adjustments)
|
|
121
|
+
const scaleDomain = scale.domain();
|
|
122
|
+
const actualDomain = Array.isArray(scaleDomain) && scaleDomain.length === 2 ? {
|
|
123
|
+
min: scaleDomain[0],
|
|
124
|
+
max: scaleDomain[1]
|
|
125
|
+
} : axisConfig.domain;
|
|
126
|
+
const finalAxisConfig = _extends({}, axisConfig, {
|
|
127
|
+
domain: actualDomain
|
|
128
|
+
});
|
|
129
|
+
return {
|
|
130
|
+
xAxis: finalAxisConfig,
|
|
131
|
+
xScale: scale
|
|
132
|
+
};
|
|
79
133
|
}, [xAxisConfig, series, chartRect]);
|
|
80
|
-
const
|
|
134
|
+
const xSerializableScale = useMemo(() => {
|
|
135
|
+
if (!xScale) return;
|
|
136
|
+
return convertToSerializableScale(xScale);
|
|
137
|
+
}, [xScale]);
|
|
138
|
+
const {
|
|
139
|
+
yAxes,
|
|
140
|
+
yScales
|
|
141
|
+
} = useMemo(() => {
|
|
81
142
|
const axes = new Map();
|
|
82
|
-
|
|
143
|
+
const scales = new Map();
|
|
144
|
+
if (!chartRect || chartRect.width <= 0 || chartRect.height <= 0) return {
|
|
145
|
+
yAxes: axes,
|
|
146
|
+
yScales: scales
|
|
147
|
+
};
|
|
83
148
|
yAxisConfig.forEach(axisParam => {
|
|
84
149
|
var _axisParam$id, _series$filter, _axisParam$domainLimi;
|
|
85
150
|
const axisId = (_axisParam$id = axisParam.id) != null ? _axisParam$id : defaultAxisId;
|
|
@@ -90,33 +155,19 @@ export const CartesianChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, r
|
|
|
90
155
|
return ((_s$yAxisId = s.yAxisId) != null ? _s$yAxisId : defaultAxisId) === axisId;
|
|
91
156
|
})) != null ? _series$filter : [];
|
|
92
157
|
|
|
93
|
-
// Calculate domain and range
|
|
94
|
-
const
|
|
158
|
+
// Calculate domain and range
|
|
159
|
+
const dataDomain = getAxisDomain(axisParam, relevantSeries, 'y');
|
|
95
160
|
const range = getAxisRange(axisParam, chartRect, 'y');
|
|
96
|
-
|
|
161
|
+
const axisConfig = {
|
|
97
162
|
scaleType: axisParam.scaleType,
|
|
98
|
-
domain,
|
|
163
|
+
domain: dataDomain,
|
|
99
164
|
range,
|
|
100
165
|
data: axisParam.data,
|
|
101
166
|
categoryPadding: axisParam.categoryPadding,
|
|
102
167
|
domainLimit: (_axisParam$domainLimi = axisParam.domainLimit) != null ? _axisParam$domainLimi : 'nice'
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}, [yAxisConfig, series, chartRect]);
|
|
107
|
-
const xScale = useMemo(() => {
|
|
108
|
-
if (!chartRect || chartRect.width <= 0 || chartRect.height <= 0 || xAxis === undefined) return undefined;
|
|
109
|
-
return getAxisScale({
|
|
110
|
-
config: xAxis,
|
|
111
|
-
type: 'x',
|
|
112
|
-
range: xAxis.range,
|
|
113
|
-
dataDomain: xAxis.domain
|
|
114
|
-
});
|
|
115
|
-
}, [chartRect, xAxis]);
|
|
116
|
-
const yScales = useMemo(() => {
|
|
117
|
-
const scales = new Map();
|
|
118
|
-
if (!chartRect || chartRect.width <= 0 || chartRect.height <= 0) return scales;
|
|
119
|
-
yAxes.forEach((axisConfig, axisId) => {
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
// Create the scale
|
|
120
171
|
const scale = getAxisScale({
|
|
121
172
|
config: axisConfig,
|
|
122
173
|
type: 'y',
|
|
@@ -125,17 +176,42 @@ export const CartesianChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, r
|
|
|
125
176
|
});
|
|
126
177
|
if (scale) {
|
|
127
178
|
scales.set(axisId, scale);
|
|
179
|
+
|
|
180
|
+
// Update axis config with actual scale domain (after .nice() or other adjustments)
|
|
181
|
+
const scaleDomain = scale.domain();
|
|
182
|
+
const actualDomain = Array.isArray(scaleDomain) && scaleDomain.length === 2 ? {
|
|
183
|
+
min: scaleDomain[0],
|
|
184
|
+
max: scaleDomain[1]
|
|
185
|
+
} : axisConfig.domain;
|
|
186
|
+
axes.set(axisId, _extends({}, axisConfig, {
|
|
187
|
+
domain: actualDomain
|
|
188
|
+
}));
|
|
128
189
|
}
|
|
129
190
|
});
|
|
130
|
-
return
|
|
131
|
-
|
|
191
|
+
return {
|
|
192
|
+
yAxes: axes,
|
|
193
|
+
yScales: scales
|
|
194
|
+
};
|
|
195
|
+
}, [yAxisConfig, series, chartRect]);
|
|
196
|
+
|
|
197
|
+
// We need a set of serialized scales usable in UI thread
|
|
198
|
+
const ySerializableScales = useMemo(() => {
|
|
199
|
+
const serializableScales = new Map();
|
|
200
|
+
yScales.forEach((scale, id) => {
|
|
201
|
+
const serializableScale = convertToSerializableScale(scale);
|
|
202
|
+
if (serializableScale) {
|
|
203
|
+
serializableScales.set(id, serializableScale);
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
return serializableScales;
|
|
207
|
+
}, [yScales]);
|
|
132
208
|
const getXAxis = useCallback(() => xAxis, [xAxis]);
|
|
133
209
|
const getYAxis = useCallback(id => yAxes.get(id != null ? id : defaultAxisId), [yAxes]);
|
|
134
210
|
const getXScale = useCallback(() => xScale, [xScale]);
|
|
135
211
|
const getYScale = useCallback(id => yScales.get(id != null ? id : defaultAxisId), [yScales]);
|
|
212
|
+
const getXSerializableScale = useCallback(() => xSerializableScale, [xSerializableScale]);
|
|
213
|
+
const getYSerializableScale = useCallback(id => ySerializableScales.get(id != null ? id : defaultAxisId), [ySerializableScales]);
|
|
136
214
|
const getSeries = useCallback(seriesId => series == null ? void 0 : series.find(s => s.id === seriesId), [series]);
|
|
137
|
-
|
|
138
|
-
// Compute stacked data for series with stack properties
|
|
139
215
|
const stackedDataMap = useMemo(() => {
|
|
140
216
|
if (!series) return new Map();
|
|
141
217
|
return calculateStackedSeriesData(series);
|
|
@@ -144,6 +220,20 @@ export const CartesianChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, r
|
|
|
144
220
|
if (!seriesId) return undefined;
|
|
145
221
|
return stackedDataMap.get(seriesId);
|
|
146
222
|
}, [stackedDataMap]);
|
|
223
|
+
const dataLength = useMemo(() => {
|
|
224
|
+
// If xAxis has categorical data, use that length
|
|
225
|
+
if (xAxisConfig.data && xAxisConfig.data.length > 0) {
|
|
226
|
+
return xAxisConfig.data.length;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Otherwise, find the longest series
|
|
230
|
+
if (!series || series.length === 0) return 0;
|
|
231
|
+
return series.reduce((max, s) => {
|
|
232
|
+
var _seriesData$length;
|
|
233
|
+
const seriesData = getStackedSeriesData(s.id);
|
|
234
|
+
return Math.max(max, (_seriesData$length = seriesData == null ? void 0 : seriesData.length) != null ? _seriesData$length : 0);
|
|
235
|
+
}, 0);
|
|
236
|
+
}, [xAxisConfig.data, series, getStackedSeriesData]);
|
|
147
237
|
const getAxisBounds = useCallback(axisId => {
|
|
148
238
|
const axis = renderedAxes.get(axisId);
|
|
149
239
|
if (!axis || !chartRect) return;
|
|
@@ -155,7 +245,7 @@ export const CartesianChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, r
|
|
|
155
245
|
const offsetFromPreviousAxes = axesAtPosition.slice(0, axisIndex).reduce((sum, a) => sum + a.size, 0);
|
|
156
246
|
if (axis.position === 'top') {
|
|
157
247
|
// Position above the chart rect, accounting for user inset
|
|
158
|
-
const startY =
|
|
248
|
+
const startY = calculatedInset.top + offsetFromPreviousAxes;
|
|
159
249
|
return {
|
|
160
250
|
x: chartRect.x,
|
|
161
251
|
y: startY,
|
|
@@ -173,7 +263,7 @@ export const CartesianChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, r
|
|
|
173
263
|
};
|
|
174
264
|
} else if (axis.position === 'left') {
|
|
175
265
|
// Position to the left of the chart rect, accounting for user inset
|
|
176
|
-
const startX =
|
|
266
|
+
const startX = calculatedInset.left + offsetFromPreviousAxes;
|
|
177
267
|
return {
|
|
178
268
|
x: startX,
|
|
179
269
|
y: chartRect.y,
|
|
@@ -190,7 +280,11 @@ export const CartesianChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, r
|
|
|
190
280
|
height: chartRect.height
|
|
191
281
|
};
|
|
192
282
|
}
|
|
193
|
-
}, [renderedAxes, chartRect,
|
|
283
|
+
}, [renderedAxes, chartRect, calculatedInset]);
|
|
284
|
+
const fontProvider = useMemo(() => {
|
|
285
|
+
if (fontProviderProp) return fontProviderProp;
|
|
286
|
+
return Skia.TypefaceFontProvider.Make();
|
|
287
|
+
}, [fontProviderProp]);
|
|
194
288
|
const contextValue = useMemo(() => ({
|
|
195
289
|
series: series != null ? series : [],
|
|
196
290
|
getSeries,
|
|
@@ -198,25 +292,23 @@ export const CartesianChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, r
|
|
|
198
292
|
animate,
|
|
199
293
|
width: chartWidth,
|
|
200
294
|
height: chartHeight,
|
|
295
|
+
fontFamilies,
|
|
296
|
+
fontProvider,
|
|
201
297
|
getXAxis,
|
|
202
298
|
getYAxis,
|
|
203
299
|
getXScale,
|
|
204
300
|
getYScale,
|
|
301
|
+
getXSerializableScale,
|
|
302
|
+
getYSerializableScale,
|
|
205
303
|
drawingArea: chartRect,
|
|
304
|
+
dataLength,
|
|
206
305
|
registerAxis,
|
|
207
306
|
unregisterAxis,
|
|
208
307
|
getAxisBounds
|
|
209
|
-
}), [series, getSeries, getStackedSeriesData, animate, chartWidth, chartHeight, getXAxis, getYAxis, getXScale, getYScale, chartRect, registerAxis, unregisterAxis, getAxisBounds]);
|
|
210
|
-
const
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
dynamicStyles.width = width;
|
|
214
|
-
}
|
|
215
|
-
if (typeof height === 'string') {
|
|
216
|
-
dynamicStyles.height = height;
|
|
217
|
-
}
|
|
218
|
-
return [style, dynamicStyles];
|
|
219
|
-
}, [style, width, height]);
|
|
308
|
+
}), [series, getSeries, getStackedSeriesData, animate, chartWidth, chartHeight, fontFamilies, fontProvider, getXAxis, getYAxis, getXScale, getYScale, getXSerializableScale, getYSerializableScale, chartRect, dataLength, registerAxis, unregisterAxis, getAxisBounds]);
|
|
309
|
+
const rootStyles = useMemo(() => {
|
|
310
|
+
return [style, styles == null ? void 0 : styles.root];
|
|
311
|
+
}, [style, styles == null ? void 0 : styles.root]);
|
|
220
312
|
return /*#__PURE__*/_jsx(CartesianChartProvider, {
|
|
221
313
|
value: contextValue,
|
|
222
314
|
children: /*#__PURE__*/_jsx(ScrubberProvider, {
|
|
@@ -227,12 +319,14 @@ export const CartesianChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, r
|
|
|
227
319
|
ref: ref,
|
|
228
320
|
accessibilityLiveRegion: "polite",
|
|
229
321
|
accessibilityRole: "image",
|
|
322
|
+
collapsable: collapsable,
|
|
323
|
+
height: height,
|
|
230
324
|
onLayout: onContainerLayout,
|
|
231
|
-
style:
|
|
325
|
+
style: rootStyles,
|
|
326
|
+
width: width
|
|
232
327
|
}, props, {
|
|
233
|
-
children: /*#__PURE__*/_jsx(
|
|
234
|
-
|
|
235
|
-
width: chartWidth,
|
|
328
|
+
children: /*#__PURE__*/_jsx(ChartCanvas, {
|
|
329
|
+
style: styles == null ? void 0 : styles.chart,
|
|
236
330
|
children: children
|
|
237
331
|
})
|
|
238
332
|
}))
|
|
@@ -0,0 +1,148 @@
|
|
|
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
|
+
/**
|
|
3
|
+
* Simplified context bridge utilities for React Native.
|
|
4
|
+
* Adapted from its-fine to enable context sharing across React renderers
|
|
5
|
+
* https://github.com/pmndrs/its-fine/blob/598b81f02778c22ed21121c2b1a786bdefb14e23/src/index.tsx
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import * as React from 'react';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Represents a react-internal tree node.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Represents a tree node selector for traversal.
|
|
16
|
+
*/
|
|
17
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
18
|
+
/**
|
|
19
|
+
* Traverses up or down a React tree, return `true` to stop and select a node.
|
|
20
|
+
*/
|
|
21
|
+
function traverseTreeNode(node, ascending, selector) {
|
|
22
|
+
if (!node) return;
|
|
23
|
+
if (selector(node) === true) return node;
|
|
24
|
+
let child = ascending ? node.return : node.child;
|
|
25
|
+
while (child) {
|
|
26
|
+
const match = traverseTreeNode(child, ascending, selector);
|
|
27
|
+
if (match) return match;
|
|
28
|
+
child = ascending ? null : child.sibling;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Wraps context to hide React development warnings about using contexts between renderers.
|
|
34
|
+
*/
|
|
35
|
+
function wrapContext(context) {
|
|
36
|
+
try {
|
|
37
|
+
return Object.defineProperties(context, {
|
|
38
|
+
_currentRenderer: {
|
|
39
|
+
get() {
|
|
40
|
+
return null;
|
|
41
|
+
},
|
|
42
|
+
set() {}
|
|
43
|
+
},
|
|
44
|
+
_currentRenderer2: {
|
|
45
|
+
get() {
|
|
46
|
+
return null;
|
|
47
|
+
},
|
|
48
|
+
set() {}
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
} catch (_) {
|
|
52
|
+
return context;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// In development, React will warn about using contexts between renderers.
|
|
57
|
+
// Suppress the warning because our context bridge fixes this issue
|
|
58
|
+
const error = console.error;
|
|
59
|
+
console.error = function () {
|
|
60
|
+
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
61
|
+
args[_key] = arguments[_key];
|
|
62
|
+
}
|
|
63
|
+
const message = args.join('');
|
|
64
|
+
if (message != null && message.startsWith('Warning:') && message.includes('useContext')) {
|
|
65
|
+
console.error = error;
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
return error.apply(this, args);
|
|
69
|
+
};
|
|
70
|
+
const TreeNodeContext = wrapContext(/*#__PURE__*/React.createContext(null));
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* A react-internal tree node provider that binds React children to the React tree for chart context bridging.
|
|
74
|
+
*/
|
|
75
|
+
export class ChartBridgeProvider extends React.Component {
|
|
76
|
+
render() {
|
|
77
|
+
return /*#__PURE__*/_jsx(TreeNodeContext.Provider, {
|
|
78
|
+
value: this._reactInternals,
|
|
79
|
+
children: this.props.children
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Returns the current react-internal tree node.
|
|
86
|
+
*/
|
|
87
|
+
function useTreeNode() {
|
|
88
|
+
const root = React.useContext(TreeNodeContext);
|
|
89
|
+
if (root === null) throw new Error('useTreeNode must be called within a <ChartBridgeProvider />!');
|
|
90
|
+
const id = React.useId();
|
|
91
|
+
const treeNode = React.useMemo(() => {
|
|
92
|
+
for (const maybeNode of [root, root == null ? void 0 : root.alternate]) {
|
|
93
|
+
if (!maybeNode) continue;
|
|
94
|
+
const node = traverseTreeNode(maybeNode, false, node => {
|
|
95
|
+
let state = node.memoizedState;
|
|
96
|
+
while (state) {
|
|
97
|
+
if (state.memoizedState === id) return true;
|
|
98
|
+
state = state.next;
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
if (node) return node;
|
|
102
|
+
}
|
|
103
|
+
}, [root, id]);
|
|
104
|
+
return treeNode;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Returns a map of all contexts and their values.
|
|
108
|
+
*/
|
|
109
|
+
function useContextMap() {
|
|
110
|
+
const treeNode = useTreeNode();
|
|
111
|
+
const [contextMap] = React.useState(() => new Map());
|
|
112
|
+
|
|
113
|
+
// Collect live context
|
|
114
|
+
contextMap.clear();
|
|
115
|
+
let node = treeNode;
|
|
116
|
+
while (node) {
|
|
117
|
+
if (node.type && typeof node.type === 'object') {
|
|
118
|
+
// https://github.com/facebook/react/pull/28226
|
|
119
|
+
const enableRenderableContext = node.type._context === undefined && node.type.Provider === node.type;
|
|
120
|
+
const context = enableRenderableContext ? node.type : node.type._context;
|
|
121
|
+
if (context && context !== TreeNodeContext && !contextMap.has(context)) {
|
|
122
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
123
|
+
contextMap.set(context, React.useContext(wrapContext(context)));
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
node = node.return;
|
|
127
|
+
}
|
|
128
|
+
return contextMap;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Represents a chart context bridge provider component.
|
|
133
|
+
*/
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Returns a ChartContextBridge of live context providers to pierce Context across renderers.
|
|
137
|
+
* Pass ChartContextBridge as a component to a secondary renderer (e.g., Skia Canvas) to enable context-sharing in charts.
|
|
138
|
+
*/
|
|
139
|
+
export function useChartContextBridge() {
|
|
140
|
+
const contextMap = useContextMap();
|
|
141
|
+
|
|
142
|
+
// Flatten context and their memoized values into a `ChartContextBridge` provider
|
|
143
|
+
return React.useMemo(() => Array.from(contextMap.keys()).reduce((Prev, context) => props => /*#__PURE__*/_jsx(Prev, {
|
|
144
|
+
children: /*#__PURE__*/_jsx(context.Provider, _extends({}, props, {
|
|
145
|
+
value: contextMap.get(context)
|
|
146
|
+
}))
|
|
147
|
+
}), props => /*#__PURE__*/_jsx(ChartBridgeProvider, _extends({}, props))), [contextMap]);
|
|
148
|
+
}
|