@coinbase/cds-mobile-visualization 3.4.0-beta.9 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. package/CHANGELOG.md +132 -0
  2. package/dts/chart/CartesianChart.d.ts +92 -7
  3. package/dts/chart/CartesianChart.d.ts.map +1 -1
  4. package/dts/chart/ChartContextBridge.d.ts.map +1 -1
  5. package/dts/chart/ChartProvider.d.ts +3 -0
  6. package/dts/chart/ChartProvider.d.ts.map +1 -1
  7. package/dts/chart/Path.d.ts +36 -13
  8. package/dts/chart/Path.d.ts.map +1 -1
  9. package/dts/chart/PeriodSelector.d.ts +20 -5
  10. package/dts/chart/PeriodSelector.d.ts.map +1 -1
  11. package/dts/chart/area/Area.d.ts +14 -11
  12. package/dts/chart/area/Area.d.ts.map +1 -1
  13. package/dts/chart/area/AreaChart.d.ts +33 -9
  14. package/dts/chart/area/AreaChart.d.ts.map +1 -1
  15. package/dts/chart/area/DottedArea.d.ts.map +1 -1
  16. package/dts/chart/area/GradientArea.d.ts.map +1 -1
  17. package/dts/chart/area/SolidArea.d.ts.map +1 -1
  18. package/dts/chart/axis/Axis.d.ts +22 -42
  19. package/dts/chart/axis/Axis.d.ts.map +1 -1
  20. package/dts/chart/axis/XAxis.d.ts +6 -0
  21. package/dts/chart/axis/XAxis.d.ts.map +1 -1
  22. package/dts/chart/axis/YAxis.d.ts +1 -0
  23. package/dts/chart/axis/YAxis.d.ts.map +1 -1
  24. package/dts/chart/bar/Bar.d.ts +51 -51
  25. package/dts/chart/bar/Bar.d.ts.map +1 -1
  26. package/dts/chart/bar/BarChart.d.ts +56 -11
  27. package/dts/chart/bar/BarChart.d.ts.map +1 -1
  28. package/dts/chart/bar/BarPlot.d.ts +2 -1
  29. package/dts/chart/bar/BarPlot.d.ts.map +1 -1
  30. package/dts/chart/bar/BarStack.d.ts +45 -20
  31. package/dts/chart/bar/BarStack.d.ts.map +1 -1
  32. package/dts/chart/bar/BarStackGroup.d.ts +2 -1
  33. package/dts/chart/bar/BarStackGroup.d.ts.map +1 -1
  34. package/dts/chart/bar/DefaultBar.d.ts.map +1 -1
  35. package/dts/chart/bar/DefaultBarStack.d.ts.map +1 -1
  36. package/dts/chart/gradient/Gradient.d.ts +5 -0
  37. package/dts/chart/gradient/Gradient.d.ts.map +1 -1
  38. package/dts/chart/index.d.ts +1 -0
  39. package/dts/chart/index.d.ts.map +1 -1
  40. package/dts/chart/legend/DefaultLegendEntry.d.ts +5 -0
  41. package/dts/chart/legend/DefaultLegendEntry.d.ts.map +1 -0
  42. package/dts/chart/legend/DefaultLegendShape.d.ts +5 -0
  43. package/dts/chart/legend/DefaultLegendShape.d.ts.map +1 -0
  44. package/dts/chart/legend/Legend.d.ts +168 -0
  45. package/dts/chart/legend/Legend.d.ts.map +1 -0
  46. package/dts/chart/legend/index.d.ts +4 -0
  47. package/dts/chart/legend/index.d.ts.map +1 -0
  48. package/dts/chart/line/DottedLine.d.ts.map +1 -1
  49. package/dts/chart/line/Line.d.ts +23 -19
  50. package/dts/chart/line/Line.d.ts.map +1 -1
  51. package/dts/chart/line/LineChart.d.ts +26 -9
  52. package/dts/chart/line/LineChart.d.ts.map +1 -1
  53. package/dts/chart/line/ReferenceLine.d.ts +1 -0
  54. package/dts/chart/line/ReferenceLine.d.ts.map +1 -1
  55. package/dts/chart/line/SolidLine.d.ts.map +1 -1
  56. package/dts/chart/point/Point.d.ts +26 -2
  57. package/dts/chart/point/Point.d.ts.map +1 -1
  58. package/dts/chart/scrubber/DefaultScrubberBeacon.d.ts +32 -2
  59. package/dts/chart/scrubber/DefaultScrubberBeacon.d.ts.map +1 -1
  60. package/dts/chart/scrubber/DefaultScrubberLabel.d.ts +2 -1
  61. package/dts/chart/scrubber/DefaultScrubberLabel.d.ts.map +1 -1
  62. package/dts/chart/scrubber/Scrubber.d.ts +86 -17
  63. package/dts/chart/scrubber/Scrubber.d.ts.map +1 -1
  64. package/dts/chart/scrubber/ScrubberAccessibilityView.d.ts +12 -0
  65. package/dts/chart/scrubber/ScrubberAccessibilityView.d.ts.map +1 -0
  66. package/dts/chart/scrubber/ScrubberBeaconGroup.d.ts +10 -0
  67. package/dts/chart/scrubber/ScrubberBeaconGroup.d.ts.map +1 -1
  68. package/dts/chart/scrubber/ScrubberBeaconLabelGroup.d.ts +16 -1
  69. package/dts/chart/scrubber/ScrubberBeaconLabelGroup.d.ts.map +1 -1
  70. package/dts/chart/scrubber/ScrubberProvider.d.ts.map +1 -1
  71. package/dts/chart/utils/axis.d.ts +45 -10
  72. package/dts/chart/utils/axis.d.ts.map +1 -1
  73. package/dts/chart/utils/bar.d.ts +190 -0
  74. package/dts/chart/utils/bar.d.ts.map +1 -1
  75. package/dts/chart/utils/chart.d.ts +32 -0
  76. package/dts/chart/utils/chart.d.ts.map +1 -1
  77. package/dts/chart/utils/context.d.ts +21 -6
  78. package/dts/chart/utils/context.d.ts.map +1 -1
  79. package/dts/chart/utils/gradient.d.ts +3 -1
  80. package/dts/chart/utils/gradient.d.ts.map +1 -1
  81. package/dts/chart/utils/path.d.ts +26 -0
  82. package/dts/chart/utils/path.d.ts.map +1 -1
  83. package/dts/chart/utils/point.d.ts +24 -12
  84. package/dts/chart/utils/point.d.ts.map +1 -1
  85. package/dts/chart/utils/scale.d.ts +11 -0
  86. package/dts/chart/utils/scale.d.ts.map +1 -1
  87. package/dts/chart/utils/scrubber.d.ts +2 -1
  88. package/dts/chart/utils/scrubber.d.ts.map +1 -1
  89. package/dts/chart/utils/transition.d.ts +63 -22
  90. package/dts/chart/utils/transition.d.ts.map +1 -1
  91. package/dts/sparkline/Sparkline.d.ts +2 -1
  92. package/dts/sparkline/Sparkline.d.ts.map +1 -1
  93. package/dts/sparkline/SparklineArea.d.ts +2 -1
  94. package/dts/sparkline/SparklineArea.d.ts.map +1 -1
  95. package/dts/sparkline/SparklineGradient.d.ts +2 -1
  96. package/dts/sparkline/SparklineGradient.d.ts.map +1 -1
  97. package/dts/sparkline/sparkline-interactive/SparklineInteractive.d.ts +2 -1
  98. package/dts/sparkline/sparkline-interactive/SparklineInteractive.d.ts.map +1 -1
  99. package/esm/chart/CartesianChart.js +176 -82
  100. package/esm/chart/ChartContextBridge.js +14 -3
  101. package/esm/chart/ChartProvider.js +2 -2
  102. package/esm/chart/Path.js +34 -29
  103. package/esm/chart/PeriodSelector.js +5 -1
  104. package/esm/chart/__stories__/CartesianChart.stories.js +16 -80
  105. package/esm/chart/__stories__/ChartAccessibility.stories.js +721 -0
  106. package/esm/chart/__stories__/ChartTransitions.stories.js +625 -0
  107. package/esm/chart/__stories__/PeriodSelector.stories.js +99 -1
  108. package/esm/chart/area/Area.js +21 -9
  109. package/esm/chart/area/AreaChart.js +18 -13
  110. package/esm/chart/area/DottedArea.js +28 -18
  111. package/esm/chart/area/GradientArea.js +14 -7
  112. package/esm/chart/area/SolidArea.js +6 -2
  113. package/esm/chart/area/__stories__/AreaChart.stories.js +47 -5
  114. package/esm/chart/axis/Axis.js +5 -41
  115. package/esm/chart/axis/XAxis.js +116 -47
  116. package/esm/chart/axis/YAxis.js +105 -26
  117. package/esm/chart/axis/__stories__/Axis.stories.js +324 -48
  118. package/esm/chart/bar/Bar.js +17 -15
  119. package/esm/chart/bar/BarChart.js +38 -33
  120. package/esm/chart/bar/BarPlot.js +40 -45
  121. package/esm/chart/bar/BarStack.js +92 -475
  122. package/esm/chart/bar/BarStackGroup.js +37 -27
  123. package/esm/chart/bar/DefaultBar.js +27 -18
  124. package/esm/chart/bar/DefaultBarStack.js +25 -9
  125. package/esm/chart/bar/__stories__/BarChart.stories.js +728 -54
  126. package/esm/chart/gradient/Gradient.js +2 -1
  127. package/esm/chart/index.js +1 -0
  128. package/esm/chart/legend/DefaultLegendEntry.js +42 -0
  129. package/esm/chart/legend/DefaultLegendShape.js +64 -0
  130. package/esm/chart/legend/Legend.js +59 -0
  131. package/esm/chart/legend/__stories__/Legend.stories.js +574 -0
  132. package/esm/chart/legend/index.js +3 -0
  133. package/esm/chart/line/DottedLine.js +6 -2
  134. package/esm/chart/line/Line.js +42 -38
  135. package/esm/chart/line/LineChart.js +36 -12
  136. package/esm/chart/line/SolidLine.js +6 -2
  137. package/esm/chart/line/__stories__/LineChart.stories.js +236 -590
  138. package/esm/chart/line/__stories__/ReferenceLine.stories.js +95 -1
  139. package/esm/chart/point/Point.js +35 -36
  140. package/esm/chart/scrubber/DefaultScrubberBeacon.js +41 -38
  141. package/esm/chart/scrubber/DefaultScrubberLabel.js +26 -10
  142. package/esm/chart/scrubber/Scrubber.js +67 -35
  143. package/esm/chart/scrubber/ScrubberAccessibilityView.js +177 -0
  144. package/esm/chart/scrubber/ScrubberBeaconGroup.js +30 -22
  145. package/esm/chart/scrubber/ScrubberBeaconLabelGroup.js +35 -8
  146. package/esm/chart/scrubber/ScrubberProvider.js +29 -24
  147. package/esm/chart/scrubber/__stories__/Scrubber.stories.js +946 -0
  148. package/esm/chart/utils/axis.js +88 -44
  149. package/esm/chart/utils/bar.js +820 -0
  150. package/esm/chart/utils/chart.js +34 -7
  151. package/esm/chart/utils/context.js +7 -0
  152. package/esm/chart/utils/gradient.js +8 -4
  153. package/esm/chart/utils/path.js +91 -61
  154. package/esm/chart/utils/point.js +92 -39
  155. package/esm/chart/utils/scale.js +13 -2
  156. package/esm/chart/utils/scrubber.js +12 -5
  157. package/esm/chart/utils/transition.js +108 -60
  158. package/esm/sparkline/Sparkline.js +2 -1
  159. package/esm/sparkline/SparklineArea.js +2 -1
  160. package/esm/sparkline/SparklineGradient.js +2 -1
  161. package/esm/sparkline/__figma__/Sparkline.figma.js +1 -1
  162. package/esm/sparkline/sparkline-interactive/SparklineInteractive.js +2 -1
  163. package/esm/sparkline/sparkline-interactive/__figma__/SparklineInteractive.figma.js +1 -1
  164. package/esm/sparkline/sparkline-interactive-header/__figma__/SparklineInteractiveHeader.figma.js +1 -1
  165. package/esm/sparkline/sparkline-interactive-header/__stories__/SparklineInteractiveHeader.stories.js +2 -0
  166. package/package.json +5 -6
  167. package/esm/chart/__stories__/Chart.stories.js +0 -77
@@ -1,19 +1,18 @@
1
1
  const _excluded = ["dataX", "dataY"],
2
2
  _excluded2 = ["label"],
3
- _excluded3 = ["style"],
4
- _excluded4 = ["x", "y", "width", "height", "originY", "dataX"],
5
- _excluded5 = ["seriesId", "color", "label"];
3
+ _excluded3 = ["style"];
6
4
  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); }
7
5
  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; }
8
- import { forwardRef, memo, useCallback, useEffect, useId, useMemo, useRef, useState } from 'react';
6
+ import { forwardRef, memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
9
7
  import { useAnimatedReaction, useDerivedValue, useSharedValue, withDelay, withTiming } from 'react-native-reanimated';
10
- import { assets } from '@coinbase/cds-common/internal/data/assets';
11
- import { candles as btcCandles } from '@coinbase/cds-common/internal/data/candles';
8
+ import { assets, ethBackground } from '@coinbase/cds-common/internal/data/assets';
12
9
  import { prices } from '@coinbase/cds-common/internal/data/prices';
13
10
  import { sparklineInteractiveData } from '@coinbase/cds-common/internal/visualizations/SparklineInteractiveData';
14
11
  import { useTabsContext } from '@coinbase/cds-common/tabs/TabsContext';
12
+ import { NoopFn } from '@coinbase/cds-common/utils/mockUtils';
15
13
  import { useTheme } from '@coinbase/cds-mobile';
16
- import { Button, IconButton } from '@coinbase/cds-mobile/buttons';
14
+ import { DataCard } from '@coinbase/cds-mobile/alpha/data-card/DataCard';
15
+ import { IconButton } from '@coinbase/cds-mobile/buttons';
17
16
  import { ListCell } from '@coinbase/cds-mobile/cells';
18
17
  import { ExampleScreen } from '@coinbase/cds-mobile/examples/ExampleScreen';
19
18
  import { Box, HStack, VStack } from '@coinbase/cds-mobile/layout';
@@ -22,45 +21,37 @@ import { SectionHeader } from '@coinbase/cds-mobile/section-header/SectionHeader
22
21
  import { Pressable } from '@coinbase/cds-mobile/system';
23
22
  import { SegmentedTab } from '@coinbase/cds-mobile/tabs/SegmentedTab';
24
23
  import { Text } from '@coinbase/cds-mobile/typography';
25
- import { Circle, FontWeight, Group, Line as SkiaLine, Rect, Skia, TextAlign } from '@shopify/react-native-skia';
24
+ import { Circle, FontWeight, Group, Skia, TextAlign } from '@shopify/react-native-skia';
26
25
  import { Area, DottedArea } from '../../area';
27
26
  import { DefaultAxisTickLabel, XAxis, YAxis } from '../../axis';
28
- import { BarPlot } from '../../bar';
29
27
  import { CartesianChart } from '../../CartesianChart';
30
28
  import { useCartesianChartContext } from '../../ChartProvider';
31
29
  import { PeriodSelector, PeriodSelectorActiveIndicator } from '../../PeriodSelector';
32
30
  import { Point } from '../../point';
33
- import { DefaultScrubberBeacon, DefaultScrubberBeaconLabel, DefaultScrubberLabel, Scrubber } from '../../scrubber';
34
- import { buildTransition, defaultTransition, getLineData, getPointOnSerializableScale, projectPointWithSerializableScale, unwrapAnimatedValue, useScrubberContext } from '../../utils';
31
+ import { DefaultScrubberBeacon, Scrubber } from '../../scrubber';
32
+ import { buildTransition, defaultTransition, projectPointWithSerializableScale, unwrapAnimatedValue, useScrubberContext } from '../../utils';
35
33
  import { DottedLine, Line, LineChart, ReferenceLine, SolidLine } from '..';
36
34
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
37
35
  function MultipleLine() {
38
36
  const theme = useTheme();
39
- const [scrubberPosition, setScrubberPosition] = useState();
40
37
  const pages = useMemo(() => ['Page A', 'Page B', 'Page C', 'Page D', 'Page E', 'Page F', 'Page G'], []);
41
38
  const pageViews = useMemo(() => [2400, 1398, 9800, 3908, 4800, 3800, 4300], []);
42
39
  const uniqueVisitors = useMemo(() => [4000, 3000, 2000, 2780, 1890, 2390, 3490], []);
43
40
  const chartAccessibilityLabel = "Website visitors across " + pageViews.length + " pages.";
44
- const scrubberAccessibilityLabel = useCallback(index => {
45
- return pages[index] + " has " + pageViews[index] + " views and " + uniqueVisitors[index] + " unique visitors.";
46
- }, [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]);
47
43
  const numberFormatter = useCallback(value => new Intl.NumberFormat('en-US', {
48
44
  maximumFractionDigits: 0
49
45
  }).format(value), []);
50
- const accessibilityLabel = useMemo(() => {
51
- if (scrubberPosition !== undefined) {
52
- return scrubberAccessibilityLabel(scrubberPosition);
53
- }
54
- return chartAccessibilityLabel;
55
- }, [scrubberPosition, chartAccessibilityLabel, scrubberAccessibilityLabel]);
56
46
  return /*#__PURE__*/_jsx(LineChart, {
57
47
  enableScrubbing: true,
58
48
  showArea: true,
59
49
  showXAxis: true,
60
50
  showYAxis: true,
61
- accessibilityLabel: accessibilityLabel,
51
+ accessibilityHint: chartAccessibilityHint,
52
+ accessibilityLabel: chartAccessibilityLabel + " " + chartAccessibilityHint,
53
+ getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
62
54
  height: 200,
63
- onScrubberPositionChange: setScrubberPosition,
64
55
  series: [{
65
56
  id: 'pageViews',
66
57
  data: pageViews,
@@ -87,27 +78,19 @@ function MultipleLine() {
87
78
  });
88
79
  }
89
80
  function DataFormat() {
90
- const [scrubberPosition, setScrubberPosition] = useState();
91
81
  const yData = useMemo(() => [2, 5.5, 2, 8.5, 1.5, 5], []);
92
82
  const xData = useMemo(() => [1, 2, 3, 5, 8, 10], []);
93
83
  const chartAccessibilityLabel = "Chart with custom X and Y data. " + yData.length + " data points";
94
- const scrubberAccessibilityLabel = useCallback(index => {
95
- return "Point " + (index + 1) + ": X value " + xData[index] + ", Y value " + yData[index];
96
- }, [xData, yData]);
97
- const accessibilityLabel = useMemo(() => {
98
- if (scrubberPosition !== undefined) {
99
- return scrubberAccessibilityLabel(scrubberPosition);
100
- }
101
- return chartAccessibilityLabel;
102
- }, [scrubberPosition, chartAccessibilityLabel, scrubberAccessibilityLabel]);
84
+ const getScrubberAccessibilityLabel = useCallback(index => "Point " + (index + 1) + ": X value " + xData[index] + ", Y value " + yData[index], [xData, yData]);
103
85
  return /*#__PURE__*/_jsx(LineChart, {
104
86
  enableScrubbing: true,
105
87
  points: true,
106
88
  showArea: true,
107
89
  showXAxis: true,
108
90
  showYAxis: true,
109
- accessibilityLabel: accessibilityLabel,
91
+ accessibilityLabel: chartAccessibilityLabel,
110
92
  curve: "natural",
93
+ getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
111
94
  height: 200,
112
95
  inset: {
113
96
  top: 16,
@@ -115,7 +98,6 @@ function DataFormat() {
115
98
  bottom: 0,
116
99
  left: 0
117
100
  },
118
- onScrubberPositionChange: setScrubberPosition,
119
101
  series: [{
120
102
  id: 'line',
121
103
  data: yData
@@ -146,6 +128,8 @@ function LiveUpdates() {
146
128
  return sparklineInteractiveData.hour.map(d => d.value);
147
129
  }, []);
148
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]);
149
133
  const lastDataPointTimeRef = useRef(Date.now());
150
134
  const updateCountRef = useRef(0);
151
135
  const intervalSeconds = 3600 / initialData.length;
@@ -184,6 +168,8 @@ function LiveUpdates() {
184
168
  return /*#__PURE__*/_jsx(LineChart, {
185
169
  enableScrubbing: true,
186
170
  showArea: true,
171
+ accessibilityLabel: chartAccessibilityLabel,
172
+ getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
187
173
  height: 200,
188
174
  inset: {
189
175
  right: 64
@@ -200,9 +186,17 @@ function LiveUpdates() {
200
186
  }
201
187
  function MissingData() {
202
188
  const theme = useTheme();
203
- const pages = ['Page A', 'Page B', 'Page C', 'Page D', 'Page E', 'Page F', 'Page G'];
204
- const pageViews = [2400, 1398, null, 3908, 4800, 3800, 4300];
205
- 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]);
206
200
  const numberFormatter = useCallback(value => new Intl.NumberFormat('en-US', {
207
201
  maximumFractionDigits: 0
208
202
  }).format(value), []);
@@ -212,6 +206,8 @@ function MissingData() {
212
206
  showArea: true,
213
207
  showXAxis: true,
214
208
  showYAxis: true,
209
+ accessibilityLabel: chartAccessibilityLabel,
210
+ getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
215
211
  height: 200,
216
212
  series: [{
217
213
  id: 'pageViews',
@@ -241,6 +237,9 @@ function MissingData() {
241
237
  }
242
238
  function Interaction() {
243
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]);
244
243
  return /*#__PURE__*/_jsxs(VStack, {
245
244
  gap: 2,
246
245
  children: [/*#__PURE__*/_jsx(Text, {
@@ -249,11 +248,13 @@ function Interaction() {
249
248
  }), /*#__PURE__*/_jsx(LineChart, {
250
249
  enableScrubbing: true,
251
250
  showArea: true,
251
+ accessibilityLabel: chartAccessibilityLabel,
252
+ getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
252
253
  height: 200,
253
254
  onScrubberPositionChange: setScrubberPosition,
254
255
  series: [{
255
256
  id: 'prices',
256
- data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58]
257
+ data
257
258
  }],
258
259
  children: /*#__PURE__*/_jsx(Scrubber, {})
259
260
  })]
@@ -393,8 +394,12 @@ function Transitions() {
393
394
  color: positiveColor
394
395
  }]
395
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]);
396
399
  return /*#__PURE__*/_jsxs(CartesianChart, {
397
400
  enableScrubbing: true,
401
+ accessibilityLabel: chartAccessibilityLabel,
402
+ getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
398
403
  height: 200,
399
404
  inset: {
400
405
  top: 32,
@@ -435,7 +440,6 @@ function Transitions() {
435
440
  return /*#__PURE__*/_jsx(CustomTransitionsChart, {});
436
441
  }
437
442
  function BasicAccessible() {
438
- const [scrubberPosition, setScrubberPosition] = useState();
439
443
  const data = useMemo(() => [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58], []);
440
444
 
441
445
  // Chart-level accessibility label provides overview
@@ -443,24 +447,14 @@ function BasicAccessible() {
443
447
  const currentPrice = data[data.length - 1];
444
448
  return "Price chart showing trend over " + data.length + " data points. Current value: " + currentPrice + ". Use arrow keys to adjust view";
445
449
  }, [data]);
446
-
447
- // Scrubber-level accessibility label provides specific position info
448
- const scrubberAccessibilityLabel = useCallback(index => {
449
- return "Price at position " + (index + 1) + " of " + data.length + ": " + data[index];
450
- }, [data]);
451
- const accessibilityLabel = useMemo(() => {
452
- if (scrubberPosition !== undefined) {
453
- return scrubberAccessibilityLabel(scrubberPosition);
454
- }
455
- return chartAccessibilityLabel;
456
- }, [scrubberPosition, chartAccessibilityLabel, scrubberAccessibilityLabel]);
450
+ const getScrubberAccessibilityLabel = useCallback(index => "Price at position " + (index + 1) + " of " + data.length + ": " + data[index], [data]);
457
451
  return /*#__PURE__*/_jsx(LineChart, {
458
452
  enableScrubbing: true,
459
453
  showArea: true,
460
454
  showYAxis: true,
461
- accessibilityLabel: accessibilityLabel,
455
+ accessibilityLabel: chartAccessibilityLabel,
456
+ getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
462
457
  height: 200,
463
- onScrubberPositionChange: setScrubberPosition,
464
458
  series: [{
465
459
  id: 'prices',
466
460
  data: data
@@ -620,8 +614,12 @@ function GainLossChart() {
620
614
  }
621
615
  }
622
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]);
623
619
  return /*#__PURE__*/_jsxs(CartesianChart, {
624
620
  enableScrubbing: true,
621
+ accessibilityLabel: chartAccessibilityLabel,
622
+ getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
625
623
  height: 200,
626
624
  series: [{
627
625
  id: 'prices',
@@ -676,9 +674,11 @@ function HighLowPrice() {
676
674
  }
677
675
  function StylingScrubber() {
678
676
  const theme = useTheme();
679
- const pages = ['Page A', 'Page B', 'Page C', 'Page D', 'Page E', 'Page F', 'Page G'];
680
- const pageViews = [2400, 1398, 9800, 3908, 4800, 3800, 4300];
681
- 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]);
682
682
  const numberFormatter = useCallback(value => new Intl.NumberFormat('en-US', {
683
683
  maximumFractionDigits: 0
684
684
  }).format(value), []);
@@ -687,6 +687,8 @@ function StylingScrubber() {
687
687
  showArea: true,
688
688
  showXAxis: true,
689
689
  showYAxis: true,
690
+ accessibilityLabel: chartAccessibilityLabel,
691
+ getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
690
692
  height: 200,
691
693
  series: [{
692
694
  id: 'pageViews',
@@ -768,6 +770,7 @@ function Compact() {
768
770
  subdetail
769
771
  } = _ref7;
770
772
  return /*#__PURE__*/_jsx(ListCell, {
773
+ accessibilityLabel: "Compact chart cell",
771
774
  detail: formatPrice(parseFloat(prices[0])),
772
775
  intermediary: /*#__PURE__*/_jsx(CompactChart, {
773
776
  color: color,
@@ -907,6 +910,12 @@ function AssetPriceWithDottedArea() {
907
910
  });
908
911
  return dayOfWeek + ", " + monthDay + ", " + time;
909
912
  }, []);
913
+ const chartAccessibilityLabel = "Bitcoin price chart for " + timePeriod.label + " period. Current price: " + formatPrice(currentPrice) + ".";
914
+ const getScrubberAccessibilityLabel = useCallback(index => {
915
+ const price = formatPrice(sparklineTimePeriodDataValues[index]);
916
+ const date = formatDate(sparklineTimePeriodDataTimestamps[index]);
917
+ return price + " " + date;
918
+ }, [formatDate, formatPrice, sparklineTimePeriodDataTimestamps, sparklineTimePeriodDataValues]);
910
919
  return /*#__PURE__*/_jsxs(VStack, {
911
920
  gap: 2,
912
921
  children: [/*#__PURE__*/_jsx(SectionHeader, {
@@ -929,7 +938,9 @@ function AssetPriceWithDottedArea() {
929
938
  }), /*#__PURE__*/_jsx(LineChart, {
930
939
  enableScrubbing: true,
931
940
  showArea: true,
941
+ accessibilityLabel: chartAccessibilityLabel,
932
942
  areaType: "dotted",
943
+ getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
933
944
  height: 200,
934
945
  inset: {
935
946
  top: 52
@@ -992,7 +1003,7 @@ const LegendDot = /*#__PURE__*/memo(props => {
992
1003
  width: 10
993
1004
  }, props));
994
1005
  });
995
- const LegendItem = /*#__PURE__*/memo(_ref0 => {
1006
+ const LegendEntry = /*#__PURE__*/memo(_ref0 => {
996
1007
  let {
997
1008
  color = assets.btc.color,
998
1009
  label,
@@ -1037,15 +1048,15 @@ const PerformanceHeader = /*#__PURE__*/memo(_ref1 => {
1037
1048
  return /*#__PURE__*/_jsxs(HStack, {
1038
1049
  gap: 1,
1039
1050
  paddingX: 1,
1040
- children: [/*#__PURE__*/_jsx(LegendItem, {
1051
+ children: [/*#__PURE__*/_jsx(LegendEntry, {
1041
1052
  color: theme.color.fgPositive,
1042
1053
  label: "High Price",
1043
1054
  value: formatPriceThousands(sparklineTimePeriodDataValues[shownPosition] * 1.2)
1044
- }), /*#__PURE__*/_jsx(LegendItem, {
1055
+ }), /*#__PURE__*/_jsx(LegendEntry, {
1045
1056
  color: assets.btc.color,
1046
1057
  label: "Actual Price",
1047
1058
  value: formatPriceThousands(sparklineTimePeriodDataValues[shownPosition])
1048
- }), /*#__PURE__*/_jsx(LegendItem, {
1059
+ }), /*#__PURE__*/_jsx(LegendEntry, {
1049
1060
  color: theme.color.fgNegative,
1050
1061
  label: "Low Price",
1051
1062
  value: formatPriceThousands(sparklineTimePeriodDataValues[shownPosition] * 0.8)
@@ -1091,11 +1102,19 @@ const PerformanceChart = /*#__PURE__*/memo(_ref10 => {
1091
1102
  return dayOfWeek + ", " + monthDay + ", " + time;
1092
1103
  }, []);
1093
1104
  const getScrubberLabel = useCallback(d => formatDate(sparklineTimePeriodDataTimestamps[d]), [formatDate, sparklineTimePeriodDataTimestamps]);
1105
+ const chartAccessibilityLabel = "Bitcoin price chart with high, actual, and low series. " + sparklineTimePeriodDataValues.length + " data points. Swipe to navigate.";
1106
+ const getScrubberAccessibilityLabel = useCallback(index => {
1107
+ const price = formatPriceThousands(sparklineTimePeriodDataValues[index]);
1108
+ const date = formatDate(sparklineTimePeriodDataTimestamps[index]);
1109
+ return "Point " + (index + 1) + ": " + price + ", " + date;
1110
+ }, [formatDate, formatPriceThousands, sparklineTimePeriodDataTimestamps, sparklineTimePeriodDataValues]);
1094
1111
  return /*#__PURE__*/_jsx(LineChart, {
1095
1112
  enableScrubbing: true,
1096
1113
  showArea: true,
1097
1114
  showYAxis: true,
1115
+ accessibilityLabel: chartAccessibilityLabel,
1098
1116
  areaType: "dotted",
1117
+ getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
1099
1118
  height: 300,
1100
1119
  inset: {
1101
1120
  top: 52,
@@ -1179,210 +1198,6 @@ function Performance() {
1179
1198
  })]
1180
1199
  });
1181
1200
  }
1182
- const candlestickStockData = btcCandles.slice(0, 90).reverse();
1183
- const CandlesticksHeader = /*#__PURE__*/memo(_ref11 => {
1184
- let {
1185
- currentIndex
1186
- } = _ref11;
1187
- const formatPrice = useCallback(price => {
1188
- return new Intl.NumberFormat('en-US', {
1189
- style: 'currency',
1190
- currency: 'USD'
1191
- }).format(parseFloat(price));
1192
- }, []);
1193
- const formatThousandsPriceNumber = useCallback(price => {
1194
- const formattedPrice = new Intl.NumberFormat('en-US', {
1195
- style: 'currency',
1196
- currency: 'USD',
1197
- minimumFractionDigits: 0,
1198
- maximumFractionDigits: 0
1199
- }).format(price / 1000);
1200
- return formattedPrice + "k";
1201
- }, []);
1202
- const currentText = useMemo(() => {
1203
- if (currentIndex !== undefined) {
1204
- return "Open: " + formatThousandsPriceNumber(parseFloat(candlestickStockData[currentIndex].open)) + ", Close: " + formatThousandsPriceNumber(parseFloat(candlestickStockData[currentIndex].close)) + ", Volume: " + (parseFloat(candlestickStockData[currentIndex].volume) / 1000).toFixed(2) + "k";
1205
- }
1206
- return formatPrice(candlestickStockData[candlestickStockData.length - 1].close);
1207
- }, [currentIndex, formatThousandsPriceNumber, formatPrice]);
1208
- return /*#__PURE__*/_jsx(Text, {
1209
- "aria-live": "polite",
1210
- font: "headline",
1211
- children: currentText
1212
- });
1213
- });
1214
- const CandlesticksChart = /*#__PURE__*/memo(_ref12 => {
1215
- let {
1216
- infoTextId,
1217
- onScrubberPositionChange
1218
- } = _ref12;
1219
- const theme = useTheme();
1220
- const min = useMemo(() => Math.min(...candlestickStockData.map(data => parseFloat(data.low))), []);
1221
- const ThinSolidLine = /*#__PURE__*/memo(props => /*#__PURE__*/_jsx(SolidLine, _extends({}, props, {
1222
- strokeWidth: 1
1223
- })));
1224
-
1225
- // Custom line component that renders a rect to highlight the entire bandwidth
1226
- const BandwidthHighlight = /*#__PURE__*/memo(_ref13 => {
1227
- let {
1228
- stroke
1229
- } = _ref13;
1230
- const {
1231
- getXSerializableScale,
1232
- drawingArea
1233
- } = useCartesianChartContext();
1234
- const {
1235
- scrubberPosition
1236
- } = useScrubberContext();
1237
- const xScale = useMemo(() => getXSerializableScale(), [getXSerializableScale]);
1238
- const rectWidth = useMemo(() => {
1239
- if (xScale !== undefined && xScale.type === 'band') {
1240
- return xScale.bandwidth;
1241
- }
1242
- return 0;
1243
- }, [xScale]);
1244
- const xPos = useDerivedValue(() => {
1245
- const position = unwrapAnimatedValue(scrubberPosition);
1246
- const xPos = position !== undefined && xScale ? getPointOnSerializableScale(position, xScale) : undefined;
1247
- return xPos !== undefined ? xPos - rectWidth / 2 : 0;
1248
- }, [scrubberPosition, xScale]);
1249
- const opacity = useDerivedValue(() => xPos.value !== undefined ? 1 : 0, [xPos]);
1250
- return /*#__PURE__*/_jsx(Rect, {
1251
- color: stroke,
1252
- height: drawingArea.height,
1253
- opacity: opacity,
1254
- width: rectWidth,
1255
- x: xPos,
1256
- y: drawingArea.y
1257
- });
1258
- });
1259
- const candlesData = useMemo(() => candlestickStockData.map(data => [parseFloat(data.low), parseFloat(data.high)]), []);
1260
- const CandlestickBarComponent = /*#__PURE__*/memo(_ref14 => {
1261
- var _yScale, _yScale2;
1262
- let {
1263
- x,
1264
- y,
1265
- width,
1266
- height,
1267
- dataX
1268
- } = _ref14,
1269
- props = _objectWithoutPropertiesLoose(_ref14, _excluded4);
1270
- const {
1271
- getYScale
1272
- } = useCartesianChartContext();
1273
- const yScale = getYScale();
1274
- const wickX = x + width / 2;
1275
- const timePeriodValue = candlestickStockData[dataX];
1276
- const open = parseFloat(timePeriodValue.open);
1277
- const close = parseFloat(timePeriodValue.close);
1278
- const bullish = open < close;
1279
- const theme = useTheme();
1280
- const color = bullish ? theme.color.fgPositive : theme.color.fgNegative;
1281
- const openY = (_yScale = yScale == null ? void 0 : yScale(open)) != null ? _yScale : 0;
1282
- const closeY = (_yScale2 = yScale == null ? void 0 : yScale(close)) != null ? _yScale2 : 0;
1283
- const bodyHeight = Math.abs(openY - closeY);
1284
- const bodyY = openY < closeY ? openY : closeY;
1285
- return /*#__PURE__*/_jsxs(_Fragment, {
1286
- children: [/*#__PURE__*/_jsx(SkiaLine, {
1287
- color: color,
1288
- p1: {
1289
- x: wickX,
1290
- y
1291
- },
1292
- p2: {
1293
- x: wickX,
1294
- y: y + height
1295
- },
1296
- strokeWidth: 1
1297
- }), /*#__PURE__*/_jsx(Rect, {
1298
- color: color,
1299
- height: bodyHeight,
1300
- width: width,
1301
- x: x,
1302
- y: bodyY
1303
- })]
1304
- });
1305
- });
1306
- const formatThousandsPriceNumber = useCallback(price => {
1307
- const formattedPrice = new Intl.NumberFormat('en-US', {
1308
- style: 'currency',
1309
- currency: 'USD',
1310
- minimumFractionDigits: 0,
1311
- maximumFractionDigits: 0
1312
- }).format(price / 1000);
1313
- return formattedPrice + "k";
1314
- }, []);
1315
- const formatTime = useCallback(index => {
1316
- if (index === null || index === undefined || index >= candlestickStockData.length) return '';
1317
- const ts = parseInt(candlestickStockData[index].start);
1318
- return new Date(ts * 1000).toLocaleDateString('en-US', {
1319
- month: 'short',
1320
- day: 'numeric'
1321
- });
1322
- }, []);
1323
- return /*#__PURE__*/_jsxs(CartesianChart, {
1324
- enableScrubbing: true,
1325
- animate: false,
1326
- "aria-labelledby": infoTextId,
1327
- borderRadius: 0,
1328
- height: 150,
1329
- inset: {
1330
- top: 8,
1331
- bottom: 8,
1332
- left: 0,
1333
- right: 0
1334
- },
1335
- onScrubberPositionChange: onScrubberPositionChange,
1336
- series: [{
1337
- id: 'stock-prices',
1338
- data: candlesData
1339
- }],
1340
- xAxis: {
1341
- scaleType: 'band'
1342
- },
1343
- yAxis: {
1344
- domain: {
1345
- min
1346
- }
1347
- },
1348
- children: [/*#__PURE__*/_jsx(XAxis, {
1349
- tickLabelFormatter: formatTime
1350
- }), /*#__PURE__*/_jsx(YAxis, {
1351
- showGrid: true,
1352
- GridLineComponent: ThinSolidLine,
1353
- tickLabelFormatter: formatThousandsPriceNumber,
1354
- width: 40
1355
- }), /*#__PURE__*/_jsx(Scrubber, {
1356
- hideOverlay: true,
1357
- LineComponent: BandwidthHighlight,
1358
- lineStroke: theme.color.fgMuted,
1359
- seriesIds: []
1360
- }), /*#__PURE__*/_jsx(BarPlot, {
1361
- BarComponent: CandlestickBarComponent,
1362
- BarStackComponent: _ref15 => {
1363
- let {
1364
- children
1365
- } = _ref15;
1366
- return /*#__PURE__*/_jsx("g", {
1367
- children: children
1368
- });
1369
- }
1370
- })]
1371
- });
1372
- });
1373
- function Candlesticks() {
1374
- const infoTextId = useId();
1375
- const [currentIndex, setCurrentIndex] = useState();
1376
- return /*#__PURE__*/_jsxs(VStack, {
1377
- gap: 2,
1378
- children: [/*#__PURE__*/_jsx(CandlesticksHeader, {
1379
- currentIndex: currentIndex
1380
- }), /*#__PURE__*/_jsx(CandlesticksChart, {
1381
- infoTextId: infoTextId,
1382
- onScrubberPositionChange: setCurrentIndex
1383
- })]
1384
- });
1385
- }
1386
1201
  function MonotoneAssetPrice() {
1387
1202
  const theme = useTheme();
1388
1203
  const prices = sparklineInteractiveData.hour;
@@ -1456,14 +1271,20 @@ function MonotoneAssetPrice() {
1456
1271
  dy: -12,
1457
1272
  horizontalAlignment: "left"
1458
1273
  })), []);
1459
- const CustomScrubberBeacon = /*#__PURE__*/memo(_ref16 => {
1274
+ const chartAccessibilityLabel = "Price chart with " + prices.length + " data points. Swipe to navigate.";
1275
+ const getScrubberAccessibilityLabel = useCallback(index => {
1276
+ const price = scrubberPriceFormatter.format(prices[index].value);
1277
+ const date = formatDate(prices[index].date);
1278
+ return price + " USD " + date;
1279
+ }, [formatDate, prices, scrubberPriceFormatter]);
1280
+ const CustomScrubberBeacon = /*#__PURE__*/memo(_ref11 => {
1460
1281
  let {
1461
1282
  dataX,
1462
1283
  dataY,
1463
1284
  seriesId,
1464
1285
  isIdle,
1465
1286
  animate = true
1466
- } = _ref16;
1287
+ } = _ref11;
1467
1288
  const {
1468
1289
  getSeries,
1469
1290
  getXSerializableScale,
@@ -1529,6 +1350,8 @@ function MonotoneAssetPrice() {
1529
1350
  return /*#__PURE__*/_jsx(LineChart, {
1530
1351
  enableScrubbing: true,
1531
1352
  showYAxis: true,
1353
+ accessibilityLabel: chartAccessibilityLabel,
1354
+ getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
1532
1355
  height: 200,
1533
1356
  inset: {
1534
1357
  top: 64
@@ -1539,10 +1362,10 @@ function MonotoneAssetPrice() {
1539
1362
  color: theme.color.fg,
1540
1363
  gradient: {
1541
1364
  axis: 'x',
1542
- stops: _ref17 => {
1365
+ stops: _ref12 => {
1543
1366
  let {
1544
1367
  min
1545
- } = _ref17;
1368
+ } = _ref12;
1546
1369
  return [{
1547
1370
  offset: min,
1548
1371
  color: theme.color.fg,
@@ -1556,10 +1379,10 @@ function MonotoneAssetPrice() {
1556
1379
  }
1557
1380
  }],
1558
1381
  xAxis: {
1559
- range: _ref18 => {
1382
+ range: _ref13 => {
1560
1383
  let {
1561
1384
  max
1562
- } = _ref18;
1385
+ } = _ref13;
1563
1386
  return {
1564
1387
  min: 96,
1565
1388
  max
@@ -1603,18 +1426,22 @@ function ServiceAvailability() {
1603
1426
  date: new Date('2022-01-10'),
1604
1427
  availability: 86
1605
1428
  }], []);
1429
+ const chartAccessibilityLabel = "Service availability chart with " + availabilityEvents.length + " data points. Swipe to navigate.";
1430
+ const getScrubberAccessibilityLabel = useCallback(index => "Point " + (index + 1) + ": " + availabilityEvents[index].availability + "% availability on " + availabilityEvents[index].date.toLocaleDateString(), [availabilityEvents]);
1606
1431
  return /*#__PURE__*/_jsxs(CartesianChart, {
1607
1432
  enableScrubbing: true,
1433
+ accessibilityLabel: chartAccessibilityLabel,
1434
+ getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
1608
1435
  height: 200,
1609
1436
  series: [{
1610
1437
  id: 'availability',
1611
1438
  data: availabilityEvents.map(event => event.availability),
1612
1439
  gradient: {
1613
- stops: _ref19 => {
1440
+ stops: _ref14 => {
1614
1441
  let {
1615
1442
  min,
1616
1443
  max
1617
- } = _ref19;
1444
+ } = _ref14;
1618
1445
  return [{
1619
1446
  offset: min,
1620
1447
  color: theme.color.fgNegative
@@ -1641,11 +1468,11 @@ function ServiceAvailability() {
1641
1468
  data: availabilityEvents.map(event => event.date.getTime())
1642
1469
  },
1643
1470
  yAxis: {
1644
- domain: _ref20 => {
1471
+ domain: _ref15 => {
1645
1472
  let {
1646
1473
  min,
1647
1474
  max
1648
- } = _ref20;
1475
+ } = _ref15;
1649
1476
  return {
1650
1477
  min: Math.max(min - 2, 0),
1651
1478
  max: Math.min(max + 2, 100)
@@ -1677,7 +1504,7 @@ function ServiceAvailability() {
1677
1504
  }
1678
1505
  function ForecastAssetPrice() {
1679
1506
  const startYear = 2020;
1680
- const data = [50, 45, 47, 46, 54, 54, 60, 61, 63, 66, 70];
1507
+ const data = useMemo(() => [50, 45, 47, 46, 54, 54, 60, 61, 63, 66, 70], []);
1681
1508
  const currentIndex = 6;
1682
1509
  const strokeWidth = 3;
1683
1510
  // To prevent cutting off the edge of our lines
@@ -1781,8 +1608,12 @@ function ForecastAssetPrice() {
1781
1608
  })]
1782
1609
  });
1783
1610
  });
1611
+ const chartAccessibilityLabel = "Forecast chart with " + data.length + " data points. Swipe to navigate.";
1612
+ const getScrubberAccessibilityLabel = useCallback(index => "Point " + (index + 1) + ": " + axisFormatter(index) + ", value " + data[index], [axisFormatter, data]);
1784
1613
  return /*#__PURE__*/_jsxs(CartesianChart, {
1785
1614
  enableScrubbing: true,
1615
+ accessibilityLabel: chartAccessibilityLabel,
1616
+ getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
1786
1617
  height: 200,
1787
1618
  series: [{
1788
1619
  id: 'price',
@@ -1805,307 +1636,136 @@ function ForecastAssetPrice() {
1805
1636
  }), /*#__PURE__*/_jsx(CustomScrubber, {})]
1806
1637
  });
1807
1638
  }
1808
- function ImperativeHandle() {
1809
- const theme = useTheme();
1810
- const scrubberRef = useRef(null);
1639
+ function DataCardWithLineChart() {
1640
+ const {
1641
+ spectrum
1642
+ } = useTheme();
1643
+ const exampleThumbnail = /*#__PURE__*/_jsx(RemoteImage, {
1644
+ accessibilityLabel: "Ethereum",
1645
+ shape: "circle",
1646
+ size: "xl",
1647
+ source: ethBackground,
1648
+ testID: "thumbnail"
1649
+ });
1650
+ const getLineChartSeries = useCallback(() => [{
1651
+ id: 'price',
1652
+ data: prices.slice(0, 30).map(price => parseFloat(price)),
1653
+ color: "rgb(" + spectrum.green70 + ")"
1654
+ }], [spectrum.green70]);
1655
+ const lineChartSeries = useMemo(() => getLineChartSeries(), [getLineChartSeries]);
1656
+ const lineChartSeries2 = useMemo(() => getLineChartSeries(), [getLineChartSeries]);
1657
+ const ref = useRef(null);
1811
1658
  return /*#__PURE__*/_jsxs(VStack, {
1812
1659
  gap: 2,
1813
- children: [/*#__PURE__*/_jsx(LineChart, {
1814
- enableScrubbing: true,
1815
- showYAxis: true,
1816
- height: 250,
1817
- series: [{
1818
- id: 'priceA',
1819
- data: [2400, 1398, 9800, 3908, 4800, 3800, 4300],
1820
- label: 'Price A',
1821
- color: theme.color.accentBoldBlue
1822
- }, {
1823
- id: 'priceB',
1824
- data: [2000, 2491, 4501, 6049, 5019, 4930, 5910],
1825
- label: 'Price B',
1826
- color: theme.color.accentBoldGreen
1827
- }, {
1828
- id: 'priceC',
1829
- data: [1000, 4910, 2300, 5910, 3940, 2940, 1940],
1830
- label: 'Price C',
1831
- color: theme.color.accentBoldPurple
1832
- }, {
1833
- id: 'priceD',
1834
- data: [4810, 2030, 5810, 3940, 2940, 1940, 940],
1835
- label: 'Price D',
1836
- color: theme.color.accentBoldYellow
1837
- }],
1838
- xAxis: {
1839
- // Give space for pulse animation
1840
- range: _ref21 => {
1841
- let {
1842
- min,
1843
- max
1844
- } = _ref21;
1845
- return {
1846
- min,
1847
- max: max - 8
1848
- };
1849
- }
1850
- },
1851
- yAxis: {
1852
- domain: {
1853
- min: 0
1854
- },
1855
- showGrid: true,
1856
- tickLabelFormatter: value => value.toLocaleString()
1857
- },
1858
- children: /*#__PURE__*/_jsx(Scrubber, {
1859
- ref: scrubberRef
1660
+ children: [/*#__PURE__*/_jsx(DataCard, {
1661
+ layout: "vertical",
1662
+ subtitle: "Price trend",
1663
+ thumbnail: exampleThumbnail,
1664
+ title: "Line Chart Card",
1665
+ children: /*#__PURE__*/_jsx(LineChart, {
1666
+ showArea: true,
1667
+ accessibilityLabel: "Ethereum price chart",
1668
+ areaType: "dotted",
1669
+ height: 120,
1670
+ inset: 0,
1671
+ series: lineChartSeries
1672
+ })
1673
+ }), /*#__PURE__*/_jsx(DataCard, {
1674
+ layout: "vertical",
1675
+ subtitle: "Price trend",
1676
+ thumbnail: exampleThumbnail,
1677
+ title: "Line Chart with Tag",
1678
+ titleAccessory: /*#__PURE__*/_jsx(Text, {
1679
+ dangerouslySetColor: "rgb(" + spectrum.green70 + ")",
1680
+ font: "label1",
1681
+ children: "\u2197 25.25%"
1682
+ }),
1683
+ children: /*#__PURE__*/_jsx(LineChart, {
1684
+ showArea: true,
1685
+ accessibilityLabel: "Ethereum price chart",
1686
+ areaType: "dotted",
1687
+ height: 100,
1688
+ inset: 0,
1689
+ series: lineChartSeries
1690
+ })
1691
+ }), /*#__PURE__*/_jsx(DataCard, {
1692
+ ref: ref,
1693
+ renderAsPressable: true,
1694
+ layout: "vertical",
1695
+ onPress: NoopFn,
1696
+ subtitle: "Clickable line chart card",
1697
+ thumbnail: exampleThumbnail,
1698
+ title: "Actionable Line Chart",
1699
+ titleAccessory: /*#__PURE__*/_jsx(Text, {
1700
+ dangerouslySetColor: "rgb(" + spectrum.green70 + ")",
1701
+ font: "label1",
1702
+ children: "\u2197 8.5%"
1703
+ }),
1704
+ children: /*#__PURE__*/_jsx(LineChart, {
1705
+ showArea: true,
1706
+ accessibilityLabel: "Ethereum price chart",
1707
+ areaType: "dotted",
1708
+ height: 120,
1709
+ inset: 0,
1710
+ series: lineChartSeries,
1711
+ showXAxis: false,
1712
+ showYAxis: false
1713
+ })
1714
+ }), /*#__PURE__*/_jsx(DataCard, {
1715
+ layout: "vertical",
1716
+ subtitle: "Price trend",
1717
+ thumbnail: /*#__PURE__*/_jsx(RemoteImage, {
1718
+ accessibilityLabel: "Bitcoin",
1719
+ shape: "circle",
1720
+ size: "xl",
1721
+ source: assets.btc.imageUrl,
1722
+ testID: "thumbnail"
1723
+ }),
1724
+ title: "Card with Line Chart",
1725
+ titleAccessory: /*#__PURE__*/_jsx(Text, {
1726
+ dangerouslySetColor: "rgb(" + spectrum.green70 + ")",
1727
+ font: "label1",
1728
+ children: "\u2197 25.25%"
1729
+ }),
1730
+ children: /*#__PURE__*/_jsx(LineChart, {
1731
+ showArea: true,
1732
+ accessibilityLabel: "Price chart",
1733
+ areaType: "dotted",
1734
+ height: 100,
1735
+ inset: 0,
1736
+ series: lineChartSeries2,
1737
+ showXAxis: false,
1738
+ showYAxis: false
1860
1739
  })
1861
- }), /*#__PURE__*/_jsx(Button, {
1862
- onPress: () => {
1863
- var _scrubberRef$current2;
1864
- return (_scrubberRef$current2 = scrubberRef.current) == null ? void 0 : _scrubberRef$current2.pulse();
1865
- },
1866
- children: "Pulse"
1867
1740
  })]
1868
1741
  });
1869
1742
  }
1870
- function CustomBeaconLabel() {
1871
- const theme = useTheme();
1872
- // This custom component label shows the percentage value of the data at the scrubber position.
1873
- const MyScrubberBeaconLabel = /*#__PURE__*/memo(_ref22 => {
1874
- let {
1875
- seriesId,
1876
- color,
1877
- label
1878
- } = _ref22,
1879
- props = _objectWithoutPropertiesLoose(_ref22, _excluded5);
1880
- const {
1881
- getSeriesData,
1882
- series
1883
- } = useCartesianChartContext();
1884
- const {
1885
- scrubberPosition
1886
- } = useScrubberContext();
1887
- const seriesData = useMemo(() => getLineData(getSeriesData(seriesId)), [getSeriesData, seriesId]);
1888
- const dataLength = useMemo(() => {
1889
- var _series$reduce;
1890
- return (_series$reduce = series == null ? void 0 : series.reduce((max, s) => {
1891
- var _seriesData$length;
1892
- const seriesData = getSeriesData(s.id);
1893
- return Math.max(max, (_seriesData$length = seriesData == null ? void 0 : seriesData.length) != null ? _seriesData$length : 0);
1894
- }, 0)) != null ? _series$reduce : 0;
1895
- }, [series, getSeriesData]);
1896
- const dataIndex = useDerivedValue(() => {
1897
- var _scrubberPosition$val;
1898
- return (_scrubberPosition$val = scrubberPosition.value) != null ? _scrubberPosition$val : Math.max(0, dataLength - 1);
1899
- }, [scrubberPosition, dataLength]);
1900
- const percentageLabel = useDerivedValue(() => {
1901
- if (seriesData !== undefined) {
1902
- const dataAtPosition = seriesData[dataIndex.value];
1903
- return unwrapAnimatedValue(label) + " \xB7 " + dataAtPosition + "%";
1904
- }
1905
- return unwrapAnimatedValue(label);
1906
- }, [label, seriesData, dataIndex]);
1907
- return /*#__PURE__*/_jsx(DefaultScrubberBeaconLabel, _extends({}, props, {
1908
- background: color,
1909
- color: theme.color.bg,
1910
- label: percentageLabel,
1911
- seriesId: seriesId
1912
- }));
1913
- });
1743
+ function HorizontalLayoutLineChart() {
1744
+ const symbols = ['BTC', 'ETH', 'SOL', 'DOGE', 'ADA'];
1745
+ const allocations = [72, 46, 33, 21, 14];
1914
1746
  return /*#__PURE__*/_jsx(LineChart, {
1915
- enableScrubbing: true,
1747
+ points: true,
1916
1748
  showArea: true,
1749
+ showXAxis: true,
1917
1750
  showYAxis: true,
1918
- areaType: "dotted",
1919
- height: 200,
1920
- series: [{
1921
- id: 'Boston',
1922
- data: [25, 30, 35, 45, 60, 100],
1923
- color: "rgb(" + theme.spectrum.green40 + ")",
1924
- label: 'Boston'
1925
- }, {
1926
- id: 'Miami',
1927
- data: [20, 25, 30, 35, 20, 0],
1928
- color: "rgb(" + theme.spectrum.blue40 + ")",
1929
- label: 'Miami'
1930
- }, {
1931
- id: 'Denver',
1932
- data: [10, 15, 20, 25, 40, 0],
1933
- color: "rgb(" + theme.spectrum.orange40 + ")",
1934
- label: 'Denver'
1935
- }, {
1936
- id: 'Phoenix',
1937
- data: [15, 10, 5, 0, 0, 0],
1938
- color: "rgb(" + theme.spectrum.red40 + ")",
1939
- label: 'Phoenix'
1940
- }],
1941
- yAxis: {
1942
- showGrid: true
1943
- },
1944
- children: /*#__PURE__*/_jsx(Scrubber, {
1945
- BeaconLabelComponent: MyScrubberBeaconLabel
1946
- })
1947
- });
1948
- }
1949
- function CustomLabelComponent() {
1950
- const CustomLabelComponent = /*#__PURE__*/memo(props => {
1951
- const theme = useTheme();
1952
- const {
1953
- drawingArea
1954
- } = useCartesianChartContext();
1955
- if (!drawingArea) return;
1956
- return /*#__PURE__*/_jsx(DefaultScrubberLabel, _extends({}, props, {
1957
- elevated: true,
1958
- background: theme.color.bgPrimary,
1959
- color: theme.color.bgPrimaryWash,
1960
- dy: 32,
1961
- fontWeight: FontWeight.Bold,
1962
- y: drawingArea.y + drawingArea.height
1963
- }));
1964
- });
1965
- return /*#__PURE__*/_jsx(LineChart, {
1966
- enableScrubbing: true,
1967
- showArea: true,
1968
- height: 200,
1969
- inset: {
1970
- top: 16,
1971
- bottom: 64
1972
- },
1751
+ height: 240,
1752
+ layout: "horizontal",
1973
1753
  series: [{
1974
- id: 'prices',
1975
- data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58]
1976
- }],
1977
- children: /*#__PURE__*/_jsx(Scrubber, {
1978
- LabelComponent: CustomLabelComponent,
1979
- label: dataIndex => "Day " + (dataIndex + 1)
1980
- })
1981
- });
1982
- }
1983
- function HiddenScrubberWhenIdle() {
1984
- const MyScrubberBeacon = /*#__PURE__*/memo(props => {
1985
- const {
1986
- scrubberPosition
1987
- } = useScrubberContext();
1988
- const beaconOpacity = useDerivedValue(() => scrubberPosition.value !== undefined ? 1 : 0, [scrubberPosition]);
1989
- return /*#__PURE__*/_jsx(DefaultScrubberBeacon, _extends({}, props, {
1990
- opacity: beaconOpacity
1991
- }));
1992
- });
1993
- const MyScrubberBeaconLabel = /*#__PURE__*/memo(props => {
1994
- const {
1995
- scrubberPosition
1996
- } = useScrubberContext();
1997
- const labelOpacity = useDerivedValue(() => scrubberPosition.value !== undefined ? 1 : 0, [scrubberPosition]);
1998
- return /*#__PURE__*/_jsx(DefaultScrubberBeaconLabel, _extends({}, props, {
1999
- opacity: labelOpacity
2000
- }));
2001
- });
2002
- return /*#__PURE__*/_jsx(LineChart, {
2003
- enableScrubbing: true,
2004
- showArea: true,
2005
- height: 150,
2006
- series: [{
2007
- id: 'prices',
2008
- data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58],
2009
- label: 'hello'
1754
+ id: 'allocations',
1755
+ data: allocations,
1756
+ color: assets.btc.color
2010
1757
  }],
2011
- children: /*#__PURE__*/_jsx(Scrubber, {
2012
- BeaconComponent: MyScrubberBeacon,
2013
- BeaconLabelComponent: MyScrubberBeaconLabel
2014
- })
2015
- });
2016
- }
2017
- function TwoLineScrubberLabel() {
2018
- const theme = useTheme();
2019
- const data = useMemo(() => [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58], []);
2020
- const [alignment, setAlignment] = useState(TextAlign.Center);
2021
- const fontMgr = useMemo(() => {
2022
- const fontProvider = Skia.TypefaceFontProvider.Make();
2023
- return fontProvider;
2024
- }, []);
2025
- const formatPrice = useCallback(price => {
2026
- return new Intl.NumberFormat('en-US', {
2027
- style: 'currency',
2028
- currency: 'USD',
2029
- minimumFractionDigits: 2,
2030
- maximumFractionDigits: 2
2031
- }).format(price);
2032
- }, []);
2033
- const scrubberLabel = useCallback(index => {
2034
- const price = formatPrice(data[index] * 100);
2035
- const day = "Day " + (index + 100);
2036
- const priceStyle = {
2037
- fontFamilies: ['Inter'],
2038
- fontSize: 16,
2039
- fontStyle: {
2040
- weight: FontWeight.Bold
2041
- },
2042
- color: Skia.Color(theme.color.fg)
2043
- };
2044
- const dayStyle = {
2045
- fontFamilies: ['Inter'],
2046
- fontSize: 14,
2047
- fontStyle: {
2048
- weight: FontWeight.Normal
2049
- },
2050
- color: Skia.Color(theme.color.fgMuted)
2051
- };
2052
- const builder = Skia.ParagraphBuilder.Make({
2053
- textAlign: alignment
2054
- }, fontMgr);
2055
- builder.pushStyle(priceStyle);
2056
- builder.addText(price);
2057
- builder.addText('\n');
2058
- builder.pushStyle(dayStyle);
2059
- builder.addText(day);
2060
- const para = builder.build();
2061
- // First layout with large width to get intrinsic size
2062
- para.layout(384);
2063
- return para;
2064
- }, [data, formatPrice, theme.color.fg, theme.color.fgMuted, fontMgr, alignment]);
2065
-
2066
- // Custom scrubber label component that uses the selected alignment
2067
- const AlignedScrubberLabel = /*#__PURE__*/memo(props => /*#__PURE__*/_jsx(DefaultScrubberLabel, _extends({}, props, {
2068
- paragraphAlignment: alignment
2069
- })));
2070
- return /*#__PURE__*/_jsxs(VStack, {
2071
- gap: 2,
2072
- children: [/*#__PURE__*/_jsxs(HStack, {
2073
- gap: 1,
2074
- children: [/*#__PURE__*/_jsx(Button, {
2075
- compact: true,
2076
- onPress: () => setAlignment(TextAlign.Left),
2077
- variant: alignment === TextAlign.Left ? 'primary' : 'secondary',
2078
- children: "Left"
2079
- }), /*#__PURE__*/_jsx(Button, {
2080
- compact: true,
2081
- onPress: () => setAlignment(TextAlign.Center),
2082
- variant: alignment === TextAlign.Center ? 'primary' : 'secondary',
2083
- children: "Center"
2084
- }), /*#__PURE__*/_jsx(Button, {
2085
- compact: true,
2086
- onPress: () => setAlignment(TextAlign.Right),
2087
- variant: alignment === TextAlign.Right ? 'primary' : 'secondary',
2088
- children: "Right"
2089
- })]
2090
- }), /*#__PURE__*/_jsx(LineChart, {
2091
- enableScrubbing: true,
2092
- showArea: true,
2093
- height: 200,
2094
- inset: {
2095
- top: 64
1758
+ xAxis: {
1759
+ domain: {
1760
+ min: 0,
1761
+ max: 80
2096
1762
  },
2097
- series: [{
2098
- id: 'prices',
2099
- data: data,
2100
- color: theme.color.accentBoldBlue
2101
- }],
2102
- children: /*#__PURE__*/_jsx(Scrubber, {
2103
- idlePulse: true,
2104
- labelElevated: true,
2105
- LabelComponent: AlignedScrubberLabel,
2106
- label: scrubberLabel
2107
- })
2108
- })]
1763
+ tickLabelFormatter: value => value + "%"
1764
+ },
1765
+ yAxis: {
1766
+ data: symbols,
1767
+ scaleType: 'band'
1768
+ }
2109
1769
  });
2110
1770
  }
2111
1771
  function ExampleNavigator() {
@@ -2122,8 +1782,8 @@ function ExampleNavigator() {
2122
1782
  }]
2123
1783
  })
2124
1784
  }, {
2125
- title: 'Imperative Handle',
2126
- component: /*#__PURE__*/_jsx(ImperativeHandle, {})
1785
+ title: 'Horizontal Layout',
1786
+ component: /*#__PURE__*/_jsx(HorizontalLayoutLineChart, {})
2127
1787
  }, {
2128
1788
  title: 'Multiple Lines',
2129
1789
  component: /*#__PURE__*/_jsx(MultipleLine, {})
@@ -2252,6 +1912,8 @@ function ExampleNavigator() {
2252
1912
  component: /*#__PURE__*/_jsxs(LineChart, {
2253
1913
  enableScrubbing: true,
2254
1914
  showArea: true,
1915
+ accessibilityLabel: "Price chart with reference line. 14 data points. Swipe to navigate.",
1916
+ getScrubberAccessibilityLabel: index => "Point " + (index + 1),
2255
1917
  height: 200,
2256
1918
  series: [{
2257
1919
  id: 'prices',
@@ -2260,11 +1922,11 @@ function ExampleNavigator() {
2260
1922
  }],
2261
1923
  xAxis: {
2262
1924
  // Give space before the end of the chart for the scrubber
2263
- range: _ref23 => {
1925
+ range: _ref16 => {
2264
1926
  let {
2265
1927
  min,
2266
1928
  max
2267
- } = _ref23;
1929
+ } = _ref16;
2268
1930
  return {
2269
1931
  min,
2270
1932
  max: max - 24
@@ -2295,9 +1957,6 @@ function ExampleNavigator() {
2295
1957
  }, {
2296
1958
  title: 'Performance',
2297
1959
  component: /*#__PURE__*/_jsx(Performance, {})
2298
- }, {
2299
- title: 'Candlesticks',
2300
- component: /*#__PURE__*/_jsx(Candlesticks, {})
2301
1960
  }, {
2302
1961
  title: 'Monotone Asset Price',
2303
1962
  component: /*#__PURE__*/_jsx(MonotoneAssetPrice, {})
@@ -2308,28 +1967,18 @@ function ExampleNavigator() {
2308
1967
  title: 'Forecast Asset Price',
2309
1968
  component: /*#__PURE__*/_jsx(ForecastAssetPrice, {})
2310
1969
  }, {
2311
- title: 'Custom Beacon Label',
2312
- component: /*#__PURE__*/_jsx(CustomBeaconLabel, {})
2313
- }, {
2314
- title: 'Custom Label Component',
2315
- component: /*#__PURE__*/_jsx(CustomLabelComponent, {})
2316
- }, {
2317
- title: 'Hidden Scrubber When Idle',
2318
- component: /*#__PURE__*/_jsx(HiddenScrubberWhenIdle, {})
2319
- }, {
2320
- title: 'Two-Line Scrubber Label',
2321
- component: /*#__PURE__*/_jsx(TwoLineScrubberLabel, {})
1970
+ title: 'In DataCard',
1971
+ component: /*#__PURE__*/_jsx(DataCardWithLineChart, {})
2322
1972
  }], [theme.color.fg, theme.color.fgPositive, theme.spectrum.gray50]);
2323
1973
  const currentExample = examples[currentIndex];
2324
- const isFirstExample = currentIndex === 0;
2325
- const isLastExample = currentIndex === examples.length - 1;
2326
1974
  const handlePrevious = useCallback(() => {
2327
- setCurrentIndex(prev => Math.max(0, prev - 1));
2328
- }, []);
1975
+ setCurrentIndex(prev => (prev - 1 + examples.length) % examples.length);
1976
+ }, [examples.length]);
2329
1977
  const handleNext = useCallback(() => {
2330
- setCurrentIndex(prev => Math.min(examples.length - 1, prev + 1));
1978
+ setCurrentIndex(prev => (prev + 1 + examples.length) % examples.length);
2331
1979
  }, [examples.length]);
2332
1980
  return /*#__PURE__*/_jsx(ExampleScreen, {
1981
+ paddingX: 0,
2333
1982
  children: /*#__PURE__*/_jsxs(VStack, {
2334
1983
  gap: 4,
2335
1984
  children: [/*#__PURE__*/_jsxs(HStack, {
@@ -2339,13 +1988,11 @@ function ExampleNavigator() {
2339
1988
  children: [/*#__PURE__*/_jsx(IconButton, {
2340
1989
  accessibilityHint: "Navigate to previous example",
2341
1990
  accessibilityLabel: "Previous",
2342
- disabled: isFirstExample,
2343
1991
  name: "arrowLeft",
2344
1992
  onPress: handlePrevious,
2345
1993
  variant: "secondary"
2346
1994
  }), /*#__PURE__*/_jsxs(VStack, {
2347
1995
  alignItems: "center",
2348
- gap: 1,
2349
1996
  children: [/*#__PURE__*/_jsx(Text, {
2350
1997
  font: "title3",
2351
1998
  children: currentExample.title
@@ -2357,7 +2004,6 @@ function ExampleNavigator() {
2357
2004
  }), /*#__PURE__*/_jsx(IconButton, {
2358
2005
  accessibilityHint: "Navigate to next example",
2359
2006
  accessibilityLabel: "Next",
2360
- disabled: isLastExample,
2361
2007
  name: "arrowRight",
2362
2008
  onPress: handleNext,
2363
2009
  variant: "secondary"