@coinbase/cds-mobile-visualization 3.4.0-beta.23 → 3.4.0-beta.24
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 +6 -0
- package/dts/chart/CartesianChart.d.ts +19 -0
- package/dts/chart/CartesianChart.d.ts.map +1 -1
- package/dts/chart/line/LineChart.d.ts +17 -3
- package/dts/chart/line/LineChart.d.ts.map +1 -1
- package/dts/chart/scrubber/ScrubberAccessibilityView.d.ts +12 -0
- package/dts/chart/scrubber/ScrubberAccessibilityView.d.ts.map +1 -0
- package/esm/chart/CartesianChart.js +39 -14
- package/esm/chart/__stories__/CartesianChart.stories.js +10 -0
- package/esm/chart/__stories__/ChartAccessibility.stories.js +721 -0
- package/esm/chart/area/__stories__/AreaChart.stories.js +17 -3
- package/esm/chart/axis/__stories__/Axis.stories.js +65 -48
- package/esm/chart/bar/__stories__/BarChart.stories.js +6 -0
- package/esm/chart/line/LineChart.js +22 -1
- package/esm/chart/line/__stories__/LineChart.stories.js +84 -46
- package/esm/chart/scrubber/ScrubberAccessibilityView.js +177 -0
- package/esm/chart/scrubber/__stories__/Scrubber.stories.js +57 -5
- package/package.json +5 -5
|
@@ -1,17 +1,22 @@
|
|
|
1
|
+
import { useCallback } from 'react';
|
|
1
2
|
import { Example, ExampleScreen } from '@coinbase/cds-mobile/examples/ExampleScreen';
|
|
2
3
|
import { useTheme } from '@coinbase/cds-mobile/hooks/useTheme';
|
|
3
4
|
import { DottedLine } from '../../line';
|
|
4
5
|
import { Scrubber } from '../../scrubber/Scrubber';
|
|
5
6
|
import { AreaChart } from '..';
|
|
6
7
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
8
|
+
const basicData = [24, 13, 98, 39, 48, 38, 43];
|
|
7
9
|
const BasicExample = () => {
|
|
10
|
+
const getScrubberAccessibilityLabel = useCallback(index => "Point " + (index + 1) + ": " + basicData[index], []);
|
|
8
11
|
return /*#__PURE__*/_jsx(AreaChart, {
|
|
9
12
|
enableScrubbing: true,
|
|
10
13
|
showYAxis: true,
|
|
14
|
+
accessibilityLabel: "Area chart with " + basicData.length + " data points. Swipe to navigate.",
|
|
15
|
+
getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
|
|
11
16
|
height: 400,
|
|
12
17
|
series: [{
|
|
13
18
|
id: 'pageViews',
|
|
14
|
-
data:
|
|
19
|
+
data: basicData
|
|
15
20
|
}],
|
|
16
21
|
yAxis: {
|
|
17
22
|
showGrid: true,
|
|
@@ -22,21 +27,26 @@ const BasicExample = () => {
|
|
|
22
27
|
children: /*#__PURE__*/_jsx(Scrubber, {})
|
|
23
28
|
});
|
|
24
29
|
};
|
|
30
|
+
const currentRewardsData = [100, 150, 200, 280, 380, 500, 650, 820, 1020, 1250, 1510, 1800, 2120, 2470, 2850, 3260, 3700, 4170];
|
|
31
|
+
const potentialRewardsData = [150, 220, 300, 400, 520, 660, 820, 1000, 1200, 1420, 1660, 1920, 2200, 2500, 2820, 3160, 3520, 3900];
|
|
25
32
|
const StackedExample = () => {
|
|
26
33
|
const theme = useTheme();
|
|
34
|
+
const getScrubberAccessibilityLabel = useCallback(index => "Point " + (index + 1) + ": current " + currentRewardsData[index] + ", potential " + potentialRewardsData[index], []);
|
|
27
35
|
return /*#__PURE__*/_jsx(AreaChart, {
|
|
28
36
|
enableScrubbing: true,
|
|
29
37
|
showLines: true,
|
|
30
38
|
stacked: true,
|
|
39
|
+
accessibilityLabel: "Stacked rewards chart with " + currentRewardsData.length + " data points. Swipe to navigate.",
|
|
31
40
|
curve: "natural",
|
|
41
|
+
getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
|
|
32
42
|
height: 256,
|
|
33
43
|
series: [{
|
|
34
44
|
id: 'currentRewards',
|
|
35
|
-
data:
|
|
45
|
+
data: currentRewardsData,
|
|
36
46
|
color: theme.color.fg
|
|
37
47
|
}, {
|
|
38
48
|
id: 'potentialRewards',
|
|
39
|
-
data:
|
|
49
|
+
data: potentialRewardsData,
|
|
40
50
|
color: theme.color.fgPositive,
|
|
41
51
|
type: 'dotted',
|
|
42
52
|
LineComponent: DottedLine
|
|
@@ -59,6 +69,8 @@ const AreaChartStories = () => {
|
|
|
59
69
|
enableScrubbing: true,
|
|
60
70
|
showLines: true,
|
|
61
71
|
showYAxis: true,
|
|
72
|
+
accessibilityLabel: "Area chart with negative values. 7 data points. Swipe to navigate.",
|
|
73
|
+
getScrubberAccessibilityLabel: index => "Point " + (index + 1) + ": " + [24, 13, -98, 39, 48, 38, 43][index],
|
|
62
74
|
height: 150,
|
|
63
75
|
series: [{
|
|
64
76
|
id: 'pageViews',
|
|
@@ -101,6 +113,8 @@ const AreaChartStories = () => {
|
|
|
101
113
|
showLines: true,
|
|
102
114
|
showXAxis: true,
|
|
103
115
|
showYAxis: true,
|
|
116
|
+
accessibilityLabel: "Volume by asset. 5 data points. Swipe to navigate.",
|
|
117
|
+
getScrubberAccessibilityLabel: index => ['BTC', 'ETH', 'SOL', 'DOGE', 'ADA'][index] + ": " + [68, 54, 43, 29, 18][index] + "%",
|
|
104
118
|
height: 280,
|
|
105
119
|
layout: "horizontal",
|
|
106
120
|
series: [{
|
|
@@ -53,10 +53,14 @@ const Simple = () => {
|
|
|
53
53
|
const pageViews = data.map(d => d.pv);
|
|
54
54
|
const pageNames = data.map(d => d.name);
|
|
55
55
|
const pageUniqueVisitors = data.map(d => d.uv);
|
|
56
|
+
const chartAccessibilityLabel = "Page views and unique visitors across " + pageNames.length + " pages. Swipe to navigate.";
|
|
57
|
+
const getScrubberAccessibilityLabel = useCallback(index => pageNames[index] + ": " + pageViews[index] + " views, " + pageUniqueVisitors[index] + " unique visitors", [pageNames, pageViews, pageUniqueVisitors]);
|
|
56
58
|
return /*#__PURE__*/_jsx(LineChart, {
|
|
57
59
|
enableScrubbing: true,
|
|
58
60
|
showXAxis: true,
|
|
59
61
|
showYAxis: true,
|
|
62
|
+
accessibilityLabel: chartAccessibilityLabel,
|
|
63
|
+
getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
|
|
60
64
|
height: defaultChartHeight,
|
|
61
65
|
inset: 32,
|
|
62
66
|
series: [{
|
|
@@ -97,8 +101,8 @@ const Simple = () => {
|
|
|
97
101
|
};
|
|
98
102
|
const TimeOfDayAxesExample = () => {
|
|
99
103
|
const theme = useTheme();
|
|
100
|
-
const lineA = [5, 5, 10, 90, 85, 70, 30, 25, 25];
|
|
101
|
-
const lineB = [90, 85, 70, 25, 23, 40, 45, 40, 50];
|
|
104
|
+
const lineA = useMemo(() => [5, 5, 10, 90, 85, 70, 30, 25, 25], []);
|
|
105
|
+
const lineB = useMemo(() => [90, 85, 70, 25, 23, 40, 45, 40, 50], []);
|
|
102
106
|
const timeData = useMemo(() => [new Date(2023, 7, 31), new Date(2023, 7, 31, 12), new Date(2023, 8, 1), new Date(2023, 8, 1, 12), new Date(2023, 8, 2), new Date(2023, 8, 2, 12), new Date(2023, 8, 3), new Date(2023, 8, 3, 12), new Date(2023, 8, 4)].map(d => d.getTime()), []);
|
|
103
107
|
const dateFormatter = useCallback(index => {
|
|
104
108
|
return new Date(timeData[index]).toLocaleDateString('en-US', {
|
|
@@ -117,8 +121,12 @@ const TimeOfDayAxesExample = () => {
|
|
|
117
121
|
const dateTicks = useMemo(() => {
|
|
118
122
|
return timeData.map((d, index) => index).filter(d => d % 2 === 0);
|
|
119
123
|
}, [timeData]);
|
|
124
|
+
const chartAccessibilityLabel = "Chart with " + lineA.length + " data points. Swipe to navigate.";
|
|
125
|
+
const getScrubberAccessibilityLabel = useCallback(index => "Point " + (index + 1) + ": lineA " + lineA[index] + ", lineB " + lineB[index], [lineA, lineB]);
|
|
120
126
|
return /*#__PURE__*/_jsxs(LineChart, {
|
|
121
127
|
enableScrubbing: true,
|
|
128
|
+
accessibilityLabel: chartAccessibilityLabel,
|
|
129
|
+
getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
|
|
122
130
|
height: defaultChartHeight,
|
|
123
131
|
series: [{
|
|
124
132
|
id: 'lineA',
|
|
@@ -150,51 +158,57 @@ const TimeOfDayAxesExample = () => {
|
|
|
150
158
|
}), /*#__PURE__*/_jsx(Scrubber, {})]
|
|
151
159
|
});
|
|
152
160
|
};
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
161
|
+
const multipleYAxesData = [1, 10, 30, 50, 70, 90, 100];
|
|
162
|
+
const MultipleYAxesExample = () => {
|
|
163
|
+
const getScrubberAccessibilityLabel = useCallback(index => "Point " + (index + 1) + ": linear " + multipleYAxesData[index] + ", log " + multipleYAxesData[index], []);
|
|
164
|
+
return /*#__PURE__*/_jsxs(CartesianChart, {
|
|
165
|
+
enableScrubbing: true,
|
|
166
|
+
accessibilityLabel: "Chart with linear and log axes. 7 data points. Swipe to navigate.",
|
|
167
|
+
getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
|
|
168
|
+
height: defaultChartHeight,
|
|
169
|
+
series: [{
|
|
170
|
+
id: 'linear',
|
|
171
|
+
yAxisId: 'linearAxis',
|
|
172
|
+
data: multipleYAxesData,
|
|
173
|
+
label: 'linear'
|
|
174
|
+
}, {
|
|
175
|
+
id: 'log',
|
|
176
|
+
yAxisId: 'logAxis',
|
|
177
|
+
data: multipleYAxesData,
|
|
178
|
+
label: 'log'
|
|
179
|
+
}],
|
|
180
|
+
xAxis: {
|
|
181
|
+
data: multipleYAxesData
|
|
182
|
+
},
|
|
183
|
+
yAxis: [{
|
|
184
|
+
id: 'linearAxis',
|
|
185
|
+
scaleType: 'linear'
|
|
186
|
+
}, {
|
|
187
|
+
id: 'logAxis',
|
|
188
|
+
scaleType: 'log'
|
|
189
|
+
}],
|
|
190
|
+
children: [/*#__PURE__*/_jsx(XAxis, {
|
|
191
|
+
showLine: true,
|
|
192
|
+
showTickMarks: true
|
|
193
|
+
}), /*#__PURE__*/_jsx(YAxis, {
|
|
194
|
+
showLine: true,
|
|
195
|
+
showTickMarks: true,
|
|
196
|
+
axisId: "logAxis",
|
|
197
|
+
position: "left"
|
|
198
|
+
}), /*#__PURE__*/_jsx(YAxis, {
|
|
199
|
+
showLine: true,
|
|
200
|
+
showTickMarks: true,
|
|
201
|
+
axisId: "linearAxis",
|
|
202
|
+
position: "left"
|
|
203
|
+
}), /*#__PURE__*/_jsx(Line, {
|
|
204
|
+
curve: "natural",
|
|
205
|
+
seriesId: "linear"
|
|
206
|
+
}), /*#__PURE__*/_jsx(Line, {
|
|
207
|
+
curve: "natural",
|
|
208
|
+
seriesId: "log"
|
|
209
|
+
}), /*#__PURE__*/_jsx(Scrubber, {})]
|
|
210
|
+
});
|
|
211
|
+
};
|
|
198
212
|
const AxesOnAllSides = () => {
|
|
199
213
|
const theme = useTheme();
|
|
200
214
|
const data = [30, 45, 60, 80, 55, 40, 65];
|
|
@@ -298,9 +312,12 @@ const DomainLimitType = _ref => {
|
|
|
298
312
|
let {
|
|
299
313
|
limit
|
|
300
314
|
} = _ref;
|
|
301
|
-
const exponentialData = [1, 2, 4, 8, 15, 30, 65, 140, 280, 580, 1200, 2400, 4800, 9500, 19000, 38000, 75000, 150000];
|
|
315
|
+
const exponentialData = useMemo(() => [1, 2, 4, 8, 15, 30, 65, 140, 280, 580, 1200, 2400, 4800, 9500, 19000, 38000, 75000, 150000], []);
|
|
316
|
+
const getScrubberAccessibilityLabel = useCallback(index => "Point " + (index + 1) + ": " + exponentialData[index], [exponentialData]);
|
|
302
317
|
return /*#__PURE__*/_jsxs(CartesianChart, {
|
|
303
318
|
enableScrubbing: true,
|
|
319
|
+
accessibilityLabel: "Exponential growth chart with " + exponentialData.length + " data points. Swipe to navigate.",
|
|
320
|
+
getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
|
|
304
321
|
height: defaultChartHeight,
|
|
305
322
|
series: [{
|
|
306
323
|
id: 'growthLinear',
|
|
@@ -801,11 +801,17 @@ const CandlesticksChart = /*#__PURE__*/memo(_ref8 => {
|
|
|
801
801
|
day: 'numeric'
|
|
802
802
|
});
|
|
803
803
|
}, []);
|
|
804
|
+
const getScrubberAccessibilityLabel = useCallback(index => {
|
|
805
|
+
const candle = candlestickStockData[index];
|
|
806
|
+
return formatTime(index) + ": O " + formatThousandsPriceNumber(parseFloat(candle.open)) + " H " + formatThousandsPriceNumber(parseFloat(candle.high)) + " L " + formatThousandsPriceNumber(parseFloat(candle.low)) + " C " + formatThousandsPriceNumber(parseFloat(candle.close));
|
|
807
|
+
}, [formatTime, formatThousandsPriceNumber]);
|
|
804
808
|
return /*#__PURE__*/_jsxs(CartesianChart, {
|
|
805
809
|
enableScrubbing: true,
|
|
810
|
+
accessibilityLabel: "Candlestick chart with " + candlesData.length + " data points. Swipe to navigate.",
|
|
806
811
|
animate: false,
|
|
807
812
|
"aria-labelledby": infoTextId,
|
|
808
813
|
borderRadius: 0,
|
|
814
|
+
getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
|
|
809
815
|
height: 150,
|
|
810
816
|
inset: {
|
|
811
817
|
top: 8,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const _excluded = ["series", "showArea", "areaType", "type", "LineComponent", "AreaComponent", "curve", "points", "strokeWidth", "strokeOpacity", "connectNulls", "transition", "transitions", "opacity", "showXAxis", "showYAxis", "xAxis", "yAxis", "inset", "children"],
|
|
1
|
+
const _excluded = ["series", "showArea", "areaType", "type", "LineComponent", "AreaComponent", "curve", "points", "strokeWidth", "strokeOpacity", "connectNulls", "transition", "transitions", "opacity", "showXAxis", "showYAxis", "xAxis", "yAxis", "inset", "scrubberAccessibilityLabelStep", "layout", "children"],
|
|
2
2
|
_excluded2 = ["scaleType", "data", "categoryPadding", "domain", "domainLimit", "range", "id"],
|
|
3
3
|
_excluded3 = ["scaleType", "data", "categoryPadding", "domain", "domainLimit", "range", "id"],
|
|
4
4
|
_excluded4 = ["id", "data", "label", "color", "xAxisId", "yAxisId"];
|
|
@@ -10,6 +10,13 @@ import { YAxis } from '../axis/YAxis';
|
|
|
10
10
|
import { CartesianChart } from '../CartesianChart';
|
|
11
11
|
import { Line } from './Line';
|
|
12
12
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
|
+
const getDefaultScrubberAccessibilityStep = function (dataLength, sampleCount) {
|
|
14
|
+
if (sampleCount === void 0) {
|
|
15
|
+
sampleCount = 10;
|
|
16
|
+
}
|
|
17
|
+
if (dataLength <= 0) return 1;
|
|
18
|
+
return Math.max(1, Math.ceil(dataLength / sampleCount));
|
|
19
|
+
};
|
|
13
20
|
export const LineChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, ref) => {
|
|
14
21
|
let {
|
|
15
22
|
series,
|
|
@@ -31,6 +38,8 @@ export const LineChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, ref) =
|
|
|
31
38
|
xAxis,
|
|
32
39
|
yAxis,
|
|
33
40
|
inset,
|
|
41
|
+
scrubberAccessibilityLabelStep,
|
|
42
|
+
layout = 'vertical',
|
|
34
43
|
children
|
|
35
44
|
} = _ref,
|
|
36
45
|
chartProps = _objectWithoutPropertiesLoose(_ref, _excluded);
|
|
@@ -88,9 +97,21 @@ export const LineChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, ref) =
|
|
|
88
97
|
domainLimit: yDomainLimit,
|
|
89
98
|
range: yRange
|
|
90
99
|
};
|
|
100
|
+
const categoryAxisData = layout === 'horizontal' ? yData : xData;
|
|
101
|
+
const lineChartDataLength = useMemo(() => {
|
|
102
|
+
if (categoryAxisData && categoryAxisData.length > 0) return categoryAxisData.length;
|
|
103
|
+
if (!series || series.length === 0) return 0;
|
|
104
|
+
return series.reduce((max, s) => {
|
|
105
|
+
var _s$data$length, _s$data;
|
|
106
|
+
return Math.max(max, (_s$data$length = (_s$data = s.data) == null ? void 0 : _s$data.length) != null ? _s$data$length : 0);
|
|
107
|
+
}, 0);
|
|
108
|
+
}, [categoryAxisData, series]);
|
|
109
|
+
const resolvedScrubberAccessibilityLabelStep = useMemo(() => scrubberAccessibilityLabelStep != null ? scrubberAccessibilityLabelStep : getDefaultScrubberAccessibilityStep(lineChartDataLength), [scrubberAccessibilityLabelStep, lineChartDataLength]);
|
|
91
110
|
return /*#__PURE__*/_jsxs(CartesianChart, _extends({}, chartProps, {
|
|
92
111
|
ref: ref,
|
|
93
112
|
inset: inset,
|
|
113
|
+
layout: layout,
|
|
114
|
+
scrubberAccessibilityLabelStep: resolvedScrubberAccessibilityLabelStep,
|
|
94
115
|
series: chartSeries,
|
|
95
116
|
xAxis: xAxisConfig,
|
|
96
117
|
yAxis: yAxisConfig,
|
|
@@ -34,31 +34,24 @@ import { DottedLine, Line, LineChart, ReferenceLine, SolidLine } from '..';
|
|
|
34
34
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
35
35
|
function MultipleLine() {
|
|
36
36
|
const theme = useTheme();
|
|
37
|
-
const [scrubberPosition, setScrubberPosition] = useState();
|
|
38
37
|
const pages = useMemo(() => ['Page A', 'Page B', 'Page C', 'Page D', 'Page E', 'Page F', 'Page G'], []);
|
|
39
38
|
const pageViews = useMemo(() => [2400, 1398, 9800, 3908, 4800, 3800, 4300], []);
|
|
40
39
|
const uniqueVisitors = useMemo(() => [4000, 3000, 2000, 2780, 1890, 2390, 3490], []);
|
|
41
40
|
const chartAccessibilityLabel = "Website visitors across " + pageViews.length + " pages.";
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
}, [pages, pageViews, uniqueVisitors]);
|
|
41
|
+
const chartAccessibilityHint = 'Swipe left or right to hear details for each page.';
|
|
42
|
+
const getScrubberAccessibilityLabel = useCallback(index => pages[index] + " has " + pageViews[index] + " views and " + uniqueVisitors[index] + " unique visitors.", [pages, pageViews, uniqueVisitors]);
|
|
45
43
|
const numberFormatter = useCallback(value => new Intl.NumberFormat('en-US', {
|
|
46
44
|
maximumFractionDigits: 0
|
|
47
45
|
}).format(value), []);
|
|
48
|
-
const accessibilityLabel = useMemo(() => {
|
|
49
|
-
if (scrubberPosition !== undefined) {
|
|
50
|
-
return scrubberAccessibilityLabel(scrubberPosition);
|
|
51
|
-
}
|
|
52
|
-
return chartAccessibilityLabel;
|
|
53
|
-
}, [scrubberPosition, chartAccessibilityLabel, scrubberAccessibilityLabel]);
|
|
54
46
|
return /*#__PURE__*/_jsx(LineChart, {
|
|
55
47
|
enableScrubbing: true,
|
|
56
48
|
showArea: true,
|
|
57
49
|
showXAxis: true,
|
|
58
50
|
showYAxis: true,
|
|
59
|
-
|
|
51
|
+
accessibilityHint: chartAccessibilityHint,
|
|
52
|
+
accessibilityLabel: chartAccessibilityLabel + " " + chartAccessibilityHint,
|
|
53
|
+
getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
|
|
60
54
|
height: 200,
|
|
61
|
-
onScrubberPositionChange: setScrubberPosition,
|
|
62
55
|
series: [{
|
|
63
56
|
id: 'pageViews',
|
|
64
57
|
data: pageViews,
|
|
@@ -85,27 +78,19 @@ function MultipleLine() {
|
|
|
85
78
|
});
|
|
86
79
|
}
|
|
87
80
|
function DataFormat() {
|
|
88
|
-
const [scrubberPosition, setScrubberPosition] = useState();
|
|
89
81
|
const yData = useMemo(() => [2, 5.5, 2, 8.5, 1.5, 5], []);
|
|
90
82
|
const xData = useMemo(() => [1, 2, 3, 5, 8, 10], []);
|
|
91
83
|
const chartAccessibilityLabel = "Chart with custom X and Y data. " + yData.length + " data points";
|
|
92
|
-
const
|
|
93
|
-
return "Point " + (index + 1) + ": X value " + xData[index] + ", Y value " + yData[index];
|
|
94
|
-
}, [xData, yData]);
|
|
95
|
-
const accessibilityLabel = useMemo(() => {
|
|
96
|
-
if (scrubberPosition !== undefined) {
|
|
97
|
-
return scrubberAccessibilityLabel(scrubberPosition);
|
|
98
|
-
}
|
|
99
|
-
return chartAccessibilityLabel;
|
|
100
|
-
}, [scrubberPosition, chartAccessibilityLabel, scrubberAccessibilityLabel]);
|
|
84
|
+
const getScrubberAccessibilityLabel = useCallback(index => "Point " + (index + 1) + ": X value " + xData[index] + ", Y value " + yData[index], [xData, yData]);
|
|
101
85
|
return /*#__PURE__*/_jsx(LineChart, {
|
|
102
86
|
enableScrubbing: true,
|
|
103
87
|
points: true,
|
|
104
88
|
showArea: true,
|
|
105
89
|
showXAxis: true,
|
|
106
90
|
showYAxis: true,
|
|
107
|
-
accessibilityLabel:
|
|
91
|
+
accessibilityLabel: chartAccessibilityLabel,
|
|
108
92
|
curve: "natural",
|
|
93
|
+
getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
|
|
109
94
|
height: 200,
|
|
110
95
|
inset: {
|
|
111
96
|
top: 16,
|
|
@@ -113,7 +98,6 @@ function DataFormat() {
|
|
|
113
98
|
bottom: 0,
|
|
114
99
|
left: 0
|
|
115
100
|
},
|
|
116
|
-
onScrubberPositionChange: setScrubberPosition,
|
|
117
101
|
series: [{
|
|
118
102
|
id: 'line',
|
|
119
103
|
data: yData
|
|
@@ -144,6 +128,8 @@ function LiveUpdates() {
|
|
|
144
128
|
return sparklineInteractiveData.hour.map(d => d.value);
|
|
145
129
|
}, []);
|
|
146
130
|
const [priceData, setPriceData] = useState(initialData);
|
|
131
|
+
const chartAccessibilityLabel = "Live price chart with " + priceData.length + " data points.";
|
|
132
|
+
const getScrubberAccessibilityLabel = useCallback(index => "Point " + (index + 1) + ": " + priceData[index], [priceData]);
|
|
147
133
|
const lastDataPointTimeRef = useRef(Date.now());
|
|
148
134
|
const updateCountRef = useRef(0);
|
|
149
135
|
const intervalSeconds = 3600 / initialData.length;
|
|
@@ -182,6 +168,8 @@ function LiveUpdates() {
|
|
|
182
168
|
return /*#__PURE__*/_jsx(LineChart, {
|
|
183
169
|
enableScrubbing: true,
|
|
184
170
|
showArea: true,
|
|
171
|
+
accessibilityLabel: chartAccessibilityLabel,
|
|
172
|
+
getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
|
|
185
173
|
height: 200,
|
|
186
174
|
inset: {
|
|
187
175
|
right: 64
|
|
@@ -198,9 +186,17 @@ function LiveUpdates() {
|
|
|
198
186
|
}
|
|
199
187
|
function MissingData() {
|
|
200
188
|
const theme = useTheme();
|
|
201
|
-
const pages = ['Page A', 'Page B', 'Page C', 'Page D', 'Page E', 'Page F', 'Page G'];
|
|
202
|
-
const pageViews = [2400, 1398, null, 3908, 4800, 3800, 4300];
|
|
203
|
-
const uniqueVisitors = [4000, 3000, null, 2780, 1890, 2390, 3490];
|
|
189
|
+
const pages = useMemo(() => ['Page A', 'Page B', 'Page C', 'Page D', 'Page E', 'Page F', 'Page G'], []);
|
|
190
|
+
const pageViews = useMemo(() => [2400, 1398, null, 3908, 4800, 3800, 4300], []);
|
|
191
|
+
const uniqueVisitors = useMemo(() => [4000, 3000, null, 2780, 1890, 2390, 3490], []);
|
|
192
|
+
const chartAccessibilityLabel = "Website visitors across " + pages.length + " pages. Some data points are missing.";
|
|
193
|
+
const getScrubberAccessibilityLabel = useCallback(index => {
|
|
194
|
+
const pv = pageViews[index];
|
|
195
|
+
const uv = uniqueVisitors[index];
|
|
196
|
+
const pvStr = pv != null ? pv : 'no data';
|
|
197
|
+
const uvStr = uv != null ? uv : 'no data';
|
|
198
|
+
return pages[index] + ": " + pvStr + " views, " + uvStr + " unique visitors.";
|
|
199
|
+
}, [pages, pageViews, uniqueVisitors]);
|
|
204
200
|
const numberFormatter = useCallback(value => new Intl.NumberFormat('en-US', {
|
|
205
201
|
maximumFractionDigits: 0
|
|
206
202
|
}).format(value), []);
|
|
@@ -210,6 +206,8 @@ function MissingData() {
|
|
|
210
206
|
showArea: true,
|
|
211
207
|
showXAxis: true,
|
|
212
208
|
showYAxis: true,
|
|
209
|
+
accessibilityLabel: chartAccessibilityLabel,
|
|
210
|
+
getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
|
|
213
211
|
height: 200,
|
|
214
212
|
series: [{
|
|
215
213
|
id: 'pageViews',
|
|
@@ -239,6 +237,9 @@ function MissingData() {
|
|
|
239
237
|
}
|
|
240
238
|
function Interaction() {
|
|
241
239
|
const [scrubberPosition, setScrubberPosition] = useState();
|
|
240
|
+
const data = useMemo(() => [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58], []);
|
|
241
|
+
const chartAccessibilityLabel = "Price chart with " + data.length + " data points. Swipe to navigate.";
|
|
242
|
+
const getScrubberAccessibilityLabel = useCallback(index => "Point " + (index + 1) + ": " + data[index], [data]);
|
|
242
243
|
return /*#__PURE__*/_jsxs(VStack, {
|
|
243
244
|
gap: 2,
|
|
244
245
|
children: [/*#__PURE__*/_jsx(Text, {
|
|
@@ -247,11 +248,13 @@ function Interaction() {
|
|
|
247
248
|
}), /*#__PURE__*/_jsx(LineChart, {
|
|
248
249
|
enableScrubbing: true,
|
|
249
250
|
showArea: true,
|
|
251
|
+
accessibilityLabel: chartAccessibilityLabel,
|
|
252
|
+
getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
|
|
250
253
|
height: 200,
|
|
251
254
|
onScrubberPositionChange: setScrubberPosition,
|
|
252
255
|
series: [{
|
|
253
256
|
id: 'prices',
|
|
254
|
-
data
|
|
257
|
+
data
|
|
255
258
|
}],
|
|
256
259
|
children: /*#__PURE__*/_jsx(Scrubber, {})
|
|
257
260
|
})]
|
|
@@ -391,8 +394,12 @@ function Transitions() {
|
|
|
391
394
|
color: positiveColor
|
|
392
395
|
}]
|
|
393
396
|
};
|
|
397
|
+
const chartAccessibilityLabel = "Price chart with " + data.length + " data points. Swipe to navigate.";
|
|
398
|
+
const getScrubberAccessibilityLabel = useCallback(index => "Point " + (index + 1) + ": " + valueAtIndexFormatter(index), [valueAtIndexFormatter]);
|
|
394
399
|
return /*#__PURE__*/_jsxs(CartesianChart, {
|
|
395
400
|
enableScrubbing: true,
|
|
401
|
+
accessibilityLabel: chartAccessibilityLabel,
|
|
402
|
+
getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
|
|
396
403
|
height: 200,
|
|
397
404
|
inset: {
|
|
398
405
|
top: 32,
|
|
@@ -433,7 +440,6 @@ function Transitions() {
|
|
|
433
440
|
return /*#__PURE__*/_jsx(CustomTransitionsChart, {});
|
|
434
441
|
}
|
|
435
442
|
function BasicAccessible() {
|
|
436
|
-
const [scrubberPosition, setScrubberPosition] = useState();
|
|
437
443
|
const data = useMemo(() => [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58], []);
|
|
438
444
|
|
|
439
445
|
// Chart-level accessibility label provides overview
|
|
@@ -441,24 +447,14 @@ function BasicAccessible() {
|
|
|
441
447
|
const currentPrice = data[data.length - 1];
|
|
442
448
|
return "Price chart showing trend over " + data.length + " data points. Current value: " + currentPrice + ". Use arrow keys to adjust view";
|
|
443
449
|
}, [data]);
|
|
444
|
-
|
|
445
|
-
// Scrubber-level accessibility label provides specific position info
|
|
446
|
-
const scrubberAccessibilityLabel = useCallback(index => {
|
|
447
|
-
return "Price at position " + (index + 1) + " of " + data.length + ": " + data[index];
|
|
448
|
-
}, [data]);
|
|
449
|
-
const accessibilityLabel = useMemo(() => {
|
|
450
|
-
if (scrubberPosition !== undefined) {
|
|
451
|
-
return scrubberAccessibilityLabel(scrubberPosition);
|
|
452
|
-
}
|
|
453
|
-
return chartAccessibilityLabel;
|
|
454
|
-
}, [scrubberPosition, chartAccessibilityLabel, scrubberAccessibilityLabel]);
|
|
450
|
+
const getScrubberAccessibilityLabel = useCallback(index => "Price at position " + (index + 1) + " of " + data.length + ": " + data[index], [data]);
|
|
455
451
|
return /*#__PURE__*/_jsx(LineChart, {
|
|
456
452
|
enableScrubbing: true,
|
|
457
453
|
showArea: true,
|
|
458
454
|
showYAxis: true,
|
|
459
|
-
accessibilityLabel:
|
|
455
|
+
accessibilityLabel: chartAccessibilityLabel,
|
|
456
|
+
getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
|
|
460
457
|
height: 200,
|
|
461
|
-
onScrubberPositionChange: setScrubberPosition,
|
|
462
458
|
series: [{
|
|
463
459
|
id: 'prices',
|
|
464
460
|
data: data
|
|
@@ -618,8 +614,12 @@ function GainLossChart() {
|
|
|
618
614
|
}
|
|
619
615
|
}
|
|
620
616
|
})));
|
|
617
|
+
const chartAccessibilityLabel = "Price chart with " + data.length + " data points. Swipe to navigate.";
|
|
618
|
+
const getScrubberAccessibilityLabel = useCallback(index => "Point " + (index + 1) + ": " + tickLabelFormatter(data[index]), [data, tickLabelFormatter]);
|
|
621
619
|
return /*#__PURE__*/_jsxs(CartesianChart, {
|
|
622
620
|
enableScrubbing: true,
|
|
621
|
+
accessibilityLabel: chartAccessibilityLabel,
|
|
622
|
+
getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
|
|
623
623
|
height: 200,
|
|
624
624
|
series: [{
|
|
625
625
|
id: 'prices',
|
|
@@ -674,9 +674,11 @@ function HighLowPrice() {
|
|
|
674
674
|
}
|
|
675
675
|
function StylingScrubber() {
|
|
676
676
|
const theme = useTheme();
|
|
677
|
-
const pages = ['Page A', 'Page B', 'Page C', 'Page D', 'Page E', 'Page F', 'Page G'];
|
|
678
|
-
const pageViews = [2400, 1398, 9800, 3908, 4800, 3800, 4300];
|
|
679
|
-
const uniqueVisitors = [4000, 3000, 2000, 2780, 1890, 2390, 3490];
|
|
677
|
+
const pages = useMemo(() => ['Page A', 'Page B', 'Page C', 'Page D', 'Page E', 'Page F', 'Page G'], []);
|
|
678
|
+
const pageViews = useMemo(() => [2400, 1398, 9800, 3908, 4800, 3800, 4300], []);
|
|
679
|
+
const uniqueVisitors = useMemo(() => [4000, 3000, 2000, 2780, 1890, 2390, 3490], []);
|
|
680
|
+
const chartAccessibilityLabel = "Website visitors across " + pageViews.length + " pages.";
|
|
681
|
+
const getScrubberAccessibilityLabel = useCallback(index => pages[index] + ": " + pageViews[index] + " views, " + uniqueVisitors[index] + " unique visitors.", [pages, pageViews, uniqueVisitors]);
|
|
680
682
|
const numberFormatter = useCallback(value => new Intl.NumberFormat('en-US', {
|
|
681
683
|
maximumFractionDigits: 0
|
|
682
684
|
}).format(value), []);
|
|
@@ -685,6 +687,8 @@ function StylingScrubber() {
|
|
|
685
687
|
showArea: true,
|
|
686
688
|
showXAxis: true,
|
|
687
689
|
showYAxis: true,
|
|
690
|
+
accessibilityLabel: chartAccessibilityLabel,
|
|
691
|
+
getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
|
|
688
692
|
height: 200,
|
|
689
693
|
series: [{
|
|
690
694
|
id: 'pageViews',
|
|
@@ -905,6 +909,12 @@ function AssetPriceWithDottedArea() {
|
|
|
905
909
|
});
|
|
906
910
|
return dayOfWeek + ", " + monthDay + ", " + time;
|
|
907
911
|
}, []);
|
|
912
|
+
const chartAccessibilityLabel = "Bitcoin price chart for " + timePeriod.label + " period. Current price: " + formatPrice(currentPrice) + ".";
|
|
913
|
+
const getScrubberAccessibilityLabel = useCallback(index => {
|
|
914
|
+
const price = formatPrice(sparklineTimePeriodDataValues[index]);
|
|
915
|
+
const date = formatDate(sparklineTimePeriodDataTimestamps[index]);
|
|
916
|
+
return price + " " + date;
|
|
917
|
+
}, [formatDate, formatPrice, sparklineTimePeriodDataTimestamps, sparklineTimePeriodDataValues]);
|
|
908
918
|
return /*#__PURE__*/_jsxs(VStack, {
|
|
909
919
|
gap: 2,
|
|
910
920
|
children: [/*#__PURE__*/_jsx(SectionHeader, {
|
|
@@ -927,7 +937,9 @@ function AssetPriceWithDottedArea() {
|
|
|
927
937
|
}), /*#__PURE__*/_jsx(LineChart, {
|
|
928
938
|
enableScrubbing: true,
|
|
929
939
|
showArea: true,
|
|
940
|
+
accessibilityLabel: chartAccessibilityLabel,
|
|
930
941
|
areaType: "dotted",
|
|
942
|
+
getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
|
|
931
943
|
height: 200,
|
|
932
944
|
inset: {
|
|
933
945
|
top: 52
|
|
@@ -1089,11 +1101,19 @@ const PerformanceChart = /*#__PURE__*/memo(_ref10 => {
|
|
|
1089
1101
|
return dayOfWeek + ", " + monthDay + ", " + time;
|
|
1090
1102
|
}, []);
|
|
1091
1103
|
const getScrubberLabel = useCallback(d => formatDate(sparklineTimePeriodDataTimestamps[d]), [formatDate, sparklineTimePeriodDataTimestamps]);
|
|
1104
|
+
const chartAccessibilityLabel = "Bitcoin price chart with high, actual, and low series. " + sparklineTimePeriodDataValues.length + " data points. Swipe to navigate.";
|
|
1105
|
+
const getScrubberAccessibilityLabel = useCallback(index => {
|
|
1106
|
+
const price = formatPriceThousands(sparklineTimePeriodDataValues[index]);
|
|
1107
|
+
const date = formatDate(sparklineTimePeriodDataTimestamps[index]);
|
|
1108
|
+
return "Point " + (index + 1) + ": " + price + ", " + date;
|
|
1109
|
+
}, [formatDate, formatPriceThousands, sparklineTimePeriodDataTimestamps, sparklineTimePeriodDataValues]);
|
|
1092
1110
|
return /*#__PURE__*/_jsx(LineChart, {
|
|
1093
1111
|
enableScrubbing: true,
|
|
1094
1112
|
showArea: true,
|
|
1095
1113
|
showYAxis: true,
|
|
1114
|
+
accessibilityLabel: chartAccessibilityLabel,
|
|
1096
1115
|
areaType: "dotted",
|
|
1116
|
+
getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
|
|
1097
1117
|
height: 300,
|
|
1098
1118
|
inset: {
|
|
1099
1119
|
top: 52,
|
|
@@ -1250,6 +1270,12 @@ function MonotoneAssetPrice() {
|
|
|
1250
1270
|
dy: -12,
|
|
1251
1271
|
horizontalAlignment: "left"
|
|
1252
1272
|
})), []);
|
|
1273
|
+
const chartAccessibilityLabel = "Price chart with " + prices.length + " data points. Swipe to navigate.";
|
|
1274
|
+
const getScrubberAccessibilityLabel = useCallback(index => {
|
|
1275
|
+
const price = scrubberPriceFormatter.format(prices[index].value);
|
|
1276
|
+
const date = formatDate(prices[index].date);
|
|
1277
|
+
return price + " USD " + date;
|
|
1278
|
+
}, [formatDate, prices, scrubberPriceFormatter]);
|
|
1253
1279
|
const CustomScrubberBeacon = /*#__PURE__*/memo(_ref11 => {
|
|
1254
1280
|
let {
|
|
1255
1281
|
dataX,
|
|
@@ -1323,6 +1349,8 @@ function MonotoneAssetPrice() {
|
|
|
1323
1349
|
return /*#__PURE__*/_jsx(LineChart, {
|
|
1324
1350
|
enableScrubbing: true,
|
|
1325
1351
|
showYAxis: true,
|
|
1352
|
+
accessibilityLabel: chartAccessibilityLabel,
|
|
1353
|
+
getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
|
|
1326
1354
|
height: 200,
|
|
1327
1355
|
inset: {
|
|
1328
1356
|
top: 64
|
|
@@ -1397,8 +1425,12 @@ function ServiceAvailability() {
|
|
|
1397
1425
|
date: new Date('2022-01-10'),
|
|
1398
1426
|
availability: 86
|
|
1399
1427
|
}], []);
|
|
1428
|
+
const chartAccessibilityLabel = "Service availability chart with " + availabilityEvents.length + " data points. Swipe to navigate.";
|
|
1429
|
+
const getScrubberAccessibilityLabel = useCallback(index => "Point " + (index + 1) + ": " + availabilityEvents[index].availability + "% availability on " + availabilityEvents[index].date.toLocaleDateString(), [availabilityEvents]);
|
|
1400
1430
|
return /*#__PURE__*/_jsxs(CartesianChart, {
|
|
1401
1431
|
enableScrubbing: true,
|
|
1432
|
+
accessibilityLabel: chartAccessibilityLabel,
|
|
1433
|
+
getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
|
|
1402
1434
|
height: 200,
|
|
1403
1435
|
series: [{
|
|
1404
1436
|
id: 'availability',
|
|
@@ -1471,7 +1503,7 @@ function ServiceAvailability() {
|
|
|
1471
1503
|
}
|
|
1472
1504
|
function ForecastAssetPrice() {
|
|
1473
1505
|
const startYear = 2020;
|
|
1474
|
-
const data = [50, 45, 47, 46, 54, 54, 60, 61, 63, 66, 70];
|
|
1506
|
+
const data = useMemo(() => [50, 45, 47, 46, 54, 54, 60, 61, 63, 66, 70], []);
|
|
1475
1507
|
const currentIndex = 6;
|
|
1476
1508
|
const strokeWidth = 3;
|
|
1477
1509
|
// To prevent cutting off the edge of our lines
|
|
@@ -1575,8 +1607,12 @@ function ForecastAssetPrice() {
|
|
|
1575
1607
|
})]
|
|
1576
1608
|
});
|
|
1577
1609
|
});
|
|
1610
|
+
const chartAccessibilityLabel = "Forecast chart with " + data.length + " data points. Swipe to navigate.";
|
|
1611
|
+
const getScrubberAccessibilityLabel = useCallback(index => "Point " + (index + 1) + ": " + axisFormatter(index) + ", value " + data[index], [axisFormatter, data]);
|
|
1578
1612
|
return /*#__PURE__*/_jsxs(CartesianChart, {
|
|
1579
1613
|
enableScrubbing: true,
|
|
1614
|
+
accessibilityLabel: chartAccessibilityLabel,
|
|
1615
|
+
getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
|
|
1580
1616
|
height: 200,
|
|
1581
1617
|
series: [{
|
|
1582
1618
|
id: 'price',
|
|
@@ -1875,6 +1911,8 @@ function ExampleNavigator() {
|
|
|
1875
1911
|
component: /*#__PURE__*/_jsxs(LineChart, {
|
|
1876
1912
|
enableScrubbing: true,
|
|
1877
1913
|
showArea: true,
|
|
1914
|
+
accessibilityLabel: "Price chart with reference line. 14 data points. Swipe to navigate.",
|
|
1915
|
+
getScrubberAccessibilityLabel: index => "Point " + (index + 1),
|
|
1878
1916
|
height: 200,
|
|
1879
1917
|
series: [{
|
|
1880
1918
|
id: 'prices',
|