@coinbase/cds-mcp-server 8.17.2 → 8.17.4

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 (284) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/mcp-docs/mobile/components/Accordion.txt +188 -0
  3. package/mcp-docs/mobile/components/AccordionItem.txt +29 -0
  4. package/mcp-docs/mobile/components/Alert.txt +155 -0
  5. package/mcp-docs/mobile/components/AreaChart.txt +265 -0
  6. package/mcp-docs/mobile/components/Avatar.txt +195 -0
  7. package/mcp-docs/mobile/components/AvatarButton.txt +225 -0
  8. package/mcp-docs/mobile/components/Banner.txt +221 -0
  9. package/mcp-docs/mobile/components/BarChart.txt +815 -0
  10. package/mcp-docs/mobile/components/Box.txt +173 -0
  11. package/mcp-docs/mobile/components/BrowserBar.txt +146 -0
  12. package/mcp-docs/mobile/components/Button.txt +198 -0
  13. package/mcp-docs/mobile/components/ButtonGroup.txt +79 -0
  14. package/mcp-docs/mobile/components/Carousel.txt +1083 -0
  15. package/mcp-docs/mobile/components/CartesianChart.txt +825 -0
  16. package/mcp-docs/mobile/components/CellMedia.txt +70 -0
  17. package/mcp-docs/mobile/components/Checkbox.txt +245 -0
  18. package/mcp-docs/mobile/components/CheckboxCell.txt +201 -0
  19. package/mcp-docs/mobile/components/CheckboxGroup.txt +284 -0
  20. package/mcp-docs/mobile/components/Chip.txt +194 -0
  21. package/mcp-docs/mobile/components/Coachmark.txt +157 -0
  22. package/mcp-docs/mobile/components/Collapsible.txt +104 -0
  23. package/mcp-docs/mobile/components/ContainedAssetCard.txt +134 -0
  24. package/mcp-docs/mobile/components/ContentCard.txt +365 -0
  25. package/mcp-docs/mobile/components/ContentCardBody.txt +135 -0
  26. package/mcp-docs/mobile/components/ContentCardFooter.txt +127 -0
  27. package/mcp-docs/mobile/components/ContentCardHeader.txt +145 -0
  28. package/mcp-docs/mobile/components/ContentCell.txt +226 -0
  29. package/mcp-docs/mobile/components/ControlGroup.txt +443 -0
  30. package/mcp-docs/mobile/components/DatePicker.txt +496 -0
  31. package/mcp-docs/mobile/components/Divider.txt +138 -0
  32. package/mcp-docs/mobile/components/DotCount.txt +145 -0
  33. package/mcp-docs/mobile/components/DotStatusColor.txt +58 -0
  34. package/mcp-docs/mobile/components/DotSymbol.txt +134 -0
  35. package/mcp-docs/mobile/components/Fallback.txt +157 -0
  36. package/mcp-docs/mobile/components/FloatingAssetCard.txt +155 -0
  37. package/mcp-docs/mobile/components/HStack.txt +234 -0
  38. package/mcp-docs/mobile/components/HeroSquare.txt +47 -0
  39. package/mcp-docs/mobile/components/Icon.txt +51 -0
  40. package/mcp-docs/mobile/components/IconButton.txt +268 -0
  41. package/mcp-docs/mobile/components/InputChip.txt +187 -0
  42. package/mcp-docs/mobile/components/Interactable.txt +186 -0
  43. package/mcp-docs/mobile/components/LineChart.txt +1324 -0
  44. package/mcp-docs/mobile/components/Link.txt +291 -0
  45. package/mcp-docs/mobile/components/ListCell.txt +412 -0
  46. package/mcp-docs/mobile/components/LogoMark.txt +84 -0
  47. package/mcp-docs/mobile/components/LogoWordMark.txt +93 -0
  48. package/mcp-docs/mobile/components/Lottie.txt +138 -0
  49. package/mcp-docs/mobile/components/LottieStatusAnimation.txt +46 -0
  50. package/mcp-docs/mobile/components/Modal.txt +83 -0
  51. package/mcp-docs/mobile/components/ModalBody.txt +33 -0
  52. package/mcp-docs/mobile/components/ModalFooter.txt +24 -0
  53. package/mcp-docs/mobile/components/ModalHeader.txt +27 -0
  54. package/mcp-docs/mobile/components/MultiContentModule.txt +379 -0
  55. package/mcp-docs/mobile/components/NavigationTitle.txt +131 -0
  56. package/mcp-docs/mobile/components/NavigationTitleSelect.txt +141 -0
  57. package/mcp-docs/mobile/components/NudgeCard.txt +89 -0
  58. package/mcp-docs/mobile/components/Numpad.txt +340 -0
  59. package/mcp-docs/mobile/components/Overlay.txt +151 -0
  60. package/mcp-docs/mobile/components/PageFooter.txt +160 -0
  61. package/mcp-docs/mobile/components/PageHeader.txt +185 -0
  62. package/mcp-docs/mobile/components/PeriodSelector.txt +407 -0
  63. package/mcp-docs/mobile/components/Pictogram.txt +47 -0
  64. package/mcp-docs/mobile/components/Point.txt +204 -0
  65. package/mcp-docs/mobile/components/PortalProvider.txt +78 -0
  66. package/mcp-docs/mobile/components/Pressable.txt +210 -0
  67. package/mcp-docs/mobile/components/ProgressBar.txt +129 -0
  68. package/mcp-docs/mobile/components/ProgressBarWithFixedLabels.txt +160 -0
  69. package/mcp-docs/mobile/components/ProgressBarWithFloatLabel.txt +137 -0
  70. package/mcp-docs/mobile/components/ProgressCircle.txt +236 -0
  71. package/mcp-docs/mobile/components/Radio.txt +241 -0
  72. package/mcp-docs/mobile/components/RadioCell.txt +201 -0
  73. package/mcp-docs/mobile/components/RadioGroup.txt +281 -0
  74. package/mcp-docs/mobile/components/ReferenceLine.txt +152 -0
  75. package/mcp-docs/mobile/components/RemoteImage.txt +105 -0
  76. package/mcp-docs/mobile/components/RemoteImageGroup.txt +60 -0
  77. package/mcp-docs/mobile/components/RollingNumber.txt +788 -0
  78. package/mcp-docs/mobile/components/Scrubber.txt +203 -0
  79. package/mcp-docs/mobile/components/SearchInput.txt +191 -0
  80. package/mcp-docs/mobile/components/SectionHeader.txt +204 -0
  81. package/mcp-docs/mobile/components/SegmentedTabs.txt +315 -0
  82. package/mcp-docs/mobile/components/Select.txt +211 -0
  83. package/mcp-docs/mobile/components/SelectChip.txt +323 -0
  84. package/mcp-docs/mobile/components/SelectOption.txt +84 -0
  85. package/mcp-docs/mobile/components/SlideButton.txt +330 -0
  86. package/mcp-docs/mobile/components/Spacer.txt +83 -0
  87. package/mcp-docs/mobile/components/Sparkline.txt +122 -0
  88. package/mcp-docs/mobile/components/SparklineGradient.txt +106 -0
  89. package/mcp-docs/mobile/components/SparklineInteractive.txt +156 -0
  90. package/mcp-docs/mobile/components/SparklineInteractiveHeader.txt +72 -0
  91. package/mcp-docs/mobile/components/Spinner.txt +48 -0
  92. package/mcp-docs/mobile/components/SpotIcon.txt +47 -0
  93. package/mcp-docs/mobile/components/SpotRectangle.txt +47 -0
  94. package/mcp-docs/mobile/components/SpotSquare.txt +47 -0
  95. package/mcp-docs/mobile/components/Stepper.txt +527 -0
  96. package/mcp-docs/mobile/components/SubBrandLogoMark.txt +125 -0
  97. package/mcp-docs/mobile/components/SubBrandLogoWordMark.txt +125 -0
  98. package/mcp-docs/mobile/components/Switch.txt +97 -0
  99. package/mcp-docs/mobile/components/TabIndicator.txt +48 -0
  100. package/mcp-docs/mobile/components/TabLabel.txt +153 -0
  101. package/mcp-docs/mobile/components/TabNavigation.txt +146 -0
  102. package/mcp-docs/mobile/components/TabbedChips.txt +142 -0
  103. package/mcp-docs/mobile/components/Tabs.txt +190 -0
  104. package/mcp-docs/mobile/components/Tag.txt +300 -0
  105. package/mcp-docs/mobile/components/Text.txt +211 -0
  106. package/mcp-docs/mobile/components/TextInput.txt +717 -0
  107. package/mcp-docs/mobile/components/ThemeProvider.txt +132 -0
  108. package/mcp-docs/mobile/components/Toast.txt +196 -0
  109. package/mcp-docs/mobile/components/Tooltip.txt +59 -0
  110. package/mcp-docs/mobile/components/TopNavBar.txt +161 -0
  111. package/mcp-docs/mobile/components/Tour.txt +158 -0
  112. package/mcp-docs/mobile/components/Tray.txt +252 -0
  113. package/mcp-docs/mobile/components/UpsellCard.txt +321 -0
  114. package/mcp-docs/mobile/components/VStack.txt +222 -0
  115. package/mcp-docs/mobile/components/XAxis.txt +621 -0
  116. package/mcp-docs/mobile/components/YAxis.txt +567 -0
  117. package/mcp-docs/mobile/getting-started/ai-overview.txt +108 -0
  118. package/mcp-docs/mobile/getting-started/installation.txt +57 -0
  119. package/mcp-docs/mobile/getting-started/introduction.txt +102 -0
  120. package/mcp-docs/mobile/getting-started/playground.txt +28 -0
  121. package/mcp-docs/mobile/getting-started/styling.txt +84 -0
  122. package/mcp-docs/mobile/getting-started/theming.txt +286 -0
  123. package/mcp-docs/mobile/hooks/useDimensions.txt +72 -0
  124. package/mcp-docs/mobile/hooks/useEventHandler.txt +120 -0
  125. package/mcp-docs/mobile/hooks/useMergeRefs.txt +116 -0
  126. package/mcp-docs/mobile/hooks/useOverlayContentContext.txt +280 -0
  127. package/mcp-docs/mobile/hooks/usePreviousValue.txt +74 -0
  128. package/mcp-docs/mobile/hooks/useRefMap.txt +178 -0
  129. package/mcp-docs/mobile/hooks/useTheme.txt +321 -0
  130. package/mcp-docs/mobile/routes.txt +139 -0
  131. package/mcp-docs/web/components/Accordion.txt +189 -0
  132. package/mcp-docs/web/components/AccordionItem.txt +31 -0
  133. package/mcp-docs/web/components/Alert.txt +164 -0
  134. package/mcp-docs/web/components/AreaChart.txt +510 -0
  135. package/mcp-docs/web/components/Avatar.txt +211 -0
  136. package/mcp-docs/web/components/AvatarButton.txt +240 -0
  137. package/mcp-docs/web/components/Banner.txt +226 -0
  138. package/mcp-docs/web/components/BarChart.txt +1267 -0
  139. package/mcp-docs/web/components/Box.txt +175 -0
  140. package/mcp-docs/web/components/Button.txt +212 -0
  141. package/mcp-docs/web/components/ButtonGroup.txt +79 -0
  142. package/mcp-docs/web/components/Calendar.txt +181 -0
  143. package/mcp-docs/web/components/Carousel.txt +1575 -0
  144. package/mcp-docs/web/components/CartesianChart.txt +1044 -0
  145. package/mcp-docs/web/components/CellMedia.txt +56 -0
  146. package/mcp-docs/web/components/Checkbox.txt +188 -0
  147. package/mcp-docs/web/components/CheckboxCell.txt +202 -0
  148. package/mcp-docs/web/components/CheckboxGroup.txt +219 -0
  149. package/mcp-docs/web/components/Chip.txt +196 -0
  150. package/mcp-docs/web/components/Coachmark.txt +188 -0
  151. package/mcp-docs/web/components/Collapsible.txt +119 -0
  152. package/mcp-docs/web/components/ContainedAssetCard.txt +232 -0
  153. package/mcp-docs/web/components/ContentCard.txt +367 -0
  154. package/mcp-docs/web/components/ContentCardBody.txt +137 -0
  155. package/mcp-docs/web/components/ContentCardFooter.txt +129 -0
  156. package/mcp-docs/web/components/ContentCardHeader.txt +147 -0
  157. package/mcp-docs/web/components/ContentCell.txt +219 -0
  158. package/mcp-docs/web/components/ControlGroup.txt +436 -0
  159. package/mcp-docs/web/components/DatePicker.txt +505 -0
  160. package/mcp-docs/web/components/Divider.txt +143 -0
  161. package/mcp-docs/web/components/DotCount.txt +149 -0
  162. package/mcp-docs/web/components/DotStatusColor.txt +58 -0
  163. package/mcp-docs/web/components/DotSymbol.txt +137 -0
  164. package/mcp-docs/web/components/Dropdown.txt +119 -0
  165. package/mcp-docs/web/components/Fallback.txt +163 -0
  166. package/mcp-docs/web/components/FloatingAssetCard.txt +250 -0
  167. package/mcp-docs/web/components/FullscreenAlert.txt +69 -0
  168. package/mcp-docs/web/components/FullscreenModal.txt +145 -0
  169. package/mcp-docs/web/components/FullscreenModalLayout.txt +187 -0
  170. package/mcp-docs/web/components/Grid.txt +236 -0
  171. package/mcp-docs/web/components/GridColumn.txt +209 -0
  172. package/mcp-docs/web/components/HStack.txt +236 -0
  173. package/mcp-docs/web/components/HeroSquare.txt +48 -0
  174. package/mcp-docs/web/components/Icon.txt +145 -0
  175. package/mcp-docs/web/components/IconButton.txt +390 -0
  176. package/mcp-docs/web/components/InputChip.txt +187 -0
  177. package/mcp-docs/web/components/Interactable.txt +193 -0
  178. package/mcp-docs/web/components/LineChart.txt +1576 -0
  179. package/mcp-docs/web/components/Link.txt +243 -0
  180. package/mcp-docs/web/components/ListCell.txt +418 -0
  181. package/mcp-docs/web/components/LogoMark.txt +84 -0
  182. package/mcp-docs/web/components/LogoWordMark.txt +93 -0
  183. package/mcp-docs/web/components/Lottie.txt +157 -0
  184. package/mcp-docs/web/components/LottieStatusAnimation.txt +57 -0
  185. package/mcp-docs/web/components/MediaQueryProvider.txt +108 -0
  186. package/mcp-docs/web/components/Modal.txt +196 -0
  187. package/mcp-docs/web/components/ModalBody.txt +117 -0
  188. package/mcp-docs/web/components/ModalFooter.txt +119 -0
  189. package/mcp-docs/web/components/ModalHeader.txt +123 -0
  190. package/mcp-docs/web/components/MultiContentModule.txt +381 -0
  191. package/mcp-docs/web/components/NavigationBar.txt +102 -0
  192. package/mcp-docs/web/components/NavigationTitle.txt +25 -0
  193. package/mcp-docs/web/components/NavigationTitleSelect.txt +45 -0
  194. package/mcp-docs/web/components/NudgeCard.txt +181 -0
  195. package/mcp-docs/web/components/Overlay.txt +171 -0
  196. package/mcp-docs/web/components/PageFooter.txt +184 -0
  197. package/mcp-docs/web/components/PageHeader.txt +243 -0
  198. package/mcp-docs/web/components/Pagination.txt +499 -0
  199. package/mcp-docs/web/components/PeriodSelector.txt +703 -0
  200. package/mcp-docs/web/components/Pictogram.txt +48 -0
  201. package/mcp-docs/web/components/Point.txt +460 -0
  202. package/mcp-docs/web/components/PortalProvider.txt +76 -0
  203. package/mcp-docs/web/components/Pressable.txt +193 -0
  204. package/mcp-docs/web/components/ProgressBar.txt +163 -0
  205. package/mcp-docs/web/components/ProgressBarWithFixedLabels.txt +212 -0
  206. package/mcp-docs/web/components/ProgressBarWithFloatLabel.txt +181 -0
  207. package/mcp-docs/web/components/ProgressCircle.txt +443 -0
  208. package/mcp-docs/web/components/Radio.txt +219 -0
  209. package/mcp-docs/web/components/RadioCell.txt +215 -0
  210. package/mcp-docs/web/components/RadioGroup.txt +288 -0
  211. package/mcp-docs/web/components/ReferenceLine.txt +451 -0
  212. package/mcp-docs/web/components/RemoteImage.txt +165 -0
  213. package/mcp-docs/web/components/RemoteImageGroup.txt +86 -0
  214. package/mcp-docs/web/components/RollingNumber.txt +1021 -0
  215. package/mcp-docs/web/components/Scrubber.txt +231 -0
  216. package/mcp-docs/web/components/SearchInput.txt +117 -0
  217. package/mcp-docs/web/components/SectionHeader.txt +217 -0
  218. package/mcp-docs/web/components/SegmentedTabs.txt +324 -0
  219. package/mcp-docs/web/components/Select.txt +224 -0
  220. package/mcp-docs/web/components/SelectChip.txt +314 -0
  221. package/mcp-docs/web/components/SelectOption.txt +165 -0
  222. package/mcp-docs/web/components/Sidebar.txt +349 -0
  223. package/mcp-docs/web/components/SidebarItem.txt +131 -0
  224. package/mcp-docs/web/components/SidebarMoreMenu.txt +30 -0
  225. package/mcp-docs/web/components/Spacer.txt +173 -0
  226. package/mcp-docs/web/components/Sparkline.txt +122 -0
  227. package/mcp-docs/web/components/SparklineGradient.txt +106 -0
  228. package/mcp-docs/web/components/SparklineInteractive.txt +153 -0
  229. package/mcp-docs/web/components/SparklineInteractiveHeader.txt +76 -0
  230. package/mcp-docs/web/components/Spinner.txt +128 -0
  231. package/mcp-docs/web/components/SpotIcon.txt +48 -0
  232. package/mcp-docs/web/components/SpotRectangle.txt +48 -0
  233. package/mcp-docs/web/components/SpotSquare.txt +48 -0
  234. package/mcp-docs/web/components/Stepper.txt +682 -0
  235. package/mcp-docs/web/components/SubBrandLogoMark.txt +125 -0
  236. package/mcp-docs/web/components/SubBrandLogoWordMark.txt +125 -0
  237. package/mcp-docs/web/components/Switch.txt +85 -0
  238. package/mcp-docs/web/components/TabIndicator.txt +48 -0
  239. package/mcp-docs/web/components/TabLabel.txt +158 -0
  240. package/mcp-docs/web/components/TabNavigation.txt +159 -0
  241. package/mcp-docs/web/components/TabbedChips.txt +155 -0
  242. package/mcp-docs/web/components/Table.txt +367 -0
  243. package/mcp-docs/web/components/TableBody.txt +83 -0
  244. package/mcp-docs/web/components/TableCaption.txt +102 -0
  245. package/mcp-docs/web/components/TableCell.txt +165 -0
  246. package/mcp-docs/web/components/TableCellFallback.txt +97 -0
  247. package/mcp-docs/web/components/TableFooter.txt +83 -0
  248. package/mcp-docs/web/components/TableHeader.txt +100 -0
  249. package/mcp-docs/web/components/TableRow.txt +140 -0
  250. package/mcp-docs/web/components/Tabs.txt +212 -0
  251. package/mcp-docs/web/components/Tag.txt +304 -0
  252. package/mcp-docs/web/components/Text.txt +232 -0
  253. package/mcp-docs/web/components/TextInput.txt +652 -0
  254. package/mcp-docs/web/components/ThemeProvider.txt +199 -0
  255. package/mcp-docs/web/components/TileButton.txt +158 -0
  256. package/mcp-docs/web/components/Toast.txt +203 -0
  257. package/mcp-docs/web/components/Tooltip.txt +89 -0
  258. package/mcp-docs/web/components/Tour.txt +179 -0
  259. package/mcp-docs/web/components/Tray.txt +288 -0
  260. package/mcp-docs/web/components/UpsellCard.txt +319 -0
  261. package/mcp-docs/web/components/VStack.txt +224 -0
  262. package/mcp-docs/web/components/XAxis.txt +619 -0
  263. package/mcp-docs/web/components/YAxis.txt +548 -0
  264. package/mcp-docs/web/getting-started/ai-overview.txt +108 -0
  265. package/mcp-docs/web/getting-started/installation.txt +103 -0
  266. package/mcp-docs/web/getting-started/introduction.txt +102 -0
  267. package/mcp-docs/web/getting-started/playground.txt +28 -0
  268. package/mcp-docs/web/getting-started/styling.txt +161 -0
  269. package/mcp-docs/web/getting-started/templates.txt +121 -0
  270. package/mcp-docs/web/getting-started/theming.txt +426 -0
  271. package/mcp-docs/web/hooks/useBreakpoints.txt +61 -0
  272. package/mcp-docs/web/hooks/useDimensions.txt +114 -0
  273. package/mcp-docs/web/hooks/useEventHandler.txt +120 -0
  274. package/mcp-docs/web/hooks/useHasMounted.txt +75 -0
  275. package/mcp-docs/web/hooks/useIsoEffect.txt +58 -0
  276. package/mcp-docs/web/hooks/useMediaQuery.txt +114 -0
  277. package/mcp-docs/web/hooks/useMergeRefs.txt +116 -0
  278. package/mcp-docs/web/hooks/useOverlayContentContext.txt +279 -0
  279. package/mcp-docs/web/hooks/usePreviousValue.txt +74 -0
  280. package/mcp-docs/web/hooks/useRefMap.txt +178 -0
  281. package/mcp-docs/web/hooks/useScrollBlocker.txt +82 -0
  282. package/mcp-docs/web/hooks/useTheme.txt +364 -0
  283. package/mcp-docs/web/routes.txt +163 -0
  284. package/package.json +1 -1
@@ -0,0 +1,1324 @@
1
+ # LineChart
2
+
3
+ A flexible line chart component for displaying data trends over time. Supports multiple series, custom curves, areas, scrubbing, and interactive data exploration.
4
+
5
+ ## Import
6
+
7
+ ```tsx
8
+ import { LineChart } from '@coinbase/cds-mobile-visualization'
9
+ ```
10
+
11
+ ## Examples
12
+
13
+ ### Basic Example
14
+
15
+ ```jsx
16
+ function BasicExample() {
17
+ const [scrubIndex, setScrubIndex] = useState(undefined);
18
+ const data = [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58];
19
+
20
+ const accessibilityLabel = useMemo(() => {
21
+ if (scrubIndex === undefined) return undefined;
22
+ return `Value: ${data[scrubIndex]} at index ${scrubIndex}`;
23
+ }, [scrubIndex, data]);
24
+
25
+ return (
26
+ <LineChart
27
+ enableScrubbing
28
+ onScrubberPositionChange={setScrubIndex}
29
+ height={150}
30
+ series={[
31
+ {
32
+ id: 'prices',
33
+ data: data,
34
+ },
35
+ ]}
36
+ curve="monotone"
37
+ showYAxis
38
+ showArea
39
+ yAxis={{
40
+ showGrid: true,
41
+ }}
42
+ accessibilityLabel={accessibilityLabel}
43
+ >
44
+ <Scrubber />
45
+ </LineChart>
46
+ );
47
+ }
48
+ ```
49
+
50
+ ### Simple
51
+
52
+ ```jsx
53
+ <LineChart
54
+ height={150}
55
+ series={[
56
+ {
57
+ id: 'prices',
58
+ data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58],
59
+ },
60
+ ]}
61
+ curve="monotone"
62
+ />
63
+ ```
64
+
65
+ ### Compact
66
+
67
+ You can specify the dimensions of the chart to make it more compact.
68
+
69
+ ```jsx
70
+ function CompactLineChart() {
71
+ const theme = useTheme();
72
+ const dimensions = { width: 62, height: 18 };
73
+
74
+ const sparklineData = prices
75
+ .map((price) => parseFloat(price))
76
+ .filter((price, index) => index % 10 === 0);
77
+ const positiveFloor = Math.min(...sparklineData) - 10;
78
+
79
+ const negativeData = sparklineData.map((price) => -1 * price).reverse();
80
+ const negativeCeiling = Math.max(...negativeData) + 10;
81
+
82
+ const formatPrice = useCallback((price: number) => {
83
+ return `$${price.toLocaleString('en-US', {
84
+ minimumFractionDigits: 2,
85
+ maximumFractionDigits: 2,
86
+ })}`;
87
+ }, []);
88
+
89
+ const CompactChart = memo(({ data, showArea, color, referenceY }) => (
90
+ <Box style={{ padding: 1 }}>
91
+ <LineChart
92
+ {...dimensions}
93
+ enableScrubbing={false}
94
+ overflow="visible"
95
+ inset={0}
96
+ showArea={showArea}
97
+ series={[
98
+ {
99
+ id: 'btc',
100
+ data,
101
+ color,
102
+ },
103
+ ]}
104
+ >
105
+ <ReferenceLine dataY={referenceY} />
106
+ </LineChart>
107
+ </Box>
108
+ ));
109
+
110
+ const ChartCell = memo(({ data, showArea, color, referenceY, subdetail, variant }) => {
111
+ return (
112
+ <ListCell
113
+ detail={formatPrice(parseFloat(prices[0]))}
114
+ intermediary={
115
+ <CompactChart data={data} showArea={showArea} color={color} referenceY={referenceY} />
116
+ }
117
+ media={<CellMedia source={assets.btc.imageUrl} title="BTC" type="image" />}
118
+ onClick={() => console.log('clicked')}
119
+ subdetail={subdetail}
120
+ title={isPhone ? undefined : assets.btc.name}
121
+ variant={variant}
122
+ style={{ padding: 0 }}
123
+ />
124
+ );
125
+ });
126
+
127
+ return (
128
+ <VStack gap={2}>
129
+ <ChartCell
130
+ data={sparklineData}
131
+ color={assets.btc.color}
132
+ referenceY={parseFloat(prices[Math.floor(prices.length / 4)])}
133
+ subdetail="-4.55%"
134
+ variant="negative"
135
+ />
136
+ <ChartCell
137
+ data={sparklineData}
138
+ showArea
139
+ color={assets.btc.color}
140
+ referenceY={parseFloat(prices[Math.floor(prices.length / 4)])}
141
+ subdetail="-4.55%"
142
+ variant="negative"
143
+ />
144
+ <ChartCell
145
+ data={sparklineData}
146
+ showArea
147
+ color={theme.color.fgPositive}
148
+ referenceY={positiveFloor}
149
+ subdetail="+0.25%"
150
+ variant="positive"
151
+ />
152
+ <ChartCell
153
+ data={negativeData}
154
+ showArea
155
+ color={theme.color.fgNegative}
156
+ referenceY={negativeCeiling}
157
+ subdetail="-4.55%"
158
+ variant="negative"
159
+ />
160
+ </VStack>
161
+ );
162
+ };
163
+ ```
164
+
165
+ ### Gain/Loss
166
+
167
+ You can use the y-axis scale and a [linearGradient](https://developer.mozilla.org/en-US/docs/Web/SVG/Reference/Element/linearGradient) to create a gain/loss chart.
168
+
169
+ ```jsx
170
+ function GainLossChart() {
171
+ const theme = useTheme();
172
+ const gradientId = useId();
173
+
174
+ const data = [-40, -28, -21, -5, 48, -5, -28, 2, -29, -46, 16, -30, -29, 8];
175
+
176
+ const priceFormatter = useCallback(
177
+ (value) =>
178
+ new Intl.NumberFormat('en-US', {
179
+ style: 'currency',
180
+ currency: 'USD',
181
+ maximumFractionDigits: 0,
182
+ }).format(value),
183
+ [],
184
+ );
185
+
186
+ const ChartDefs = ({ threshold = 0 }) => {
187
+ const { getYScale } = useCartesianChartContext();
188
+ // get the default y-axis scale
189
+ const yScale = getYScale();
190
+
191
+ if (yScale) {
192
+ const domain = yScale.domain();
193
+ const range = yScale.range();
194
+
195
+ const baselinePercentage = ((threshold - domain[0]) / (domain[1] - domain[0])) * 100;
196
+
197
+ const negativeColor = `rgb(${theme.color.gray15})`;
198
+ const positiveColor = theme.color.fgPositive;
199
+
200
+ return (
201
+ <Defs>
202
+ <LinearGradient
203
+ gradientUnits="userSpaceOnUse"
204
+ id={`${gradientId}-solid`}
205
+ x1="0%"
206
+ x2="0%"
207
+ y1={range[0]}
208
+ y2={range[1]}
209
+ >
210
+ <Stop offset="0%" stopColor={negativeColor} />
211
+ <Stop offset={`${baselinePercentage}%`} stopColor={negativeColor} />
212
+ <Stop offset={`${baselinePercentage}%`} stopColor={positiveColor} />
213
+ <Stop offset="100%" stopColor={positiveColor} />
214
+ </LinearGradient>
215
+ <LinearGradient
216
+ gradientUnits="userSpaceOnUse"
217
+ id={`${gradientId}-gradient`}
218
+ x1="0%"
219
+ x2="0%"
220
+ y1={range[0]}
221
+ y2={range[1]}
222
+ >
223
+ <Stop offset="0%" stopColor={negativeColor} stopOpacity={0.3} />
224
+ <Stop offset={`${baselinePercentage}%`} stopColor={negativeColor} stopOpacity={0} />
225
+ <Stop offset={`${baselinePercentage}%`} stopColor={positiveColor} stopOpacity={0} />
226
+ <Stop offset="100%" stopColor={positiveColor} stopOpacity={0.3} />
227
+ </LinearGradient>
228
+ </Defs>
229
+ );
230
+ }
231
+
232
+ return null;
233
+ };
234
+
235
+ const solidColor = `url(#${gradientId}-solid)`;
236
+
237
+ return (
238
+ <CartesianChart
239
+ enableScrubbing
240
+ height={150}
241
+ series={[
242
+ {
243
+ id: 'prices',
244
+ data: data,
245
+ color: solidColor,
246
+ },
247
+ ]}
248
+ padding={{ top: 1.5, bottom: 1.5, left: 2, right: 0 }}
249
+ >
250
+ <ChartDefs />
251
+ <YAxis requestedTickCount={2} showGrid tickLabelFormatter={priceFormatter} />
252
+ <Area seriesId="prices" curve="monotone" fill={`url(#${gradientId}-gradient)`} />
253
+ <Line strokeWidth={3} curve="monotone" seriesId="prices" stroke={solidColor} />
254
+ <Scrubber hideOverlay />
255
+ </CartesianChart>
256
+ );
257
+ }
258
+ ```
259
+
260
+ ### Multiple Series
261
+
262
+ You can add multiple series to a line chart.
263
+
264
+ ```jsx
265
+ function MultipleSeriesChart() {
266
+ const theme = useTheme();
267
+ const [scrubIndex, setScrubIndex] = useState(undefined);
268
+
269
+ const prices = [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58];
270
+ const volume = [4, 8, 11, 15, 16, 14, 16, 10, 12, 14, 16, 14, 16, 10];
271
+
272
+ return (
273
+ <LineChart
274
+ enableScrubbing
275
+ height={150}
276
+ series={[
277
+ {
278
+ id: 'prices',
279
+ data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58],
280
+ label: 'Prices',
281
+ color: theme.color.accentBoldBlue,
282
+ },
283
+ {
284
+ id: 'volume',
285
+ data: [4, 8, 11, 15, 16, 14, 16, 10, 12, 14, 16, 14, 16, 10],
286
+ label: 'Volume',
287
+ color: theme.color.accentBoldGreen,
288
+ },
289
+ ]}
290
+ showYAxis
291
+ yAxis={{
292
+ domain: {
293
+ min: 0,
294
+ },
295
+ showGrid: true,
296
+ }}
297
+ curve="monotone"
298
+ >
299
+ <Scrubber />
300
+ </LineChart>
301
+ );
302
+ }
303
+ ```
304
+
305
+ ### Points
306
+
307
+ You can use the `renderPoints` prop to dynamically show points on a line.
308
+
309
+ ```jsx
310
+ function PointsChart() {
311
+ const theme = useTheme();
312
+ const keyMarketShiftIndices = [4, 6, 7, 9, 10];
313
+ const data = [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58];
314
+
315
+ return (
316
+ <CartesianChart
317
+ height={150}
318
+ series={[
319
+ {
320
+ id: 'prices',
321
+ data: data,
322
+ },
323
+ ]}
324
+ >
325
+ <Area seriesId="prices" curve="monotone" fill={`rgb(${theme.color.blue5})`} />
326
+ <Line
327
+ seriesId="prices"
328
+ renderPoints={({ dataX, dataY, ...props }) =>
329
+ keyMarketShiftIndices.includes(dataX)
330
+ ? {
331
+ ...props,
332
+ strokeWidth: 2,
333
+ stroke: theme.color.bg,
334
+ radius: 5,
335
+ onClick: () =>
336
+ alert(
337
+ `You have clicked a key market shift at position ${dataX + 1} with value ${dataY}!`,
338
+ ),
339
+ accessibilityLabel: `Key market shift point at position ${dataX + 1}, value ${dataY}. Click to view details.`,
340
+ }
341
+ : false
342
+ }
343
+ curve="monotone"
344
+ />
345
+ </CartesianChart>
346
+ );
347
+ }
348
+ ```
349
+
350
+ ### Empty State
351
+
352
+ This example shows how to use an empty state for a line chart.
353
+
354
+ ```jsx
355
+ function EmptyStateChart() {
356
+ const theme = useTheme();
357
+ return (
358
+ <LineChart
359
+ series={[
360
+ {
361
+ id: 'line',
362
+ color: `rgb(${theme.color.gray50})`,
363
+ data: [1, 1],
364
+ showArea: true,
365
+ },
366
+ ]}
367
+ yAxis={{ domain: { min: -1, max: 3 } }}
368
+ height={150}
369
+ />
370
+ );
371
+ }
372
+ ```
373
+
374
+ ### Line Styles
375
+
376
+ ```jsx
377
+ <LineChart
378
+ height={150}
379
+ series={[
380
+ {
381
+ id: 'top',
382
+ data: [15, 28, 32, 44, 46, 36, 40, 45, 48, 38],
383
+ },
384
+ {
385
+ id: 'upperMiddle',
386
+ data: [12, 23, 21, 29, 34, 28, 31, 38, 42, 35],
387
+ color: '#ef4444',
388
+ type: 'dotted',
389
+ },
390
+ {
391
+ id: 'lowerMiddle',
392
+ data: [8, 15, 14, 25, 20, 18, 22, 28, 24, 30],
393
+ color: '#f59e0b',
394
+ curve: 'natural',
395
+ LineComponent: (props) => (
396
+ <GradientLine {...props} endColor="#F7931A" startColor="#E3D74D" strokeWidth={4} />
397
+ ),
398
+ },
399
+ {
400
+ id: 'bottom',
401
+ data: [4, 8, 11, 15, 16, 14, 16, 10, 12, 14],
402
+ color: '#800080',
403
+ curve: 'step',
404
+ AreaComponent: DottedArea,
405
+ showArea: true,
406
+ },
407
+ ]}
408
+ />
409
+ ```
410
+
411
+ ### Live Data
412
+
413
+ ```jsx
414
+ function LiveAssetPrice() {
415
+ const scrubberRef = useRef(null);
416
+ const [scrubIndex, setScrubIndex] = useState(undefined);
417
+
418
+ const initialData = useMemo(() => {
419
+ return sparklineInteractiveData.hour.map((d) => d.value);
420
+ }, []);
421
+
422
+ const [priceData, setPriceData] = useState(initialData);
423
+
424
+ const lastDataPointTimeRef = useRef(Date.now());
425
+ const updateCountRef = useRef(0);
426
+
427
+ const intervalSeconds = 3600 / initialData.length;
428
+
429
+ const maxPercentChange = Math.abs(initialData[initialData.length - 1] - initialData[0]) * 0.05;
430
+
431
+ useEffect(() => {
432
+ const priceUpdateInterval = setInterval(
433
+ () => {
434
+ setPriceData((currentData) => {
435
+ const newData = [...currentData];
436
+ const lastPrice = newData[newData.length - 1];
437
+
438
+ const priceChange = (Math.random() - 0.5) * maxPercentChange;
439
+ const newPrice = Math.round((lastPrice + priceChange) * 100) / 100;
440
+
441
+ // Check if we should roll over to a new data point
442
+ const currentTime = Date.now();
443
+ const timeSinceLastPoint = (currentTime - lastDataPointTimeRef.current) / 1000;
444
+
445
+ if (timeSinceLastPoint >= intervalSeconds) {
446
+ // Time for a new data point - remove first, add new at end
447
+ lastDataPointTimeRef.current = currentTime;
448
+ newData.shift(); // Remove oldest data point
449
+ newData.push(newPrice); // Add new data point
450
+ updateCountRef.current = 0;
451
+ } else {
452
+ // Just update the last data point
453
+ newData[newData.length - 1] = newPrice;
454
+ updateCountRef.current++;
455
+ }
456
+
457
+ return newData;
458
+ });
459
+
460
+ // Pulse the scrubber on each update
461
+ scrubberRef.current?.pulse();
462
+ },
463
+ 2000 + Math.random() * 1000,
464
+ );
465
+
466
+ return () => clearInterval(priceUpdateInterval);
467
+ }, [intervalSeconds, maxPercentChange]);
468
+
469
+ const accessibilityLabel = useMemo(() => {
470
+ if (scrubIndex === undefined)
471
+ return `Bitcoin Price: $${priceData[priceData.length - 1].toFixed(2)}`;
472
+ const price = priceData[scrubIndex];
473
+ return `Bitcoin Price: $${price.toFixed(2)} at position ${scrubIndex + 1}`;
474
+ }, [scrubIndex, priceData]);
475
+
476
+ return (
477
+ <LineChart
478
+ enableScrubbing
479
+ onScrubberPositionChange={setScrubIndex}
480
+ showArea
481
+ height={150}
482
+ series={[
483
+ {
484
+ id: 'btc',
485
+ data: priceData,
486
+ color: assets.btc.color,
487
+ },
488
+ ]}
489
+ inset={{ right: 64 }}
490
+ accessibilityLabel={accessibilityLabel}
491
+ >
492
+ <Scrubber ref={scrubberRef} labelProps={{ elevation: 1 }} />
493
+ </LineChart>
494
+ );
495
+ }
496
+ ```
497
+
498
+ ### Data Format
499
+
500
+ You can adjust the y values for a series of data by setting the `data` prop on the xAxis.
501
+
502
+ ```jsx
503
+ function DataFormatChart() {
504
+ const [scrubIndex, setScrubIndex] = useState(undefined);
505
+
506
+ const yData = [2, 5.5, 2, 8.5, 1.5, 5];
507
+ const xData = [1, 2, 3, 5, 8, 10];
508
+
509
+ const accessibilityLabel = useMemo(() => {
510
+ if (scrubIndex === undefined) return undefined;
511
+ return `X: ${xData[scrubIndex]}, Y: ${yData[scrubIndex]} at point ${scrubIndex + 1}`;
512
+ }, [scrubIndex, xData, yData]);
513
+
514
+ return (
515
+ <LineChart
516
+ enableScrubbing
517
+ onScrubberPositionChange={setScrubIndex}
518
+ series={[
519
+ {
520
+ id: 'line',
521
+ data: yData,
522
+ },
523
+ ]}
524
+ height={150}
525
+ showArea
526
+ renderPoints={() => true}
527
+ curve="natural"
528
+ showXAxis
529
+ xAxis={{ data: xData, showLine: true, showTickMarks: true, showGrid: true }}
530
+ showYAxis
531
+ yAxis={{
532
+ domain: { min: 0 },
533
+ position: 'left',
534
+ showLine: true,
535
+ showTickMarks: true,
536
+ showGrid: true,
537
+ }}
538
+ inset={{ top: 16, right: 16, bottom: 0, left: 0 }}
539
+ accessibilityLabel={accessibilityLabel}
540
+ >
541
+ <Scrubber hideOverlay />
542
+ </LineChart>
543
+ );
544
+ }
545
+ ```
546
+
547
+ ### Accessibility
548
+
549
+ You can use `accessibilityLabel` to provide a descriptive label for the chart. This is especially important for charts with scrubbing enabled, where the label should update dynamically to reflect the current data point.
550
+
551
+ ```jsx
552
+ function AccessibleBasicChart() {
553
+ const [scrubIndex, setScrubIndex] = useState(undefined);
554
+ const data = [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58];
555
+
556
+ const accessibilityLabel = useMemo(() => {
557
+ if (scrubIndex === undefined) {
558
+ return `Current price: ${data[data.length - 1]}`;
559
+ }
560
+ return `Price at position ${scrubIndex + 1}: ${data[scrubIndex]}`;
561
+ }, [scrubIndex, data]);
562
+
563
+ return (
564
+ <LineChart
565
+ enableScrubbing
566
+ onScrubberPositionChange={setScrubIndex}
567
+ height={150}
568
+ series={[
569
+ {
570
+ id: 'prices',
571
+ data: data,
572
+ },
573
+ ]}
574
+ curve="monotone"
575
+ showYAxis
576
+ showArea
577
+ yAxis={{
578
+ showGrid: true,
579
+ }}
580
+ accessibilityLabel={accessibilityLabel}
581
+ >
582
+ <Scrubber />
583
+ </LineChart>
584
+ );
585
+ }
586
+ ```
587
+
588
+ When a chart has a visible header or title, you can use `aria-labelledby` to reference it.
589
+
590
+ ```jsx
591
+ function AccessibleChartWithHeader() {
592
+ const headerId = useId();
593
+ const [scrubIndex, setScrubIndex] = useState(undefined);
594
+ const data = [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58];
595
+
596
+ const accessibilityLabel = useMemo(() => {
597
+ if (scrubIndex === undefined) {
598
+ return `Line chart showing price trend. Current value: ${data[data.length - 1]}`;
599
+ }
600
+ return `Value: ${data[scrubIndex]} at position ${scrubIndex + 1}`;
601
+ }, [scrubIndex, data]);
602
+
603
+ return (
604
+ <VStack gap={2}>
605
+ <Text id={headerId} font="label1">
606
+ {accessibilityLabel}
607
+ </Text>
608
+ <LineChart
609
+ enableScrubbing
610
+ onScrubberPositionChange={setScrubIndex}
611
+ height={150}
612
+ series={[
613
+ {
614
+ id: 'revenue',
615
+ data: data,
616
+ },
617
+ ]}
618
+ curve="monotone"
619
+ showYAxis
620
+ showArea
621
+ yAxis={{
622
+ showGrid: true,
623
+ }}
624
+ aria-labelledby={headerId}
625
+ >
626
+ <Scrubber />
627
+ </LineChart>
628
+ </VStack>
629
+ );
630
+ }
631
+ ```
632
+
633
+ ### Customization
634
+
635
+ #### Asset Price with Dotted Area
636
+
637
+ ```jsx
638
+ function AssetPriceWithDottedArea() {
639
+ const BTCTab: TabComponent = memo(
640
+ forwardRef(
641
+ ({ label, ...props }: SegmentedTabProps, ref: React.ForwardedRef<HTMLButtonElement>) => {
642
+ const { activeTab } = useTabsContext();
643
+ const isActive = activeTab?.id === props.id;
644
+
645
+ return (
646
+ <SegmentedTab
647
+ ref={ref}
648
+ label={
649
+ <TextLabel1
650
+ style={{
651
+ transition: 'color 0.2s ease',
652
+ color: isActive ? assets.btc.color : undefined,
653
+ }}
654
+ >
655
+ {label}
656
+ </TextLabel1>
657
+ }
658
+ {...props}
659
+ />
660
+ );
661
+ },
662
+ ),
663
+ );
664
+
665
+ const BTCActiveIndicator = memo(({ style, ...props }: TabsActiveIndicatorProps) => (
666
+ <PeriodSelectorActiveIndicator
667
+ {...props}
668
+ style={{ ...style, backgroundColor: `${assets.btc.color}1A` }}
669
+ />
670
+ ));
671
+
672
+ const AssetPriceDotted = memo(() => {
673
+ const [scrubIndex, setScrubIndex] = useState<number | undefined>(undefined);
674
+ const currentPrice =
675
+ sparklineInteractiveData.hour[sparklineInteractiveData.hour.length - 1].value;
676
+ const tabs = [
677
+ { id: 'hour', label: '1H' },
678
+ { id: 'day', label: '1D' },
679
+ { id: 'week', label: '1W' },
680
+ { id: 'month', label: '1M' },
681
+ { id: 'year', label: '1Y' },
682
+ { id: 'all', label: 'All' },
683
+ ];
684
+ const [timePeriod, setTimePeriod] = useState<TabValue>(tabs[0]);
685
+
686
+ const sparklineTimePeriodData = useMemo(() => {
687
+ return sparklineInteractiveData[timePeriod.id as keyof typeof sparklineInteractiveData];
688
+ }, [timePeriod]);
689
+
690
+ const sparklineTimePeriodDataValues = useMemo(() => {
691
+ return sparklineTimePeriodData.map((d) => d.value);
692
+ }, [sparklineTimePeriodData]);
693
+
694
+ const sparklineTimePeriodDataTimestamps = useMemo(() => {
695
+ return sparklineTimePeriodData.map((d) => d.date);
696
+ }, [sparklineTimePeriodData]);
697
+
698
+ const onPeriodChange = useCallback(
699
+ (period: TabValue | null) => {
700
+ setTimePeriod(period || tabs[0]);
701
+ },
702
+ [tabs, setTimePeriod],
703
+ );
704
+
705
+ const priceFormatter = useMemo(
706
+ () =>
707
+ new Intl.NumberFormat('en-US', {
708
+ style: 'currency',
709
+ currency: 'USD',
710
+ }),
711
+ [],
712
+ );
713
+
714
+ const scrubberPriceFormatter = useMemo(
715
+ () =>
716
+ new Intl.NumberFormat('en-US', {
717
+ minimumFractionDigits: 2,
718
+ maximumFractionDigits: 2,
719
+ }),
720
+ [],
721
+ );
722
+
723
+ const formatPrice = useCallback((price: number) => {
724
+ return priceFormatter.format(price);
725
+ }, [priceFormatter]);
726
+
727
+ const formatDate = useCallback((date: Date) => {
728
+ const dayOfWeek = date.toLocaleDateString('en-US', { weekday: 'short' });
729
+
730
+ const monthDay = date.toLocaleDateString('en-US', {
731
+ month: 'short',
732
+ day: 'numeric',
733
+ });
734
+
735
+ const time = date.toLocaleTimeString('en-US', {
736
+ hour: 'numeric',
737
+ minute: '2-digit',
738
+ hour12: true,
739
+ });
740
+
741
+ return `${dayOfWeek}, ${monthDay}, ${time}`;
742
+ }, []);
743
+
744
+ const scrubberLabel = useCallback(
745
+ (index: number) => {
746
+ const price = scrubberPriceFormatter.format(sparklineTimePeriodDataValues[index]);
747
+ const date = formatDate(sparklineTimePeriodDataTimestamps[index]);
748
+ return (
749
+ <>
750
+ <tspan style={{ fontWeight: 'bold' }}>{price} USD</tspan> {date}
751
+ </>
752
+ );
753
+ },
754
+ [scrubberPriceFormatter, sparklineTimePeriodDataValues, sparklineTimePeriodDataTimestamps, formatDate],
755
+ );
756
+
757
+ const accessibilityLabel = useCallback(
758
+ (index: number) => {
759
+ const price = scrubberPriceFormatter.format(sparklineTimePeriodDataValues[index]);
760
+ const date = formatDate(sparklineTimePeriodDataTimestamps[index]);
761
+ return `${price} USD ${date}`;
762
+ },
763
+ [scrubberPriceFormatter, sparklineTimePeriodDataValues, sparklineTimePeriodDataTimestamps, formatDate],
764
+ );
765
+
766
+ return (
767
+ <VStack gap={2}>
768
+ <SectionHeader
769
+ style={{ padding: 0 }}
770
+ title={<Text font="title1">Bitcoin</Text>}
771
+ balance={<Text font="title2">{formatPrice(currentPrice)}</Text>}
772
+ end={
773
+ <VStack justifyContent="center">
774
+ <RemoteImage source={assets.btc.imageUrl} size="xl" shape="circle" />
775
+ </VStack>
776
+ }
777
+ />
778
+ <LineChart
779
+ overflow="visible"
780
+ enableScrubbing
781
+ onScrubberPositionChange={setScrubIndex}
782
+ series={[
783
+ {
784
+ id: 'btc',
785
+ data: sparklineTimePeriodDataValues,
786
+ color: assets.btc.color,
787
+ },
788
+ ]}
789
+ showArea
790
+ areaType="dotted"
791
+ height={150}
792
+ style={{ outlineColor: assets.btc.color }}
793
+ accessibilityLabel={scrubberLabel}
794
+ padding={{ left: 2, right: 2 }}
795
+ >
796
+ <Scrubber label={scrubberLabel} labelProps={{ elevation: 1 }} idlePulse />
797
+ </LineChart>
798
+ <PeriodSelector
799
+ TabComponent={BTCTab}
800
+ TabsActiveIndicatorComponent={BTCActiveIndicator}
801
+ tabs={tabs}
802
+ activeTab={timePeriod}
803
+ onChange={onPeriodChange}
804
+ />
805
+ </VStack>
806
+ )});
807
+
808
+ return <AssetPriceDotted />;
809
+ };
810
+ ```
811
+
812
+ #### Forecast Asset Price
813
+
814
+ ```jsx
815
+ function ForecastAssetPrice() {
816
+ const ForecastAreaComponent = memo(
817
+ (props: AreaComponentProps) => (
818
+ <DottedArea {...props} peakOpacity={0.4} baselineOpacity={0.4} />
819
+ ),
820
+ );
821
+
822
+ const ForecastChart = memo(() => {
823
+ const [scrubIndex, setScrubIndex] = useState<number | undefined>(undefined);
824
+
825
+ const getDataFromSparkline = useCallback((startDate: Date) => {
826
+ const allData = sparklineInteractiveData.all;
827
+ if (!allData || allData.length === 0) return [];
828
+
829
+ const timelineData = allData.filter((point) => point.date >= startDate);
830
+
831
+ return timelineData.map((point) => ({
832
+ date: point.date,
833
+ value: point.value,
834
+ }));
835
+ }, []);
836
+
837
+ const historicalData = useMemo(() => getDataFromSparkline(new Date('2019-01-01')), [getDataFromSparkline]);
838
+
839
+ const annualGrowthRate = 10;
840
+
841
+ const generateForecastData = useCallback(
842
+ (lastDate: Date, lastPrice: number, growthRate: number) => {
843
+ const dailyGrowthRate = Math.pow(1 + growthRate / 100, 1 / 365) - 1;
844
+ const forecastData = [];
845
+ const fiveYearsFromNow = new Date(lastDate);
846
+ fiveYearsFromNow.setFullYear(fiveYearsFromNow.getFullYear() + 5);
847
+
848
+ // Generate daily forecast points for 5 years
849
+ const currentDate = new Date(lastDate);
850
+ let currentPrice = lastPrice;
851
+
852
+ while (currentDate <= fiveYearsFromNow) {
853
+ currentPrice = currentPrice * (1 + dailyGrowthRate * 10);
854
+ forecastData.push({
855
+ date: new Date(currentDate),
856
+ value: Math.round(currentPrice),
857
+ });
858
+ currentDate.setDate(currentDate.getDate() + 10);
859
+ }
860
+
861
+ return forecastData;
862
+ },
863
+ [],
864
+ );
865
+
866
+ const priceFormatter = useMemo(
867
+ () =>
868
+ new Intl.NumberFormat('en-US', {
869
+ minimumFractionDigits: 2,
870
+ maximumFractionDigits: 2,
871
+ }),
872
+ [],
873
+ );
874
+
875
+ const formatDate = useCallback((date: Date) => {
876
+ const dayOfWeek = date.toLocaleDateString('en-US', { weekday: 'short' });
877
+
878
+ const monthDay = date.toLocaleDateString('en-US', {
879
+ month: 'short',
880
+ day: 'numeric',
881
+ });
882
+
883
+ const time = date.toLocaleTimeString('en-US', {
884
+ hour: 'numeric',
885
+ minute: '2-digit',
886
+ hour12: true,
887
+ });
888
+
889
+ return `${dayOfWeek}, ${monthDay}, ${time}`;
890
+ }, []);
891
+
892
+ const forecastData = useMemo(() => {
893
+ if (historicalData.length === 0) return [];
894
+ const lastPoint = historicalData[historicalData.length - 1];
895
+ return generateForecastData(lastPoint.date, lastPoint.value, annualGrowthRate);
896
+ }, [generateForecastData, historicalData, annualGrowthRate]);
897
+
898
+ // Combine all data points with dates converted to timestamps for x-axis
899
+ const allDataPoints = useMemo(
900
+ () => [...historicalData, ...forecastData],
901
+ [historicalData, forecastData],
902
+ );
903
+
904
+ const historicalDataValues = useMemo(
905
+ () => historicalData.map((d) => d.value),
906
+ [historicalData],
907
+ );
908
+
909
+ const forecastDataValues = useMemo(
910
+ () => [...historicalData.map((d) => null), ...forecastData.map((d) => d.value)],
911
+ [historicalData, forecastData],
912
+ );
913
+
914
+ const xAxisData = useMemo(
915
+ () => allDataPoints.map((d) => d.date.getTime()),
916
+ [allDataPoints],
917
+ );
918
+
919
+ const scrubberLabel = useCallback(
920
+ (index: number) => {
921
+ const price = priceFormatter.format(allDataPoints[index].value);
922
+ const date = formatDate(allDataPoints[index].date);
923
+ return (
924
+ <>
925
+ <tspan style={{ fontWeight: 'bold' }}>{price} USD</tspan> {date}
926
+ </>
927
+ );
928
+ },
929
+ [priceFormatter, allDataPoints, formatDate],
930
+ );
931
+
932
+ const accessibilityLabel = useCallback(
933
+ (index: number) => {
934
+ const price = priceFormatter.format(allDataPoints[index].value);
935
+ const date = formatDate(allDataPoints[index].date);
936
+ return `${price} USD ${date}`;
937
+ },
938
+ [priceFormatter, allDataPoints, formatDate],
939
+ );
940
+
941
+ return (
942
+ <LineChart
943
+ overflow="visible"
944
+ animate={false}
945
+ enableScrubbing
946
+ showArea
947
+ showXAxis
948
+ AreaComponent={ForecastAreaComponent}
949
+ height={150}
950
+ padding={{
951
+ top: 4,
952
+ left: 2,
953
+ right: 2,
954
+ bottom: 0,
955
+ }}
956
+ series={[
957
+ {
958
+ id: 'historical',
959
+ data: historicalDataValues,
960
+ color: assets.btc.color,
961
+ },
962
+ {
963
+ id: 'forecast',
964
+ data: forecastDataValues,
965
+ color: assets.btc.color,
966
+ type: 'dotted',
967
+ },
968
+ ]}
969
+ xAxis={{
970
+ data: xAxisData,
971
+ tickLabelFormatter: (value: number) => {
972
+ return new Date(value).toLocaleDateString('en-US', {
973
+ month: 'numeric',
974
+ year: 'numeric',
975
+ });
976
+ },
977
+ tickInterval: 2,
978
+ }}
979
+ accessibilityLabel={accessibilityLabel}
980
+ style={{ outlineColor: assets.btc.color }}
981
+ >
982
+ <Scrubber label={scrubberLabel} labelProps={{ elevation: 1 }} />
983
+ </LineChart>
984
+ );
985
+ });
986
+
987
+ return <ForecastChart />;
988
+ };
989
+ ```
990
+
991
+ #### Availability
992
+
993
+ ```jsx
994
+ function AvailabilityChart() {
995
+ const theme = useTheme();
996
+ const [scrubIndex, setScrubIndex] = useState(undefined);
997
+
998
+ const availabilityEvents = [
999
+ {
1000
+ date: new Date('2022-01-01'),
1001
+ availability: 79,
1002
+ },
1003
+ {
1004
+ date: new Date('2022-01-03'),
1005
+ availability: 81,
1006
+ },
1007
+ {
1008
+ date: new Date('2022-01-04'),
1009
+ availability: 82,
1010
+ },
1011
+ {
1012
+ date: new Date('2022-01-06'),
1013
+ availability: 91,
1014
+ },
1015
+ {
1016
+ date: new Date('2022-01-07'),
1017
+ availability: 92,
1018
+ },
1019
+ {
1020
+ date: new Date('2022-01-10'),
1021
+ availability: 86,
1022
+ },
1023
+ ];
1024
+
1025
+ const accessibilityLabel = useMemo(() => {
1026
+ if (scrubIndex === undefined) return undefined;
1027
+ const event = availabilityEvents[scrubIndex];
1028
+ const formattedDate = event.date.toLocaleDateString('en-US', {
1029
+ weekday: 'short',
1030
+ month: 'short',
1031
+ day: 'numeric',
1032
+ year: 'numeric',
1033
+ });
1034
+ const status =
1035
+ event.availability >= 90 ? 'Good' : event.availability >= 85 ? 'Warning' : 'Critical';
1036
+ return `${formattedDate}: Availability ${event.availability}% - Status: ${status}`;
1037
+ }, [scrubIndex, availabilityEvents]);
1038
+
1039
+ const ChartDefs = memo(({ yellowThresholdPercentage = 85, greenThresholdPercentage = 90 }) => {
1040
+ const { drawingArea, height, series, getYScale, getYAxis } = useCartesianChartContext();
1041
+ const yScale = getYScale();
1042
+ const yAxis = getYAxis();
1043
+
1044
+ if (!series || !drawingArea || !yScale) return null;
1045
+
1046
+ const rangeBounds = yAxis?.domain;
1047
+ const rangeMin = rangeBounds?.min ?? 0;
1048
+ const rangeMax = rangeBounds?.max ?? 100;
1049
+
1050
+ // Calculate the Y positions in the chart coordinate system
1051
+ const yellowThresholdY = yScale(yellowThresholdPercentage) ?? 0;
1052
+ const greenThresholdY = yScale(greenThresholdPercentage) ?? 0;
1053
+ const minY = yScale(rangeMax) ?? 0; // Top of chart (max value)
1054
+ const maxY = yScale(rangeMin) ?? drawingArea.height; // Bottom of chart (min value)
1055
+
1056
+ // Calculate percentages based on actual chart positions
1057
+ const yellowThreshold = ((yellowThresholdY - minY) / (maxY - minY)) * 100;
1058
+ const greenThreshold = ((greenThresholdY - minY) / (maxY - minY)) * 100;
1059
+
1060
+ return (
1061
+ <Defs>
1062
+ <LinearGradient
1063
+ gradientUnits="userSpaceOnUse"
1064
+ id="availabilityGradient"
1065
+ x1="0%"
1066
+ x2="0%"
1067
+ y1={minY}
1068
+ y2={maxY}
1069
+ >
1070
+ <stop offset="0%" stopColor={theme.color.fgPositive} />
1071
+ <stop offset={`${greenThreshold}%`} stopColor={theme.color.fgPositive} />
1072
+ <stop offset={`${greenThreshold}%`} stopColor={theme.color.fgWarning} />
1073
+ <stop offset={`${yellowThreshold}%`} stopColor={theme.color.fgWarning} />
1074
+ <stop offset={`${yellowThreshold}%`} stopColor={theme.color.fgNegative} />
1075
+ <stop offset="100%" stopColor={theme.color.fgNegative} />
1076
+ </LinearGradient>
1077
+ </Defs>
1078
+ );
1079
+ });
1080
+
1081
+ return (
1082
+ <CartesianChart
1083
+ enableScrubbing
1084
+ onScrubberPositionChange={setScrubIndex}
1085
+ height={150}
1086
+ series={[
1087
+ {
1088
+ id: 'availability',
1089
+ data: availabilityEvents.map((event) => event.availability),
1090
+ color: 'url(#availabilityGradient)',
1091
+ },
1092
+ ]}
1093
+ xAxis={{
1094
+ data: availabilityEvents.map((event) => event.date.getTime()),
1095
+ }}
1096
+ yAxis={{
1097
+ domain: ({ min, max }) => ({ min: Math.max(min - 2, 0), max: Math.min(max + 2, 100) }),
1098
+ }}
1099
+ padding={{ left: 2, right: 2 }}
1100
+ accessibilityLabel={accessibilityLabel}
1101
+ >
1102
+ <ChartDefs />
1103
+ <XAxis
1104
+ showGrid
1105
+ showLine
1106
+ showTickMarks
1107
+ tickLabelFormatter={(value) => new Date(value).toLocaleDateString()}
1108
+ />
1109
+ <YAxis
1110
+ showGrid
1111
+ showLine
1112
+ showTickMarks
1113
+ position="left"
1114
+ tickLabelFormatter={(value) => `${value}%`}
1115
+ />
1116
+ <Line
1117
+ curve="stepAfter"
1118
+ renderPoints={() => ({
1119
+ fill: theme.color.bg,
1120
+ stroke: 'url(#availabilityGradient)',
1121
+ strokeWidth: 2,
1122
+ })}
1123
+ seriesId="availability"
1124
+ />
1125
+ <Scrubber hideOverlay />
1126
+ </CartesianChart>
1127
+ );
1128
+ }
1129
+ ```
1130
+
1131
+ #### Asset Price Widget
1132
+
1133
+ You can coordinate LineChart with custom styles to create a custom card that shows the latest price and percent change.
1134
+
1135
+ ```jsx
1136
+ function BitcoinChartWithScrubberBeacon() {
1137
+ const theme = useTheme();
1138
+ const prices = [...btcCandles].reverse().map((candle) => parseFloat(candle.close));
1139
+ const latestPrice = prices[prices.length - 1];
1140
+
1141
+ const formatPrice = (price: number) => {
1142
+ return new Intl.NumberFormat('en-US', {
1143
+ style: 'currency',
1144
+ currency: 'USD',
1145
+ }).format(price);
1146
+ };
1147
+
1148
+ const formatPercentChange = (price: number) => {
1149
+ return new Intl.NumberFormat('en-US', {
1150
+ style: 'percent',
1151
+ minimumFractionDigits: 2,
1152
+ maximumFractionDigits: 2,
1153
+ }).format(price);
1154
+ };
1155
+
1156
+ const percentChange = (latestPrice - prices[0]) / prices[0];
1157
+
1158
+ return (
1159
+ <VStack
1160
+ style={{
1161
+ background:
1162
+ 'linear-gradient(0deg, rgba(0, 0, 0, 0.80) 0%, rgba(0, 0, 0, 0.80) 100%), #ED702F',
1163
+ }}
1164
+ borderRadius={300}
1165
+ gap={2}
1166
+ padding={2}
1167
+ paddingBottom={0}
1168
+ overflow="hidden"
1169
+ >
1170
+ <HStack gap={2} alignItems="center">
1171
+ <RemoteImage source={assets.btc.imageUrl} size="xxl" shape="circle" aria-hidden />
1172
+ <VStack gap={0.25} alignItems="flex-end" flexGrow={1}>
1173
+ <Text font="title1" style={{ color: 'white' }}>
1174
+ {formatPrice(latestPrice)}
1175
+ </Text>
1176
+ <Text font="label1" color="fgPositive" accessibilityLabel={`Up ${formatPercentChange(percentChange)}`}>
1177
+ +{formatPercentChange(percentChange)}
1178
+ </Text>
1179
+ </VStack>
1180
+ </HStack>
1181
+ <div
1182
+ style={{
1183
+ marginLeft: `calc(-1 * ${theme.space[2]})`,
1184
+ marginRight: `calc(-1 * ${theme.space[2]})`,
1185
+ }}
1186
+ >
1187
+ <LineChart
1188
+ inset={{ left: 0, right: 18, bottom: 0, top: 0 }}
1189
+ series={[
1190
+ {
1191
+ id: 'btcPrice',
1192
+ data: prices,
1193
+ color: assets.btc.color,
1194
+ },
1195
+ ]}
1196
+ showArea
1197
+ width="100%"
1198
+ height={92}
1199
+ >
1200
+ <Scrubber idlePulse styles={{ beacon: { stroke: 'white' } }} />
1201
+ </LineChart>
1202
+ </div>
1203
+ </VStack>
1204
+ );
1205
+ };
1206
+ ```
1207
+
1208
+ ## Props
1209
+
1210
+ | Prop | Type | Required | Default | Description |
1211
+ | --- | --- | --- | --- | --- |
1212
+ | `AreaComponent` | `AreaComponent` | No | `-` | Custom component to render line area fill. |
1213
+ | `LineComponent` | `LineComponent` | No | `-` | Component to render the line. Takes precedence over the type prop if provided. |
1214
+ | `alignContent` | `flex-start \| flex-end \| center \| stretch \| space-between \| space-around \| space-evenly` | No | `-` | - |
1215
+ | `alignItems` | `flex-start \| flex-end \| center \| stretch \| baseline` | No | `-` | - |
1216
+ | `alignSelf` | `auto \| FlexAlignType` | No | `-` | - |
1217
+ | `allowOverflowGestures` | `boolean` | No | `-` | Allows continuous gestures on the chart to continue outside the bounds of the chart element. |
1218
+ | `animate` | `boolean` | No | `true` | Whether to animate the chart. |
1219
+ | `animated` | `boolean` | No | `-` | - |
1220
+ | `areaType` | `solid \| dotted \| gradient` | No | `'gradient'` | The type of area fill to add to the line. |
1221
+ | `aspectRatio` | `string \| number` | No | `-` | - |
1222
+ | `background` | `currentColor \| fg \| fgMuted \| fgInverse \| fgPrimary \| fgWarning \| fgPositive \| fgNegative \| bg \| bgAlternate \| bgInverse \| bgOverlay \| bgElevation1 \| bgElevation2 \| bgPrimary \| bgPrimaryWash \| bgSecondary \| bgTertiary \| bgSecondaryWash \| bgNegative \| bgNegativeWash \| bgPositive \| bgPositiveWash \| bgWarning \| bgWarningWash \| bgLine \| bgLineHeavy \| bgLineInverse \| bgLinePrimary \| bgLinePrimarySubtle \| accentSubtleRed \| accentBoldRed \| accentSubtleGreen \| accentBoldGreen \| accentSubtleBlue \| accentBoldBlue \| accentSubtlePurple \| accentBoldPurple \| accentSubtleYellow \| accentBoldYellow \| accentSubtleGray \| accentBoldGray \| transparent` | No | `-` | - |
1223
+ | `borderBottomLeftRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
1224
+ | `borderBottomRightRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
1225
+ | `borderBottomWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
1226
+ | `borderColor` | `currentColor \| fg \| fgMuted \| fgInverse \| fgPrimary \| fgWarning \| fgPositive \| fgNegative \| bg \| bgAlternate \| bgInverse \| bgOverlay \| bgElevation1 \| bgElevation2 \| bgPrimary \| bgPrimaryWash \| bgSecondary \| bgTertiary \| bgSecondaryWash \| bgNegative \| bgNegativeWash \| bgPositive \| bgPositiveWash \| bgWarning \| bgWarningWash \| bgLine \| bgLineHeavy \| bgLineInverse \| bgLinePrimary \| bgLinePrimarySubtle \| accentSubtleRed \| accentBoldRed \| accentSubtleGreen \| accentBoldGreen \| accentSubtleBlue \| accentBoldBlue \| accentSubtlePurple \| accentBoldPurple \| accentSubtleYellow \| accentBoldYellow \| accentSubtleGray \| accentBoldGray \| transparent` | No | `-` | - |
1227
+ | `borderEndWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
1228
+ | `borderRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
1229
+ | `borderStartWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
1230
+ | `borderTopLeftRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
1231
+ | `borderTopRightRadius` | `0 \| 100 \| 200 \| 300 \| 400 \| 500 \| 600 \| 700 \| 800 \| 900 \| 1000` | No | `-` | - |
1232
+ | `borderTopWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
1233
+ | `borderWidth` | `0 \| 100 \| 200 \| 300 \| 400 \| 500` | No | `-` | - |
1234
+ | `bordered` | `boolean` | No | `-` | Add a border around all sides of the box. |
1235
+ | `borderedBottom` | `boolean` | No | `-` | Add a border to the bottom side of the box. |
1236
+ | `borderedEnd` | `boolean` | No | `-` | Add a border to the trailing side of the box. |
1237
+ | `borderedHorizontal` | `boolean` | No | `-` | Add a border to the leading and trailing sides of the box. |
1238
+ | `borderedStart` | `boolean` | No | `-` | Add a border to the leading side of the box. |
1239
+ | `borderedTop` | `boolean` | No | `-` | Add a border to the top side of the box. |
1240
+ | `borderedVertical` | `boolean` | No | `-` | Add a border to the top and bottom sides of the box. |
1241
+ | `bottom` | `string \| number` | No | `-` | - |
1242
+ | `color` | `currentColor \| fg \| fgMuted \| fgInverse \| fgPrimary \| fgWarning \| fgPositive \| fgNegative \| bg \| bgAlternate \| bgInverse \| bgOverlay \| bgElevation1 \| bgElevation2 \| bgPrimary \| bgPrimaryWash \| bgSecondary \| bgTertiary \| bgSecondaryWash \| bgNegative \| bgNegativeWash \| bgPositive \| bgPositiveWash \| bgWarning \| bgWarningWash \| bgLine \| bgLineHeavy \| bgLineInverse \| bgLinePrimary \| bgLinePrimarySubtle \| accentSubtleRed \| accentBoldRed \| accentSubtleGreen \| accentBoldGreen \| accentSubtleBlue \| accentBoldBlue \| accentSubtlePurple \| accentBoldPurple \| accentSubtleYellow \| accentBoldYellow \| accentSubtleGray \| accentBoldGray \| transparent` | No | `-` | - |
1243
+ | `columnGap` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5` | No | `-` | - |
1244
+ | `curve` | `bump \| catmullRom \| linear \| linearClosed \| monotone \| natural \| step \| stepBefore \| stepAfter` | No | `'linear'` | The curve interpolation method to use for the line. |
1245
+ | `dangerouslySetBackground` | `string` | No | `-` | - |
1246
+ | `display` | `flex \| none` | No | `-` | - |
1247
+ | `elevation` | `0 \| 1 \| 2` | No | `-` | Determines box shadow styles. Parent should have overflow set to visible to ensure styles are not clipped. |
1248
+ | `enableScrubbing` | `boolean` | No | `-` | Enables scrubbing interactions. When true, allows scrubbing and makes scrubber components interactive. |
1249
+ | `flexBasis` | `string \| number` | No | `-` | - |
1250
+ | `flexDirection` | `row \| column \| row-reverse \| column-reverse` | No | `-` | - |
1251
+ | `flexGrow` | `number` | No | `-` | - |
1252
+ | `flexShrink` | `number` | No | `-` | - |
1253
+ | `flexWrap` | `wrap \| nowrap \| wrap-reverse` | No | `-` | - |
1254
+ | `font` | `inherit \| FontFamily` | No | `-` | - |
1255
+ | `fontFamily` | `inherit \| FontFamily` | No | `-` | - |
1256
+ | `fontSize` | `inherit \| FontSize` | No | `-` | - |
1257
+ | `fontWeight` | `inherit \| FontWeight` | No | `-` | - |
1258
+ | `gap` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5` | No | `-` | - |
1259
+ | `height` | `string \| number` | No | `-` | Chart height. If not provided, will use the containers measured height. |
1260
+ | `inset` | `number \| Partial<ChartInset>` | No | `-` | Inset around the entire chart (outside the axes). |
1261
+ | `justifyContent` | `flex-start \| flex-end \| center \| space-between \| space-around \| space-evenly` | No | `-` | - |
1262
+ | `key` | `Key \| null` | No | `-` | - |
1263
+ | `left` | `string \| number` | No | `-` | - |
1264
+ | `lineHeight` | `inherit \| LineHeight` | No | `-` | - |
1265
+ | `margin` | `0 \| -1 \| -2 \| -3 \| -4 \| -5 \| -6 \| -7 \| -8 \| -9 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1.5` | No | `-` | - |
1266
+ | `marginBottom` | `0 \| -1 \| -2 \| -3 \| -4 \| -5 \| -6 \| -7 \| -8 \| -9 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1.5` | No | `-` | - |
1267
+ | `marginEnd` | `0 \| -1 \| -2 \| -3 \| -4 \| -5 \| -6 \| -7 \| -8 \| -9 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1.5` | No | `-` | - |
1268
+ | `marginStart` | `0 \| -1 \| -2 \| -3 \| -4 \| -5 \| -6 \| -7 \| -8 \| -9 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1.5` | No | `-` | - |
1269
+ | `marginTop` | `0 \| -1 \| -2 \| -3 \| -4 \| -5 \| -6 \| -7 \| -8 \| -9 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1.5` | No | `-` | - |
1270
+ | `marginX` | `0 \| -1 \| -2 \| -3 \| -4 \| -5 \| -6 \| -7 \| -8 \| -9 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1.5` | No | `-` | - |
1271
+ | `marginY` | `0 \| -1 \| -2 \| -3 \| -4 \| -5 \| -6 \| -7 \| -8 \| -9 \| -10 \| -0.25 \| -0.5 \| -0.75 \| -1.5` | No | `-` | - |
1272
+ | `maxHeight` | `string \| number` | No | `-` | - |
1273
+ | `maxWidth` | `string \| number` | No | `-` | - |
1274
+ | `minHeight` | `string \| number` | No | `-` | - |
1275
+ | `minWidth` | `string \| number` | No | `-` | - |
1276
+ | `onPointerCancel` | `((event: PointerEvent) => void)` | No | `-` | - |
1277
+ | `onPointerCancelCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
1278
+ | `onPointerDown` | `((event: PointerEvent) => void)` | No | `-` | - |
1279
+ | `onPointerDownCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
1280
+ | `onPointerEnter` | `((event: PointerEvent) => void)` | No | `-` | - |
1281
+ | `onPointerEnterCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
1282
+ | `onPointerLeave` | `((event: PointerEvent) => void)` | No | `-` | - |
1283
+ | `onPointerLeaveCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
1284
+ | `onPointerMove` | `((event: PointerEvent) => void)` | No | `-` | - |
1285
+ | `onPointerMoveCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
1286
+ | `onPointerUp` | `((event: PointerEvent) => void)` | No | `-` | - |
1287
+ | `onPointerUpCapture` | `((event: PointerEvent) => void)` | No | `-` | - |
1288
+ | `onScrubberPositionChange` | `((index: number) => void) \| undefined` | No | `-` | Callback fired when the scrubber position changes. Receives the dataIndex of the scrubber or undefined when not scrubbing. |
1289
+ | `opacity` | `number \| AnimatedNode` | No | `-` | - |
1290
+ | `overflow` | `visible \| hidden \| scroll` | No | `-` | - |
1291
+ | `padding` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5` | No | `-` | - |
1292
+ | `paddingBottom` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5` | No | `-` | - |
1293
+ | `paddingEnd` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5` | No | `-` | - |
1294
+ | `paddingStart` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5` | No | `-` | - |
1295
+ | `paddingTop` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5` | No | `-` | - |
1296
+ | `paddingX` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5` | No | `-` | - |
1297
+ | `paddingY` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5` | No | `-` | - |
1298
+ | `pin` | `top \| bottom \| left \| right \| all` | No | `-` | Direction in which to absolutely pin the box. |
1299
+ | `position` | `absolute \| relative \| static \| fixed \| sticky` | No | `-` | - |
1300
+ | `ref` | `((instance: View \| null) => void) \| RefObject<View> \| null` | No | `-` | - |
1301
+ | `renderPoints` | `((params: RenderPointsParams) => boolean \| PointConfig \| null) \| undefined` | No | `-` | Callback function to determine how to render points at each data point in the series. Called for every entry in the data array. |
1302
+ | `right` | `string \| number` | No | `-` | - |
1303
+ | `rowGap` | `0 \| 1 \| 2 \| 3 \| 4 \| 5 \| 6 \| 7 \| 8 \| 9 \| 10 \| 0.25 \| 0.5 \| 0.75 \| 1.5` | No | `-` | - |
1304
+ | `series` | `LineSeries[]` | No | `-` | Configuration objects that define how to visualize the data. Each series supports Line component props for individual customization. |
1305
+ | `showArea` | `boolean` | No | `-` | Show area fill under the line. |
1306
+ | `showXAxis` | `boolean` | No | `-` | Whether to show the X axis. |
1307
+ | `showYAxis` | `boolean` | No | `-` | Whether to show the Y axis. |
1308
+ | `strokeWidth` | `number` | No | `-` | - |
1309
+ | `style` | `false \| RegisteredStyle<ViewStyle> \| Value \| AnimatedInterpolation<string \| number> \| WithAnimatedObject<ViewStyle> \| WithAnimatedArray<Falsy \| ViewStyle \| RegisteredStyle<ViewStyle> \| RecursiveArray<Falsy \| ViewStyle \| RegisteredStyle<ViewStyle>> \| readonly (Falsy \| ViewStyle \| RegisteredStyle<ViewStyle>)[]> \| null` | No | `-` | - |
1310
+ | `testID` | `string` | No | `-` | Used to locate this element in unit and end-to-end tests. Used to locate this view in end-to-end tests. |
1311
+ | `textAlign` | `auto \| left \| right \| center \| justify` | No | `-` | - |
1312
+ | `textDecorationLine` | `none \| underline \| line-through \| underline line-through` | No | `-` | - |
1313
+ | `textDecorationStyle` | `solid \| dotted \| dashed \| double` | No | `-` | - |
1314
+ | `textTransform` | `none \| capitalize \| uppercase \| lowercase` | No | `-` | - |
1315
+ | `top` | `string \| number` | No | `-` | - |
1316
+ | `transform` | `string \| (({ scaleX: AnimatableNumericValue; } & { scaleY?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ scaleY: AnimatableNumericValue; } & { scaleX?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ translateX: AnimatableNumericValue \| ${number}%; } & { scaleX?: undefined; scaleY?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ translateY: AnimatableNumericValue \| ${number}%; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ perspective: AnimatableNumericValue; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ rotate: AnimatableStringValue; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ rotateX: AnimatableStringValue; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ rotateY: AnimatableStringValue; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ rotateZ: AnimatableStringValue; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ scale: AnimatableNumericValue; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ skewX: AnimatableStringValue; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ skewY: AnimatableStringValue; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; matrix?: undefined; }) \| ({ matrix: AnimatableNumericValue[]; } & { scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; skewX?: undefined; skewY?: undefined; }))[]` | No | `-` | - |
1317
+ | `type` | `solid \| dotted \| gradient` | No | `'solid'` | The type of line to render. |
1318
+ | `userSelect` | `auto \| none \| text \| contain \| all` | No | `-` | - |
1319
+ | `width` | `string \| number` | No | `-` | Chart width. If not provided, will use the containers measured width. |
1320
+ | `xAxis` | `(Partial<AxisConfigProps> & AxisBaseProps & { className?: string; classNames?: { root?: string \| undefined; tickLabel?: string \| undefined; gridLine?: string \| undefined; line?: string \| undefined; tickMark?: string \| undefined; } \| undefined; style?: CSSProperties \| undefined; styles?: { root?: CSSProperties \| undefined; tickLabel?: CSSProperties \| undefined; gridLine?: CSSProperties \| undefined; line?: CSSProperties \| undefined; tickMark?: CSSProperties \| undefined; } \| undefined; } & { position?: top \| bottom \| undefined; height?: number \| undefined; }) \| undefined` | No | `-` | - |
1321
+ | `yAxis` | `(Partial<AxisConfigProps> & AxisBaseProps & { className?: string; classNames?: { root?: string \| undefined; tickLabel?: string \| undefined; gridLine?: string \| undefined; line?: string \| undefined; tickMark?: string \| undefined; } \| undefined; style?: CSSProperties \| undefined; styles?: { root?: CSSProperties \| undefined; tickLabel?: CSSProperties \| undefined; gridLine?: CSSProperties \| undefined; line?: CSSProperties \| undefined; tickMark?: CSSProperties \| undefined; } \| undefined; } & { axisId?: string \| undefined; position?: left \| right \| undefined; width?: number \| undefined; }) \| undefined` | No | `-` | - |
1322
+ | `zIndex` | `number` | No | `-` | - |
1323
+
1324
+