@coinbase/cds-mobile-visualization 0.0.0 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/README.md +3 -0
  2. package/dts/index.d.ts +2 -0
  3. package/dts/index.d.ts.map +1 -0
  4. package/dts/sparkline/Counter.d.ts +3 -0
  5. package/dts/sparkline/Counter.d.ts.map +1 -0
  6. package/dts/sparkline/Sparkline.d.ts +22 -0
  7. package/dts/sparkline/Sparkline.d.ts.map +1 -0
  8. package/dts/sparkline/SparklineArea.d.ts +8 -0
  9. package/dts/sparkline/SparklineArea.d.ts.map +1 -0
  10. package/dts/sparkline/SparklineAreaPattern.d.ts +6 -0
  11. package/dts/sparkline/SparklineAreaPattern.d.ts.map +1 -0
  12. package/dts/sparkline/SparklineGradient.d.ts +12 -0
  13. package/dts/sparkline/SparklineGradient.d.ts.map +1 -0
  14. package/dts/sparkline/__figma__/Sparkline.figma.d.ts +2 -0
  15. package/dts/sparkline/__figma__/Sparkline.figma.d.ts.map +1 -0
  16. package/dts/sparkline/__stories__/Sparkline.stories.d.ts +3 -0
  17. package/dts/sparkline/__stories__/Sparkline.stories.d.ts.map +1 -0
  18. package/dts/sparkline/__stories__/SparklineGradient.stories.d.ts +3 -0
  19. package/dts/sparkline/__stories__/SparklineGradient.stories.d.ts.map +1 -0
  20. package/dts/sparkline/generateSparklineWithId.d.ts +5 -0
  21. package/dts/sparkline/generateSparklineWithId.d.ts.map +1 -0
  22. package/dts/sparkline/index.d.ts +6 -0
  23. package/dts/sparkline/index.d.ts.map +1 -0
  24. package/dts/sparkline/sparkline-interactive/SparklineAccessibleView.d.ts +18 -0
  25. package/dts/sparkline/sparkline-interactive/SparklineAccessibleView.d.ts.map +1 -0
  26. package/dts/sparkline/sparkline-interactive/SparklineInteractive.d.ts +162 -0
  27. package/dts/sparkline/sparkline-interactive/SparklineInteractive.d.ts.map +1 -0
  28. package/dts/sparkline/sparkline-interactive/SparklineInteractiveAnimatedPath.d.ts +12 -0
  29. package/dts/sparkline/sparkline-interactive/SparklineInteractiveAnimatedPath.d.ts.map +1 -0
  30. package/dts/sparkline/sparkline-interactive/SparklineInteractiveHoverDate.d.ts +17 -0
  31. package/dts/sparkline/sparkline-interactive/SparklineInteractiveHoverDate.d.ts.map +1 -0
  32. package/dts/sparkline/sparkline-interactive/SparklineInteractiveLineVertical.d.ts +8 -0
  33. package/dts/sparkline/sparkline-interactive/SparklineInteractiveLineVertical.d.ts.map +1 -0
  34. package/dts/sparkline/sparkline-interactive/SparklineInteractiveMarkerDates.d.ts +12 -0
  35. package/dts/sparkline/sparkline-interactive/SparklineInteractiveMarkerDates.d.ts.map +1 -0
  36. package/dts/sparkline/sparkline-interactive/SparklineInteractiveMinMax.d.ts +9 -0
  37. package/dts/sparkline/sparkline-interactive/SparklineInteractiveMinMax.d.ts.map +1 -0
  38. package/dts/sparkline/sparkline-interactive/SparklineInteractivePanGestureHandler.d.ts +14 -0
  39. package/dts/sparkline/sparkline-interactive/SparklineInteractivePanGestureHandler.d.ts.map +1 -0
  40. package/dts/sparkline/sparkline-interactive/SparklineInteractivePaths.d.ts +11 -0
  41. package/dts/sparkline/sparkline-interactive/SparklineInteractivePaths.d.ts.map +1 -0
  42. package/dts/sparkline/sparkline-interactive/SparklineInteractivePeriodSelector.d.ts +20 -0
  43. package/dts/sparkline/sparkline-interactive/SparklineInteractivePeriodSelector.d.ts.map +1 -0
  44. package/dts/sparkline/sparkline-interactive/SparklineInteractiveProvider.d.ts +33 -0
  45. package/dts/sparkline/sparkline-interactive/SparklineInteractiveProvider.d.ts.map +1 -0
  46. package/dts/sparkline/sparkline-interactive/SparklineInteractiveTimeseriesPaths.d.ts +23 -0
  47. package/dts/sparkline/sparkline-interactive/SparklineInteractiveTimeseriesPaths.d.ts.map +1 -0
  48. package/dts/sparkline/sparkline-interactive/__figma__/SparklineInteractive.figma.d.ts +2 -0
  49. package/dts/sparkline/sparkline-interactive/__figma__/SparklineInteractive.figma.d.ts.map +1 -0
  50. package/dts/sparkline/sparkline-interactive/__stories__/SparklineInteractive.stories.d.ts +3 -0
  51. package/dts/sparkline/sparkline-interactive/__stories__/SparklineInteractive.stories.d.ts.map +1 -0
  52. package/dts/sparkline/sparkline-interactive/__tests__/SparklineInteractive.test.d.ts +2 -0
  53. package/dts/sparkline/sparkline-interactive/__tests__/SparklineInteractive.test.d.ts.map +1 -0
  54. package/dts/sparkline/sparkline-interactive/__tests__/SparklineInteractiveHoverDate.test.d.ts +2 -0
  55. package/dts/sparkline/sparkline-interactive/__tests__/SparklineInteractiveHoverDate.test.d.ts.map +1 -0
  56. package/dts/sparkline/sparkline-interactive/__tests__/SparklineInteractivePanGestureHandler.test.d.ts +2 -0
  57. package/dts/sparkline/sparkline-interactive/__tests__/SparklineInteractivePanGestureHandler.test.d.ts.map +1 -0
  58. package/dts/sparkline/sparkline-interactive/__tests__/SparklineInteractivePeriodSelector.test.d.ts +2 -0
  59. package/dts/sparkline/sparkline-interactive/__tests__/SparklineInteractivePeriodSelector.test.d.ts.map +1 -0
  60. package/dts/sparkline/sparkline-interactive/__tests__/SparklineInteractiveTimeseriesPaths.test.d.ts +2 -0
  61. package/dts/sparkline/sparkline-interactive/__tests__/SparklineInteractiveTimeseriesPaths.test.d.ts.map +1 -0
  62. package/dts/sparkline/sparkline-interactive/__tests__/useMinMaxTransform.test.d.ts +2 -0
  63. package/dts/sparkline/sparkline-interactive/__tests__/useMinMaxTransform.test.d.ts.map +1 -0
  64. package/dts/sparkline/sparkline-interactive/useInterruptiblePathAnimation.d.ts +9 -0
  65. package/dts/sparkline/sparkline-interactive/useInterruptiblePathAnimation.d.ts.map +1 -0
  66. package/dts/sparkline/sparkline-interactive/useInterruptiblePathAnimation.test.disable.d.ts +2 -0
  67. package/dts/sparkline/sparkline-interactive/useInterruptiblePathAnimation.test.disable.d.ts.map +1 -0
  68. package/dts/sparkline/sparkline-interactive/useMinMaxTransform.d.ts +11 -0
  69. package/dts/sparkline/sparkline-interactive/useMinMaxTransform.d.ts.map +1 -0
  70. package/dts/sparkline/sparkline-interactive/useOpacityAnimation.d.ts +3 -0
  71. package/dts/sparkline/sparkline-interactive/useOpacityAnimation.d.ts.map +1 -0
  72. package/dts/sparkline/sparkline-interactive/useSparklineInteractiveConstants.d.ts +22 -0
  73. package/dts/sparkline/sparkline-interactive/useSparklineInteractiveConstants.d.ts.map +1 -0
  74. package/dts/sparkline/sparkline-interactive/useSparklineInteractiveLineStyles.d.ts +31 -0
  75. package/dts/sparkline/sparkline-interactive/useSparklineInteractiveLineStyles.d.ts.map +1 -0
  76. package/dts/sparkline/sparkline-interactive-header/SparklineInteractiveHeader.d.ts +110 -0
  77. package/dts/sparkline/sparkline-interactive-header/SparklineInteractiveHeader.d.ts.map +1 -0
  78. package/dts/sparkline/sparkline-interactive-header/__figma__/SparklineInteractiveHeader.figma.d.ts +2 -0
  79. package/dts/sparkline/sparkline-interactive-header/__figma__/SparklineInteractiveHeader.figma.d.ts.map +1 -0
  80. package/dts/sparkline/sparkline-interactive-header/__stories__/SparklineInteractiveHeader.stories.d.ts +4 -0
  81. package/dts/sparkline/sparkline-interactive-header/__stories__/SparklineInteractiveHeader.stories.d.ts.map +1 -0
  82. package/dts/sparkline/sparkline-interactive-header/__tests__/SparklineInteractiveHeader.test.d.ts +2 -0
  83. package/dts/sparkline/sparkline-interactive-header/__tests__/SparklineInteractiveHeader.test.d.ts.map +1 -0
  84. package/dts/sparkline/sparkline-interactive-header/__tests__/useSparklineInteractiveHeaderStyles.test.d.ts +2 -0
  85. package/dts/sparkline/sparkline-interactive-header/__tests__/useSparklineInteractiveHeaderStyles.test.d.ts.map +1 -0
  86. package/dts/sparkline/sparkline-interactive-header/useSparklineInteractiveHeaderStyles.d.ts +26 -0
  87. package/dts/sparkline/sparkline-interactive-header/useSparklineInteractiveHeaderStyles.d.ts.map +1 -0
  88. package/esm/index.js +1 -0
  89. package/esm/sparkline/Counter.js +45 -0
  90. package/esm/sparkline/Sparkline.js +51 -0
  91. package/esm/sparkline/SparklineArea.js +14 -0
  92. package/esm/sparkline/SparklineAreaPattern.js +36 -0
  93. package/esm/sparkline/SparklineGradient.js +72 -0
  94. package/esm/sparkline/__figma__/Sparkline.figma.js +22 -0
  95. package/esm/sparkline/__stories__/Sparkline.stories.js +120 -0
  96. package/esm/sparkline/__stories__/SparklineGradient.stories.js +123 -0
  97. package/esm/sparkline/generateSparklineWithId.js +6 -0
  98. package/esm/sparkline/index.js +5 -0
  99. package/esm/sparkline/sparkline-interactive/SparklineAccessibleView.js +75 -0
  100. package/esm/sparkline/sparkline-interactive/SparklineInteractive.js +303 -0
  101. package/esm/sparkline/sparkline-interactive/SparklineInteractiveAnimatedPath.js +113 -0
  102. package/esm/sparkline/sparkline-interactive/SparklineInteractiveHoverDate.js +131 -0
  103. package/esm/sparkline/sparkline-interactive/SparklineInteractiveLineVertical.js +99 -0
  104. package/esm/sparkline/sparkline-interactive/SparklineInteractiveMarkerDates.js +82 -0
  105. package/esm/sparkline/sparkline-interactive/SparklineInteractiveMinMax.js +103 -0
  106. package/esm/sparkline/sparkline-interactive/SparklineInteractivePanGestureHandler.js +104 -0
  107. package/esm/sparkline/sparkline-interactive/SparklineInteractivePaths.js +53 -0
  108. package/esm/sparkline/sparkline-interactive/SparklineInteractivePeriodSelector.js +124 -0
  109. package/esm/sparkline/sparkline-interactive/SparklineInteractiveProvider.js +80 -0
  110. package/esm/sparkline/sparkline-interactive/SparklineInteractiveTimeseriesPaths.js +109 -0
  111. package/esm/sparkline/sparkline-interactive/__figma__/SparklineInteractive.figma.js +85 -0
  112. package/esm/sparkline/sparkline-interactive/__stories__/SparklineInteractive.stories.js +474 -0
  113. package/esm/sparkline/sparkline-interactive/useInterruptiblePathAnimation.js +58 -0
  114. package/esm/sparkline/sparkline-interactive/useInterruptiblePathAnimation.test.disable.js +37 -0
  115. package/esm/sparkline/sparkline-interactive/useMinMaxTransform.js +56 -0
  116. package/esm/sparkline/sparkline-interactive/useOpacityAnimation.js +23 -0
  117. package/esm/sparkline/sparkline-interactive/useSparklineInteractiveConstants.js +47 -0
  118. package/esm/sparkline/sparkline-interactive/useSparklineInteractiveLineStyles.js +34 -0
  119. package/esm/sparkline/sparkline-interactive-header/SparklineInteractiveHeader.js +233 -0
  120. package/esm/sparkline/sparkline-interactive-header/__figma__/SparklineInteractiveHeader.figma.js +104 -0
  121. package/esm/sparkline/sparkline-interactive-header/__stories__/SparklineInteractiveHeader.stories.js +555 -0
  122. package/esm/sparkline/sparkline-interactive-header/useSparklineInteractiveHeaderStyles.js +117 -0
  123. package/package.json +64 -5
  124. package/index.js +0 -1
@@ -0,0 +1,474 @@
1
+ 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); }
2
+ import React, { memo, useCallback, useMemo, useRef, useState } from 'react';
3
+ import { sparklineInteractiveData, sparklineInteractiveHoverData, strokeColor } from '@coinbase/cds-common/internal/visualizations/SparklineInteractiveData';
4
+ import { Example, ExampleScreen } from '@coinbase/cds-mobile/examples/ExampleScreen';
5
+ import { Box } from '@coinbase/cds-mobile/layout';
6
+ import { TextTitle3 } from '@coinbase/cds-mobile/typography/TextTitle3';
7
+ import { SparklineInteractiveHeader } from '../../sparkline-interactive-header/SparklineInteractiveHeader';
8
+ import { SparklineInteractive } from '../SparklineInteractive';
9
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
10
+ const DEFAULT_PERIOD = 'day';
11
+ function numToLocaleString(num) {
12
+ return num.toLocaleString('en-US', {
13
+ maximumFractionDigits: 2
14
+ });
15
+ }
16
+ const getFormattingConfigForPeriod = period => {
17
+ switch (period) {
18
+ case 'hour':
19
+ case 'day':
20
+ return {
21
+ hour: 'numeric',
22
+ minute: 'numeric'
23
+ };
24
+ case 'week':
25
+ case 'month':
26
+ return {
27
+ month: 'numeric',
28
+ day: 'numeric'
29
+ };
30
+ case 'year':
31
+ case 'all':
32
+ return {
33
+ month: 'numeric',
34
+ year: 'numeric'
35
+ };
36
+ }
37
+ };
38
+ const getDateHoverOptions = period => {
39
+ switch (period) {
40
+ case 'hour':
41
+ case 'day':
42
+ case 'week':
43
+ case 'month':
44
+ return {
45
+ weekday: 'short',
46
+ month: 'short',
47
+ day: 'numeric',
48
+ hour: 'numeric',
49
+ minute: 'numeric'
50
+ };
51
+ default:
52
+ return {
53
+ weekday: 'short',
54
+ year: 'numeric',
55
+ month: 'short',
56
+ day: 'numeric'
57
+ };
58
+ }
59
+ };
60
+ const periods = [{
61
+ label: '1H',
62
+ value: 'hour'
63
+ }, {
64
+ label: '1D',
65
+ value: 'day'
66
+ }, {
67
+ label: '1W',
68
+ value: 'week'
69
+ }, {
70
+ label: '1M',
71
+ value: 'month'
72
+ }, {
73
+ label: '1Y',
74
+ value: 'year'
75
+ }, {
76
+ label: 'All',
77
+ value: 'all'
78
+ }];
79
+ const SparklineInteractiveBuild = /*#__PURE__*/memo(props => {
80
+ var _props$defaultPeriod;
81
+ const formatDateWithConfig = useCallback((value, period) => {
82
+ const config = getFormattingConfigForPeriod(period);
83
+ return value.toLocaleString('en-US', _extends({}, config));
84
+ }, []);
85
+ const formatHoverDate = useCallback((date, period) => {
86
+ return date.toLocaleString('en-US', _extends({}, getDateHoverOptions(period)));
87
+ }, []);
88
+ const formatMinMaxLabel = useCallback(amount => {
89
+ return "$" + numToLocaleString(parseInt(amount, 10));
90
+ }, []);
91
+ return /*#__PURE__*/_jsx(SparklineInteractive, _extends({
92
+ disableScrubbing: !__DEV__
93
+ }, props, {
94
+ defaultPeriod: (_props$defaultPeriod = props.defaultPeriod) != null ? _props$defaultPeriod : DEFAULT_PERIOD,
95
+ formatDate: formatDateWithConfig,
96
+ formatHoverDate: !props.hideHoverDate ? formatHoverDate : undefined,
97
+ formatMinMaxLabel: formatMinMaxLabel,
98
+ periods: periods
99
+ }));
100
+ });
101
+ const generateSubHead = (point, period, sparklineInteractiveData) => {
102
+ const data = sparklineInteractiveData[period];
103
+ const firstPoint = data[0];
104
+ const increase = point.value > firstPoint.value;
105
+ return {
106
+ percent: numToLocaleString(Math.abs((point.value - firstPoint.value) / firstPoint.value) * 100) + "%",
107
+ sign: increase ? 'upwardTrend' : 'downwardTrend',
108
+ variant: increase ? 'positive' : 'negative',
109
+ accessibilityLabel: "" + (increase ? 'up' : 'down'),
110
+ priceChange: "$" + numToLocaleString(Math.abs(point.value - firstPoint.value))
111
+ };
112
+ };
113
+ const SparklineInteractiveWithHeaderBuild = /*#__PURE__*/memo(props => {
114
+ var _props$defaultPeriod2;
115
+ const {
116
+ data: sparklineData,
117
+ trailing,
118
+ labelNode,
119
+ compact
120
+ } = props;
121
+ const sparklineInteractiveData = sparklineData;
122
+ const headerRef = useRef(null);
123
+ const [currentPeriod, setCurrentPeriod] = useState((_props$defaultPeriod2 = props.defaultPeriod) != null ? _props$defaultPeriod2 : DEFAULT_PERIOD);
124
+ const data = sparklineInteractiveData[currentPeriod];
125
+ const lastPoint = data[data.length - 1];
126
+ const handleScrub = useCallback(_ref => {
127
+ var _headerRef$current;
128
+ let {
129
+ point,
130
+ period
131
+ } = _ref;
132
+ (_headerRef$current = headerRef.current) == null || _headerRef$current.update({
133
+ title: "$" + point.value.toLocaleString('en-US'),
134
+ subHead: generateSubHead(point, period, sparklineInteractiveData)
135
+ });
136
+ }, [sparklineInteractiveData, headerRef]);
137
+ const handleScrubEnd = useCallback(() => {
138
+ var _headerRef$current2;
139
+ (_headerRef$current2 = headerRef.current) == null || _headerRef$current2.update({
140
+ title: "$" + numToLocaleString(lastPoint.value),
141
+ subHead: generateSubHead(lastPoint, currentPeriod, sparklineInteractiveData)
142
+ });
143
+ }, [currentPeriod, sparklineInteractiveData, lastPoint, headerRef]);
144
+ const handleOnPeriodChanged = useCallback(period => {
145
+ var _headerRef$current3;
146
+ setCurrentPeriod(period);
147
+ const newData = sparklineInteractiveData[period];
148
+ const newLastPoint = newData[newData.length - 1];
149
+ (_headerRef$current3 = headerRef.current) == null || _headerRef$current3.update({
150
+ title: "$" + numToLocaleString(newLastPoint.value),
151
+ subHead: generateSubHead(newLastPoint, period, sparklineInteractiveData)
152
+ });
153
+ }, [sparklineInteractiveData, headerRef]);
154
+ const header = useMemo(() => /*#__PURE__*/_jsx(SparklineInteractiveHeader, {
155
+ ref: headerRef,
156
+ compact: compact,
157
+ defaultLabel: labelNode ? 'CustomHeader' : 'Bitcoin Price',
158
+ defaultSubHead: generateSubHead(lastPoint, currentPeriod, sparklineInteractiveData),
159
+ defaultTitle: "$" + numToLocaleString(lastPoint.value),
160
+ labelNode: labelNode,
161
+ trailing: trailing
162
+ }), [compact, labelNode, lastPoint, currentPeriod, sparklineInteractiveData, trailing]);
163
+ return /*#__PURE__*/_jsx(SparklineInteractiveBuild, _extends({}, props, {
164
+ headerNode: header,
165
+ onPeriodChanged: handleOnPeriodChanged,
166
+ onScrub: handleScrub,
167
+ onScrubEnd: handleScrubEnd
168
+ }));
169
+ });
170
+ const rgbaStrokeColor = 'rgba(123, 1, 1, 5)';
171
+ const rgbStrokeColor = 'rgb(123, 1, 121)';
172
+ const autoStrokeColor = 'auto';
173
+ const SparklineInteractiveScreen = () => {
174
+ return /*#__PURE__*/_jsxs(ExampleScreen, {
175
+ children: [/*#__PURE__*/_jsx(Example, {
176
+ padding: 0,
177
+ children: /*#__PURE__*/_jsxs(Box, {
178
+ children: [/*#__PURE__*/_jsx(TextTitle3, {
179
+ paddingX: 3,
180
+ paddingY: 3,
181
+ children: "Default"
182
+ }), /*#__PURE__*/_jsx(SparklineInteractiveBuild, {
183
+ data: sparklineInteractiveData,
184
+ strokeColor: strokeColor
185
+ })]
186
+ })
187
+ }), /*#__PURE__*/_jsx(Example, {
188
+ padding: 0,
189
+ children: /*#__PURE__*/_jsxs(Box, {
190
+ children: [/*#__PURE__*/_jsx(TextTitle3, {
191
+ paddingX: 3,
192
+ paddingY: 3,
193
+ children: "Compact"
194
+ }), /*#__PURE__*/_jsx(SparklineInteractiveBuild, {
195
+ compact: true,
196
+ data: sparklineInteractiveData,
197
+ strokeColor: strokeColor
198
+ })]
199
+ })
200
+ }), /*#__PURE__*/_jsx(Example, {
201
+ padding: 0,
202
+ children: /*#__PURE__*/_jsxs(Box, {
203
+ children: [/*#__PURE__*/_jsx(TextTitle3, {
204
+ paddingX: 3,
205
+ paddingY: 3,
206
+ children: "Disable Scrubbing"
207
+ }), /*#__PURE__*/_jsx(SparklineInteractiveBuild, {
208
+ disableScrubbing: true,
209
+ data: sparklineInteractiveData,
210
+ strokeColor: strokeColor
211
+ })]
212
+ })
213
+ }), /*#__PURE__*/_jsx(Example, {
214
+ padding: 0,
215
+ children: /*#__PURE__*/_jsxs(Box, {
216
+ children: [/*#__PURE__*/_jsx(TextTitle3, {
217
+ paddingX: 3,
218
+ paddingY: 3,
219
+ children: "Hide period selector"
220
+ }), /*#__PURE__*/_jsx(SparklineInteractiveBuild, {
221
+ hidePeriodSelector: true,
222
+ data: sparklineInteractiveData,
223
+ strokeColor: strokeColor
224
+ })]
225
+ })
226
+ }), /*#__PURE__*/_jsx(Example, {
227
+ padding: 0,
228
+ children: /*#__PURE__*/_jsxs(Box, {
229
+ children: [/*#__PURE__*/_jsx(TextTitle3, {
230
+ paddingX: 3,
231
+ paddingY: 3,
232
+ children: "Hide min/max label"
233
+ }), /*#__PURE__*/_jsx(SparklineInteractiveBuild, {
234
+ hideMinMaxLabel: true,
235
+ data: sparklineInteractiveData,
236
+ strokeColor: strokeColor
237
+ })]
238
+ })
239
+ }), /*#__PURE__*/_jsx(Example, {
240
+ padding: 0,
241
+ children: /*#__PURE__*/_jsxs(Box, {
242
+ children: [/*#__PURE__*/_jsx(TextTitle3, {
243
+ paddingX: 3,
244
+ paddingY: 3,
245
+ children: "Default period All"
246
+ }), /*#__PURE__*/_jsx(SparklineInteractiveBuild, {
247
+ data: sparklineInteractiveData,
248
+ defaultPeriod: "all",
249
+ strokeColor: strokeColor
250
+ })]
251
+ })
252
+ }), /*#__PURE__*/_jsx(Example, {
253
+ padding: 0,
254
+ children: /*#__PURE__*/_jsxs(Box, {
255
+ children: [/*#__PURE__*/_jsx(TextTitle3, {
256
+ paddingX: 3,
257
+ paddingY: 3,
258
+ children: "Fill Disabled"
259
+ }), /*#__PURE__*/_jsx(SparklineInteractiveBuild, {
260
+ data: sparklineInteractiveData,
261
+ fill: false,
262
+ strokeColor: strokeColor
263
+ })]
264
+ })
265
+ }), /*#__PURE__*/_jsx(Example, {
266
+ padding: 0,
267
+ children: /*#__PURE__*/_jsxs(Box, {
268
+ children: [/*#__PURE__*/_jsx(TextTitle3, {
269
+ paddingX: 3,
270
+ paddingY: 3,
271
+ children: "Y axis scaling"
272
+ }), /*#__PURE__*/_jsx(SparklineInteractiveBuild, {
273
+ data: sparklineInteractiveData,
274
+ strokeColor: strokeColor,
275
+ yAxisScalingFactor: 0.1
276
+ })]
277
+ })
278
+ }), /*#__PURE__*/_jsx(Example, {
279
+ padding: 0,
280
+ children: /*#__PURE__*/_jsxs(Box, {
281
+ children: [/*#__PURE__*/_jsx(TextTitle3, {
282
+ paddingX: 3,
283
+ paddingY: 3,
284
+ children: "Fallback"
285
+ }), /*#__PURE__*/_jsx(SparklineInteractiveBuild, {
286
+ strokeColor: strokeColor
287
+ })]
288
+ })
289
+ }), /*#__PURE__*/_jsx(Example, {
290
+ padding: 0,
291
+ children: /*#__PURE__*/_jsxs(Box, {
292
+ children: [/*#__PURE__*/_jsx(TextTitle3, {
293
+ paddingX: 3,
294
+ paddingY: 3,
295
+ children: "Fallback Negative"
296
+ }), /*#__PURE__*/_jsx(SparklineInteractiveBuild, {
297
+ fallbackType: "negative",
298
+ strokeColor: strokeColor
299
+ })]
300
+ })
301
+ }), /*#__PURE__*/_jsx(Example, {
302
+ padding: 0,
303
+ children: /*#__PURE__*/_jsxs(Box, {
304
+ children: [/*#__PURE__*/_jsx(TextTitle3, {
305
+ paddingX: 3,
306
+ paddingY: 3,
307
+ children: "Fallback Compact"
308
+ }), /*#__PURE__*/_jsx(SparklineInteractiveBuild, {
309
+ compact: true,
310
+ strokeColor: strokeColor
311
+ })]
312
+ })
313
+ }), /*#__PURE__*/_jsx(Example, {
314
+ padding: 0,
315
+ children: /*#__PURE__*/_jsxs(Box, {
316
+ children: [/*#__PURE__*/_jsx(TextTitle3, {
317
+ paddingX: 3,
318
+ paddingY: 3,
319
+ children: "No Hover Date"
320
+ }), /*#__PURE__*/_jsx(SparklineInteractiveBuild, {
321
+ hideHoverDate: true,
322
+ data: sparklineInteractiveData,
323
+ strokeColor: strokeColor
324
+ })]
325
+ })
326
+ }), /*#__PURE__*/_jsx(Example, {
327
+ padding: 0,
328
+ children: /*#__PURE__*/_jsxs(Box, {
329
+ children: [/*#__PURE__*/_jsx(TextTitle3, {
330
+ paddingX: 3,
331
+ paddingY: 3,
332
+ children: "With Header Node"
333
+ }), /*#__PURE__*/_jsx(SparklineInteractiveWithHeaderBuild, {
334
+ data: sparklineInteractiveData,
335
+ strokeColor: "#F7931A"
336
+ })]
337
+ })
338
+ }), /*#__PURE__*/_jsx(Example, {
339
+ padding: 0,
340
+ children: /*#__PURE__*/_jsxs(Box, {
341
+ children: [/*#__PURE__*/_jsx(TextTitle3, {
342
+ paddingX: 3,
343
+ paddingY: 3,
344
+ children: "No padding"
345
+ }), /*#__PURE__*/_jsx(SparklineInteractiveBuild, {
346
+ data: sparklineInteractiveData,
347
+ gutter: 0,
348
+ strokeColor: "#F7931A",
349
+ timePeriodGutter: 3
350
+ })]
351
+ })
352
+ }), /*#__PURE__*/_jsx(Example, {
353
+ padding: 4,
354
+ children: /*#__PURE__*/_jsxs(Box, {
355
+ children: [/*#__PURE__*/_jsx(TextTitle3, {
356
+ paddingY: 3,
357
+ children: "In Container With 4 padding"
358
+ }), /*#__PURE__*/_jsx(SparklineInteractiveWithHeaderBuild, {
359
+ disableHorizontalPadding: true,
360
+ data: sparklineInteractiveData,
361
+ gutter: 4,
362
+ strokeColor: "#F7931A"
363
+ })]
364
+ })
365
+ }), /*#__PURE__*/_jsx(Example, {
366
+ padding: 0,
367
+ children: /*#__PURE__*/_jsxs(Box, {
368
+ children: [/*#__PURE__*/_jsx(TextTitle3, {
369
+ paddingX: 3,
370
+ paddingY: 3,
371
+ children: "Custom screen padding 6"
372
+ }), /*#__PURE__*/_jsx(SparklineInteractiveBuild, {
373
+ data: sparklineInteractiveData,
374
+ gutter: 6,
375
+ strokeColor: "#F7931A"
376
+ })]
377
+ })
378
+ }), /*#__PURE__*/_jsx(Example, {
379
+ padding: 0,
380
+ children: /*#__PURE__*/_jsxs(Box, {
381
+ children: [/*#__PURE__*/_jsx(TextTitle3, {
382
+ paddingX: 3,
383
+ paddingY: 3,
384
+ children: "Hover data"
385
+ }), /*#__PURE__*/_jsx(SparklineInteractiveBuild, {
386
+ data: sparklineInteractiveData,
387
+ hoverData: sparklineInteractiveHoverData,
388
+ strokeColor: strokeColor
389
+ })]
390
+ })
391
+ }), /*#__PURE__*/_jsx(Example, {
392
+ padding: 0,
393
+ children: /*#__PURE__*/_jsxs(Box, {
394
+ children: [/*#__PURE__*/_jsx(TextTitle3, {
395
+ paddingX: 3,
396
+ paddingY: 3,
397
+ children: "Auto Stoke Color"
398
+ }), /*#__PURE__*/_jsx(SparklineInteractiveBuild, {
399
+ data: sparklineInteractiveData,
400
+ strokeColor: autoStrokeColor
401
+ })]
402
+ })
403
+ }), /*#__PURE__*/_jsx(Example, {
404
+ padding: 0,
405
+ children: /*#__PURE__*/_jsxs(Box, {
406
+ children: [/*#__PURE__*/_jsx(TextTitle3, {
407
+ paddingX: 3,
408
+ paddingY: 3,
409
+ children: "Custom RGB Stoke Color"
410
+ }), /*#__PURE__*/_jsx(SparklineInteractiveBuild, {
411
+ data: sparklineInteractiveData,
412
+ strokeColor: rgbStrokeColor
413
+ })]
414
+ })
415
+ }), /*#__PURE__*/_jsx(Example, {
416
+ padding: 0,
417
+ children: /*#__PURE__*/_jsxs(Box, {
418
+ children: [/*#__PURE__*/_jsx(TextTitle3, {
419
+ paddingX: 3,
420
+ paddingY: 3,
421
+ children: "Custom RGBA Stoke Color"
422
+ }), /*#__PURE__*/_jsx(SparklineInteractiveBuild, {
423
+ data: sparklineInteractiveData,
424
+ strokeColor: rgbaStrokeColor
425
+ })]
426
+ })
427
+ }), /*#__PURE__*/_jsx(Example, {
428
+ padding: 0,
429
+ children: /*#__PURE__*/_jsxs(Box, {
430
+ children: [/*#__PURE__*/_jsx(TextTitle3, {
431
+ paddingX: 3,
432
+ paddingY: 3,
433
+ children: "No Data In SelectedPeriod"
434
+ }), /*#__PURE__*/_jsx(SparklineInteractiveBuild, {
435
+ data: _extends({}, sparklineInteractiveData, {
436
+ hour: []
437
+ }),
438
+ strokeColor: rgbaStrokeColor
439
+ })]
440
+ })
441
+ }), /*#__PURE__*/_jsx(Example, {
442
+ padding: 0,
443
+ children: /*#__PURE__*/_jsxs(Box, {
444
+ children: [/*#__PURE__*/_jsx(TextTitle3, {
445
+ paddingX: 3,
446
+ paddingY: 3,
447
+ children: "Enable Interaction When Outside"
448
+ }), /*#__PURE__*/_jsx(SparklineInteractiveBuild, {
449
+ allowOverflowGestures: true,
450
+ data: sparklineInteractiveData,
451
+ strokeColor: strokeColor
452
+ })]
453
+ })
454
+ }), /*#__PURE__*/_jsx(Example, {
455
+ padding: 0,
456
+ children: /*#__PURE__*/_jsxs(Box, {
457
+ children: [/*#__PURE__*/_jsx(TextTitle3, {
458
+ paddingX: 3,
459
+ paddingY: 3,
460
+ children: "Custom Node Header Styles"
461
+ }), /*#__PURE__*/_jsx(SparklineInteractiveWithHeaderBuild, {
462
+ data: sparklineInteractiveData,
463
+ strokeColor: "#F7931A",
464
+ styles: {
465
+ header: {
466
+ paddingBottom: 0
467
+ }
468
+ }
469
+ })]
470
+ })
471
+ })]
472
+ });
473
+ };
474
+ export default SparklineInteractiveScreen;
@@ -0,0 +1,58 @@
1
+ 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); }
2
+ import { useCallback, useEffect, useRef } from 'react';
3
+ import { Animated } from 'react-native';
4
+ import { animatedPathConfig } from '@coinbase/cds-common/animation/sparkline';
5
+ import { useSparklineInteractiveContext } from './SparklineInteractiveProvider';
6
+ const animationConfig = _extends({}, animatedPathConfig, {
7
+ toValue: 1,
8
+ useNativeDriver: true
9
+ });
10
+ export const useInterruptiblePathAnimation = _ref => {
11
+ let {
12
+ animationListener,
13
+ onInterrupt,
14
+ ignoreMinMax
15
+ } = _ref;
16
+ const {
17
+ animateMinMaxIn
18
+ } = useSparklineInteractiveContext();
19
+ const isRunning = useRef(false);
20
+ const animationProgress = useRef(new Animated.Value(0)).current;
21
+ const animations = [Animated.timing(animationProgress, animationConfig)];
22
+ if (!ignoreMinMax) {
23
+ animations.push(animateMinMaxIn);
24
+ }
25
+ const animation = Animated.sequence(animations);
26
+ const onFinishAnimation = useCallback(_ref2 => {
27
+ let {
28
+ finished
29
+ } = _ref2;
30
+ if (finished) {
31
+ animationProgress.removeAllListeners();
32
+ animationProgress.setValue(0);
33
+ isRunning.current = false;
34
+ }
35
+ }, [animationProgress]);
36
+
37
+ // Clean up listeners
38
+ useEffect(() => {
39
+ return () => {
40
+ animationProgress.removeAllListeners();
41
+ };
42
+ }, [animationProgress]);
43
+ return useCallback(() => {
44
+ // If try to re-run animation while currently running
45
+ // we should interrupt it and start new one
46
+ if (isRunning.current) {
47
+ animation.stop();
48
+ onFinishAnimation({
49
+ finished: true
50
+ });
51
+ onInterrupt();
52
+ } else {
53
+ isRunning.current = true;
54
+ animationProgress.addListener(animationListener);
55
+ animation.start(onFinishAnimation);
56
+ }
57
+ }, [animation, animationListener, animationProgress, onFinishAnimation, onInterrupt]);
58
+ };
@@ -0,0 +1,37 @@
1
+ import { Animated } from 'react-native';
2
+ import { renderHook } from '@testing-library/react-hooks';
3
+ import { useInterruptiblePathAnimation } from './useInterruptiblePathAnimation';
4
+ jest.useFakeTimers({
5
+ legacyFakeTimers: true
6
+ });
7
+ describe('useInterruptiblePathAnimation', () => {
8
+ const animationListenerSpy = jest.fn();
9
+ const onInterruptSpy = jest.fn();
10
+ it('plays correctly', () => {
11
+ const {
12
+ result
13
+ } = renderHook(() => {
14
+ return useInterruptiblePathAnimation({
15
+ animationListener: animationListenerSpy,
16
+ onInterrupt: onInterruptSpy
17
+ });
18
+ });
19
+ result.current();
20
+ expect(Animated.timing).toHaveBeenCalled();
21
+ });
22
+ it('interrupts correctly if triggering play while already playing', () => {
23
+ const {
24
+ result
25
+ } = renderHook(() => {
26
+ return useInterruptiblePathAnimation({
27
+ animationListener: animationListenerSpy,
28
+ onInterrupt: onInterruptSpy
29
+ });
30
+ });
31
+ result.current();
32
+ expect(Animated.timing).toHaveBeenCalled();
33
+ result.current();
34
+ expect(onInterruptSpy).toHaveBeenCalled();
35
+ jest.runAllTimers();
36
+ });
37
+ });
@@ -0,0 +1,56 @@
1
+ import { useEffect } from 'react';
2
+ import { Animated } from 'react-native';
3
+ import { durations } from '@coinbase/cds-common/motion/tokens';
4
+ import { useTheme } from '@coinbase/cds-mobile/hooks/useTheme';
5
+ import { useSparklineInteractiveContext } from './SparklineInteractiveProvider';
6
+ import { useSparklineInteractiveConstants } from './useSparklineInteractiveConstants';
7
+ export function useMinMaxTransform(_ref) {
8
+ let {
9
+ minMaxLayout,
10
+ x,
11
+ transform,
12
+ opacity
13
+ } = _ref;
14
+ const theme = useTheme();
15
+ const {
16
+ height,
17
+ width
18
+ } = minMaxLayout;
19
+ const {
20
+ SparklineInteractiveMinMaxLabelHeight,
21
+ chartWidth
22
+ } = useSparklineInteractiveConstants({});
23
+ const {
24
+ gutter
25
+ } = useSparklineInteractiveContext();
26
+ useEffect(() => {
27
+ // If onLayout has not finished we don't want to show min/max
28
+ // or else it will abruptly change positions
29
+ if (height === 0 && width === 0) {
30
+ opacity.setValue(0);
31
+ return;
32
+ }
33
+
34
+ // if we have no gutter the min/max label needs some space so it's not right up against the edge of the screen
35
+ const minGutter = gutter === 0 ? theme.space['1'] : 0;
36
+
37
+ // Position min or max at center of the desired x coordinate when possible.
38
+ // If this is not possible, ensure that it's never positioned outside of chart container.
39
+ // This means the x transform should never be less than 0 or greater than chartWidth - labelWidth
40
+ const idealX = x - width / 2;
41
+ const translateX = Math.round(Math.max(minGutter, Math.min(idealX, chartWidth - width - minGutter)));
42
+ // Vertically center the min/max label within SparklineInteractiveMinMaxLabelHeight.
43
+ // This is the area between the vertical dotted line and the top or bottom
44
+ // of sparkline where min/max is displayed
45
+ const translateY = SparklineInteractiveMinMaxLabelHeight / 2 - height / 2;
46
+ transform.setValue({
47
+ x: translateX,
48
+ y: translateY
49
+ });
50
+ Animated.timing(opacity, {
51
+ toValue: 1,
52
+ duration: durations.moderate1,
53
+ useNativeDriver: true
54
+ }).start();
55
+ }, [SparklineInteractiveMinMaxLabelHeight, chartWidth, gutter, height, opacity, theme.space, transform, width, x]);
56
+ }
@@ -0,0 +1,23 @@
1
+ import { useMemo, useRef } from 'react';
2
+ import { Animated } from 'react-native';
3
+ import { fadeDuration } from '@coinbase/cds-common/tokens/sparkline';
4
+ export function useOpacityAnimation(initialValue, duration) {
5
+ if (initialValue === void 0) {
6
+ initialValue = 0;
7
+ }
8
+ if (duration === void 0) {
9
+ duration = fadeDuration;
10
+ }
11
+ const animation = useRef(new Animated.Value(initialValue)).current;
12
+ const animateIn = useMemo(() => Animated.timing(animation, {
13
+ toValue: 1,
14
+ duration,
15
+ useNativeDriver: true
16
+ }), [animation, duration]);
17
+ const animateOut = useMemo(() => Animated.timing(animation, {
18
+ toValue: 0,
19
+ duration,
20
+ useNativeDriver: true
21
+ }), [animation, duration]);
22
+ return [animation, animateIn, animateOut];
23
+ }
@@ -0,0 +1,47 @@
1
+ import { useMemo } from 'react';
2
+ import { useWindowDimensions } from 'react-native';
3
+ import { borderWidth, chartCompactHeight, chartHeight as chartHeightToken } from '@coinbase/cds-common/tokens/sparkline';
4
+ import { useTheme } from '@coinbase/cds-mobile/hooks/useTheme';
5
+ import { useSparklineInteractiveContext } from './SparklineInteractiveProvider';
6
+ export function useSparklineInteractiveConstants(_ref) {
7
+ let {
8
+ compact = false
9
+ } = _ref;
10
+ const theme = useTheme();
11
+ const {
12
+ width: screenWidth
13
+ } = useWindowDimensions();
14
+ const {
15
+ gutter
16
+ } = useSparklineInteractiveContext();
17
+ return useMemo(() => {
18
+ const chartHorizontalGutter = theme.space[gutter];
19
+ const chartWidth = screenWidth - chartHorizontalGutter * 2;
20
+ const chartHeight = compact ? chartCompactHeight : chartHeightToken;
21
+ const chartMarkerSize = theme.space[2];
22
+ const SparklineInteractiveMinMaxLabelHeight = theme.space[3];
23
+ const SparklineInteractiveMinMaxVerticalGutter = theme.space[0.5];
24
+ const chartVerticalLineWidth = borderWidth;
25
+ const xRange = [borderWidth, chartWidth - borderWidth];
26
+ const yRange = [chartHeight - borderWidth, borderWidth];
27
+ const startX = 0;
28
+ const endX = xRange[1];
29
+ return {
30
+ chartHorizontalGutter,
31
+ chartWidth,
32
+ chartHeight,
33
+ chartDimensionStyles: {
34
+ height: chartHeight,
35
+ width: chartWidth
36
+ },
37
+ chartMarkerSize,
38
+ SparklineInteractiveMinMaxLabelHeight,
39
+ SparklineInteractiveMinMaxVerticalGutter,
40
+ chartVerticalLineWidth,
41
+ xRange,
42
+ yRange,
43
+ startX,
44
+ endX
45
+ };
46
+ }, [compact, gutter, screenWidth, theme.space]);
47
+ }