@coinbase/cds-mobile-visualization 3.4.0-beta.2 → 3.4.0-beta.21

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 (211) hide show
  1. package/CHANGELOG.md +128 -0
  2. package/dts/chart/CartesianChart.d.ts +92 -34
  3. package/dts/chart/CartesianChart.d.ts.map +1 -1
  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 +3 -0
  7. package/dts/chart/ChartProvider.d.ts.map +1 -1
  8. package/dts/chart/Path.d.ts +97 -32
  9. package/dts/chart/Path.d.ts.map +1 -1
  10. package/dts/chart/PeriodSelector.d.ts +6 -13
  11. package/dts/chart/PeriodSelector.d.ts.map +1 -1
  12. package/dts/chart/area/Area.d.ts +39 -28
  13. package/dts/chart/area/Area.d.ts.map +1 -1
  14. package/dts/chart/area/AreaChart.d.ts +51 -10
  15. package/dts/chart/area/AreaChart.d.ts.map +1 -1
  16. package/dts/chart/area/DottedArea.d.ts +21 -2
  17. package/dts/chart/area/DottedArea.d.ts.map +1 -1
  18. package/dts/chart/area/GradientArea.d.ts +19 -13
  19. package/dts/chart/area/GradientArea.d.ts.map +1 -1
  20. package/dts/chart/area/SolidArea.d.ts +17 -2
  21. package/dts/chart/area/SolidArea.d.ts.map +1 -1
  22. package/dts/chart/axis/Axis.d.ts +86 -118
  23. package/dts/chart/axis/Axis.d.ts.map +1 -1
  24. package/dts/chart/axis/DefaultAxisTickLabel.d.ts +8 -0
  25. package/dts/chart/axis/DefaultAxisTickLabel.d.ts.map +1 -0
  26. package/dts/chart/axis/XAxis.d.ts +1 -1
  27. package/dts/chart/axis/XAxis.d.ts.map +1 -1
  28. package/dts/chart/axis/YAxis.d.ts +2 -2
  29. package/dts/chart/axis/YAxis.d.ts.map +1 -1
  30. package/dts/chart/axis/index.d.ts +1 -0
  31. package/dts/chart/axis/index.d.ts.map +1 -1
  32. package/dts/chart/bar/Bar.d.ts +49 -12
  33. package/dts/chart/bar/Bar.d.ts.map +1 -1
  34. package/dts/chart/bar/BarChart.d.ts +40 -19
  35. package/dts/chart/bar/BarChart.d.ts.map +1 -1
  36. package/dts/chart/bar/BarPlot.d.ts +3 -1
  37. package/dts/chart/bar/BarPlot.d.ts.map +1 -1
  38. package/dts/chart/bar/BarStack.d.ts +41 -46
  39. package/dts/chart/bar/BarStack.d.ts.map +1 -1
  40. package/dts/chart/bar/BarStackGroup.d.ts +2 -0
  41. package/dts/chart/bar/BarStackGroup.d.ts.map +1 -1
  42. package/dts/chart/bar/DefaultBar.d.ts +1 -1
  43. package/dts/chart/bar/DefaultBar.d.ts.map +1 -1
  44. package/dts/chart/bar/DefaultBarStack.d.ts.map +1 -1
  45. package/dts/chart/gradient/Gradient.d.ts +25 -0
  46. package/dts/chart/gradient/Gradient.d.ts.map +1 -0
  47. package/dts/chart/gradient/index.d.ts +2 -0
  48. package/dts/chart/gradient/index.d.ts.map +1 -0
  49. package/dts/chart/index.d.ts +4 -1
  50. package/dts/chart/index.d.ts.map +1 -1
  51. package/dts/chart/legend/DefaultLegendEntry.d.ts +5 -0
  52. package/dts/chart/legend/DefaultLegendEntry.d.ts.map +1 -0
  53. package/dts/chart/legend/DefaultLegendShape.d.ts +5 -0
  54. package/dts/chart/legend/DefaultLegendShape.d.ts.map +1 -0
  55. package/dts/chart/legend/Legend.d.ts +168 -0
  56. package/dts/chart/legend/Legend.d.ts.map +1 -0
  57. package/dts/chart/legend/index.d.ts +4 -0
  58. package/dts/chart/legend/index.d.ts.map +1 -0
  59. package/dts/chart/line/DefaultReferenceLineLabel.d.ts +9 -0
  60. package/dts/chart/line/DefaultReferenceLineLabel.d.ts.map +1 -0
  61. package/dts/chart/line/DottedLine.d.ts +13 -5
  62. package/dts/chart/line/DottedLine.d.ts.map +1 -1
  63. package/dts/chart/line/Line.d.ts +61 -27
  64. package/dts/chart/line/Line.d.ts.map +1 -1
  65. package/dts/chart/line/LineChart.d.ts +43 -9
  66. package/dts/chart/line/LineChart.d.ts.map +1 -1
  67. package/dts/chart/line/ReferenceLine.d.ts +68 -20
  68. package/dts/chart/line/ReferenceLine.d.ts.map +1 -1
  69. package/dts/chart/line/SolidLine.d.ts +8 -5
  70. package/dts/chart/line/SolidLine.d.ts.map +1 -1
  71. package/dts/chart/line/index.d.ts +1 -1
  72. package/dts/chart/line/index.d.ts.map +1 -1
  73. package/dts/chart/point/DefaultPointLabel.d.ts +10 -0
  74. package/dts/chart/point/DefaultPointLabel.d.ts.map +1 -0
  75. package/dts/chart/point/Point.d.ts +136 -0
  76. package/dts/chart/point/Point.d.ts.map +1 -0
  77. package/dts/chart/point/index.d.ts +3 -0
  78. package/dts/chart/point/index.d.ts.map +1 -0
  79. package/dts/chart/scrubber/DefaultScrubberBeacon.d.ts +38 -0
  80. package/dts/chart/scrubber/DefaultScrubberBeacon.d.ts.map +1 -0
  81. package/dts/chart/scrubber/DefaultScrubberBeaconLabel.d.ts +12 -0
  82. package/dts/chart/scrubber/DefaultScrubberBeaconLabel.d.ts.map +1 -0
  83. package/dts/chart/scrubber/DefaultScrubberLabel.d.ts +11 -0
  84. package/dts/chart/scrubber/DefaultScrubberLabel.d.ts.map +1 -0
  85. package/dts/chart/scrubber/Scrubber.d.ts +230 -42
  86. package/dts/chart/scrubber/Scrubber.d.ts.map +1 -1
  87. package/dts/chart/scrubber/ScrubberBeaconGroup.d.ts +54 -0
  88. package/dts/chart/scrubber/ScrubberBeaconGroup.d.ts.map +1 -0
  89. package/dts/chart/scrubber/ScrubberBeaconLabelGroup.d.ts +46 -0
  90. package/dts/chart/scrubber/ScrubberBeaconLabelGroup.d.ts.map +1 -0
  91. package/dts/chart/scrubber/ScrubberProvider.d.ts +6 -3
  92. package/dts/chart/scrubber/ScrubberProvider.d.ts.map +1 -1
  93. package/dts/chart/scrubber/index.d.ts +3 -0
  94. package/dts/chart/scrubber/index.d.ts.map +1 -1
  95. package/dts/chart/text/ChartText.d.ts +151 -77
  96. package/dts/chart/text/ChartText.d.ts.map +1 -1
  97. package/dts/chart/text/{SmartChartTextGroup.d.ts → ChartTextGroup.d.ts} +9 -3
  98. package/dts/chart/text/ChartTextGroup.d.ts.map +1 -0
  99. package/dts/chart/text/index.d.ts +1 -1
  100. package/dts/chart/text/index.d.ts.map +1 -1
  101. package/dts/chart/utils/axis.d.ts +25 -1
  102. package/dts/chart/utils/axis.d.ts.map +1 -1
  103. package/dts/chart/utils/bar.d.ts +34 -0
  104. package/dts/chart/utils/bar.d.ts.map +1 -1
  105. package/dts/chart/utils/chart.d.ts +52 -7
  106. package/dts/chart/utils/chart.d.ts.map +1 -1
  107. package/dts/chart/utils/context.d.ts +28 -7
  108. package/dts/chart/utils/context.d.ts.map +1 -1
  109. package/dts/chart/utils/gradient.d.ts +117 -0
  110. package/dts/chart/utils/gradient.d.ts.map +1 -0
  111. package/dts/chart/utils/index.d.ts +3 -0
  112. package/dts/chart/utils/index.d.ts.map +1 -1
  113. package/dts/chart/utils/path.d.ts +59 -0
  114. package/dts/chart/utils/path.d.ts.map +1 -1
  115. package/dts/chart/utils/point.d.ts +71 -7
  116. package/dts/chart/utils/point.d.ts.map +1 -1
  117. package/dts/chart/utils/scale.d.ts +102 -0
  118. package/dts/chart/utils/scale.d.ts.map +1 -1
  119. package/dts/chart/utils/scrubber.d.ts +40 -0
  120. package/dts/chart/utils/scrubber.d.ts.map +1 -0
  121. package/dts/chart/utils/transition.d.ts +178 -0
  122. package/dts/chart/utils/transition.d.ts.map +1 -0
  123. package/esm/chart/CartesianChart.js +199 -75
  124. package/esm/chart/ChartContextBridge.js +159 -0
  125. package/esm/chart/ChartProvider.js +2 -2
  126. package/esm/chart/Path.js +200 -114
  127. package/esm/chart/PeriodSelector.js +7 -3
  128. package/esm/chart/__stories__/CartesianChart.stories.js +307 -134
  129. package/esm/chart/__stories__/ChartTransitions.stories.js +629 -0
  130. package/esm/chart/__stories__/PeriodSelector.stories.js +201 -75
  131. package/esm/chart/area/Area.js +27 -35
  132. package/esm/chart/area/AreaChart.js +17 -12
  133. package/esm/chart/area/DottedArea.js +64 -108
  134. package/esm/chart/area/GradientArea.js +37 -91
  135. package/esm/chart/area/SolidArea.js +24 -8
  136. package/esm/chart/area/__stories__/AreaChart.stories.js +1 -1
  137. package/esm/chart/axis/Axis.js +5 -39
  138. package/esm/chart/axis/DefaultAxisTickLabel.js +11 -0
  139. package/esm/chart/axis/XAxis.js +148 -66
  140. package/esm/chart/axis/YAxis.js +149 -65
  141. package/esm/chart/axis/__stories__/Axis.stories.js +259 -1
  142. package/esm/chart/axis/index.js +1 -0
  143. package/esm/chart/bar/Bar.js +7 -1
  144. package/esm/chart/bar/BarChart.js +17 -37
  145. package/esm/chart/bar/BarPlot.js +43 -35
  146. package/esm/chart/bar/BarStack.js +84 -37
  147. package/esm/chart/bar/BarStackGroup.js +7 -17
  148. package/esm/chart/bar/DefaultBar.js +29 -51
  149. package/esm/chart/bar/DefaultBarStack.js +34 -58
  150. package/esm/chart/bar/__stories__/BarChart.stories.js +948 -88
  151. package/esm/chart/gradient/Gradient.js +53 -0
  152. package/esm/chart/gradient/index.js +1 -0
  153. package/esm/chart/index.js +4 -1
  154. package/esm/chart/legend/DefaultLegendEntry.js +42 -0
  155. package/esm/chart/legend/DefaultLegendShape.js +64 -0
  156. package/esm/chart/legend/Legend.js +59 -0
  157. package/esm/chart/legend/__stories__/Legend.stories.js +574 -0
  158. package/esm/chart/legend/index.js +3 -0
  159. package/esm/chart/line/DefaultReferenceLineLabel.js +66 -0
  160. package/esm/chart/line/DottedLine.js +31 -14
  161. package/esm/chart/line/Line.js +96 -68
  162. package/esm/chart/line/LineChart.js +21 -14
  163. package/esm/chart/line/ReferenceLine.js +80 -63
  164. package/esm/chart/line/SolidLine.js +27 -10
  165. package/esm/chart/line/__stories__/LineChart.stories.js +1748 -2048
  166. package/esm/chart/line/__stories__/ReferenceLine.stories.js +177 -28
  167. package/esm/chart/line/index.js +1 -1
  168. package/esm/chart/point/DefaultPointLabel.js +39 -0
  169. package/esm/chart/point/Point.js +186 -0
  170. package/esm/chart/point/index.js +2 -0
  171. package/esm/chart/scrubber/DefaultScrubberBeacon.js +180 -0
  172. package/esm/chart/scrubber/DefaultScrubberBeaconLabel.js +43 -0
  173. package/esm/chart/scrubber/DefaultScrubberLabel.js +28 -0
  174. package/esm/chart/scrubber/Scrubber.js +130 -144
  175. package/esm/chart/scrubber/ScrubberBeaconGroup.js +165 -0
  176. package/esm/chart/scrubber/ScrubberBeaconLabelGroup.js +208 -0
  177. package/esm/chart/scrubber/ScrubberProvider.js +46 -54
  178. package/esm/chart/scrubber/__stories__/Scrubber.stories.js +760 -0
  179. package/esm/chart/scrubber/index.js +3 -1
  180. package/esm/chart/text/ChartText.js +242 -174
  181. package/esm/chart/text/{SmartChartTextGroup.js → ChartTextGroup.js} +6 -5
  182. package/esm/chart/text/index.js +1 -1
  183. package/esm/chart/utils/axis.js +47 -31
  184. package/esm/chart/utils/bar.js +43 -0
  185. package/esm/chart/utils/chart.js +57 -3
  186. package/esm/chart/utils/gradient.js +305 -0
  187. package/esm/chart/utils/index.js +3 -0
  188. package/esm/chart/utils/path.js +84 -8
  189. package/esm/chart/utils/point.js +171 -17
  190. package/esm/chart/utils/scale.js +242 -2
  191. package/esm/chart/utils/scrubber.js +146 -0
  192. package/esm/chart/utils/transition.js +215 -0
  193. package/esm/sparkline/__figma__/Sparkline.figma.js +1 -1
  194. package/esm/sparkline/__stories__/Sparkline.stories.js +11 -7
  195. package/esm/sparkline/__stories__/SparklineGradient.stories.js +7 -4
  196. package/esm/sparkline/sparkline-interactive/__figma__/SparklineInteractive.figma.js +1 -1
  197. package/esm/sparkline/sparkline-interactive/__stories__/SparklineInteractive.stories.js +51 -26
  198. package/esm/sparkline/sparkline-interactive-header/__figma__/SparklineInteractiveHeader.figma.js +1 -1
  199. package/esm/sparkline/sparkline-interactive-header/__stories__/SparklineInteractiveHeader.stories.js +17 -9
  200. package/package.json +15 -10
  201. package/dts/chart/Point.d.ts +0 -103
  202. package/dts/chart/Point.d.ts.map +0 -1
  203. package/dts/chart/line/GradientLine.d.ts +0 -45
  204. package/dts/chart/line/GradientLine.d.ts.map +0 -1
  205. package/dts/chart/scrubber/ScrubberBeacon.d.ts +0 -75
  206. package/dts/chart/scrubber/ScrubberBeacon.d.ts.map +0 -1
  207. package/dts/chart/text/SmartChartTextGroup.d.ts.map +0 -1
  208. package/esm/chart/Point.js +0 -111
  209. package/esm/chart/__stories__/Chart.stories.js +0 -79
  210. package/esm/chart/line/GradientLine.js +0 -62
  211. package/esm/chart/scrubber/ScrubberBeacon.js +0 -199
@@ -0,0 +1,159 @@
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
+ /**
3
+ * Simplified context bridge utilities for React Native.
4
+ * Adapted from its-fine to enable context sharing across React renderers
5
+ * https://github.com/pmndrs/its-fine/blob/598b81f02778c22ed21121c2b1a786bdefb14e23/src/index.tsx
6
+ */
7
+
8
+ import * as React from 'react';
9
+ import { ThemeContext } from '@coinbase/cds-mobile/system/ThemeProvider';
10
+ import { ScrubberContext } from './utils/context';
11
+ import { CartesianChartContext } from './ChartProvider';
12
+
13
+ /**
14
+ * Whitelist of contexts that should be bridged to the Skia canvas.
15
+ * Only these contexts will be made available inside the chart's Skia tree.
16
+ * This improves performance by avoiding the overhead of rendering every bridged context.
17
+ */
18
+ import { jsx as _jsx } from "react/jsx-runtime";
19
+ const BRIDGED_CONTEXTS = [ThemeContext, CartesianChartContext, ScrubberContext];
20
+
21
+ /**
22
+ * Represents a react-internal tree node.
23
+ */
24
+
25
+ /**
26
+ * Represents a tree node selector for traversal.
27
+ */
28
+
29
+ /**
30
+ * Traverses up or down a React tree, return `true` to stop and select a node.
31
+ */
32
+ function traverseTreeNode(node, ascending, selector) {
33
+ if (!node) return;
34
+ if (selector(node) === true) return node;
35
+ let child = ascending ? node.return : node.child;
36
+ while (child) {
37
+ const match = traverseTreeNode(child, ascending, selector);
38
+ if (match) return match;
39
+ child = ascending ? null : child.sibling;
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Wraps context to hide React development warnings about using contexts between renderers.
45
+ */
46
+ function wrapContext(context) {
47
+ try {
48
+ return Object.defineProperties(context, {
49
+ _currentRenderer: {
50
+ get() {
51
+ return null;
52
+ },
53
+ set() {}
54
+ },
55
+ _currentRenderer2: {
56
+ get() {
57
+ return null;
58
+ },
59
+ set() {}
60
+ }
61
+ });
62
+ } catch (_) {
63
+ return context;
64
+ }
65
+ }
66
+
67
+ // In development, React will warn about using contexts between renderers.
68
+ // Suppress the warning because our context bridge fixes this issue
69
+ const error = console.error;
70
+ console.error = function () {
71
+ for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
72
+ args[_key] = arguments[_key];
73
+ }
74
+ const message = args.join('');
75
+ if (message != null && message.startsWith('Warning:') && message.includes('useContext')) {
76
+ console.error = error;
77
+ return;
78
+ }
79
+ return error.apply(this, args);
80
+ };
81
+ const TreeNodeContext = wrapContext(/*#__PURE__*/React.createContext(null));
82
+
83
+ /**
84
+ * A react-internal tree node provider that binds React children to the React tree for chart context bridging.
85
+ */
86
+ export class ChartBridgeProvider extends React.Component {
87
+ render() {
88
+ return /*#__PURE__*/_jsx(TreeNodeContext.Provider, {
89
+ value: this._reactInternals,
90
+ children: this.props.children
91
+ });
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Returns the current react-internal tree node.
97
+ */
98
+ function useTreeNode() {
99
+ const root = React.useContext(TreeNodeContext);
100
+ if (root === null) throw new Error('useTreeNode must be called within a <ChartBridgeProvider />!');
101
+ const id = React.useId();
102
+ const treeNode = React.useMemo(() => {
103
+ for (const maybeNode of [root, root == null ? void 0 : root.alternate]) {
104
+ if (!maybeNode) continue;
105
+ const node = traverseTreeNode(maybeNode, false, node => {
106
+ let state = node.memoizedState;
107
+ while (state) {
108
+ if (state.memoizedState === id) return true;
109
+ state = state.next;
110
+ }
111
+ });
112
+ if (node) return node;
113
+ }
114
+ }, [root, id]);
115
+ return treeNode;
116
+ }
117
+ /**
118
+ * Returns a map of whitelisted contexts and their values.
119
+ */
120
+ function useContextMap() {
121
+ const treeNode = useTreeNode();
122
+ const [contextMap] = React.useState(() => new Map());
123
+
124
+ // Collect live context
125
+ contextMap.clear();
126
+ let node = treeNode;
127
+ while (node) {
128
+ if (node.type && typeof node.type === 'object') {
129
+ // https://github.com/facebook/react/pull/28226
130
+ const enableRenderableContext = node.type._context === undefined && node.type.Provider === node.type;
131
+ const context = enableRenderableContext ? node.type : node.type._context;
132
+ if (context && context !== TreeNodeContext && BRIDGED_CONTEXTS.includes(context) && !contextMap.has(context)) {
133
+ // eslint-disable-next-line react-hooks/rules-of-hooks
134
+ contextMap.set(context, React.useContext(wrapContext(context)));
135
+ }
136
+ }
137
+ node = node.return;
138
+ }
139
+ return contextMap;
140
+ }
141
+
142
+ /**
143
+ * Represents a chart context bridge provider component.
144
+ */
145
+
146
+ /**
147
+ * Returns a ChartContextBridge of live context providers to pierce Context across renderers.
148
+ * Pass ChartContextBridge as a component to a secondary renderer (e.g., Skia Canvas) to enable context-sharing in charts.
149
+ */
150
+ export function useChartContextBridge() {
151
+ const contextMap = useContextMap();
152
+
153
+ // Flatten context and their memoized values into a `ChartContextBridge` provider
154
+ return React.useMemo(() => Array.from(contextMap.keys()).reduce((Prev, context) => props => /*#__PURE__*/_jsx(Prev, {
155
+ children: /*#__PURE__*/_jsx(context.Provider, _extends({}, props, {
156
+ value: contextMap.get(context)
157
+ }))
158
+ }), props => /*#__PURE__*/_jsx(ChartBridgeProvider, _extends({}, props))), [contextMap]);
159
+ }
@@ -1,9 +1,9 @@
1
1
  import { createContext, useContext } from 'react';
2
- const CartesianChartContext = /*#__PURE__*/createContext(undefined);
2
+ export const CartesianChartContext = /*#__PURE__*/createContext(undefined);
3
3
  export const useCartesianChartContext = () => {
4
4
  const context = useContext(CartesianChartContext);
5
5
  if (!context) {
6
- throw new Error('useCartesianChartContext must be used within a CartesianChart component. See http://cds.coinbase.com/components/graphs/CartesianChart.');
6
+ throw new Error('useCartesianChartContext must be used within a CartesianChart component. See https://cds.coinbase.com/components/charts/CartesianChart.');
7
7
  }
8
8
  return context;
9
9
  };
package/esm/chart/Path.js CHANGED
@@ -1,133 +1,219 @@
1
- const _excluded = ["clipRect", "clipOffset", "d", "fill", "stroke", "strokeWidth", "strokeOpacity", "fillOpacity", "strokeDasharray", "testID", "animate"];
2
- 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; }
1
+ const _excluded = ["d", "initialPath", "fill", "fillOpacity", "stroke", "strokeOpacity", "strokeWidth", "strokeCap", "strokeJoin", "children", "transitions"],
2
+ _excluded2 = ["animate", "clipRect", "clipPath", "clipOffset", "d", "initialPath", "fill", "fillOpacity", "stroke", "strokeOpacity", "strokeWidth", "strokeCap", "strokeJoin", "children", "transitions", "transition"];
3
3
  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); }
4
- import { memo, useCallback, useEffect, useId, useMemo, useRef } from 'react';
5
- import Reanimated, { runOnJS, useAnimatedProps, useAnimatedReaction, useSharedValue, withTiming } from 'react-native-reanimated';
6
- import { ClipPath, Defs, G, Path as SvgPath, Rect } from 'react-native-svg';
7
- import { usePreviousValue } from '@coinbase/cds-common/hooks/usePreviousValue';
8
- import * as interpolate from 'd3-interpolate-path';
4
+ 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; }
5
+ import { memo, useEffect, useMemo } from 'react';
6
+ import { useDerivedValue, useSharedValue } from 'react-native-reanimated';
7
+ import { Group, Path as SkiaPath, Skia, usePathInterpolation } from '@shopify/react-native-skia';
8
+ import { defaultPathEnterTransition } from './utils/path';
9
+ import { buildTransition, defaultTransition, getTransition, usePathTransition } from './utils/transition';
9
10
  import { useCartesianChartContext } from './ChartProvider';
10
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
11
- const AnimatedRect = Reanimated.createAnimatedComponent(Rect);
12
- const AnimatedSvgRect = /*#__PURE__*/memo(_ref => {
11
+ import { unwrapAnimatedValue } from './utils';
12
+
13
+ /**
14
+ * Duration in milliseconds for path enter transition.
15
+ */
16
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
17
+ export const pathEnterTransitionDuration = 500;
18
+ const AnimatedPath = /*#__PURE__*/memo(_ref => {
13
19
  let {
14
- width,
15
- totalOffset,
16
- rectProps
17
- } = _ref;
18
- const animatedWidth = useSharedValue(width + totalOffset);
19
- const animatedProps = useAnimatedProps(() => {
20
- return {
21
- width: animatedWidth.value
22
- };
20
+ d = '',
21
+ initialPath,
22
+ fill,
23
+ fillOpacity,
24
+ stroke,
25
+ strokeOpacity,
26
+ strokeWidth,
27
+ strokeCap,
28
+ strokeJoin,
29
+ children,
30
+ transitions
31
+ } = _ref,
32
+ pathProps = _objectWithoutPropertiesLoose(_ref, _excluded);
33
+ const isDAnimated = typeof d !== 'string';
34
+ const animatedPath = usePathTransition({
35
+ currentPath: isDAnimated ? '' : d,
36
+ initialPath,
37
+ transitions
38
+ });
39
+ const isFilled = fill !== undefined && fill !== 'none';
40
+ const isStroked = stroke !== undefined && stroke !== 'none';
41
+ const activePath = useDerivedValue(() => {
42
+ if (isDAnimated) {
43
+ var _d$value;
44
+ return (_d$value = d.value) != null ? _d$value : Skia.Path.Make();
45
+ }
46
+ return animatedPath.value;
47
+ });
48
+ return /*#__PURE__*/_jsxs(_Fragment, {
49
+ children: [isFilled && /*#__PURE__*/_jsx(SkiaPath, _extends({
50
+ color: fill,
51
+ opacity: fillOpacity,
52
+ path: activePath,
53
+ style: "fill"
54
+ }, pathProps, {
55
+ children: children
56
+ })), isStroked && /*#__PURE__*/_jsx(SkiaPath, _extends({
57
+ color: stroke,
58
+ opacity: strokeOpacity,
59
+ path: activePath,
60
+ strokeCap: strokeCap,
61
+ strokeJoin: strokeJoin,
62
+ strokeWidth: strokeWidth,
63
+ style: "stroke"
64
+ }, pathProps, {
65
+ children: children
66
+ }))]
23
67
  });
24
- useEffect(() => {
25
- animatedWidth.value = withTiming(width + totalOffset, {
26
- duration: 1000
27
- });
28
- }, [animatedWidth, width, totalOffset]);
29
- return /*#__PURE__*/_jsx(AnimatedRect, _extends({
30
- animatedProps: animatedProps
31
- }, rectProps));
32
68
  });
33
- export const Path = /*#__PURE__*/memo(_ref2 => {
34
- let {
69
+ export const Path = /*#__PURE__*/memo(props => {
70
+ const {
71
+ animate: animateProp,
35
72
  clipRect,
36
- clipOffset,
73
+ clipPath: clipPathProp,
74
+ clipOffset = 0,
37
75
  d = '',
76
+ initialPath,
38
77
  fill,
78
+ fillOpacity,
39
79
  stroke,
40
- strokeWidth,
41
80
  strokeOpacity,
42
- fillOpacity,
43
- strokeDasharray,
44
- testID,
45
- animate: animateProp
46
- } = _ref2,
47
- pathProps = _objectWithoutPropertiesLoose(_ref2, _excluded);
48
- const pathRef = useRef(null);
49
- const {
50
- animate: animateContext,
51
- drawingArea: contextRect
52
- } = useCartesianChartContext();
53
- const rect = clipRect != null ? clipRect : contextRect;
54
- const animate = animateProp != null ? animateProp : animateContext;
55
- const clipPathId = useId();
56
- const animationProgress = useSharedValue(0);
57
- const targetPath = useMemo(() => d, [d]);
58
- const previousPath = usePreviousValue(targetPath);
59
- const fromPath = useMemo(() => {
60
- if (!animate) return targetPath;
61
- return previousPath != null ? previousPath : targetPath;
62
- }, [animate, previousPath, targetPath]);
63
- const pathInterpolator = useMemo(() => interpolate.interpolatePath(fromPath, targetPath), [fromPath, targetPath]);
64
- const updatePath = useCallback(progress => {
65
- var _pathRef$current;
66
- if (!pathInterpolator) return;
67
- const val = Number(progress.toFixed(4));
68
- (_pathRef$current = pathRef.current) == null || _pathRef$current.setNativeProps({
69
- d: pathInterpolator(val)
70
- });
71
- }, [pathInterpolator]);
72
- useAnimatedReaction(() => animationProgress.value, progress => {
73
- 'worklet';
81
+ strokeWidth,
82
+ strokeCap,
83
+ strokeJoin,
84
+ children,
85
+ transitions,
86
+ transition
87
+ } = props,
88
+ pathProps = _objectWithoutPropertiesLoose(props, _excluded2);
89
+ const context = useCartesianChartContext();
90
+ const rect = clipRect != null ? clipRect : context.drawingArea;
91
+ const animate = animateProp != null ? animateProp : context.animate;
92
+ const isReady = !!context.getXScale();
93
+ const enterTransition = useMemo(() => getTransition(transitions == null ? void 0 : transitions.enter, animate, defaultPathEnterTransition), [animate, transitions == null ? void 0 : transitions.enter]);
94
+ const updateTransition = useMemo(() => getTransition((transitions == null ? void 0 : transitions.update) !== undefined ? transitions.update : transition, animate, defaultTransition), [animate, transitions == null ? void 0 : transitions.update, transition]);
95
+
96
+ // The clip offset provides extra padding to prevent path from being cut off
97
+ // Area charts typically use offset=0 for exact clipping, while lines use offset=2 for breathing room
98
+ const totalOffset = clipOffset * 2; // Applied on both sides
74
99
 
75
- runOnJS(updatePath)(progress);
76
- }, [updatePath]);
100
+ // Animation progress for clip path reveal
101
+ const clipProgress = useSharedValue(animate ? 0 : 1);
77
102
  useEffect(() => {
78
- if (!pathRef.current) return;
79
- if (!animate || !pathInterpolator) {
80
- pathRef.current.setNativeProps({
81
- d: targetPath
82
- });
83
- animationProgress.value = 1;
84
- return;
103
+ if (animate && isReady) {
104
+ clipProgress.value = buildTransition(1, enterTransition);
85
105
  }
86
- animationProgress.value = 0;
87
- animationProgress.value = withTiming(1, {
88
- duration: 200
106
+ }, [animate, isReady, clipProgress, enterTransition]);
107
+
108
+ // Create initial and target clip paths for animation
109
+ const {
110
+ initialClipPath,
111
+ targetClipPath
112
+ } = useMemo(() => {
113
+ if (!rect) return {
114
+ initialClipPath: null,
115
+ targetClipPath: null
116
+ };
117
+
118
+ // Initial clip path (width = 0)
119
+ const initial = Skia.Path.Make();
120
+ initial.addRect({
121
+ x: rect.x - clipOffset,
122
+ y: rect.y - clipOffset,
123
+ width: 0,
124
+ height: rect.height + totalOffset
89
125
  });
90
- }, [animate, animationProgress, targetPath, pathInterpolator]);
91
- if (!d || !rect) return;
92
126
 
93
- // The clip offset provides extra padding to prevent path from being cut off
94
- // Area charts typically use offset=0 for exact clipping, while lines use offset=2 for breathing room
95
- const totalOffset = (clipOffset != null ? clipOffset : 0) * 2; // Applied on both sides
127
+ // Target clip path (full width)
128
+ const target = Skia.Path.Make();
129
+ target.addRect({
130
+ x: rect.x - clipOffset,
131
+ y: rect.y - clipOffset,
132
+ width: rect.width + totalOffset,
133
+ height: rect.height + totalOffset
134
+ });
135
+ return {
136
+ initialClipPath: initial,
137
+ targetClipPath: target
138
+ };
139
+ }, [rect, clipOffset, totalOffset]);
140
+
141
+ // Use usePathInterpolation for animated clip path
142
+ const animatedClipPath = usePathInterpolation(clipProgress, [0, 1], animate && initialClipPath && targetClipPath ? [initialClipPath, targetClipPath] : targetClipPath ? [targetClipPath, targetClipPath] : [Skia.Path.Make(), Skia.Path.Make()]);
96
143
 
97
- return /*#__PURE__*/_jsxs(G, {
98
- children: [/*#__PURE__*/_jsx(Defs, {
99
- children: animate ? /*#__PURE__*/_jsx(ClipPath, {
100
- id: clipPathId,
101
- children: /*#__PURE__*/_jsx(AnimatedSvgRect, {
102
- rectProps: {
103
- height: rect.height + totalOffset,
104
- x: rect.x - (clipOffset != null ? clipOffset : 0),
105
- y: rect.y - (clipOffset != null ? clipOffset : 0)
106
- },
107
- totalOffset: totalOffset,
108
- width: rect.width
109
- })
110
- }) : /*#__PURE__*/_jsx(ClipPath, {
111
- id: clipPathId,
112
- children: /*#__PURE__*/_jsx(Rect, {
113
- height: contextRect.height + totalOffset,
114
- width: contextRect.width + totalOffset,
115
- x: contextRect.x - (clipOffset != null ? clipOffset : 0),
116
- y: contextRect.y - (clipOffset != null ? clipOffset : 0)
117
- })
118
- })
119
- }), /*#__PURE__*/_jsx(SvgPath, _extends({
120
- ref: pathRef,
121
- clipPath: "url(#" + clipPathId + ")",
122
- clipRule: "nonzero",
123
- d: fromPath,
124
- fill: fill,
125
- fillOpacity: fillOpacity,
126
- stroke: stroke,
127
- strokeDasharray: strokeDasharray,
128
- strokeOpacity: strokeOpacity,
144
+ // Resolve the final clip path:
145
+ // 1. If clipPath prop was explicitly provided, use it (even if null = no clipping)
146
+ // 2. If animating, use the interpolated clip path
147
+ // 3. Otherwise, use static target clip path
148
+ const resolvedClipPath = useMemo(() => {
149
+ // If clipPath was explicitly provided (null or string), use it directly
150
+ if (clipPathProp !== undefined) {
151
+ return clipPathProp;
152
+ }
153
+
154
+ // If not animating or paths are null, return target clip path
155
+ if (!animate || !targetClipPath) {
156
+ return targetClipPath;
157
+ }
158
+
159
+ // Return undefined here since we'll use animatedClipPath directly
160
+ return undefined;
161
+ }, [clipPathProp, animate, targetClipPath]);
162
+
163
+ // Convert SVG path string to SkPath for static rendering
164
+ const staticPath = useDerivedValue(() => {
165
+ var _Skia$Path$MakeFromSV;
166
+ const dValue = unwrapAnimatedValue(d);
167
+ if (!dValue) return Skia.Path.Make();
168
+ return (_Skia$Path$MakeFromSV = Skia.Path.MakeFromSVGString(dValue)) != null ? _Skia$Path$MakeFromSV : Skia.Path.Make();
169
+ }, [d]);
170
+ const isFilled = fill !== undefined && fill !== 'none';
171
+ const isStroked = stroke !== undefined && stroke !== 'none';
172
+ const content = !animate ? /*#__PURE__*/_jsxs(_Fragment, {
173
+ children: [isFilled && /*#__PURE__*/_jsx(SkiaPath, _extends({
174
+ color: fill,
175
+ opacity: fillOpacity,
176
+ path: staticPath,
177
+ style: "fill"
178
+ }, pathProps, {
179
+ children: children
180
+ })), isStroked && /*#__PURE__*/_jsx(SkiaPath, _extends({
181
+ color: stroke,
182
+ opacity: strokeOpacity,
183
+ path: staticPath,
184
+ strokeCap: strokeCap,
185
+ strokeJoin: strokeJoin,
129
186
  strokeWidth: strokeWidth,
130
- testID: testID
131
- }, pathProps))]
187
+ style: "stroke"
188
+ }, pathProps, {
189
+ children: children
190
+ }))]
191
+ }) : /*#__PURE__*/_jsx(AnimatedPath, {
192
+ d: d,
193
+ fill: fill,
194
+ fillOpacity: fillOpacity,
195
+ initialPath: initialPath,
196
+ stroke: stroke,
197
+ strokeCap: strokeCap,
198
+ strokeJoin: strokeJoin,
199
+ strokeOpacity: strokeOpacity,
200
+ strokeWidth: strokeWidth,
201
+ transitions: {
202
+ enter: enterTransition,
203
+ update: updateTransition
204
+ },
205
+ children: children
206
+ });
207
+
208
+ // Determine which clip path to use
209
+ const finalClipPath = animate && resolvedClipPath === undefined ? animatedClipPath : resolvedClipPath;
210
+
211
+ // If finalClipPath is null, render without clipping
212
+ if (finalClipPath === null) {
213
+ return content;
214
+ }
215
+ return /*#__PURE__*/_jsx(Group, {
216
+ clip: finalClipPath,
217
+ children: content
132
218
  });
133
219
  });
@@ -9,7 +9,7 @@ import { useTheme } from '@coinbase/cds-mobile/hooks/useTheme';
9
9
  import { SegmentedTabs } from '@coinbase/cds-mobile/tabs';
10
10
  import { SegmentedTab } from '@coinbase/cds-mobile/tabs/SegmentedTab';
11
11
  import { tabsSpringConfig } from '@coinbase/cds-mobile/tabs/Tabs';
12
- import { Text } from '@coinbase/cds-mobile/typography/Text';
12
+ import { Text } from '@coinbase/cds-mobile/typography';
13
13
 
14
14
  // Animated active indicator to support smooth transition of background color
15
15
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
@@ -24,7 +24,8 @@ export const PeriodSelectorActiveIndicator = _ref => {
24
24
  const {
25
25
  width,
26
26
  height,
27
- x
27
+ x,
28
+ y
28
29
  } = activeTabRect;
29
30
 
30
31
  // Get the target background color
@@ -38,6 +39,7 @@ export const PeriodSelectorActiveIndicator = _ref => {
38
39
  // Combined animated value for position, size, and color
39
40
  const newAnimatedValues = {
40
41
  x,
42
+ y,
41
43
  width,
42
44
  backgroundColor: targetColor
43
45
  };
@@ -51,11 +53,13 @@ export const PeriodSelectorActiveIndicator = _ref => {
51
53
  const animatedStyles = useAnimatedStyle(() => ({
52
54
  transform: [{
53
55
  translateX: animatedValues.value.x
56
+ }, {
57
+ translateY: animatedValues.value.y
54
58
  }],
55
59
  width: animatedValues.value.width,
56
60
  backgroundColor: animatedValues.value.backgroundColor
57
61
  }), [animatedValues]);
58
- if (!width) return null;
62
+ if (!width) return;
59
63
  return /*#__PURE__*/_jsx(Animated.View, {
60
64
  style: [{
61
65
  position: position,