@coinbase/cds-mobile-visualization 3.3.0 → 3.4.0-beta.10

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 (265) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/dts/chart/CartesianChart.d.ts +125 -0
  3. package/dts/chart/CartesianChart.d.ts.map +1 -0
  4. package/dts/chart/ChartContextBridge.d.ts +28 -0
  5. package/dts/chart/ChartContextBridge.d.ts.map +1 -0
  6. package/dts/chart/ChartProvider.d.ts +6 -0
  7. package/dts/chart/ChartProvider.d.ts.map +1 -0
  8. package/dts/chart/Path.d.ts +91 -0
  9. package/dts/chart/Path.d.ts.map +1 -0
  10. package/dts/chart/PeriodSelector.d.ts +85 -0
  11. package/dts/chart/PeriodSelector.d.ts.map +1 -0
  12. package/dts/chart/area/Area.d.ts +77 -0
  13. package/dts/chart/area/Area.d.ts.map +1 -0
  14. package/dts/chart/area/AreaChart.d.ts +131 -0
  15. package/dts/chart/area/AreaChart.d.ts.map +1 -0
  16. package/dts/chart/area/DottedArea.d.ts +46 -0
  17. package/dts/chart/area/DottedArea.d.ts.map +1 -0
  18. package/dts/chart/area/GradientArea.d.ts +36 -0
  19. package/dts/chart/area/GradientArea.d.ts.map +1 -0
  20. package/dts/chart/area/SolidArea.d.ts +23 -0
  21. package/dts/chart/area/SolidArea.d.ts.map +1 -0
  22. package/dts/chart/area/index.d.ts +6 -0
  23. package/dts/chart/area/index.d.ts.map +1 -0
  24. package/dts/chart/axis/Axis.d.ts +194 -0
  25. package/dts/chart/axis/Axis.d.ts.map +1 -0
  26. package/dts/chart/axis/DefaultAxisTickLabel.d.ts +8 -0
  27. package/dts/chart/axis/DefaultAxisTickLabel.d.ts.map +1 -0
  28. package/dts/chart/axis/XAxis.d.ts +16 -0
  29. package/dts/chart/axis/XAxis.d.ts.map +1 -0
  30. package/dts/chart/axis/YAxis.d.ts +21 -0
  31. package/dts/chart/axis/YAxis.d.ts.map +1 -0
  32. package/dts/chart/axis/index.d.ts +5 -0
  33. package/dts/chart/axis/index.d.ts.map +1 -0
  34. package/dts/chart/bar/Bar.d.ts +92 -0
  35. package/dts/chart/bar/Bar.d.ts.map +1 -0
  36. package/dts/chart/bar/BarChart.d.ts +113 -0
  37. package/dts/chart/bar/BarChart.d.ts.map +1 -0
  38. package/dts/chart/bar/BarPlot.d.ts +30 -0
  39. package/dts/chart/bar/BarPlot.d.ts.map +1 -0
  40. package/dts/chart/bar/BarStack.d.ts +102 -0
  41. package/dts/chart/bar/BarStack.d.ts.map +1 -0
  42. package/dts/chart/bar/BarStackGroup.d.ts +36 -0
  43. package/dts/chart/bar/BarStackGroup.d.ts.map +1 -0
  44. package/dts/chart/bar/DefaultBar.d.ts +7 -0
  45. package/dts/chart/bar/DefaultBar.d.ts.map +1 -0
  46. package/dts/chart/bar/DefaultBarStack.d.ts +7 -0
  47. package/dts/chart/bar/DefaultBarStack.d.ts.map +1 -0
  48. package/dts/chart/bar/index.d.ts +8 -0
  49. package/dts/chart/bar/index.d.ts.map +1 -0
  50. package/dts/chart/gradient/Gradient.d.ts +25 -0
  51. package/dts/chart/gradient/Gradient.d.ts.map +1 -0
  52. package/dts/chart/gradient/index.d.ts +2 -0
  53. package/dts/chart/gradient/index.d.ts.map +1 -0
  54. package/dts/chart/index.d.ts +15 -0
  55. package/dts/chart/index.d.ts.map +1 -0
  56. package/dts/chart/line/DefaultReferenceLineLabel.d.ts +9 -0
  57. package/dts/chart/line/DefaultReferenceLineLabel.d.ts.map +1 -0
  58. package/dts/chart/line/DottedLine.d.ts +20 -0
  59. package/dts/chart/line/DottedLine.d.ts.map +1 -0
  60. package/dts/chart/line/Line.d.ts +115 -0
  61. package/dts/chart/line/Line.d.ts.map +1 -0
  62. package/dts/chart/line/LineChart.d.ts +118 -0
  63. package/dts/chart/line/LineChart.d.ts.map +1 -0
  64. package/dts/chart/line/ReferenceLine.d.ts +139 -0
  65. package/dts/chart/line/ReferenceLine.d.ts.map +1 -0
  66. package/dts/chart/line/SolidLine.d.ts +15 -0
  67. package/dts/chart/line/SolidLine.d.ts.map +1 -0
  68. package/dts/chart/line/index.d.ts +7 -0
  69. package/dts/chart/line/index.d.ts.map +1 -0
  70. package/dts/chart/point/DefaultPointLabel.d.ts +10 -0
  71. package/dts/chart/point/DefaultPointLabel.d.ts.map +1 -0
  72. package/dts/chart/point/Point.d.ts +120 -0
  73. package/dts/chart/point/Point.d.ts.map +1 -0
  74. package/dts/chart/point/index.d.ts +3 -0
  75. package/dts/chart/point/index.d.ts.map +1 -0
  76. package/dts/chart/scrubber/DefaultScrubberBeacon.d.ts +8 -0
  77. package/dts/chart/scrubber/DefaultScrubberBeacon.d.ts.map +1 -0
  78. package/dts/chart/scrubber/DefaultScrubberBeaconLabel.d.ts +12 -0
  79. package/dts/chart/scrubber/DefaultScrubberBeaconLabel.d.ts.map +1 -0
  80. package/dts/chart/scrubber/DefaultScrubberLabel.d.ts +11 -0
  81. package/dts/chart/scrubber/DefaultScrubberLabel.d.ts.map +1 -0
  82. package/dts/chart/scrubber/Scrubber.d.ts +233 -0
  83. package/dts/chart/scrubber/Scrubber.d.ts.map +1 -0
  84. package/dts/chart/scrubber/ScrubberBeaconGroup.d.ts +44 -0
  85. package/dts/chart/scrubber/ScrubberBeaconGroup.d.ts.map +1 -0
  86. package/dts/chart/scrubber/ScrubberBeaconLabelGroup.d.ts +31 -0
  87. package/dts/chart/scrubber/ScrubberBeaconLabelGroup.d.ts.map +1 -0
  88. package/dts/chart/scrubber/ScrubberProvider.d.ts +20 -0
  89. package/dts/chart/scrubber/ScrubberProvider.d.ts.map +1 -0
  90. package/dts/chart/scrubber/index.d.ts +5 -0
  91. package/dts/chart/scrubber/index.d.ts.map +1 -0
  92. package/dts/chart/text/ChartText.d.ts +164 -0
  93. package/dts/chart/text/ChartText.d.ts.map +1 -0
  94. package/dts/chart/text/ChartTextGroup.d.ts +61 -0
  95. package/dts/chart/text/ChartTextGroup.d.ts.map +1 -0
  96. package/dts/chart/text/index.d.ts +3 -0
  97. package/dts/chart/text/index.d.ts.map +1 -0
  98. package/dts/chart/utils/axis.d.ts +342 -0
  99. package/dts/chart/utils/axis.d.ts.map +1 -0
  100. package/dts/chart/utils/bar.d.ts +20 -0
  101. package/dts/chart/utils/bar.d.ts.map +1 -0
  102. package/dts/chart/utils/chart.d.ts +124 -0
  103. package/dts/chart/utils/chart.d.ts.map +1 -0
  104. package/dts/chart/utils/context.d.ts +116 -0
  105. package/dts/chart/utils/context.d.ts.map +1 -0
  106. package/dts/chart/utils/gradient.d.ts +117 -0
  107. package/dts/chart/utils/gradient.d.ts.map +1 -0
  108. package/dts/chart/utils/index.d.ts +11 -0
  109. package/dts/chart/utils/index.d.ts.map +1 -0
  110. package/dts/chart/utils/path.d.ts +160 -0
  111. package/dts/chart/utils/path.d.ts.map +1 -0
  112. package/dts/chart/utils/point.d.ts +134 -0
  113. package/dts/chart/utils/point.d.ts.map +1 -0
  114. package/dts/chart/utils/scale.d.ts +134 -0
  115. package/dts/chart/utils/scale.d.ts.map +1 -0
  116. package/dts/chart/utils/scrubber.d.ts +39 -0
  117. package/dts/chart/utils/scrubber.d.ts.map +1 -0
  118. package/dts/chart/utils/transition.d.ts +140 -0
  119. package/dts/chart/utils/transition.d.ts.map +1 -0
  120. package/dts/index.d.ts +2 -1
  121. package/dts/index.d.ts.map +1 -1
  122. package/dts/sparkline/Counter.d.ts +7 -2
  123. package/dts/sparkline/Sparkline.d.ts +67 -16
  124. package/dts/sparkline/Sparkline.d.ts.map +1 -1
  125. package/dts/sparkline/SparklineArea.d.ts +10 -4
  126. package/dts/sparkline/SparklineArea.d.ts.map +1 -1
  127. package/dts/sparkline/SparklineAreaPattern.d.ts +12 -4
  128. package/dts/sparkline/SparklineAreaPattern.d.ts.map +1 -1
  129. package/dts/sparkline/SparklineGradient.d.ts +21 -10
  130. package/dts/sparkline/SparklineGradient.d.ts.map +1 -1
  131. package/dts/sparkline/__figma__/Sparkline.figma.d.ts +1 -1
  132. package/dts/sparkline/generateSparklineWithId.d.ts +8 -2
  133. package/dts/sparkline/generateSparklineWithId.d.ts.map +1 -1
  134. package/dts/sparkline/index.d.ts +1 -1
  135. package/dts/sparkline/sparkline-interactive/SparklineAccessibleView.d.ts +8 -3
  136. package/dts/sparkline/sparkline-interactive/SparklineInteractive.d.ts +132 -110
  137. package/dts/sparkline/sparkline-interactive/SparklineInteractive.d.ts.map +1 -1
  138. package/dts/sparkline/sparkline-interactive/SparklineInteractiveAnimatedPath.d.ts +22 -9
  139. package/dts/sparkline/sparkline-interactive/SparklineInteractiveAnimatedPath.d.ts.map +1 -1
  140. package/dts/sparkline/sparkline-interactive/SparklineInteractiveHoverDate.d.ts +18 -7
  141. package/dts/sparkline/sparkline-interactive/SparklineInteractiveLineVertical.d.ts +9 -4
  142. package/dts/sparkline/sparkline-interactive/SparklineInteractiveMarkerDates.d.ts +11 -6
  143. package/dts/sparkline/sparkline-interactive/SparklineInteractiveMinMax.d.ts +7 -5
  144. package/dts/sparkline/sparkline-interactive/SparklineInteractivePanGestureHandler.d.ts +22 -10
  145. package/dts/sparkline/sparkline-interactive/SparklineInteractivePaths.d.ts +21 -7
  146. package/dts/sparkline/sparkline-interactive/SparklineInteractivePaths.d.ts.map +1 -1
  147. package/dts/sparkline/sparkline-interactive/SparklineInteractivePeriodSelector.d.ts +21 -16
  148. package/dts/sparkline/sparkline-interactive/SparklineInteractiveProvider.d.ts +29 -23
  149. package/dts/sparkline/sparkline-interactive/SparklineInteractiveTimeseriesPaths.d.ts +22 -14
  150. package/dts/sparkline/sparkline-interactive/__figma__/SparklineInteractive.figma.d.ts +1 -1
  151. package/dts/sparkline/sparkline-interactive/useInterruptiblePathAnimation.d.ts +9 -5
  152. package/dts/sparkline/sparkline-interactive/useMinMaxTransform.d.ts +11 -6
  153. package/dts/sparkline/sparkline-interactive/useOpacityAnimation.d.ts +5 -2
  154. package/dts/sparkline/sparkline-interactive/useSparklineInteractiveConstants.d.ts +17 -17
  155. package/dts/sparkline/sparkline-interactive/useSparklineInteractiveLineStyles.d.ts +16 -13
  156. package/dts/sparkline/sparkline-interactive-header/SparklineInteractiveHeader.d.ts +106 -98
  157. package/dts/sparkline/sparkline-interactive-header/__figma__/SparklineInteractiveHeader.figma.d.ts +1 -1
  158. package/dts/sparkline/sparkline-interactive-header/useSparklineInteractiveHeaderStyles.d.ts +22 -19
  159. package/esm/chart/CartesianChart.js +335 -0
  160. package/esm/chart/ChartContextBridge.js +148 -0
  161. package/esm/chart/ChartProvider.js +10 -0
  162. package/esm/chart/Path.js +218 -0
  163. package/esm/chart/PeriodSelector.js +136 -0
  164. package/esm/chart/__stories__/CartesianChart.stories.js +723 -0
  165. package/esm/chart/__stories__/Chart.stories.js +77 -0
  166. package/esm/chart/__stories__/PeriodSelector.stories.js +322 -0
  167. package/esm/chart/area/Area.js +75 -0
  168. package/esm/chart/area/AreaChart.js +151 -0
  169. package/esm/chart/area/DottedArea.js +80 -0
  170. package/esm/chart/area/GradientArea.js +54 -0
  171. package/esm/chart/area/SolidArea.js +38 -0
  172. package/esm/chart/area/__stories__/AreaChart.stories.js +100 -0
  173. package/esm/chart/area/index.js +7 -0
  174. package/esm/chart/axis/Axis.js +45 -0
  175. package/esm/chart/axis/DefaultAxisTickLabel.js +11 -0
  176. package/esm/chart/axis/XAxis.js +188 -0
  177. package/esm/chart/axis/YAxis.js +177 -0
  178. package/esm/chart/axis/__stories__/Axis.stories.js +276 -0
  179. package/esm/chart/axis/index.js +6 -0
  180. package/esm/chart/bar/Bar.js +69 -0
  181. package/esm/chart/bar/BarChart.js +125 -0
  182. package/esm/chart/bar/BarPlot.js +102 -0
  183. package/esm/chart/bar/BarStack.js +551 -0
  184. package/esm/chart/bar/BarStackGroup.js +79 -0
  185. package/esm/chart/bar/DefaultBar.js +56 -0
  186. package/esm/chart/bar/DefaultBarStack.js +47 -0
  187. package/esm/chart/bar/__stories__/BarChart.stories.js +668 -0
  188. package/esm/chart/bar/index.js +9 -0
  189. package/esm/chart/gradient/Gradient.js +53 -0
  190. package/esm/chart/gradient/index.js +1 -0
  191. package/esm/chart/index.js +16 -0
  192. package/esm/chart/line/DefaultReferenceLineLabel.js +66 -0
  193. package/esm/chart/line/DottedLine.js +50 -0
  194. package/esm/chart/line/Line.js +178 -0
  195. package/esm/chart/line/LineChart.js +121 -0
  196. package/esm/chart/line/ReferenceLine.js +132 -0
  197. package/esm/chart/line/SolidLine.js +46 -0
  198. package/esm/chart/line/__stories__/LineChart.stories.js +2372 -0
  199. package/esm/chart/line/__stories__/ReferenceLine.stories.js +132 -0
  200. package/esm/chart/line/index.js +8 -0
  201. package/esm/chart/point/DefaultPointLabel.js +39 -0
  202. package/esm/chart/point/Point.js +188 -0
  203. package/esm/chart/point/index.js +2 -0
  204. package/esm/chart/scrubber/DefaultScrubberBeacon.js +179 -0
  205. package/esm/chart/scrubber/DefaultScrubberBeaconLabel.js +43 -0
  206. package/esm/chart/scrubber/DefaultScrubberLabel.js +28 -0
  207. package/esm/chart/scrubber/Scrubber.js +166 -0
  208. package/esm/chart/scrubber/ScrubberBeaconGroup.js +161 -0
  209. package/esm/chart/scrubber/ScrubberBeaconLabelGroup.js +185 -0
  210. package/esm/chart/scrubber/ScrubberProvider.js +135 -0
  211. package/esm/chart/scrubber/index.js +4 -0
  212. package/esm/chart/text/ChartText.js +305 -0
  213. package/esm/chart/text/ChartTextGroup.js +211 -0
  214. package/esm/chart/text/index.js +4 -0
  215. package/esm/chart/utils/axis.js +592 -0
  216. package/esm/chart/utils/bar.js +24 -0
  217. package/esm/chart/utils/chart.js +270 -0
  218. package/esm/chart/utils/context.js +15 -0
  219. package/esm/chart/utils/gradient.js +305 -0
  220. package/esm/chart/utils/index.js +12 -0
  221. package/esm/chart/utils/path.js +274 -0
  222. package/esm/chart/utils/point.js +229 -0
  223. package/esm/chart/utils/scale.js +277 -0
  224. package/esm/chart/utils/scrubber.js +139 -0
  225. package/esm/chart/utils/transition.js +185 -0
  226. package/esm/index.js +4 -1
  227. package/esm/sparkline/Sparkline.js +129 -16
  228. package/esm/sparkline/SparklineArea.js +7 -2
  229. package/esm/sparkline/SparklineAreaPattern.js +4 -2
  230. package/esm/sparkline/SparklineGradient.js +4 -0
  231. package/esm/sparkline/__stories__/Sparkline.stories.js +11 -7
  232. package/esm/sparkline/__stories__/SparklineGradient.stories.js +7 -4
  233. package/esm/sparkline/generateSparklineWithId.js +3 -2
  234. package/esm/sparkline/sparkline-interactive/SparklineInteractive.js +5 -1
  235. package/esm/sparkline/sparkline-interactive/SparklineInteractiveAnimatedPath.js +5 -2
  236. package/esm/sparkline/sparkline-interactive/SparklineInteractivePaths.js +4 -0
  237. package/esm/sparkline/sparkline-interactive/__stories__/SparklineInteractive.stories.js +76 -24
  238. package/esm/sparkline/sparkline-interactive-header/__stories__/SparklineInteractiveHeader.stories.js +17 -9
  239. package/package.json +17 -11
  240. package/dts/sparkline/__stories__/Sparkline.stories.d.ts +0 -3
  241. package/dts/sparkline/__stories__/Sparkline.stories.d.ts.map +0 -1
  242. package/dts/sparkline/__stories__/SparklineGradient.stories.d.ts +0 -3
  243. package/dts/sparkline/__stories__/SparklineGradient.stories.d.ts.map +0 -1
  244. package/dts/sparkline/sparkline-interactive/__stories__/SparklineInteractive.stories.d.ts +0 -3
  245. package/dts/sparkline/sparkline-interactive/__stories__/SparklineInteractive.stories.d.ts.map +0 -1
  246. package/dts/sparkline/sparkline-interactive/__tests__/SparklineInteractive.test.d.ts +0 -2
  247. package/dts/sparkline/sparkline-interactive/__tests__/SparklineInteractive.test.d.ts.map +0 -1
  248. package/dts/sparkline/sparkline-interactive/__tests__/SparklineInteractiveHoverDate.test.d.ts +0 -2
  249. package/dts/sparkline/sparkline-interactive/__tests__/SparklineInteractiveHoverDate.test.d.ts.map +0 -1
  250. package/dts/sparkline/sparkline-interactive/__tests__/SparklineInteractivePanGestureHandler.test.d.ts +0 -2
  251. package/dts/sparkline/sparkline-interactive/__tests__/SparklineInteractivePanGestureHandler.test.d.ts.map +0 -1
  252. package/dts/sparkline/sparkline-interactive/__tests__/SparklineInteractivePeriodSelector.test.d.ts +0 -2
  253. package/dts/sparkline/sparkline-interactive/__tests__/SparklineInteractivePeriodSelector.test.d.ts.map +0 -1
  254. package/dts/sparkline/sparkline-interactive/__tests__/SparklineInteractiveTimeseriesPaths.test.d.ts +0 -2
  255. package/dts/sparkline/sparkline-interactive/__tests__/SparklineInteractiveTimeseriesPaths.test.d.ts.map +0 -1
  256. package/dts/sparkline/sparkline-interactive/__tests__/useMinMaxTransform.test.d.ts +0 -2
  257. package/dts/sparkline/sparkline-interactive/__tests__/useMinMaxTransform.test.d.ts.map +0 -1
  258. package/dts/sparkline/sparkline-interactive/useInterruptiblePathAnimation.test.disable.d.ts +0 -2
  259. package/dts/sparkline/sparkline-interactive/useInterruptiblePathAnimation.test.disable.d.ts.map +0 -1
  260. package/dts/sparkline/sparkline-interactive-header/__stories__/SparklineInteractiveHeader.stories.d.ts +0 -4
  261. package/dts/sparkline/sparkline-interactive-header/__stories__/SparklineInteractiveHeader.stories.d.ts.map +0 -1
  262. package/dts/sparkline/sparkline-interactive-header/__tests__/SparklineInteractiveHeader.test.d.ts +0 -2
  263. package/dts/sparkline/sparkline-interactive-header/__tests__/SparklineInteractiveHeader.test.d.ts.map +0 -1
  264. package/dts/sparkline/sparkline-interactive-header/__tests__/useSparklineInteractiveHeaderStyles.test.d.ts +0 -2
  265. package/dts/sparkline/sparkline-interactive-header/__tests__/useSparklineInteractiveHeaderStyles.test.d.ts.map +0 -1
@@ -0,0 +1,2372 @@
1
+ const _excluded = ["dataX", "dataY"],
2
+ _excluded2 = ["label"],
3
+ _excluded3 = ["style"],
4
+ _excluded4 = ["x", "y", "width", "height", "originY", "dataX"],
5
+ _excluded5 = ["seriesId", "color", "label"];
6
+ 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
+ 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';
9
+ 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';
12
+ import { prices } from '@coinbase/cds-common/internal/data/prices';
13
+ import { sparklineInteractiveData } from '@coinbase/cds-common/internal/visualizations/SparklineInteractiveData';
14
+ import { useTabsContext } from '@coinbase/cds-common/tabs/TabsContext';
15
+ import { useTheme } from '@coinbase/cds-mobile';
16
+ import { Button, IconButton } from '@coinbase/cds-mobile/buttons';
17
+ import { ListCell } from '@coinbase/cds-mobile/cells';
18
+ import { ExampleScreen } from '@coinbase/cds-mobile/examples/ExampleScreen';
19
+ import { Box, HStack, VStack } from '@coinbase/cds-mobile/layout';
20
+ import { Avatar, RemoteImage } from '@coinbase/cds-mobile/media';
21
+ import { SectionHeader } from '@coinbase/cds-mobile/section-header/SectionHeader';
22
+ import { Pressable } from '@coinbase/cds-mobile/system';
23
+ import { SegmentedTab } from '@coinbase/cds-mobile/tabs/SegmentedTab';
24
+ import { Text } from '@coinbase/cds-mobile/typography';
25
+ import { Circle, FontWeight, Group, Line as SkiaLine, Rect, Skia, TextAlign } from '@shopify/react-native-skia';
26
+ import { Area, DottedArea } from '../../area';
27
+ import { DefaultAxisTickLabel, XAxis, YAxis } from '../../axis';
28
+ import { BarPlot } from '../../bar';
29
+ import { CartesianChart } from '../../CartesianChart';
30
+ import { useCartesianChartContext } from '../../ChartProvider';
31
+ import { PeriodSelector, PeriodSelectorActiveIndicator } from '../../PeriodSelector';
32
+ import { Point } from '../../point';
33
+ import { DefaultScrubberBeacon, DefaultScrubberBeaconLabel, DefaultScrubberLabel, Scrubber } from '../../scrubber';
34
+ import { buildTransition, defaultTransition, getLineData, getPointOnSerializableScale, projectPointWithSerializableScale, unwrapAnimatedValue, useScrubberContext } from '../../utils';
35
+ import { DottedLine, Line, LineChart, ReferenceLine, SolidLine } from '..';
36
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
37
+ function MultipleLine() {
38
+ const theme = useTheme();
39
+ const [scrubberPosition, setScrubberPosition] = useState();
40
+ const pages = useMemo(() => ['Page A', 'Page B', 'Page C', 'Page D', 'Page E', 'Page F', 'Page G'], []);
41
+ const pageViews = useMemo(() => [2400, 1398, 9800, 3908, 4800, 3800, 4300], []);
42
+ const uniqueVisitors = useMemo(() => [4000, 3000, 2000, 2780, 1890, 2390, 3490], []);
43
+ 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]);
47
+ const numberFormatter = useCallback(value => new Intl.NumberFormat('en-US', {
48
+ maximumFractionDigits: 0
49
+ }).format(value), []);
50
+ const accessibilityLabel = useMemo(() => {
51
+ if (scrubberPosition !== undefined) {
52
+ return scrubberAccessibilityLabel(scrubberPosition);
53
+ }
54
+ return chartAccessibilityLabel;
55
+ }, [scrubberPosition, chartAccessibilityLabel, scrubberAccessibilityLabel]);
56
+ return /*#__PURE__*/_jsx(LineChart, {
57
+ enableScrubbing: true,
58
+ showArea: true,
59
+ showXAxis: true,
60
+ showYAxis: true,
61
+ accessibilityLabel: accessibilityLabel,
62
+ height: 200,
63
+ onScrubberPositionChange: setScrubberPosition,
64
+ series: [{
65
+ id: 'pageViews',
66
+ data: pageViews,
67
+ color: theme.color.accentBoldGreen,
68
+ // Label will render next to scrubber beacon
69
+ label: 'Page Views'
70
+ }, {
71
+ id: 'uniqueVisitors',
72
+ data: uniqueVisitors,
73
+ color: theme.color.accentBoldPurple,
74
+ label: 'Unique Visitors',
75
+ // Default area is gradient
76
+ areaType: 'dotted'
77
+ }],
78
+ xAxis: {
79
+ // Used on the x-axis to provide context for each index from the series data array
80
+ data: pages
81
+ },
82
+ yAxis: {
83
+ showGrid: true,
84
+ tickLabelFormatter: numberFormatter
85
+ },
86
+ children: /*#__PURE__*/_jsx(Scrubber, {})
87
+ });
88
+ }
89
+ function DataFormat() {
90
+ const [scrubberPosition, setScrubberPosition] = useState();
91
+ const yData = useMemo(() => [2, 5.5, 2, 8.5, 1.5, 5], []);
92
+ const xData = useMemo(() => [1, 2, 3, 5, 8, 10], []);
93
+ 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]);
103
+ return /*#__PURE__*/_jsx(LineChart, {
104
+ enableScrubbing: true,
105
+ points: true,
106
+ showArea: true,
107
+ showXAxis: true,
108
+ showYAxis: true,
109
+ accessibilityLabel: accessibilityLabel,
110
+ curve: "natural",
111
+ height: 200,
112
+ inset: {
113
+ top: 16,
114
+ right: 16,
115
+ bottom: 0,
116
+ left: 0
117
+ },
118
+ onScrubberPositionChange: setScrubberPosition,
119
+ series: [{
120
+ id: 'line',
121
+ data: yData
122
+ }],
123
+ xAxis: {
124
+ data: xData,
125
+ showLine: true,
126
+ showTickMarks: true,
127
+ showGrid: true
128
+ },
129
+ yAxis: {
130
+ domain: {
131
+ min: 0
132
+ },
133
+ position: 'left',
134
+ showLine: true,
135
+ showTickMarks: true,
136
+ showGrid: true
137
+ },
138
+ children: /*#__PURE__*/_jsx(Scrubber, {
139
+ hideOverlay: true
140
+ })
141
+ });
142
+ }
143
+ function LiveUpdates() {
144
+ const scrubberRef = useRef(null);
145
+ const initialData = useMemo(() => {
146
+ return sparklineInteractiveData.hour.map(d => d.value);
147
+ }, []);
148
+ const [priceData, setPriceData] = useState(initialData);
149
+ const lastDataPointTimeRef = useRef(Date.now());
150
+ const updateCountRef = useRef(0);
151
+ const intervalSeconds = 3600 / initialData.length;
152
+ const maxPercentChange = Math.abs(initialData[initialData.length - 1] - initialData[0]) * 0.05;
153
+ useEffect(() => {
154
+ const priceUpdateInterval = setInterval(() => {
155
+ var _scrubberRef$current;
156
+ setPriceData(currentData => {
157
+ const newData = [...currentData];
158
+ const lastPrice = newData[newData.length - 1];
159
+ const priceChange = (Math.random() - 0.5) * maxPercentChange;
160
+ const newPrice = Math.round((lastPrice + priceChange) * 100) / 100;
161
+
162
+ // Check if we should roll over to a new data point
163
+ const currentTime = Date.now();
164
+ const timeSinceLastPoint = (currentTime - lastDataPointTimeRef.current) / 1000;
165
+ if (timeSinceLastPoint >= intervalSeconds) {
166
+ // Time for a new data point - remove first, add new at end
167
+ lastDataPointTimeRef.current = currentTime;
168
+ newData.shift(); // Remove oldest data point
169
+ newData.push(newPrice); // Add new data point
170
+ updateCountRef.current = 0;
171
+ } else {
172
+ // Just update the last data point
173
+ newData[newData.length - 1] = newPrice;
174
+ updateCountRef.current++;
175
+ }
176
+ return newData;
177
+ });
178
+
179
+ // Pulse the scrubber on each update
180
+ (_scrubberRef$current = scrubberRef.current) == null || _scrubberRef$current.pulse();
181
+ }, 2000 + Math.random() * 1000);
182
+ return () => clearInterval(priceUpdateInterval);
183
+ }, [intervalSeconds, maxPercentChange]);
184
+ return /*#__PURE__*/_jsx(LineChart, {
185
+ enableScrubbing: true,
186
+ showArea: true,
187
+ height: 200,
188
+ inset: {
189
+ right: 64
190
+ },
191
+ series: [{
192
+ id: 'btc',
193
+ data: priceData,
194
+ color: assets.btc.color
195
+ }],
196
+ children: /*#__PURE__*/_jsx(Scrubber, {
197
+ ref: scrubberRef
198
+ })
199
+ });
200
+ }
201
+ function MissingData() {
202
+ 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];
206
+ const numberFormatter = useCallback(value => new Intl.NumberFormat('en-US', {
207
+ maximumFractionDigits: 0
208
+ }).format(value), []);
209
+ return /*#__PURE__*/_jsx(LineChart, {
210
+ enableScrubbing: true,
211
+ points: true,
212
+ showArea: true,
213
+ showXAxis: true,
214
+ showYAxis: true,
215
+ height: 200,
216
+ series: [{
217
+ id: 'pageViews',
218
+ data: pageViews,
219
+ color: theme.color.accentBoldGreen,
220
+ // Label will render next to scrubber beacon
221
+ label: 'Page Views',
222
+ connectNulls: true
223
+ }, {
224
+ id: 'uniqueVisitors',
225
+ data: uniqueVisitors,
226
+ color: theme.color.accentBoldPurple,
227
+ label: 'Unique Visitors'
228
+ }],
229
+ xAxis: {
230
+ // Used on the x-axis to provide context for each index from the series data array
231
+ data: pages
232
+ },
233
+ yAxis: {
234
+ showGrid: true,
235
+ tickLabelFormatter: numberFormatter
236
+ },
237
+ children: /*#__PURE__*/_jsx(Scrubber, {
238
+ overlayOffset: 6
239
+ })
240
+ });
241
+ }
242
+ function Interaction() {
243
+ const [scrubberPosition, setScrubberPosition] = useState();
244
+ return /*#__PURE__*/_jsxs(VStack, {
245
+ gap: 2,
246
+ children: [/*#__PURE__*/_jsx(Text, {
247
+ font: "label1",
248
+ children: scrubberPosition !== undefined ? "Scrubber position: " + scrubberPosition : 'Not scrubbing'
249
+ }), /*#__PURE__*/_jsx(LineChart, {
250
+ enableScrubbing: true,
251
+ showArea: true,
252
+ height: 200,
253
+ onScrubberPositionChange: setScrubberPosition,
254
+ series: [{
255
+ id: 'prices',
256
+ data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58]
257
+ }],
258
+ children: /*#__PURE__*/_jsx(Scrubber, {})
259
+ })]
260
+ });
261
+ }
262
+ function Points() {
263
+ const theme = useTheme();
264
+ const keyMarketShiftIndices = [4, 6, 7, 9, 10];
265
+ const data = [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58];
266
+ return /*#__PURE__*/_jsxs(CartesianChart, {
267
+ height: 200,
268
+ series: [{
269
+ id: 'prices',
270
+ data: data
271
+ }],
272
+ children: [/*#__PURE__*/_jsx(Area, {
273
+ fill: "rgb(" + theme.spectrum.blue5 + ")",
274
+ seriesId: "prices"
275
+ }), /*#__PURE__*/_jsx(Line, {
276
+ points: _ref => {
277
+ let {
278
+ dataX,
279
+ dataY
280
+ } = _ref,
281
+ props = _objectWithoutPropertiesLoose(_ref, _excluded);
282
+ return keyMarketShiftIndices.includes(dataX) ? _extends({}, props, {
283
+ strokeWidth: 2,
284
+ stroke: theme.color.bg,
285
+ radius: 5,
286
+ onClick: () => alert("You have clicked a key market shift at position " + (dataX + 1) + " with value " + dataY + "!"),
287
+ accessibilityLabel: "Key market shift point at position " + (dataX + 1) + ", value " + dataY + ". Click to view details."
288
+ }) : false;
289
+ },
290
+ seriesId: "prices"
291
+ })]
292
+ });
293
+ }
294
+ function Transitions() {
295
+ const theme = useTheme();
296
+ const dataCount = 20;
297
+ const maxDataOffset = 15000;
298
+ const minStepOffset = 2500;
299
+ const maxStepOffset = 10000;
300
+ const domainLimit = 20000;
301
+ const updateInterval = 500;
302
+ const myTransitionConfig = {
303
+ type: 'spring',
304
+ stiffness: 700,
305
+ damping: 20
306
+ };
307
+ const negativeColor = "rgb(" + theme.spectrum.gray15 + ")";
308
+ const positiveColor = theme.color.fgPositive;
309
+ function generateNextValue(previousValue) {
310
+ const range = maxStepOffset - minStepOffset;
311
+ const offset = Math.random() * range + minStepOffset;
312
+ let direction;
313
+ if (previousValue >= maxDataOffset) {
314
+ direction = -1;
315
+ } else if (previousValue <= -maxDataOffset) {
316
+ direction = 1;
317
+ } else {
318
+ direction = Math.random() < 0.5 ? -1 : 1;
319
+ }
320
+ let newValue = previousValue + offset * direction;
321
+ newValue = Math.max(-maxDataOffset, Math.min(maxDataOffset, newValue));
322
+ return newValue;
323
+ }
324
+ function generateInitialData() {
325
+ const data = [];
326
+ let previousValue = Math.random() * 2 * maxDataOffset - maxDataOffset;
327
+ data.push(previousValue);
328
+ for (let i = 1; i < dataCount; i++) {
329
+ const newValue = generateNextValue(previousValue);
330
+ data.push(newValue);
331
+ previousValue = newValue;
332
+ }
333
+ return data;
334
+ }
335
+ const MyGradient = /*#__PURE__*/memo(props => {
336
+ const areaGradient = {
337
+ stops: _ref2 => {
338
+ let {
339
+ min,
340
+ max
341
+ } = _ref2;
342
+ return [{
343
+ offset: min,
344
+ color: negativeColor,
345
+ opacity: 1
346
+ }, {
347
+ offset: 0,
348
+ color: negativeColor,
349
+ opacity: 0
350
+ }, {
351
+ offset: 0,
352
+ color: positiveColor,
353
+ opacity: 0
354
+ }, {
355
+ offset: max,
356
+ color: positiveColor,
357
+ opacity: 1
358
+ }];
359
+ }
360
+ };
361
+ return /*#__PURE__*/_jsx(DottedArea, _extends({}, props, {
362
+ gradient: areaGradient
363
+ }));
364
+ });
365
+ function CustomTransitionsChart() {
366
+ const [data, setData] = useState(generateInitialData);
367
+ useEffect(() => {
368
+ const intervalId = setInterval(() => {
369
+ setData(currentData => {
370
+ var _currentData;
371
+ const lastValue = (_currentData = currentData[currentData.length - 1]) != null ? _currentData : 0;
372
+ const newValue = generateNextValue(lastValue);
373
+ return [...currentData.slice(1), newValue];
374
+ });
375
+ }, updateInterval);
376
+ return () => clearInterval(intervalId);
377
+ }, []);
378
+ const tickLabelFormatter = useCallback(value => new Intl.NumberFormat('en-US', {
379
+ style: 'currency',
380
+ currency: 'USD',
381
+ maximumFractionDigits: 0
382
+ }).format(value), []);
383
+ const valueAtIndexFormatter = useCallback(dataIndex => new Intl.NumberFormat('en-US', {
384
+ style: 'currency',
385
+ currency: 'USD'
386
+ }).format(data[dataIndex]), [data]);
387
+ const lineGradient = {
388
+ stops: [{
389
+ offset: 0,
390
+ color: negativeColor
391
+ }, {
392
+ offset: 0,
393
+ color: positiveColor
394
+ }]
395
+ };
396
+ return /*#__PURE__*/_jsxs(CartesianChart, {
397
+ enableScrubbing: true,
398
+ height: 200,
399
+ inset: {
400
+ top: 32,
401
+ bottom: 32,
402
+ left: 16,
403
+ right: 16
404
+ },
405
+ series: [{
406
+ id: 'prices',
407
+ data: data,
408
+ gradient: lineGradient
409
+ }],
410
+ yAxis: {
411
+ domain: {
412
+ min: -domainLimit,
413
+ max: domainLimit
414
+ }
415
+ },
416
+ children: [/*#__PURE__*/_jsx(YAxis, {
417
+ showGrid: true,
418
+ requestedTickCount: 2,
419
+ tickLabelFormatter: tickLabelFormatter
420
+ }), /*#__PURE__*/_jsx(Line, {
421
+ showArea: true,
422
+ AreaComponent: MyGradient,
423
+ seriesId: "prices",
424
+ strokeWidth: 3,
425
+ transition: myTransitionConfig
426
+ }), /*#__PURE__*/_jsx(Scrubber, {
427
+ hideOverlay: true,
428
+ beaconTransitions: {
429
+ update: myTransitionConfig
430
+ },
431
+ label: valueAtIndexFormatter
432
+ })]
433
+ });
434
+ }
435
+ return /*#__PURE__*/_jsx(CustomTransitionsChart, {});
436
+ }
437
+ function BasicAccessible() {
438
+ const [scrubberPosition, setScrubberPosition] = useState();
439
+ const data = useMemo(() => [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58], []);
440
+
441
+ // Chart-level accessibility label provides overview
442
+ const chartAccessibilityLabel = useMemo(() => {
443
+ const currentPrice = data[data.length - 1];
444
+ return "Price chart showing trend over " + data.length + " data points. Current value: " + currentPrice + ". Use arrow keys to adjust view";
445
+ }, [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]);
457
+ return /*#__PURE__*/_jsx(LineChart, {
458
+ enableScrubbing: true,
459
+ showArea: true,
460
+ showYAxis: true,
461
+ accessibilityLabel: accessibilityLabel,
462
+ height: 200,
463
+ onScrubberPositionChange: setScrubberPosition,
464
+ series: [{
465
+ id: 'prices',
466
+ data: data
467
+ }],
468
+ yAxis: {
469
+ showGrid: true
470
+ },
471
+ children: /*#__PURE__*/_jsx(Scrubber, {})
472
+ });
473
+ }
474
+ function Gradients() {
475
+ const theme = useTheme();
476
+ const spectrumColors = ['blue', 'green', 'orange', 'yellow', 'gray', 'indigo', 'pink', 'purple', 'red', 'teal', 'chartreuse'];
477
+ const data = [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58];
478
+ const [currentSpectrumColor, setCurrentSpectrumColor] = useState('pink');
479
+ return /*#__PURE__*/_jsxs(VStack, {
480
+ gap: 2,
481
+ children: [/*#__PURE__*/_jsx(HStack, {
482
+ flexWrap: "wrap",
483
+ gap: 1,
484
+ justifyContent: "flex-end",
485
+ children: spectrumColors.map(color => /*#__PURE__*/_jsx(Pressable, {
486
+ accessibilityLabel: "Select " + color,
487
+ height: 16,
488
+ onPress: () => setCurrentSpectrumColor(color),
489
+ style: {
490
+ backgroundColor: "rgb(" + theme.spectrum[color + "20"] + ")",
491
+ borderColor: "rgb(" + theme.spectrum[color + "50"] + ")",
492
+ borderWidth: 2
493
+ },
494
+ width: 16
495
+ }, color))
496
+ }), /*#__PURE__*/_jsx(LineChart, {
497
+ points: true,
498
+ showYAxis: true,
499
+ height: 200,
500
+ series: [{
501
+ id: 'continuousGradient',
502
+ data: data,
503
+ gradient: {
504
+ stops: [{
505
+ offset: 0,
506
+ color: "rgb(" + theme.spectrum[currentSpectrumColor + "80"] + ")"
507
+ }, {
508
+ offset: Math.max(...data),
509
+ color: "rgb(" + theme.spectrum[currentSpectrumColor + "20"] + ")"
510
+ }]
511
+ }
512
+ }, {
513
+ id: 'discreteGradient',
514
+ data: data.map(d => d + 50),
515
+ // You can create a "discrete" gradient by having multiple stops at the same offset
516
+ gradient: {
517
+ stops: _ref3 => {
518
+ let {
519
+ min,
520
+ max
521
+ } = _ref3;
522
+ return [
523
+ // Allows a function which accepts min/max or direct array
524
+ {
525
+ offset: min,
526
+ color: "rgb(" + theme.spectrum[currentSpectrumColor + "80"] + ")"
527
+ }, {
528
+ offset: min + (max - min) / 3,
529
+ color: "rgb(" + theme.spectrum[currentSpectrumColor + "80"] + ")"
530
+ }, {
531
+ offset: min + (max - min) / 3,
532
+ color: "rgb(" + theme.spectrum[currentSpectrumColor + "50"] + ")"
533
+ }, {
534
+ offset: min + (max - min) / 3 * 2,
535
+ color: "rgb(" + theme.spectrum[currentSpectrumColor + "50"] + ")"
536
+ }, {
537
+ offset: min + (max - min) / 3 * 2,
538
+ color: "rgb(" + theme.spectrum[currentSpectrumColor + "20"] + ")"
539
+ }, {
540
+ offset: max,
541
+ color: "rgb(" + theme.spectrum[currentSpectrumColor + "20"] + ")"
542
+ }];
543
+ }
544
+ }
545
+ }, {
546
+ id: 'xAxisGradient',
547
+ data: data.map(d => d + 100),
548
+ gradient: {
549
+ // You can also configure by the x-axis.
550
+ axis: 'x',
551
+ stops: _ref4 => {
552
+ let {
553
+ min,
554
+ max
555
+ } = _ref4;
556
+ return [{
557
+ offset: min,
558
+ color: "rgb(" + theme.spectrum[currentSpectrumColor + "80"] + ")",
559
+ opacity: 0
560
+ }, {
561
+ offset: max,
562
+ color: "rgb(" + theme.spectrum[currentSpectrumColor + "20"] + ")",
563
+ opacity: 1
564
+ }];
565
+ }
566
+ }
567
+ }],
568
+ strokeWidth: 4,
569
+ yAxis: {
570
+ showGrid: true
571
+ }
572
+ })]
573
+ });
574
+ }
575
+ function GainLossChart() {
576
+ const theme = useTheme();
577
+ const data = useMemo(() => [-40, -28, -21, -5, 48, -5, -28, 2, -29, -46, 16, -30, -29, 8], []);
578
+ const negativeColor = "rgb(" + theme.spectrum.gray15 + ")";
579
+ const positiveColor = theme.color.fgPositive;
580
+ const tickLabelFormatter = useCallback(value => new Intl.NumberFormat('en-US', {
581
+ style: 'currency',
582
+ currency: 'USD',
583
+ maximumFractionDigits: 0
584
+ }).format(value), []);
585
+
586
+ // Line gradient: hard color change at 0 (full opacity for line)
587
+ const lineGradient = {
588
+ stops: [{
589
+ offset: 0,
590
+ color: negativeColor
591
+ }, {
592
+ offset: 0,
593
+ color: positiveColor
594
+ }]
595
+ };
596
+ const GradientDottedArea = /*#__PURE__*/memo(props => /*#__PURE__*/_jsx(DottedArea, _extends({}, props, {
597
+ gradient: {
598
+ stops: _ref5 => {
599
+ let {
600
+ min,
601
+ max
602
+ } = _ref5;
603
+ return [{
604
+ offset: min,
605
+ color: negativeColor,
606
+ opacity: 0.4
607
+ }, {
608
+ offset: 0,
609
+ color: negativeColor,
610
+ opacity: 0
611
+ }, {
612
+ offset: 0,
613
+ color: positiveColor,
614
+ opacity: 0
615
+ }, {
616
+ offset: max,
617
+ color: positiveColor,
618
+ opacity: 0.4
619
+ }];
620
+ }
621
+ }
622
+ })));
623
+ return /*#__PURE__*/_jsxs(CartesianChart, {
624
+ enableScrubbing: true,
625
+ height: 200,
626
+ series: [{
627
+ id: 'prices',
628
+ data: data,
629
+ gradient: lineGradient
630
+ }],
631
+ children: [/*#__PURE__*/_jsx(YAxis, {
632
+ showGrid: true,
633
+ requestedTickCount: 2,
634
+ tickLabelFormatter: tickLabelFormatter
635
+ }), /*#__PURE__*/_jsx(Line, {
636
+ showArea: true,
637
+ AreaComponent: GradientDottedArea,
638
+ seriesId: "prices",
639
+ strokeWidth: 3
640
+ }), /*#__PURE__*/_jsx(Scrubber, {
641
+ hideOverlay: true
642
+ })]
643
+ });
644
+ }
645
+ function HighLowPrice() {
646
+ const data = [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58];
647
+ const minPrice = Math.min(...data);
648
+ const maxPrice = Math.max(...data);
649
+ const minPriceIndex = data.indexOf(minPrice);
650
+ const maxPriceIndex = data.indexOf(maxPrice);
651
+ const formatPrice = useCallback(price => {
652
+ return "$" + price.toLocaleString('en-US', {
653
+ minimumFractionDigits: 2,
654
+ maximumFractionDigits: 2
655
+ });
656
+ }, []);
657
+ return /*#__PURE__*/_jsxs(LineChart, {
658
+ showArea: true,
659
+ height: 200,
660
+ series: [{
661
+ id: 'prices',
662
+ data: data
663
+ }],
664
+ children: [/*#__PURE__*/_jsx(Point, {
665
+ dataX: minPriceIndex,
666
+ dataY: minPrice,
667
+ label: formatPrice(minPrice),
668
+ labelPosition: "bottom"
669
+ }), /*#__PURE__*/_jsx(Point, {
670
+ dataX: maxPriceIndex,
671
+ dataY: maxPrice,
672
+ label: formatPrice(maxPrice),
673
+ labelPosition: "top"
674
+ })]
675
+ });
676
+ }
677
+ function StylingScrubber() {
678
+ 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];
682
+ const numberFormatter = useCallback(value => new Intl.NumberFormat('en-US', {
683
+ maximumFractionDigits: 0
684
+ }).format(value), []);
685
+ return /*#__PURE__*/_jsx(LineChart, {
686
+ enableScrubbing: true,
687
+ showArea: true,
688
+ showXAxis: true,
689
+ showYAxis: true,
690
+ height: 200,
691
+ series: [{
692
+ id: 'pageViews',
693
+ data: pageViews,
694
+ color: theme.color.accentBoldGreen,
695
+ // Label will render next to scrubber beacon
696
+ label: 'Page Views'
697
+ }, {
698
+ id: 'uniqueVisitors',
699
+ data: uniqueVisitors,
700
+ color: theme.color.accentBoldPurple,
701
+ label: 'Unique Visitors',
702
+ // Default area is gradient
703
+ areaType: 'dotted'
704
+ }],
705
+ xAxis: {
706
+ // Used on the x-axis to provide context for each index from the series data array
707
+ data: pages
708
+ },
709
+ yAxis: {
710
+ showGrid: true,
711
+ tickLabelFormatter: numberFormatter
712
+ },
713
+ children: /*#__PURE__*/_jsx(Scrubber, {
714
+ idlePulse: true,
715
+ LineComponent: SolidLine,
716
+ seriesIds: ['pageViews']
717
+ })
718
+ });
719
+ }
720
+ function Compact() {
721
+ const theme = useTheme();
722
+ const dimensions = {
723
+ width: 62,
724
+ height: 18
725
+ };
726
+ const sparklineData = prices.map(price => parseFloat(price)).filter((price, index) => index % 10 === 0);
727
+ const positiveFloor = Math.min(...sparklineData) - 10;
728
+ const negativeData = sparklineData.map(price => -1 * price).reverse();
729
+ const negativeCeiling = Math.max(...negativeData) + 10;
730
+ const formatPrice = useCallback(price => {
731
+ return "$" + price.toLocaleString('en-US', {
732
+ minimumFractionDigits: 2,
733
+ maximumFractionDigits: 2
734
+ });
735
+ }, []);
736
+ const CompactChart = /*#__PURE__*/memo(_ref6 => {
737
+ let {
738
+ data,
739
+ showArea,
740
+ color,
741
+ referenceY
742
+ } = _ref6;
743
+ return /*#__PURE__*/_jsx(Box, {
744
+ style: {
745
+ padding: 1
746
+ },
747
+ children: /*#__PURE__*/_jsx(LineChart, _extends({}, dimensions, {
748
+ enableScrubbing: false,
749
+ inset: 0,
750
+ series: [{
751
+ id: 'btc',
752
+ data,
753
+ color
754
+ }],
755
+ showArea: showArea,
756
+ children: /*#__PURE__*/_jsx(ReferenceLine, {
757
+ dataY: referenceY
758
+ })
759
+ }))
760
+ });
761
+ });
762
+ const ChartCell = /*#__PURE__*/memo(_ref7 => {
763
+ let {
764
+ data,
765
+ showArea,
766
+ color,
767
+ referenceY,
768
+ subdetail
769
+ } = _ref7;
770
+ return /*#__PURE__*/_jsx(ListCell, {
771
+ detail: formatPrice(parseFloat(prices[0])),
772
+ intermediary: /*#__PURE__*/_jsx(CompactChart, {
773
+ color: color,
774
+ data: data,
775
+ referenceY: referenceY,
776
+ showArea: showArea
777
+ }),
778
+ media: /*#__PURE__*/_jsx(Avatar, {
779
+ src: assets.btc.imageUrl
780
+ }),
781
+ onPress: () => console.log('clicked'),
782
+ spacingVariant: "condensed",
783
+ style: {
784
+ padding: 0
785
+ },
786
+ subdetail: subdetail
787
+ });
788
+ });
789
+ return /*#__PURE__*/_jsxs(VStack, {
790
+ children: [/*#__PURE__*/_jsx(ChartCell, {
791
+ color: assets.btc.color,
792
+ data: sparklineData,
793
+ referenceY: parseFloat(prices[Math.floor(prices.length / 4)]),
794
+ subdetail: "-4.55%"
795
+ }), /*#__PURE__*/_jsx(ChartCell, {
796
+ showArea: true,
797
+ color: assets.btc.color,
798
+ data: sparklineData,
799
+ referenceY: parseFloat(prices[Math.floor(prices.length / 4)]),
800
+ subdetail: "-4.55%"
801
+ }), /*#__PURE__*/_jsx(ChartCell, {
802
+ showArea: true,
803
+ color: theme.color.fgPositive,
804
+ data: sparklineData,
805
+ referenceY: positiveFloor,
806
+ subdetail: "+0.25%"
807
+ }), /*#__PURE__*/_jsx(ChartCell, {
808
+ showArea: true,
809
+ color: theme.color.fgNegative,
810
+ data: negativeData,
811
+ referenceY: negativeCeiling,
812
+ subdetail: "-4.55%"
813
+ })]
814
+ });
815
+ }
816
+ function AssetPriceWithDottedArea() {
817
+ const fontMgr = useMemo(() => {
818
+ const fontProvider = Skia.TypefaceFontProvider.Make();
819
+ // Register system fonts if available, otherwise Skia will use defaults
820
+ return fontProvider;
821
+ }, []);
822
+ const BTCTab = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref8, ref) => {
823
+ let {
824
+ label
825
+ } = _ref8,
826
+ props = _objectWithoutPropertiesLoose(_ref8, _excluded2);
827
+ const {
828
+ activeTab
829
+ } = useTabsContext();
830
+ const isActive = (activeTab == null ? void 0 : activeTab.id) === props.id;
831
+ return /*#__PURE__*/_jsx(SegmentedTab, _extends({
832
+ ref: ref,
833
+ label: /*#__PURE__*/_jsx(Text, {
834
+ font: "label1",
835
+ style: {
836
+ color: isActive ? assets.btc.color : undefined
837
+ },
838
+ children: label
839
+ })
840
+ }, props));
841
+ }));
842
+ const BTCActiveIndicator = /*#__PURE__*/memo(_ref9 => {
843
+ let {
844
+ style
845
+ } = _ref9,
846
+ props = _objectWithoutPropertiesLoose(_ref9, _excluded3);
847
+ return /*#__PURE__*/_jsx(PeriodSelectorActiveIndicator, _extends({}, props, {
848
+ style: [style, {
849
+ backgroundColor: assets.btc.color + "1A"
850
+ }]
851
+ }));
852
+ });
853
+ const AssetPriceDotted = /*#__PURE__*/memo(() => {
854
+ const theme = useTheme();
855
+ const currentPrice = sparklineInteractiveData.hour[sparklineInteractiveData.hour.length - 1].value;
856
+ const tabs = useMemo(() => [{
857
+ id: 'hour',
858
+ label: '1H'
859
+ }, {
860
+ id: 'day',
861
+ label: '1D'
862
+ }, {
863
+ id: 'week',
864
+ label: '1W'
865
+ }, {
866
+ id: 'month',
867
+ label: '1M'
868
+ }, {
869
+ id: 'year',
870
+ label: '1Y'
871
+ }, {
872
+ id: 'all',
873
+ label: 'All'
874
+ }], []);
875
+ const [timePeriod, setTimePeriod] = useState(tabs[0]);
876
+ const sparklineTimePeriodData = useMemo(() => {
877
+ return sparklineInteractiveData[timePeriod.id];
878
+ }, [timePeriod]);
879
+ const sparklineTimePeriodDataValues = useMemo(() => {
880
+ return sparklineTimePeriodData.map(d => d.value);
881
+ }, [sparklineTimePeriodData]);
882
+ const sparklineTimePeriodDataTimestamps = useMemo(() => {
883
+ return sparklineTimePeriodData.map(d => d.date);
884
+ }, [sparklineTimePeriodData]);
885
+ const onPeriodChange = useCallback(period => {
886
+ setTimePeriod(period || tabs[0]);
887
+ }, [tabs, setTimePeriod]);
888
+ const priceFormatter = useMemo(() => new Intl.NumberFormat('en-US', {
889
+ style: 'currency',
890
+ currency: 'USD'
891
+ }), []);
892
+ const formatPrice = useCallback(price => {
893
+ return priceFormatter.format(price);
894
+ }, [priceFormatter]);
895
+ const formatDate = useCallback(date => {
896
+ const dayOfWeek = date.toLocaleDateString('en-US', {
897
+ weekday: 'short'
898
+ });
899
+ const monthDay = date.toLocaleDateString('en-US', {
900
+ month: 'short',
901
+ day: 'numeric'
902
+ });
903
+ const time = date.toLocaleTimeString('en-US', {
904
+ hour: 'numeric',
905
+ minute: '2-digit',
906
+ hour12: true
907
+ });
908
+ return dayOfWeek + ", " + monthDay + ", " + time;
909
+ }, []);
910
+ return /*#__PURE__*/_jsxs(VStack, {
911
+ gap: 2,
912
+ children: [/*#__PURE__*/_jsx(SectionHeader, {
913
+ balance: /*#__PURE__*/_jsx(Text, {
914
+ font: "title2",
915
+ children: formatPrice(currentPrice)
916
+ }),
917
+ end: /*#__PURE__*/_jsx(VStack, {
918
+ justifyContent: "center",
919
+ children: /*#__PURE__*/_jsx(RemoteImage, {
920
+ shape: "circle",
921
+ size: "xl",
922
+ source: assets.btc.imageUrl
923
+ })
924
+ }),
925
+ title: /*#__PURE__*/_jsx(Text, {
926
+ font: "title1",
927
+ children: "Bitcoin"
928
+ })
929
+ }), /*#__PURE__*/_jsx(LineChart, {
930
+ enableScrubbing: true,
931
+ showArea: true,
932
+ areaType: "dotted",
933
+ height: 200,
934
+ inset: {
935
+ top: 52
936
+ },
937
+ series: [{
938
+ id: 'btc',
939
+ data: sparklineTimePeriodDataValues,
940
+ color: assets.btc.color
941
+ }],
942
+ children: /*#__PURE__*/_jsx(Scrubber, {
943
+ idlePulse: true,
944
+ labelElevated: true,
945
+ label: d => {
946
+ const date = formatDate(sparklineTimePeriodDataTimestamps[d]);
947
+ const price = formatPrice(sparklineTimePeriodDataValues[d]);
948
+ const regularStyle = {
949
+ fontFamilies: ['Inter'],
950
+ fontSize: 14,
951
+ fontStyle: {
952
+ weight: FontWeight.Normal
953
+ },
954
+ color: Skia.Color(theme.color.fgMuted)
955
+ };
956
+ const boldStyle = _extends({
957
+ fontFamilies: ['Inter']
958
+ }, regularStyle, {
959
+ fontStyle: {
960
+ weight: FontWeight.Bold
961
+ }
962
+ });
963
+
964
+ // 3. Use the ParagraphBuilder
965
+ const builder = Skia.ParagraphBuilder.Make({
966
+ textAlign: TextAlign.Left
967
+ }, fontMgr);
968
+ builder.pushStyle(boldStyle);
969
+ builder.addText(price);
970
+ builder.pushStyle(regularStyle);
971
+ builder.addText(" " + date);
972
+ const para = builder.build();
973
+ para.layout(512);
974
+ return para;
975
+ }
976
+ })
977
+ }), /*#__PURE__*/_jsx(PeriodSelector, {
978
+ TabComponent: BTCTab,
979
+ TabsActiveIndicatorComponent: BTCActiveIndicator,
980
+ activeTab: timePeriod,
981
+ onChange: onPeriodChange,
982
+ tabs: tabs
983
+ })]
984
+ });
985
+ });
986
+ return /*#__PURE__*/_jsx(AssetPriceDotted, {});
987
+ }
988
+ const LegendDot = /*#__PURE__*/memo(props => {
989
+ return /*#__PURE__*/_jsx(Box, _extends({
990
+ borderRadius: 1000,
991
+ height: 10,
992
+ width: 10
993
+ }, props));
994
+ });
995
+ const LegendItem = /*#__PURE__*/memo(_ref0 => {
996
+ let {
997
+ color = assets.btc.color,
998
+ label,
999
+ value
1000
+ } = _ref0;
1001
+ return /*#__PURE__*/_jsxs(Box, {
1002
+ alignItems: "center",
1003
+ flexDirection: "row",
1004
+ gap: 0.5,
1005
+ children: [/*#__PURE__*/_jsx(LegendDot, {
1006
+ style: {
1007
+ backgroundColor: color
1008
+ }
1009
+ }), /*#__PURE__*/_jsx(Text, {
1010
+ font: "label2",
1011
+ children: label
1012
+ }), value && /*#__PURE__*/_jsx(Text, {
1013
+ color: "fgMuted",
1014
+ font: "label2",
1015
+ style: {
1016
+ fontWeight: 'bold'
1017
+ },
1018
+ children: value
1019
+ })]
1020
+ });
1021
+ });
1022
+ const PerformanceHeader = /*#__PURE__*/memo(_ref1 => {
1023
+ let {
1024
+ scrubberPosition,
1025
+ sparklineTimePeriodDataValues
1026
+ } = _ref1;
1027
+ const theme = useTheme();
1028
+ const formatPriceThousands = useCallback(price => {
1029
+ return new Intl.NumberFormat('en-US', {
1030
+ style: 'currency',
1031
+ currency: 'USD',
1032
+ minimumFractionDigits: 0,
1033
+ maximumFractionDigits: 0
1034
+ }).format(price / 1000) + "k";
1035
+ }, []);
1036
+ const shownPosition = scrubberPosition !== undefined ? scrubberPosition : sparklineTimePeriodDataValues.length - 1;
1037
+ return /*#__PURE__*/_jsxs(HStack, {
1038
+ gap: 1,
1039
+ paddingX: 1,
1040
+ children: [/*#__PURE__*/_jsx(LegendItem, {
1041
+ color: theme.color.fgPositive,
1042
+ label: "High Price",
1043
+ value: formatPriceThousands(sparklineTimePeriodDataValues[shownPosition] * 1.2)
1044
+ }), /*#__PURE__*/_jsx(LegendItem, {
1045
+ color: assets.btc.color,
1046
+ label: "Actual Price",
1047
+ value: formatPriceThousands(sparklineTimePeriodDataValues[shownPosition])
1048
+ }), /*#__PURE__*/_jsx(LegendItem, {
1049
+ color: theme.color.fgNegative,
1050
+ label: "Low Price",
1051
+ value: formatPriceThousands(sparklineTimePeriodDataValues[shownPosition] * 0.8)
1052
+ })]
1053
+ });
1054
+ });
1055
+ const PerformanceChart = /*#__PURE__*/memo(_ref10 => {
1056
+ let {
1057
+ timePeriod,
1058
+ onScrubberPositionChange
1059
+ } = _ref10;
1060
+ const theme = useTheme();
1061
+ const sparklineTimePeriodData = useMemo(() => {
1062
+ return sparklineInteractiveData[timePeriod.id];
1063
+ }, [timePeriod]);
1064
+ const sparklineTimePeriodDataValues = useMemo(() => {
1065
+ return sparklineTimePeriodData.map(d => d.value);
1066
+ }, [sparklineTimePeriodData]);
1067
+ const sparklineTimePeriodDataTimestamps = useMemo(() => {
1068
+ return sparklineTimePeriodData.map(d => d.date);
1069
+ }, [sparklineTimePeriodData]);
1070
+ const formatPriceThousands = useCallback(price => {
1071
+ return new Intl.NumberFormat('en-US', {
1072
+ style: 'currency',
1073
+ currency: 'USD',
1074
+ minimumFractionDigits: 0,
1075
+ maximumFractionDigits: 0
1076
+ }).format(price / 1000) + "k";
1077
+ }, []);
1078
+ const formatDate = useCallback(date => {
1079
+ const dayOfWeek = date.toLocaleDateString('en-US', {
1080
+ weekday: 'short'
1081
+ });
1082
+ const monthDay = date.toLocaleDateString('en-US', {
1083
+ month: 'short',
1084
+ day: 'numeric'
1085
+ });
1086
+ const time = date.toLocaleTimeString('en-US', {
1087
+ hour: 'numeric',
1088
+ minute: '2-digit',
1089
+ hour12: true
1090
+ });
1091
+ return dayOfWeek + ", " + monthDay + ", " + time;
1092
+ }, []);
1093
+ const getScrubberLabel = useCallback(d => formatDate(sparklineTimePeriodDataTimestamps[d]), [formatDate, sparklineTimePeriodDataTimestamps]);
1094
+ return /*#__PURE__*/_jsx(LineChart, {
1095
+ enableScrubbing: true,
1096
+ showArea: true,
1097
+ showYAxis: true,
1098
+ areaType: "dotted",
1099
+ height: 300,
1100
+ inset: {
1101
+ top: 52,
1102
+ left: 0,
1103
+ right: 0
1104
+ },
1105
+ onScrubberPositionChange: onScrubberPositionChange,
1106
+ series: [{
1107
+ id: 'high',
1108
+ data: sparklineTimePeriodDataValues.map(d => d * 1.2),
1109
+ color: theme.color.fgPositive,
1110
+ label: 'High Price'
1111
+ }, {
1112
+ id: 'btc',
1113
+ data: sparklineTimePeriodDataValues,
1114
+ color: assets.btc.color,
1115
+ label: 'Actual Price'
1116
+ }, {
1117
+ id: 'low',
1118
+ data: sparklineTimePeriodDataValues.map(d => d * 0.8),
1119
+ color: theme.color.fgNegative,
1120
+ label: 'Low Price'
1121
+ }],
1122
+ yAxis: {
1123
+ showGrid: true,
1124
+ tickLabelFormatter: formatPriceThousands
1125
+ },
1126
+ children: /*#__PURE__*/_jsx(Scrubber, {
1127
+ idlePulse: true,
1128
+ label: getScrubberLabel
1129
+ })
1130
+ });
1131
+ });
1132
+ function Performance() {
1133
+ const tabs = useMemo(() => [{
1134
+ id: 'hour',
1135
+ label: '1H'
1136
+ }, {
1137
+ id: 'day',
1138
+ label: '1D'
1139
+ }, {
1140
+ id: 'week',
1141
+ label: '1W'
1142
+ }, {
1143
+ id: 'month',
1144
+ label: '1M'
1145
+ }, {
1146
+ id: 'year',
1147
+ label: '1Y'
1148
+ }, {
1149
+ id: 'all',
1150
+ label: 'All'
1151
+ }], []);
1152
+ const [timePeriod, setTimePeriod] = useState(tabs[0]);
1153
+ const [scrubberPosition, setScrubberPosition] = useState();
1154
+ const sparklineTimePeriodData = useMemo(() => {
1155
+ return sparklineInteractiveData[timePeriod.id];
1156
+ }, [timePeriod]);
1157
+ const sparklineTimePeriodDataValues = useMemo(() => {
1158
+ return sparklineTimePeriodData.map(d => d.value);
1159
+ }, [sparklineTimePeriodData]);
1160
+ const onPeriodChange = useCallback(period => {
1161
+ setTimePeriod(period || tabs[0]);
1162
+ }, [tabs]);
1163
+ return /*#__PURE__*/_jsxs(VStack, {
1164
+ gap: 2,
1165
+ style: {
1166
+ marginLeft: -8,
1167
+ marginRight: -8
1168
+ },
1169
+ children: [/*#__PURE__*/_jsx(PerformanceHeader, {
1170
+ scrubberPosition: scrubberPosition,
1171
+ sparklineTimePeriodDataValues: sparklineTimePeriodDataValues
1172
+ }), /*#__PURE__*/_jsx(PerformanceChart, {
1173
+ onScrubberPositionChange: setScrubberPosition,
1174
+ timePeriod: timePeriod
1175
+ }), /*#__PURE__*/_jsx(PeriodSelector, {
1176
+ activeTab: timePeriod,
1177
+ onChange: onPeriodChange,
1178
+ tabs: tabs
1179
+ })]
1180
+ });
1181
+ }
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
+ function MonotoneAssetPrice() {
1387
+ const theme = useTheme();
1388
+ const prices = sparklineInteractiveData.hour;
1389
+ const fontMgr = useMemo(() => {
1390
+ const fontProvider = Skia.TypefaceFontProvider.Make();
1391
+ // Register system fonts if available, otherwise Skia will use defaults
1392
+ return fontProvider;
1393
+ }, []);
1394
+ const priceFormatter = useMemo(() => new Intl.NumberFormat('en-US', {
1395
+ style: 'currency',
1396
+ currency: 'USD'
1397
+ }), []);
1398
+ const scrubberPriceFormatter = useMemo(() => new Intl.NumberFormat('en-US', {
1399
+ minimumFractionDigits: 2,
1400
+ maximumFractionDigits: 2
1401
+ }), []);
1402
+ const formatPrice = useCallback(price => {
1403
+ return priceFormatter.format(price);
1404
+ }, [priceFormatter]);
1405
+ const formatDate = useCallback(date => {
1406
+ const dayOfWeek = date.toLocaleDateString('en-US', {
1407
+ weekday: 'short'
1408
+ });
1409
+ const monthDay = date.toLocaleDateString('en-US', {
1410
+ month: 'short',
1411
+ day: 'numeric'
1412
+ });
1413
+ const time = date.toLocaleTimeString('en-US', {
1414
+ hour: 'numeric',
1415
+ minute: '2-digit',
1416
+ hour12: true
1417
+ });
1418
+ return dayOfWeek + ", " + monthDay + ", " + time;
1419
+ }, []);
1420
+ const scrubberLabel = useCallback(index => {
1421
+ const price = scrubberPriceFormatter.format(prices[index].value);
1422
+ const date = formatDate(prices[index].date);
1423
+ const regularStyle = {
1424
+ fontFamilies: ['Inter'],
1425
+ fontSize: 14,
1426
+ fontStyle: {
1427
+ weight: FontWeight.Normal
1428
+ },
1429
+ color: Skia.Color(theme.color.fgMuted)
1430
+ };
1431
+ const boldStyle = _extends({
1432
+ fontFamilies: ['Inter']
1433
+ }, regularStyle, {
1434
+ fontStyle: {
1435
+ weight: FontWeight.Bold
1436
+ }
1437
+ });
1438
+ const builder = Skia.ParagraphBuilder.Make({
1439
+ textAlign: TextAlign.Left
1440
+ }, fontMgr);
1441
+ builder.pushStyle(boldStyle);
1442
+ builder.addText(price + " USD");
1443
+ builder.pushStyle(regularStyle);
1444
+ builder.addText(" " + date);
1445
+ const para = builder.build();
1446
+ para.layout(512);
1447
+ return para;
1448
+ }, [scrubberPriceFormatter, prices, formatDate, theme.color.fgMuted, fontMgr]);
1449
+ const formatAxisLabelPrice = useCallback(price => {
1450
+ return formatPrice(price);
1451
+ }, [formatPrice]);
1452
+
1453
+ // Custom tick label component with offset positioning
1454
+ const CustomYAxisTickLabel = useCallback(props => /*#__PURE__*/_jsx(DefaultAxisTickLabel, _extends({}, props, {
1455
+ dx: 4,
1456
+ dy: -12,
1457
+ horizontalAlignment: "left"
1458
+ })), []);
1459
+ const CustomScrubberBeacon = /*#__PURE__*/memo(_ref16 => {
1460
+ let {
1461
+ dataX,
1462
+ dataY,
1463
+ seriesId,
1464
+ isIdle,
1465
+ animate = true
1466
+ } = _ref16;
1467
+ const {
1468
+ getSeries,
1469
+ getXSerializableScale,
1470
+ getYSerializableScale
1471
+ } = useCartesianChartContext();
1472
+ const targetSeries = useMemo(() => getSeries(seriesId), [getSeries, seriesId]);
1473
+ const xScale = useMemo(() => getXSerializableScale(), [getXSerializableScale]);
1474
+ const yScale = useMemo(() => getYSerializableScale(targetSeries == null ? void 0 : targetSeries.yAxisId), [getYSerializableScale, targetSeries == null ? void 0 : targetSeries.yAxisId]);
1475
+ const animatedX = useSharedValue(0);
1476
+ const animatedY = useSharedValue(0);
1477
+
1478
+ // Calculate the target point position - project data to pixels
1479
+ const targetPoint = useDerivedValue(() => {
1480
+ if (!xScale || !yScale) return {
1481
+ x: 0,
1482
+ y: 0
1483
+ };
1484
+ return projectPointWithSerializableScale({
1485
+ x: unwrapAnimatedValue(dataX),
1486
+ y: unwrapAnimatedValue(dataY),
1487
+ xScale,
1488
+ yScale
1489
+ });
1490
+ }, [dataX, dataY, xScale, yScale]);
1491
+ useAnimatedReaction(() => {
1492
+ return {
1493
+ point: targetPoint.value,
1494
+ isIdle: unwrapAnimatedValue(isIdle)
1495
+ };
1496
+ }, (current, previous) => {
1497
+ // When animation is disabled, on initial render, or when we are starting,
1498
+ // continuing, or finishing scrubbing we should immediately transition
1499
+ if (!animate || previous === null || !previous.isIdle || !current.isIdle) {
1500
+ animatedX.value = current.point.x;
1501
+ animatedY.value = current.point.y;
1502
+ return;
1503
+ }
1504
+ animatedX.value = buildTransition(current.point.x, defaultTransition);
1505
+ animatedY.value = buildTransition(current.point.y, defaultTransition);
1506
+ }, [animate]);
1507
+
1508
+ // Create animated point using the animated values
1509
+ const animatedPoint = useDerivedValue(() => {
1510
+ return {
1511
+ x: animatedX.value,
1512
+ y: animatedY.value
1513
+ };
1514
+ }, [animatedX, animatedY]);
1515
+ return /*#__PURE__*/_jsxs(_Fragment, {
1516
+ children: [/*#__PURE__*/_jsx(Circle, {
1517
+ c: animatedPoint,
1518
+ color: theme.color.bg,
1519
+ r: 5
1520
+ }), /*#__PURE__*/_jsx(Circle, {
1521
+ c: animatedPoint,
1522
+ color: theme.color.fg,
1523
+ r: 5,
1524
+ strokeWidth: 3,
1525
+ style: "stroke"
1526
+ })]
1527
+ });
1528
+ });
1529
+ return /*#__PURE__*/_jsx(LineChart, {
1530
+ enableScrubbing: true,
1531
+ showYAxis: true,
1532
+ height: 200,
1533
+ inset: {
1534
+ top: 64
1535
+ },
1536
+ series: [{
1537
+ id: 'btc',
1538
+ data: prices.map(price => price.value),
1539
+ color: theme.color.fg,
1540
+ gradient: {
1541
+ axis: 'x',
1542
+ stops: _ref17 => {
1543
+ let {
1544
+ min
1545
+ } = _ref17;
1546
+ return [{
1547
+ offset: min,
1548
+ color: theme.color.fg,
1549
+ opacity: 0
1550
+ }, {
1551
+ offset: 32,
1552
+ color: theme.color.fg,
1553
+ opacity: 1
1554
+ }];
1555
+ }
1556
+ }
1557
+ }],
1558
+ xAxis: {
1559
+ range: _ref18 => {
1560
+ let {
1561
+ max
1562
+ } = _ref18;
1563
+ return {
1564
+ min: 96,
1565
+ max
1566
+ };
1567
+ }
1568
+ },
1569
+ yAxis: {
1570
+ position: 'left',
1571
+ width: 0,
1572
+ showGrid: true,
1573
+ tickLabelFormatter: formatAxisLabelPrice,
1574
+ TickLabelComponent: CustomYAxisTickLabel
1575
+ },
1576
+ children: /*#__PURE__*/_jsx(Scrubber, {
1577
+ hideOverlay: true,
1578
+ labelElevated: true,
1579
+ BeaconComponent: CustomScrubberBeacon,
1580
+ LineComponent: SolidLine,
1581
+ label: scrubberLabel
1582
+ })
1583
+ });
1584
+ }
1585
+ function ServiceAvailability() {
1586
+ const theme = useTheme();
1587
+ const availabilityEvents = useMemo(() => [{
1588
+ date: new Date('2022-01-01'),
1589
+ availability: 79
1590
+ }, {
1591
+ date: new Date('2022-01-03'),
1592
+ availability: 81
1593
+ }, {
1594
+ date: new Date('2022-01-04'),
1595
+ availability: 82
1596
+ }, {
1597
+ date: new Date('2022-01-06'),
1598
+ availability: 91
1599
+ }, {
1600
+ date: new Date('2022-01-07'),
1601
+ availability: 92
1602
+ }, {
1603
+ date: new Date('2022-01-10'),
1604
+ availability: 86
1605
+ }], []);
1606
+ return /*#__PURE__*/_jsxs(CartesianChart, {
1607
+ enableScrubbing: true,
1608
+ height: 200,
1609
+ series: [{
1610
+ id: 'availability',
1611
+ data: availabilityEvents.map(event => event.availability),
1612
+ gradient: {
1613
+ stops: _ref19 => {
1614
+ let {
1615
+ min,
1616
+ max
1617
+ } = _ref19;
1618
+ return [{
1619
+ offset: min,
1620
+ color: theme.color.fgNegative
1621
+ }, {
1622
+ offset: 85,
1623
+ color: theme.color.fgNegative
1624
+ }, {
1625
+ offset: 85,
1626
+ color: theme.color.fgWarning
1627
+ }, {
1628
+ offset: 90,
1629
+ color: theme.color.fgWarning
1630
+ }, {
1631
+ offset: 90,
1632
+ color: theme.color.fgPositive
1633
+ }, {
1634
+ offset: max,
1635
+ color: theme.color.fgPositive
1636
+ }];
1637
+ }
1638
+ }
1639
+ }],
1640
+ xAxis: {
1641
+ data: availabilityEvents.map(event => event.date.getTime())
1642
+ },
1643
+ yAxis: {
1644
+ domain: _ref20 => {
1645
+ let {
1646
+ min,
1647
+ max
1648
+ } = _ref20;
1649
+ return {
1650
+ min: Math.max(min - 2, 0),
1651
+ max: Math.min(max + 2, 100)
1652
+ };
1653
+ }
1654
+ },
1655
+ children: [/*#__PURE__*/_jsx(XAxis, {
1656
+ showGrid: true,
1657
+ showLine: true,
1658
+ showTickMarks: true,
1659
+ tickLabelFormatter: value => new Date(value).toLocaleDateString()
1660
+ }), /*#__PURE__*/_jsx(YAxis, {
1661
+ showGrid: true,
1662
+ showLine: true,
1663
+ showTickMarks: true,
1664
+ position: "left",
1665
+ tickLabelFormatter: value => value + "%"
1666
+ }), /*#__PURE__*/_jsx(Line, {
1667
+ curve: "stepAfter",
1668
+ points: props => _extends({}, props, {
1669
+ fill: theme.color.bg,
1670
+ stroke: props.fill
1671
+ }),
1672
+ seriesId: "availability"
1673
+ }), /*#__PURE__*/_jsx(Scrubber, {
1674
+ hideOverlay: true
1675
+ })]
1676
+ });
1677
+ }
1678
+ function ForecastAssetPrice() {
1679
+ const startYear = 2020;
1680
+ const data = [50, 45, 47, 46, 54, 54, 60, 61, 63, 66, 70];
1681
+ const currentIndex = 6;
1682
+ const strokeWidth = 3;
1683
+ // To prevent cutting off the edge of our lines
1684
+ const clipOffset = strokeWidth;
1685
+ const axisFormatter = useCallback(dataIndex => {
1686
+ return "" + (startYear + dataIndex);
1687
+ }, [startYear]);
1688
+ const HistoricalLineComponent = /*#__PURE__*/memo(props => {
1689
+ const {
1690
+ drawingArea,
1691
+ getXScale
1692
+ } = useCartesianChartContext();
1693
+ const xScale = getXScale();
1694
+ const historicalClipPath = useMemo(() => {
1695
+ if (!xScale || !drawingArea) return null;
1696
+ const currentX = xScale(currentIndex);
1697
+ if (currentX === undefined) return null;
1698
+
1699
+ // Create clip path for historical data (left side)
1700
+ const clip = Skia.Path.Make();
1701
+ clip.addRect({
1702
+ x: drawingArea.x - clipOffset,
1703
+ y: drawingArea.y - clipOffset,
1704
+ width: currentX + clipOffset - drawingArea.x,
1705
+ height: drawingArea.height + clipOffset * 2
1706
+ });
1707
+ return clip;
1708
+ }, [xScale, drawingArea]);
1709
+ if (!historicalClipPath) return null;
1710
+ return /*#__PURE__*/_jsx(Group, {
1711
+ clip: historicalClipPath,
1712
+ children: /*#__PURE__*/_jsx(SolidLine, _extends({
1713
+ strokeWidth: strokeWidth
1714
+ }, props))
1715
+ });
1716
+ });
1717
+
1718
+ // Since the solid and dotted line have different curves,
1719
+ // we need two separate line components. Otherwise we could
1720
+ // have one line component with SolidLine and DottedLine inside
1721
+ // of it and two clipPaths.
1722
+ const ForecastLineComponent = /*#__PURE__*/memo(props => {
1723
+ const {
1724
+ drawingArea,
1725
+ getXScale
1726
+ } = useCartesianChartContext();
1727
+ const xScale = getXScale();
1728
+ const forecastClipPath = useMemo(() => {
1729
+ if (!xScale || !drawingArea) return null;
1730
+ const currentX = xScale(currentIndex);
1731
+ if (currentX === undefined) return null;
1732
+
1733
+ // Create clip path for forecast data (right side)
1734
+ const clip = Skia.Path.Make();
1735
+ clip.addRect({
1736
+ x: currentX,
1737
+ y: drawingArea.y - clipOffset,
1738
+ width: drawingArea.x + drawingArea.width - currentX + clipOffset * 2,
1739
+ height: drawingArea.height + clipOffset * 2
1740
+ });
1741
+ return clip;
1742
+ }, [xScale, drawingArea]);
1743
+ if (!forecastClipPath) return null;
1744
+ return /*#__PURE__*/_jsx(Group, {
1745
+ clip: forecastClipPath,
1746
+ children: /*#__PURE__*/_jsx(DottedLine, _extends({
1747
+ dashIntervals: [0, strokeWidth * 2],
1748
+ strokeWidth: strokeWidth
1749
+ }, props))
1750
+ });
1751
+ });
1752
+ const CustomScrubber = /*#__PURE__*/memo(() => {
1753
+ const {
1754
+ scrubberPosition
1755
+ } = useScrubberContext();
1756
+ const idleScrubberOpacity = useDerivedValue(() => scrubberPosition.value === undefined ? 1 : 0, [scrubberPosition]);
1757
+ const scrubberOpacity = useDerivedValue(() => scrubberPosition.value !== undefined ? 1 : 0, [scrubberPosition]);
1758
+
1759
+ // Fade in animation for the Scrubber
1760
+ const fadeInOpacity = useSharedValue(0);
1761
+ useEffect(() => {
1762
+ fadeInOpacity.value = withDelay(350, withTiming(1, {
1763
+ duration: 150
1764
+ }));
1765
+ }, [fadeInOpacity]);
1766
+ return /*#__PURE__*/_jsxs(Group, {
1767
+ opacity: fadeInOpacity,
1768
+ children: [/*#__PURE__*/_jsx(Group, {
1769
+ opacity: scrubberOpacity,
1770
+ children: /*#__PURE__*/_jsx(Scrubber, {
1771
+ hideOverlay: true
1772
+ })
1773
+ }), /*#__PURE__*/_jsx(Group, {
1774
+ opacity: idleScrubberOpacity,
1775
+ children: /*#__PURE__*/_jsx(DefaultScrubberBeacon, {
1776
+ isIdle: true,
1777
+ dataX: currentIndex,
1778
+ dataY: data[currentIndex],
1779
+ seriesId: "price"
1780
+ })
1781
+ })]
1782
+ });
1783
+ });
1784
+ return /*#__PURE__*/_jsxs(CartesianChart, {
1785
+ enableScrubbing: true,
1786
+ height: 200,
1787
+ series: [{
1788
+ id: 'price',
1789
+ data,
1790
+ color: assets.btc.color
1791
+ }],
1792
+ children: [/*#__PURE__*/_jsx(Line, {
1793
+ LineComponent: HistoricalLineComponent,
1794
+ curve: "linear",
1795
+ seriesId: "price"
1796
+ }), /*#__PURE__*/_jsx(Line, {
1797
+ LineComponent: ForecastLineComponent,
1798
+ curve: "monotone",
1799
+ seriesId: "price",
1800
+ type: "dotted"
1801
+ }), /*#__PURE__*/_jsx(XAxis, {
1802
+ position: "bottom",
1803
+ requestedTickCount: 3,
1804
+ tickLabelFormatter: axisFormatter
1805
+ }), /*#__PURE__*/_jsx(CustomScrubber, {})]
1806
+ });
1807
+ }
1808
+ function ImperativeHandle() {
1809
+ const theme = useTheme();
1810
+ const scrubberRef = useRef(null);
1811
+ return /*#__PURE__*/_jsxs(VStack, {
1812
+ 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
1860
+ })
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
+ })]
1868
+ });
1869
+ }
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
+ });
1914
+ return /*#__PURE__*/_jsx(LineChart, {
1915
+ enableScrubbing: true,
1916
+ showArea: true,
1917
+ 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
+ },
1973
+ 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'
2010
+ }],
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
2096
+ },
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
+ })]
2109
+ });
2110
+ }
2111
+ function ExampleNavigator() {
2112
+ const theme = useTheme();
2113
+ const [currentIndex, setCurrentIndex] = useState(0);
2114
+ const examples = useMemo(() => [{
2115
+ title: 'Basic',
2116
+ component: /*#__PURE__*/_jsx(LineChart, {
2117
+ showArea: true,
2118
+ height: 200,
2119
+ series: [{
2120
+ id: 'prices',
2121
+ data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58]
2122
+ }]
2123
+ })
2124
+ }, {
2125
+ title: 'Imperative Handle',
2126
+ component: /*#__PURE__*/_jsx(ImperativeHandle, {})
2127
+ }, {
2128
+ title: 'Multiple Lines',
2129
+ component: /*#__PURE__*/_jsx(MultipleLine, {})
2130
+ }, {
2131
+ title: 'Data Format',
2132
+ component: /*#__PURE__*/_jsx(DataFormat, {})
2133
+ }, {
2134
+ title: 'Live Updates',
2135
+ component: /*#__PURE__*/_jsx(LiveUpdates, {})
2136
+ }, {
2137
+ title: 'Missing Data',
2138
+ component: /*#__PURE__*/_jsx(MissingData, {})
2139
+ }, {
2140
+ title: 'Empty State',
2141
+ component: /*#__PURE__*/_jsx(LineChart, {
2142
+ height: 200,
2143
+ series: [{
2144
+ id: 'line',
2145
+ color: "rgb(" + theme.spectrum.gray50 + ")",
2146
+ data: [1, 1],
2147
+ showArea: true
2148
+ }],
2149
+ yAxis: {
2150
+ domain: {
2151
+ min: -1,
2152
+ max: 3
2153
+ }
2154
+ }
2155
+ })
2156
+ }, {
2157
+ title: 'Scales',
2158
+ component: /*#__PURE__*/_jsx(LineChart, {
2159
+ showArea: true,
2160
+ showYAxis: true,
2161
+ height: 200,
2162
+ series: [{
2163
+ id: 'prices',
2164
+ data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58]
2165
+ }],
2166
+ yAxis: {
2167
+ scaleType: 'log',
2168
+ showGrid: true,
2169
+ ticks: [1, 10, 100]
2170
+ }
2171
+ })
2172
+ }, {
2173
+ title: 'Interaction',
2174
+ component: /*#__PURE__*/_jsx(Interaction, {})
2175
+ }, {
2176
+ title: 'Points',
2177
+ component: /*#__PURE__*/_jsx(Points, {})
2178
+ }, {
2179
+ title: 'Transitions',
2180
+ component: /*#__PURE__*/_jsx(Transitions, {})
2181
+ }, {
2182
+ title: 'Basic Accessible',
2183
+ component: /*#__PURE__*/_jsx(BasicAccessible, {})
2184
+ }, {
2185
+ title: 'Styling Axes',
2186
+ component: /*#__PURE__*/_jsx(LineChart, {
2187
+ showArea: true,
2188
+ showXAxis: true,
2189
+ showYAxis: true,
2190
+ height: 200,
2191
+ series: [{
2192
+ id: 'prices',
2193
+ data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58]
2194
+ }],
2195
+ xAxis: {
2196
+ showGrid: true,
2197
+ showLine: true,
2198
+ showTickMarks: true,
2199
+ tickLabelFormatter: dataX => "Day " + dataX
2200
+ },
2201
+ yAxis: {
2202
+ showGrid: true,
2203
+ showLine: true,
2204
+ showTickMarks: true
2205
+ }
2206
+ })
2207
+ }, {
2208
+ title: 'Gradients',
2209
+ component: /*#__PURE__*/_jsx(Gradients, {})
2210
+ }, {
2211
+ title: 'Gain/Loss',
2212
+ component: /*#__PURE__*/_jsx(GainLossChart, {})
2213
+ }, {
2214
+ title: 'Styling Lines',
2215
+ component: /*#__PURE__*/_jsx(LineChart, {
2216
+ height: 200,
2217
+ series: [{
2218
+ id: 'top',
2219
+ data: [15, 28, 32, 44, 46, 36, 40, 45, 48, 38]
2220
+ }, {
2221
+ id: 'upperMiddle',
2222
+ data: [12, 23, 21, 29, 34, 28, 31, 38, 42, 35],
2223
+ color: '#ef4444',
2224
+ type: 'dotted'
2225
+ }, {
2226
+ id: 'lowerMiddle',
2227
+ data: [8, 15, 14, 25, 20, 18, 22, 28, 24, 30],
2228
+ color: '#f59e0b',
2229
+ curve: 'natural',
2230
+ gradient: {
2231
+ axis: 'x',
2232
+ stops: [{
2233
+ offset: 0,
2234
+ color: '#E3D74D'
2235
+ }, {
2236
+ offset: 9,
2237
+ color: '#F7931A'
2238
+ }]
2239
+ },
2240
+ strokeWidth: 6
2241
+ }, {
2242
+ id: 'bottom',
2243
+ data: [4, 8, 11, 15, 16, 14, 16, 10, 12, 14],
2244
+ color: '#800080',
2245
+ curve: 'step',
2246
+ AreaComponent: DottedArea,
2247
+ showArea: true
2248
+ }]
2249
+ })
2250
+ }, {
2251
+ title: 'Styling Reference Lines',
2252
+ component: /*#__PURE__*/_jsxs(LineChart, {
2253
+ enableScrubbing: true,
2254
+ showArea: true,
2255
+ height: 200,
2256
+ series: [{
2257
+ id: 'prices',
2258
+ data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58],
2259
+ color: theme.color.fgPositive
2260
+ }],
2261
+ xAxis: {
2262
+ // Give space before the end of the chart for the scrubber
2263
+ range: _ref23 => {
2264
+ let {
2265
+ min,
2266
+ max
2267
+ } = _ref23;
2268
+ return {
2269
+ min,
2270
+ max: max - 24
2271
+ };
2272
+ }
2273
+ },
2274
+ children: [/*#__PURE__*/_jsx(ReferenceLine, {
2275
+ LineComponent: props => /*#__PURE__*/_jsx(DottedLine, _extends({}, props, {
2276
+ dashIntervals: [0, 16],
2277
+ strokeWidth: 3
2278
+ })),
2279
+ dataY: 10,
2280
+ stroke: theme.color.fg
2281
+ }), /*#__PURE__*/_jsx(Scrubber, {})]
2282
+ })
2283
+ }, {
2284
+ title: 'High/Low Price',
2285
+ component: /*#__PURE__*/_jsx(HighLowPrice, {})
2286
+ }, {
2287
+ title: 'Styling Scrubber',
2288
+ component: /*#__PURE__*/_jsx(StylingScrubber, {})
2289
+ }, {
2290
+ title: 'Compact',
2291
+ component: /*#__PURE__*/_jsx(Compact, {})
2292
+ }, {
2293
+ title: 'Asset Price With Dotted Area',
2294
+ component: /*#__PURE__*/_jsx(AssetPriceWithDottedArea, {})
2295
+ }, {
2296
+ title: 'Performance',
2297
+ component: /*#__PURE__*/_jsx(Performance, {})
2298
+ }, {
2299
+ title: 'Candlesticks',
2300
+ component: /*#__PURE__*/_jsx(Candlesticks, {})
2301
+ }, {
2302
+ title: 'Monotone Asset Price',
2303
+ component: /*#__PURE__*/_jsx(MonotoneAssetPrice, {})
2304
+ }, {
2305
+ title: 'Service Availability',
2306
+ component: /*#__PURE__*/_jsx(ServiceAvailability, {})
2307
+ }, {
2308
+ title: 'Forecast Asset Price',
2309
+ component: /*#__PURE__*/_jsx(ForecastAssetPrice, {})
2310
+ }, {
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, {})
2322
+ }], [theme.color.fg, theme.color.fgPositive, theme.spectrum.gray50]);
2323
+ const currentExample = examples[currentIndex];
2324
+ const isFirstExample = currentIndex === 0;
2325
+ const isLastExample = currentIndex === examples.length - 1;
2326
+ const handlePrevious = useCallback(() => {
2327
+ setCurrentIndex(prev => Math.max(0, prev - 1));
2328
+ }, []);
2329
+ const handleNext = useCallback(() => {
2330
+ setCurrentIndex(prev => Math.min(examples.length - 1, prev + 1));
2331
+ }, [examples.length]);
2332
+ return /*#__PURE__*/_jsx(ExampleScreen, {
2333
+ children: /*#__PURE__*/_jsxs(VStack, {
2334
+ gap: 4,
2335
+ children: [/*#__PURE__*/_jsxs(HStack, {
2336
+ alignItems: "center",
2337
+ justifyContent: "space-between",
2338
+ padding: 2,
2339
+ children: [/*#__PURE__*/_jsx(IconButton, {
2340
+ accessibilityHint: "Navigate to previous example",
2341
+ accessibilityLabel: "Previous",
2342
+ disabled: isFirstExample,
2343
+ name: "arrowLeft",
2344
+ onPress: handlePrevious,
2345
+ variant: "secondary"
2346
+ }), /*#__PURE__*/_jsxs(VStack, {
2347
+ alignItems: "center",
2348
+ gap: 1,
2349
+ children: [/*#__PURE__*/_jsx(Text, {
2350
+ font: "title3",
2351
+ children: currentExample.title
2352
+ }), /*#__PURE__*/_jsxs(Text, {
2353
+ color: "fgMuted",
2354
+ font: "label1",
2355
+ children: [currentIndex + 1, " / ", examples.length]
2356
+ })]
2357
+ }), /*#__PURE__*/_jsx(IconButton, {
2358
+ accessibilityHint: "Navigate to next example",
2359
+ accessibilityLabel: "Next",
2360
+ disabled: isLastExample,
2361
+ name: "arrowRight",
2362
+ onPress: handleNext,
2363
+ variant: "secondary"
2364
+ })]
2365
+ }), /*#__PURE__*/_jsx(Box, {
2366
+ padding: 1,
2367
+ children: currentExample.component
2368
+ })]
2369
+ })
2370
+ });
2371
+ }
2372
+ export default ExampleNavigator;