@coinbase/cds-web-visualization 0.0.0 → 3.4.0-beta.1

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 (241) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +3 -0
  3. package/dts/chart/CartesianChart.d.ts +36 -0
  4. package/dts/chart/CartesianChart.d.ts.map +1 -0
  5. package/dts/chart/ChartProvider.d.ts +6 -0
  6. package/dts/chart/ChartProvider.d.ts.map +1 -0
  7. package/dts/chart/Path.d.ts +34 -0
  8. package/dts/chart/Path.d.ts.map +1 -0
  9. package/dts/chart/PeriodSelector.d.ts +61 -0
  10. package/dts/chart/PeriodSelector.d.ts.map +1 -0
  11. package/dts/chart/Point.d.ts +153 -0
  12. package/dts/chart/Point.d.ts.map +1 -0
  13. package/dts/chart/area/Area.d.ts +48 -0
  14. package/dts/chart/area/Area.d.ts.map +1 -0
  15. package/dts/chart/area/AreaChart.d.ts +52 -0
  16. package/dts/chart/area/AreaChart.d.ts.map +1 -0
  17. package/dts/chart/area/DottedArea.d.ts +68 -0
  18. package/dts/chart/area/DottedArea.d.ts.map +1 -0
  19. package/dts/chart/area/GradientArea.d.ts +30 -0
  20. package/dts/chart/area/GradientArea.d.ts.map +1 -0
  21. package/dts/chart/area/SolidArea.d.ts +8 -0
  22. package/dts/chart/area/SolidArea.d.ts.map +1 -0
  23. package/dts/chart/area/index.d.ts +6 -0
  24. package/dts/chart/area/index.d.ts.map +1 -0
  25. package/dts/chart/axis/Axis.d.ts +208 -0
  26. package/dts/chart/axis/Axis.d.ts.map +1 -0
  27. package/dts/chart/axis/XAxis.d.ts +16 -0
  28. package/dts/chart/axis/XAxis.d.ts.map +1 -0
  29. package/dts/chart/axis/YAxis.d.ts +21 -0
  30. package/dts/chart/axis/YAxis.d.ts.map +1 -0
  31. package/dts/chart/axis/index.d.ts +4 -0
  32. package/dts/chart/axis/index.d.ts.map +1 -0
  33. package/dts/chart/bar/Bar.d.ts +91 -0
  34. package/dts/chart/bar/Bar.d.ts.map +1 -0
  35. package/dts/chart/bar/BarChart.d.ts +53 -0
  36. package/dts/chart/bar/BarChart.d.ts.map +1 -0
  37. package/dts/chart/bar/BarPlot.d.ts +29 -0
  38. package/dts/chart/bar/BarPlot.d.ts.map +1 -0
  39. package/dts/chart/bar/BarStack.d.ts +111 -0
  40. package/dts/chart/bar/BarStack.d.ts.map +1 -0
  41. package/dts/chart/bar/BarStackGroup.d.ts +35 -0
  42. package/dts/chart/bar/BarStackGroup.d.ts.map +1 -0
  43. package/dts/chart/bar/DefaultBar.d.ts +17 -0
  44. package/dts/chart/bar/DefaultBar.d.ts.map +1 -0
  45. package/dts/chart/bar/DefaultBarStack.d.ts +16 -0
  46. package/dts/chart/bar/DefaultBarStack.d.ts.map +1 -0
  47. package/dts/chart/bar/index.d.ts +8 -0
  48. package/dts/chart/bar/index.d.ts.map +1 -0
  49. package/dts/chart/index.d.ts +13 -0
  50. package/dts/chart/index.d.ts.map +1 -0
  51. package/dts/chart/line/DottedLine.d.ts +14 -0
  52. package/dts/chart/line/DottedLine.d.ts.map +1 -0
  53. package/dts/chart/line/GradientLine.d.ts +42 -0
  54. package/dts/chart/line/GradientLine.d.ts.map +1 -0
  55. package/dts/chart/line/Line.d.ts +80 -0
  56. package/dts/chart/line/Line.d.ts.map +1 -0
  57. package/dts/chart/line/LineChart.d.ts +59 -0
  58. package/dts/chart/line/LineChart.d.ts.map +1 -0
  59. package/dts/chart/line/ReferenceLine.d.ts +131 -0
  60. package/dts/chart/line/ReferenceLine.d.ts.map +1 -0
  61. package/dts/chart/line/SolidLine.d.ts +14 -0
  62. package/dts/chart/line/SolidLine.d.ts.map +1 -0
  63. package/dts/chart/line/index.d.ts +7 -0
  64. package/dts/chart/line/index.d.ts.map +1 -0
  65. package/dts/chart/scrubber/Scrubber.d.ts +149 -0
  66. package/dts/chart/scrubber/Scrubber.d.ts.map +1 -0
  67. package/dts/chart/scrubber/ScrubberBeacon.d.ts +93 -0
  68. package/dts/chart/scrubber/ScrubberBeacon.d.ts.map +1 -0
  69. package/dts/chart/scrubber/ScrubberBeaconLabel.d.ts +7 -0
  70. package/dts/chart/scrubber/ScrubberBeaconLabel.d.ts.map +1 -0
  71. package/dts/chart/scrubber/ScrubberProvider.d.ts +17 -0
  72. package/dts/chart/scrubber/ScrubberProvider.d.ts.map +1 -0
  73. package/dts/chart/scrubber/index.d.ts +2 -0
  74. package/dts/chart/scrubber/index.d.ts.map +1 -0
  75. package/dts/chart/text/ChartText.d.ts +114 -0
  76. package/dts/chart/text/ChartText.d.ts.map +1 -0
  77. package/dts/chart/text/SmartChartTextGroup.d.ts +55 -0
  78. package/dts/chart/text/SmartChartTextGroup.d.ts.map +1 -0
  79. package/dts/chart/text/index.d.ts +3 -0
  80. package/dts/chart/text/index.d.ts.map +1 -0
  81. package/dts/chart/utils/axis.d.ts +342 -0
  82. package/dts/chart/utils/axis.d.ts.map +1 -0
  83. package/dts/chart/utils/bar.d.ts +20 -0
  84. package/dts/chart/utils/bar.d.ts.map +1 -0
  85. package/dts/chart/utils/chart.d.ts +97 -0
  86. package/dts/chart/utils/chart.d.ts.map +1 -0
  87. package/dts/chart/utils/context.d.ts +95 -0
  88. package/dts/chart/utils/context.d.ts.map +1 -0
  89. package/dts/chart/utils/index.d.ts +8 -0
  90. package/dts/chart/utils/index.d.ts.map +1 -0
  91. package/dts/chart/utils/path.d.ts +107 -0
  92. package/dts/chart/utils/path.d.ts.map +1 -0
  93. package/dts/chart/utils/point.d.ts +75 -0
  94. package/dts/chart/utils/point.d.ts.map +1 -0
  95. package/dts/chart/utils/scale.d.ts +43 -0
  96. package/dts/chart/utils/scale.d.ts.map +1 -0
  97. package/dts/index.d.ts +3 -0
  98. package/dts/index.d.ts.map +1 -0
  99. package/dts/sparkline/Counter.d.ts +8 -0
  100. package/dts/sparkline/Counter.d.ts.map +1 -0
  101. package/dts/sparkline/Sparkline.d.ts +67 -0
  102. package/dts/sparkline/Sparkline.d.ts.map +1 -0
  103. package/dts/sparkline/SparklineArea.d.ts +15 -0
  104. package/dts/sparkline/SparklineArea.d.ts.map +1 -0
  105. package/dts/sparkline/SparklineAreaPattern.d.ts +14 -0
  106. package/dts/sparkline/SparklineAreaPattern.d.ts.map +1 -0
  107. package/dts/sparkline/SparklineGradient.d.ts +23 -0
  108. package/dts/sparkline/SparklineGradient.d.ts.map +1 -0
  109. package/dts/sparkline/SparklinePath.d.ts +12 -0
  110. package/dts/sparkline/SparklinePath.d.ts.map +1 -0
  111. package/dts/sparkline/__figma__/Sparkline.figma.d.ts +2 -0
  112. package/dts/sparkline/__figma__/Sparkline.figma.d.ts.map +1 -0
  113. package/dts/sparkline/generateSparklineWithId.d.ts +11 -0
  114. package/dts/sparkline/generateSparklineWithId.d.ts.map +1 -0
  115. package/dts/sparkline/index.d.ts +6 -0
  116. package/dts/sparkline/index.d.ts.map +1 -0
  117. package/dts/sparkline/sparkline-interactive/InnerSparklineInteractiveProvider.d.ts +13 -0
  118. package/dts/sparkline/sparkline-interactive/InnerSparklineInteractiveProvider.d.ts.map +1 -0
  119. package/dts/sparkline/sparkline-interactive/SparklineInteractive.d.ts +199 -0
  120. package/dts/sparkline/sparkline-interactive/SparklineInteractive.d.ts.map +1 -0
  121. package/dts/sparkline/sparkline-interactive/SparklineInteractiveAnimatedPath.d.ts +26 -0
  122. package/dts/sparkline/sparkline-interactive/SparklineInteractiveAnimatedPath.d.ts.map +1 -0
  123. package/dts/sparkline/sparkline-interactive/SparklineInteractiveHoverDate.d.ts +5 -0
  124. package/dts/sparkline/sparkline-interactive/SparklineInteractiveHoverDate.d.ts.map +1 -0
  125. package/dts/sparkline/sparkline-interactive/SparklineInteractiveHoverPrice.d.ts +5 -0
  126. package/dts/sparkline/sparkline-interactive/SparklineInteractiveHoverPrice.d.ts.map +1 -0
  127. package/dts/sparkline/sparkline-interactive/SparklineInteractiveLineVertical.d.ts +8 -0
  128. package/dts/sparkline/sparkline-interactive/SparklineInteractiveLineVertical.d.ts.map +1 -0
  129. package/dts/sparkline/sparkline-interactive/SparklineInteractiveMarkerDates.d.ts +17 -0
  130. package/dts/sparkline/sparkline-interactive/SparklineInteractiveMarkerDates.d.ts.map +1 -0
  131. package/dts/sparkline/sparkline-interactive/SparklineInteractivePaths.d.ts +25 -0
  132. package/dts/sparkline/sparkline-interactive/SparklineInteractivePaths.d.ts.map +1 -0
  133. package/dts/sparkline/sparkline-interactive/SparklineInteractivePeriodSelector.d.ts +25 -0
  134. package/dts/sparkline/sparkline-interactive/SparklineInteractivePeriodSelector.d.ts.map +1 -0
  135. package/dts/sparkline/sparkline-interactive/SparklineInteractiveProvider.d.ts +25 -0
  136. package/dts/sparkline/sparkline-interactive/SparklineInteractiveProvider.d.ts.map +1 -0
  137. package/dts/sparkline/sparkline-interactive/SparklineInteractiveScrubHandler.d.ts +30 -0
  138. package/dts/sparkline/sparkline-interactive/SparklineInteractiveScrubHandler.d.ts.map +1 -0
  139. package/dts/sparkline/sparkline-interactive/SparklineInteractiveScrubProvider.d.ts +18 -0
  140. package/dts/sparkline/sparkline-interactive/SparklineInteractiveScrubProvider.d.ts.map +1 -0
  141. package/dts/sparkline/sparkline-interactive/SparklineInteractiveTimeseriesPaths.d.ts +31 -0
  142. package/dts/sparkline/sparkline-interactive/SparklineInteractiveTimeseriesPaths.d.ts.map +1 -0
  143. package/dts/sparkline/sparkline-interactive/__figma__/SparklineInteractive.figma.d.ts +2 -0
  144. package/dts/sparkline/sparkline-interactive/__figma__/SparklineInteractive.figma.d.ts.map +1 -0
  145. package/dts/sparkline/sparkline-interactive/fade.d.ts +3 -0
  146. package/dts/sparkline/sparkline-interactive/fade.d.ts.map +1 -0
  147. package/dts/sparkline/sparkline-interactive/useSparklineInteractiveConstants.d.ts +13 -0
  148. package/dts/sparkline/sparkline-interactive/useSparklineInteractiveConstants.d.ts.map +1 -0
  149. package/dts/sparkline/sparkline-interactive-header/SparklineInteractiveHeader.d.ts +112 -0
  150. package/dts/sparkline/sparkline-interactive-header/SparklineInteractiveHeader.d.ts.map +1 -0
  151. package/dts/sparkline/sparkline-interactive-header/__figma__/SparklineInteractiveHeader.figma.d.ts +2 -0
  152. package/dts/sparkline/sparkline-interactive-header/__figma__/SparklineInteractiveHeader.figma.d.ts.map +1 -0
  153. package/esm/chart/CartesianChart.css +1 -0
  154. package/esm/chart/CartesianChart.js +258 -0
  155. package/esm/chart/ChartProvider.js +10 -0
  156. package/esm/chart/Path.js +89 -0
  157. package/esm/chart/PeriodSelector.css +1 -0
  158. package/esm/chart/PeriodSelector.js +126 -0
  159. package/esm/chart/Point.css +2 -0
  160. package/esm/chart/Point.js +171 -0
  161. package/esm/chart/area/Area.js +85 -0
  162. package/esm/chart/area/AreaChart.js +164 -0
  163. package/esm/chart/area/DottedArea.js +141 -0
  164. package/esm/chart/area/GradientArea.js +111 -0
  165. package/esm/chart/area/SolidArea.js +29 -0
  166. package/esm/chart/area/index.js +7 -0
  167. package/esm/chart/axis/Axis.js +46 -0
  168. package/esm/chart/axis/XAxis.css +2 -0
  169. package/esm/chart/axis/XAxis.js +195 -0
  170. package/esm/chart/axis/YAxis.css +2 -0
  171. package/esm/chart/axis/YAxis.js +183 -0
  172. package/esm/chart/axis/index.js +5 -0
  173. package/esm/chart/bar/Bar.js +59 -0
  174. package/esm/chart/bar/BarChart.js +147 -0
  175. package/esm/chart/bar/BarPlot.js +96 -0
  176. package/esm/chart/bar/BarStack.js +519 -0
  177. package/esm/chart/bar/BarStackGroup.js +96 -0
  178. package/esm/chart/bar/DefaultBar.js +64 -0
  179. package/esm/chart/bar/DefaultBarStack.js +60 -0
  180. package/esm/chart/bar/index.js +9 -0
  181. package/esm/chart/index.js +14 -0
  182. package/esm/chart/line/DottedLine.js +38 -0
  183. package/esm/chart/line/GradientLine.js +58 -0
  184. package/esm/chart/line/Line.js +159 -0
  185. package/esm/chart/line/LineChart.js +120 -0
  186. package/esm/chart/line/ReferenceLine.js +142 -0
  187. package/esm/chart/line/SolidLine.js +34 -0
  188. package/esm/chart/line/index.js +8 -0
  189. package/esm/chart/scrubber/Scrubber.js +483 -0
  190. package/esm/chart/scrubber/ScrubberBeacon.js +195 -0
  191. package/esm/chart/scrubber/ScrubberBeaconLabel.js +33 -0
  192. package/esm/chart/scrubber/ScrubberProvider.js +228 -0
  193. package/esm/chart/scrubber/index.js +2 -0
  194. package/esm/chart/text/ChartText.js +236 -0
  195. package/esm/chart/text/SmartChartTextGroup.js +226 -0
  196. package/esm/chart/text/index.js +4 -0
  197. package/esm/chart/utils/axis.js +593 -0
  198. package/esm/chart/utils/bar.js +24 -0
  199. package/esm/chart/utils/chart.js +229 -0
  200. package/esm/chart/utils/context.js +15 -0
  201. package/esm/chart/utils/index.js +9 -0
  202. package/esm/chart/utils/path.js +204 -0
  203. package/esm/chart/utils/point.js +118 -0
  204. package/esm/chart/utils/scale.js +48 -0
  205. package/esm/index.js +4 -0
  206. package/esm/sparkline/Counter.css +3 -0
  207. package/esm/sparkline/Counter.js +35 -0
  208. package/esm/sparkline/Sparkline.js +164 -0
  209. package/esm/sparkline/SparklineArea.js +18 -0
  210. package/esm/sparkline/SparklineAreaPattern.js +37 -0
  211. package/esm/sparkline/SparklineGradient.js +30 -0
  212. package/esm/sparkline/SparklinePath.js +19 -0
  213. package/esm/sparkline/__figma__/Sparkline.figma.js +24 -0
  214. package/esm/sparkline/generateSparklineWithId.js +7 -0
  215. package/esm/sparkline/index.js +5 -0
  216. package/esm/sparkline/sparkline-interactive/InnerSparklineInteractiveProvider.js +21 -0
  217. package/esm/sparkline/sparkline-interactive/SparklineInteractive.js +317 -0
  218. package/esm/sparkline/sparkline-interactive/SparklineInteractiveAnimatedPath.js +108 -0
  219. package/esm/sparkline/sparkline-interactive/SparklineInteractiveHoverDate.css +2 -0
  220. package/esm/sparkline/sparkline-interactive/SparklineInteractiveHoverDate.js +26 -0
  221. package/esm/sparkline/sparkline-interactive/SparklineInteractiveHoverPrice.css +2 -0
  222. package/esm/sparkline/sparkline-interactive/SparklineInteractiveHoverPrice.js +24 -0
  223. package/esm/sparkline/sparkline-interactive/SparklineInteractiveLineVertical.css +4 -0
  224. package/esm/sparkline/sparkline-interactive/SparklineInteractiveLineVertical.js +65 -0
  225. package/esm/sparkline/sparkline-interactive/SparklineInteractiveMarkerDates.css +1 -0
  226. package/esm/sparkline/sparkline-interactive/SparklineInteractiveMarkerDates.js +80 -0
  227. package/esm/sparkline/sparkline-interactive/SparklineInteractivePaths.js +56 -0
  228. package/esm/sparkline/sparkline-interactive/SparklineInteractivePeriodSelector.js +70 -0
  229. package/esm/sparkline/sparkline-interactive/SparklineInteractiveProvider.js +45 -0
  230. package/esm/sparkline/sparkline-interactive/SparklineInteractiveScrubHandler.css +5 -0
  231. package/esm/sparkline/sparkline-interactive/SparklineInteractiveScrubHandler.js +199 -0
  232. package/esm/sparkline/sparkline-interactive/SparklineInteractiveScrubProvider.js +39 -0
  233. package/esm/sparkline/sparkline-interactive/SparklineInteractiveTimeseriesPaths.js +92 -0
  234. package/esm/sparkline/sparkline-interactive/__figma__/SparklineInteractive.figma.js +89 -0
  235. package/esm/sparkline/sparkline-interactive/fade.css +2 -0
  236. package/esm/sparkline/sparkline-interactive/fade.js +14 -0
  237. package/esm/sparkline/sparkline-interactive/useSparklineInteractiveConstants.js +28 -0
  238. package/esm/sparkline/sparkline-interactive-header/SparklineInteractiveHeader.js +225 -0
  239. package/esm/sparkline/sparkline-interactive-header/__figma__/SparklineInteractiveHeader.figma.js +108 -0
  240. package/package.json +68 -6
  241. package/index.js +0 -1
@@ -0,0 +1,199 @@
1
+ import React, { memo, useCallback, useMemo, useRef, useState } from 'react';
2
+ import { fadeDuration, maskOpacity } from '@coinbase/cds-common/tokens/sparkline';
3
+ import { debounce } from '@coinbase/cds-common/utils/debounce';
4
+ import { noop } from '@coinbase/cds-utils';
5
+ import { cx } from '@coinbase/cds-web';
6
+ import { cubicBezier } from '@coinbase/cds-web/animation/convertMotionConfig';
7
+ import { useDimensions } from '@coinbase/cds-web/hooks/useDimensions';
8
+ import { fadeIn, fadeOut } from './fade';
9
+ import { useSparklineInteractiveContext } from './SparklineInteractiveProvider';
10
+ import { useSparklineInteractiveScrubContext } from './SparklineInteractiveScrubProvider';
11
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
12
+ export const scrubHandlerStaticClassName = 'cds-sparkline--scrubhandler';
13
+ const insetFocusRingCss = "cds-insetFocusRingCss-is0dyrn";
14
+ const scrubHandlerContainerCss = "cds-scrubHandlerContainerCss-s9euk9d";
15
+ const scrubHandlerCss = "cds-scrubHandlerCss-s6b8h5z";
16
+ const fadeInMaskCss = "cds-fadeInMaskCss-f1bwvdrs";
17
+ const fadeOutMaskCss = "cds-fadeOutMaskCss-f19rjrl4";
18
+
19
+ // Number of steps for keyboard users to navigate through the sparkline
20
+ const STEPS = 100;
21
+ const STEPS_ARRAY = Array.from(Array(STEPS).keys());
22
+ const padding = 8;
23
+ function fadeOutMask(domNode) {
24
+ domNode === null || domNode === void 0 || domNode.classList.remove(fadeInMaskCss);
25
+ domNode === null || domNode === void 0 || domNode.classList.add(fadeOutMaskCss);
26
+ }
27
+ export function fadeInMask(domNode) {
28
+ domNode === null || domNode === void 0 || domNode.classList.add(fadeInMaskCss);
29
+ domNode === null || domNode === void 0 || domNode.classList.remove(fadeOutMaskCss);
30
+ }
31
+ const SparklineInteractiveScrubHandlerWithGeneric = _ref => {
32
+ let {
33
+ onScrubEnd = noop,
34
+ onScrubStart = noop,
35
+ children,
36
+ disabled,
37
+ onScrub,
38
+ getMarker,
39
+ selectedPeriod,
40
+ formatHoverDate,
41
+ formatHoverPrice
42
+ } = _ref;
43
+ const containerRef = useRef(null);
44
+ const {
45
+ lineDOMNode,
46
+ maskDOMNode,
47
+ hoverDateDOMNode,
48
+ hoverPriceDOMNode
49
+ } = useSparklineInteractiveScrubContext();
50
+ const {
51
+ width: chartWidth
52
+ } = useSparklineInteractiveContext();
53
+ const scrubHandlerCssWithFocus = cx(scrubHandlerStaticClassName, scrubHandlerCss, insetFocusRingCss);
54
+ const [xPos, setXPos] = useState(0);
55
+ const {
56
+ width,
57
+ observe
58
+ } = useDimensions();
59
+ const steps = useMemo(() => {
60
+ const sparklineSteps = STEPS_ARRAY.map(step => {
61
+ return Math.floor(Number(width) / STEPS * step) || 1;
62
+ });
63
+
64
+ // Make sure each step is within the sparkline container
65
+ sparklineSteps[0] = 1;
66
+ sparklineSteps[STEPS] = Math.floor(width) - 1;
67
+ return sparklineSteps;
68
+ }, [width]);
69
+ const debouncedUpdatePositionHandler = useMemo(() => debounce(position => {
70
+ setXPos(position);
71
+ }, 20), [setXPos]);
72
+ const safelyUpdatePosition = useCallback(debouncedUpdatePositionHandler, [debouncedUpdatePositionHandler]);
73
+
74
+ // This method is used by mouseMove and keyboard events
75
+ const updateScrubber = useCallback(position => {
76
+ const dataPoint = getMarker(position);
77
+ if (dataPoint) {
78
+ onScrub === null || onScrub === void 0 || onScrub({
79
+ point: dataPoint,
80
+ period: selectedPeriod
81
+ });
82
+ if (lineDOMNode) {
83
+ lineDOMNode.style.transform = "translateX(".concat(position, "px)");
84
+ }
85
+ if (maskDOMNode) {
86
+ maskDOMNode.style.transform = "translateX(".concat(position, "px)");
87
+ }
88
+ if (hoverDateDOMNode && formatHoverDate) {
89
+ fadeIn(hoverDateDOMNode);
90
+ hoverDateDOMNode.innerText = formatHoverDate(dataPoint.date, selectedPeriod);
91
+ const textWidth = hoverDateDOMNode.offsetWidth;
92
+ const halfTextWidth = textWidth / 2;
93
+ let textPos = position - halfTextWidth;
94
+ textPos = Math.max(padding, textPos);
95
+ textPos = Math.min(textPos, chartWidth - textWidth - padding);
96
+ hoverDateDOMNode.style.transform = "translateX(".concat(textPos, "px)");
97
+ }
98
+ if (hoverPriceDOMNode && formatHoverPrice) {
99
+ fadeIn(hoverPriceDOMNode);
100
+ hoverPriceDOMNode.innerText = formatHoverPrice(dataPoint.value);
101
+ const textWidth = hoverPriceDOMNode.offsetWidth;
102
+ const halfTextWidth = textWidth / 2;
103
+ let textPos = position - halfTextWidth;
104
+ textPos = Math.max(padding, textPos);
105
+ textPos = Math.min(textPos, chartWidth - textWidth - padding);
106
+ hoverPriceDOMNode.style.transform = "translateX(".concat(textPos, "px)");
107
+ }
108
+ }
109
+
110
+ /**
111
+ * Keep track of the position for a seamless
112
+ * transition from MouseMove to Keyboard interaction
113
+ */
114
+ safelyUpdatePosition(position);
115
+ }, [getMarker, safelyUpdatePosition, onScrub, selectedPeriod, lineDOMNode, maskDOMNode, hoverDateDOMNode, formatHoverDate, formatHoverPrice, hoverPriceDOMNode, chartWidth]);
116
+
117
+ // Show the scrub UI
118
+ const handleMouseEnter = useCallback(() => {
119
+ onScrubStart === null || onScrubStart === void 0 || onScrubStart();
120
+ fadeIn(lineDOMNode);
121
+ fadeInMask(maskDOMNode);
122
+ }, [lineDOMNode, maskDOMNode, onScrubStart]);
123
+ const handleMouseMove = useCallback(event => {
124
+ var _containerRef$current, _containerRef$current2;
125
+ const xPosition = Math.max(0, event.clientX - ((_containerRef$current = (_containerRef$current2 = containerRef.current) === null || _containerRef$current2 === void 0 ? void 0 : _containerRef$current2.getBoundingClientRect().left) !== null && _containerRef$current !== void 0 ? _containerRef$current : 0));
126
+
127
+ // Update UI
128
+ updateScrubber(xPosition);
129
+ }, [updateScrubber]);
130
+ const getPosition = useCallback((direction, multiSkip) => {
131
+ // Use the xPos to find the nearest step
132
+ const closestStep = steps.reduce((prev, curr) => {
133
+ return Math.abs(curr - xPos) < Math.abs(prev - xPos) ? curr : prev;
134
+ });
135
+ // The index of the closest step
136
+ const currentIndex = steps.findIndex(pos => pos === closestStep);
137
+ // Holding the shift key allows users to jump 10 steps
138
+ const stepIncrement = multiSkip ? 10 : 1;
139
+
140
+ // The location to move to
141
+ const nextLocation = currentIndex + (direction === 'next' ? stepIncrement : -stepIncrement);
142
+
143
+ // return the location if we're within bounds of the chart
144
+ return nextLocation > 0 && nextLocation < STEPS ? nextLocation : null;
145
+ }, [steps, xPos]);
146
+ const handleKeyDown = useCallback(e => {
147
+ const multiSkip = !!e.shiftKey;
148
+
149
+ // Go to the correct step
150
+ if (e.key === 'ArrowRight') {
151
+ var _getPosition;
152
+ e.preventDefault();
153
+ const nextStep = (_getPosition = getPosition('next', multiSkip)) !== null && _getPosition !== void 0 ? _getPosition : STEPS;
154
+ updateScrubber(steps[nextStep] - 1);
155
+ }
156
+ if (e.key === 'ArrowLeft') {
157
+ var _getPosition2;
158
+ e.preventDefault();
159
+ const previousStep = (_getPosition2 = getPosition('previous', multiSkip)) !== null && _getPosition2 !== void 0 ? _getPosition2 : 0;
160
+ updateScrubber(steps[previousStep]);
161
+ }
162
+
163
+ // Jump to beginning or end
164
+ if (e.key === 'ArrowDown') {
165
+ e.preventDefault();
166
+ updateScrubber(steps[STEPS] - 1);
167
+ }
168
+ if (e.key === 'ArrowUp') {
169
+ e.preventDefault();
170
+ updateScrubber(0);
171
+ }
172
+ }, [getPosition, updateScrubber, steps]);
173
+ const handleMouseLeave = useCallback(() => {
174
+ onScrubEnd === null || onScrubEnd === void 0 || onScrubEnd();
175
+ fadeOut(lineDOMNode);
176
+ fadeOutMask(maskDOMNode);
177
+ fadeOut(hoverDateDOMNode);
178
+ fadeOut(hoverPriceDOMNode);
179
+ }, [hoverDateDOMNode, lineDOMNode, maskDOMNode, hoverPriceDOMNode, onScrubEnd]);
180
+ return /*#__PURE__*/_jsxs("div", {
181
+ ref: containerRef,
182
+ className: scrubHandlerContainerCss,
183
+ children: [children, !disabled && /*#__PURE__*/_jsx("div", {
184
+ ref: observe,
185
+ "aria-label": "Price chart (use arrow keys to adjust view)",
186
+ className: scrubHandlerCssWithFocus,
187
+ onBlur: handleMouseLeave,
188
+ onFocus: handleMouseEnter,
189
+ onKeyDown: handleKeyDown,
190
+ onMouseEnter: handleMouseEnter,
191
+ onMouseLeave: handleMouseLeave,
192
+ onMouseMove: handleMouseMove,
193
+ role: "button",
194
+ tabIndex: 0
195
+ })]
196
+ });
197
+ };
198
+ export const SparklineInteractiveScrubHandler = /*#__PURE__*/memo(SparklineInteractiveScrubHandlerWithGeneric);
199
+ import "./SparklineInteractiveScrubHandler.css";
@@ -0,0 +1,39 @@
1
+ import React, { createContext, memo, useContext, useMemo, useState } from 'react';
2
+ import { noop } from '@coinbase/cds-utils';
3
+ import { jsx as _jsx } from "react/jsx-runtime";
4
+ const SparklineInteractiveScrubContext = /*#__PURE__*/createContext({
5
+ setLineDOMNode: noop,
6
+ setMaskDOMNode: noop,
7
+ setHoverDateDOMNode: noop,
8
+ setHoverPriceDOMNode: noop,
9
+ lineDOMNode: null,
10
+ maskDOMNode: null,
11
+ hoverDateDOMNode: null,
12
+ hoverPriceDOMNode: null
13
+ });
14
+ export const SparklineInteractiveScrubProvider = /*#__PURE__*/memo(_ref => {
15
+ let {
16
+ children
17
+ } = _ref;
18
+ const [lineDOMNode, setLineDOMNode] = useState(null);
19
+ const [maskDOMNode, setMaskDOMNode] = useState(null);
20
+ const [hoverDateDOMNode, setHoverDateDOMNode] = useState(null);
21
+ const [hoverPriceDOMNode, setHoverPriceDOMNode] = useState(null);
22
+ const value = useMemo(() => ({
23
+ setLineDOMNode,
24
+ setMaskDOMNode,
25
+ lineDOMNode,
26
+ maskDOMNode,
27
+ hoverDateDOMNode,
28
+ setHoverDateDOMNode,
29
+ setHoverPriceDOMNode,
30
+ hoverPriceDOMNode
31
+ }), [hoverDateDOMNode, lineDOMNode, maskDOMNode, hoverPriceDOMNode]);
32
+ return /*#__PURE__*/_jsx(SparklineInteractiveScrubContext.Provider, {
33
+ value: value,
34
+ children: children
35
+ });
36
+ });
37
+ export function useSparklineInteractiveScrubContext() {
38
+ return useContext(SparklineInteractiveScrubContext);
39
+ }
@@ -0,0 +1,92 @@
1
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
2
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
3
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
4
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
5
+ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
6
+ import React, { memo, useCallback, useEffect, useMemo, useRef } from 'react';
7
+ import { animatedPathConfig } from '@coinbase/cds-common/animation/sparkline';
8
+ import { getAccessibleColor } from '@coinbase/cds-common/utils/getAccessibleColor';
9
+ import { getSparklineTransform } from '@coinbase/cds-common/visualizations/getSparklineTransform';
10
+ import { useTimeseriesPaths } from '@coinbase/cds-common/visualizations/useTimeseriesPaths';
11
+ import { useTheme } from '@coinbase/cds-web/hooks/useTheme';
12
+ import { interpolatePath } from 'd3-interpolate-path';
13
+ import { select } from 'd3-selection';
14
+ import { SparklinePath } from '../SparklinePath';
15
+ import { jsx as _jsx } from "react/jsx-runtime";
16
+ const {
17
+ duration,
18
+ easing
19
+ } = animatedPathConfig;
20
+ const TimeseriesPath = /*#__PURE__*/memo(_ref => {
21
+ let {
22
+ timeseries,
23
+ lineFn,
24
+ initialPath,
25
+ onRender,
26
+ areaFn
27
+ } = _ref;
28
+ const theme = useTheme();
29
+ const pathRef = useRef(null);
30
+ const {
31
+ strokeColor
32
+ } = timeseries;
33
+ const lineColor = strokeColor !== 'auto' ? strokeColor : getAccessibleColor({
34
+ background: theme.color.bg,
35
+ foreground: 'auto',
36
+ usage: 'graphic'
37
+ });
38
+ const newPath = useMemo(() => lineFn(timeseries.points), [lineFn, timeseries.points]);
39
+ const newArea = useMemo(() => onRender ? areaFn(timeseries.points) : null, [areaFn, onRender, timeseries.points]);
40
+ const playAnimation = useCallback(() => {
41
+ select(pathRef.current).transition().duration(duration).ease(easing).attrTween('d', function tween() {
42
+ const current = newPath;
43
+ return interpolatePath(initialPath, current);
44
+ });
45
+ }, [initialPath, newPath]);
46
+ useEffect(() => {
47
+ playAnimation();
48
+ onRender === null || onRender === void 0 || onRender({
49
+ path: newPath,
50
+ area: newArea
51
+ });
52
+ }, [newArea, newPath, onRender, playAnimation]);
53
+ return /*#__PURE__*/_jsx(SparklinePath, {
54
+ ref: pathRef,
55
+ path: initialPath,
56
+ stroke: lineColor
57
+ });
58
+ });
59
+ export const SparklineInteractiveTimeseriesPaths = /*#__PURE__*/memo(_ref2 => {
60
+ let {
61
+ data,
62
+ width,
63
+ height,
64
+ initialPath,
65
+ onRender
66
+ } = _ref2;
67
+ const {
68
+ lineFn,
69
+ areaFn
70
+ } = useTimeseriesPaths({
71
+ data,
72
+ width,
73
+ height
74
+ });
75
+ const translateProps = useMemo(() => getSparklineTransform(width, height), [width, height]);
76
+ const paths = data.map((timeseries, index) => {
77
+ return /*#__PURE__*/_jsx(TimeseriesPath, {
78
+ areaFn: areaFn,
79
+ initialPath: initialPath,
80
+ lineFn: lineFn,
81
+ onRender: index === 0 ? onRender : undefined,
82
+ timeseries: timeseries
83
+ }, timeseries.id);
84
+ });
85
+ return /*#__PURE__*/_jsx("svg", {
86
+ height: height,
87
+ width: width,
88
+ children: /*#__PURE__*/_jsx("g", _objectSpread(_objectSpread({}, translateProps), {}, {
89
+ children: paths
90
+ }))
91
+ });
92
+ });
@@ -0,0 +1,89 @@
1
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
2
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
3
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
4
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
5
+ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
6
+ import React from 'react';
7
+ import { figma } from '@figma/code-connect';
8
+ import { SparklineInteractive } from '../SparklineInteractive';
9
+ import { jsx as _jsx } from "react/jsx-runtime";
10
+ figma.connect(SparklineInteractive, 'https://www.figma.com/design/k5CtyJccNQUGMI5bI4lJ2g/✨-CDS-Components?node-id=320-14858&m=dev', {
11
+ imports: ["import { SparklineInteractive } from '@coinbase/cds-web-visualization';"],
12
+ props: {
13
+ compact: figma.boolean('compact'),
14
+ disableScrubbing: figma.boolean('scrubbing', {
15
+ false: true,
16
+ true: false
17
+ })
18
+ },
19
+ example: props => {
20
+ const periods = [{
21
+ label: '1H',
22
+ value: 'hour'
23
+ }, {
24
+ label: '1D',
25
+ value: 'day'
26
+ }, {
27
+ label: '1W',
28
+ value: 'week'
29
+ }, {
30
+ label: '1M',
31
+ value: 'month'
32
+ }, {
33
+ label: '1Y',
34
+ value: 'year'
35
+ }, {
36
+ label: 'All',
37
+ value: 'all'
38
+ }];
39
+ const data = {
40
+ hour: [],
41
+ day: [{
42
+ value: 49259.38,
43
+ date: new Date('2021-12-05T04:00:00.000Z')
44
+ }, {
45
+ value: 49163.79,
46
+ date: new Date('2021-12-05T04:05:00.000Z')
47
+ }, {
48
+ value: 49146.66,
49
+ date: new Date('2021-12-05T04:10:00.000Z')
50
+ }, {
51
+ value: 49083.92,
52
+ date: new Date('2021-12-05T04:15:00.000Z')
53
+ }, {
54
+ value: 49115.3,
55
+ date: new Date('2021-12-05T04:20:00.000Z')
56
+ }, {
57
+ value: 48992.14,
58
+ date: new Date('2021-12-05T04:25:00.000Z')
59
+ }, {
60
+ value: 49075.75,
61
+ date: new Date('2021-12-05T04:30:00.000Z')
62
+ }, {
63
+ value: 49025.78,
64
+ date: new Date('2021-12-05T04:35:00.000Z')
65
+ }, {
66
+ value: 49066.23,
67
+ date: new Date('2021-12-05T04:40:00.000Z')
68
+ }, {
69
+ value: 49247.82,
70
+ date: new Date('2021-12-05T04:45:00.000Z')
71
+ }],
72
+ week: [],
73
+ month: [],
74
+ year: [],
75
+ all: []
76
+ };
77
+ return /*#__PURE__*/_jsx(SparklineInteractive, _objectSpread({
78
+ data: data,
79
+ defaultPeriod: "day",
80
+ formatDate: date => date.toLocaleString('en-US', {
81
+ timeZone: 'America/New_York',
82
+ hour: 'numeric',
83
+ minute: 'numeric'
84
+ }),
85
+ periods: periods,
86
+ strokeColor: "#cb51bb"
87
+ }, props));
88
+ }
89
+ });
@@ -0,0 +1,2 @@
1
+ .cds-fadeInCss-f1sjpdr1.cds-fadeInCss-f1sjpdr1{-webkit-animation:cdsSparklineInteractiveFadeIn-cds-fadeInCss-f1sjpdr1 200ms cubic-bezier(0.6,0,0.15,1);animation:cdsSparklineInteractiveFadeIn-cds-fadeInCss-f1sjpdr1 200ms cubic-bezier(0.6,0,0.15,1);opacity:1;}@-webkit-keyframes cdsSparklineInteractiveFadeIn-cds-fadeInCss-f1sjpdr1{0%{opacity:0;}100%{opacity:1;}}@keyframes cdsSparklineInteractiveFadeIn-cds-fadeInCss-f1sjpdr1{0%{opacity:0;}100%{opacity:1;}}
2
+ .cds-fadeOutCss-fsxar9z.cds-fadeOutCss-fsxar9z{-webkit-animation:cdsSparklineInteractiveFadeOut-cds-fadeOutCss-fsxar9z 200ms cubic-bezier(0.6,0,0.15,1);animation:cdsSparklineInteractiveFadeOut-cds-fadeOutCss-fsxar9z 200ms cubic-bezier(0.6,0,0.15,1);opacity:0;}@-webkit-keyframes cdsSparklineInteractiveFadeOut-cds-fadeOutCss-fsxar9z{0%{opacity:1;}100%{opacity:0;}}@keyframes cdsSparklineInteractiveFadeOut-cds-fadeOutCss-fsxar9z{0%{opacity:1;}100%{opacity:0;}}
@@ -0,0 +1,14 @@
1
+ import { fadeDuration } from '@coinbase/cds-common/tokens/sparkline';
2
+ import { cubicBezier } from '@coinbase/cds-web/animation/convertMotionConfig';
3
+ // keyframes are global so they should be namespaced
4
+ const fadeInCss = "cds-fadeInCss-f1sjpdr1";
5
+ const fadeOutCss = "cds-fadeOutCss-fsxar9z";
6
+ export function fadeOut(domNode) {
7
+ domNode === null || domNode === void 0 || domNode.classList.remove(fadeInCss);
8
+ domNode === null || domNode === void 0 || domNode.classList.add(fadeOutCss);
9
+ }
10
+ export function fadeIn(domNode) {
11
+ domNode === null || domNode === void 0 || domNode.classList.add(fadeInCss);
12
+ domNode === null || domNode === void 0 || domNode.classList.remove(fadeOutCss);
13
+ }
14
+ import "./fade.css";
@@ -0,0 +1,28 @@
1
+ import { useMemo } from 'react';
2
+ import { borderWidth, chartCompactHeight, chartHeight as chartHeightToken } from '@coinbase/cds-common/tokens/sparkline';
3
+ import { useSparklineInteractiveContext } from './SparklineInteractiveProvider';
4
+ export function useSparklineInteractiveConstants() {
5
+ const {
6
+ width: chartWidth,
7
+ compact
8
+ } = useSparklineInteractiveContext();
9
+ return useMemo(() => {
10
+ const chartHeight = compact ? chartCompactHeight : chartHeightToken;
11
+ const xRange = [borderWidth, chartWidth - borderWidth];
12
+ const yRange = [chartHeight - borderWidth, borderWidth];
13
+ const startX = 0;
14
+ const endX = xRange[1];
15
+ return {
16
+ chartWidth,
17
+ chartHeight,
18
+ chartDimensionStyles: {
19
+ height: chartHeight,
20
+ width: chartWidth
21
+ },
22
+ xRange,
23
+ yRange,
24
+ startX,
25
+ endX
26
+ };
27
+ }, [chartWidth, compact]);
28
+ }