@coinbase/cds-mobile-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 (245) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +3 -0
  3. package/dts/chart/CartesianChart.d.ts +101 -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 +48 -0
  8. package/dts/chart/Path.d.ts.map +1 -0
  9. package/dts/chart/PeriodSelector.d.ts +85 -0
  10. package/dts/chart/PeriodSelector.d.ts.map +1 -0
  11. package/dts/chart/Point.d.ts +103 -0
  12. package/dts/chart/Point.d.ts.map +1 -0
  13. package/dts/chart/area/Area.d.ts +62 -0
  14. package/dts/chart/area/Area.d.ts.map +1 -0
  15. package/dts/chart/area/AreaChart.d.ts +90 -0
  16. package/dts/chart/area/AreaChart.d.ts.map +1 -0
  17. package/dts/chart/area/DottedArea.d.ts +27 -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 +204 -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 +89 -0
  34. package/dts/chart/bar/Bar.d.ts.map +1 -0
  35. package/dts/chart/bar/BarChart.d.ts +97 -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 +7 -0
  44. package/dts/chart/bar/DefaultBar.d.ts.map +1 -0
  45. package/dts/chart/bar/DefaultBarStack.d.ts +7 -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 +12 -0
  52. package/dts/chart/line/DottedLine.d.ts.map +1 -0
  53. package/dts/chart/line/GradientLine.d.ts +45 -0
  54. package/dts/chart/line/GradientLine.d.ts.map +1 -0
  55. package/dts/chart/line/Line.d.ts +78 -0
  56. package/dts/chart/line/Line.d.ts.map +1 -0
  57. package/dts/chart/line/LineChart.d.ts +84 -0
  58. package/dts/chart/line/LineChart.d.ts.map +1 -0
  59. package/dts/chart/line/ReferenceLine.d.ts +91 -0
  60. package/dts/chart/line/ReferenceLine.d.ts.map +1 -0
  61. package/dts/chart/line/SolidLine.d.ts +12 -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 +104 -0
  66. package/dts/chart/scrubber/Scrubber.d.ts.map +1 -0
  67. package/dts/chart/scrubber/ScrubberBeacon.d.ts +75 -0
  68. package/dts/chart/scrubber/ScrubberBeacon.d.ts.map +1 -0
  69. package/dts/chart/scrubber/ScrubberProvider.d.ts +17 -0
  70. package/dts/chart/scrubber/ScrubberProvider.d.ts.map +1 -0
  71. package/dts/chart/scrubber/index.d.ts +2 -0
  72. package/dts/chart/scrubber/index.d.ts.map +1 -0
  73. package/dts/chart/text/ChartText.d.ts +90 -0
  74. package/dts/chart/text/ChartText.d.ts.map +1 -0
  75. package/dts/chart/text/SmartChartTextGroup.d.ts +55 -0
  76. package/dts/chart/text/SmartChartTextGroup.d.ts.map +1 -0
  77. package/dts/chart/text/index.d.ts +3 -0
  78. package/dts/chart/text/index.d.ts.map +1 -0
  79. package/dts/chart/utils/axis.d.ts +342 -0
  80. package/dts/chart/utils/axis.d.ts.map +1 -0
  81. package/dts/chart/utils/bar.d.ts +20 -0
  82. package/dts/chart/utils/bar.d.ts.map +1 -0
  83. package/dts/chart/utils/chart.d.ts +97 -0
  84. package/dts/chart/utils/chart.d.ts.map +1 -0
  85. package/dts/chart/utils/context.d.ts +95 -0
  86. package/dts/chart/utils/context.d.ts.map +1 -0
  87. package/dts/chart/utils/index.d.ts +8 -0
  88. package/dts/chart/utils/index.d.ts.map +1 -0
  89. package/dts/chart/utils/path.d.ts +107 -0
  90. package/dts/chart/utils/path.d.ts.map +1 -0
  91. package/dts/chart/utils/point.d.ts +75 -0
  92. package/dts/chart/utils/point.d.ts.map +1 -0
  93. package/dts/chart/utils/scale.d.ts +43 -0
  94. package/dts/chart/utils/scale.d.ts.map +1 -0
  95. package/dts/index.d.ts +3 -0
  96. package/dts/index.d.ts.map +1 -0
  97. package/dts/sparkline/Counter.d.ts +8 -0
  98. package/dts/sparkline/Counter.d.ts.map +1 -0
  99. package/dts/sparkline/Sparkline.d.ts +73 -0
  100. package/dts/sparkline/Sparkline.d.ts.map +1 -0
  101. package/dts/sparkline/SparklineArea.d.ts +14 -0
  102. package/dts/sparkline/SparklineArea.d.ts.map +1 -0
  103. package/dts/sparkline/SparklineAreaPattern.d.ts +14 -0
  104. package/dts/sparkline/SparklineAreaPattern.d.ts.map +1 -0
  105. package/dts/sparkline/SparklineGradient.d.ts +23 -0
  106. package/dts/sparkline/SparklineGradient.d.ts.map +1 -0
  107. package/dts/sparkline/__figma__/Sparkline.figma.d.ts +2 -0
  108. package/dts/sparkline/__figma__/Sparkline.figma.d.ts.map +1 -0
  109. package/dts/sparkline/generateSparklineWithId.d.ts +11 -0
  110. package/dts/sparkline/generateSparklineWithId.d.ts.map +1 -0
  111. package/dts/sparkline/index.d.ts +6 -0
  112. package/dts/sparkline/index.d.ts.map +1 -0
  113. package/dts/sparkline/sparkline-interactive/SparklineAccessibleView.d.ts +23 -0
  114. package/dts/sparkline/sparkline-interactive/SparklineAccessibleView.d.ts.map +1 -0
  115. package/dts/sparkline/sparkline-interactive/SparklineInteractive.d.ts +184 -0
  116. package/dts/sparkline/sparkline-interactive/SparklineInteractive.d.ts.map +1 -0
  117. package/dts/sparkline/sparkline-interactive/SparklineInteractiveAnimatedPath.d.ts +25 -0
  118. package/dts/sparkline/sparkline-interactive/SparklineInteractiveAnimatedPath.d.ts.map +1 -0
  119. package/dts/sparkline/sparkline-interactive/SparklineInteractiveHoverDate.d.ts +28 -0
  120. package/dts/sparkline/sparkline-interactive/SparklineInteractiveHoverDate.d.ts.map +1 -0
  121. package/dts/sparkline/sparkline-interactive/SparklineInteractiveLineVertical.d.ts +13 -0
  122. package/dts/sparkline/sparkline-interactive/SparklineInteractiveLineVertical.d.ts.map +1 -0
  123. package/dts/sparkline/sparkline-interactive/SparklineInteractiveMarkerDates.d.ts +17 -0
  124. package/dts/sparkline/sparkline-interactive/SparklineInteractiveMarkerDates.d.ts.map +1 -0
  125. package/dts/sparkline/sparkline-interactive/SparklineInteractiveMinMax.d.ts +11 -0
  126. package/dts/sparkline/sparkline-interactive/SparklineInteractiveMinMax.d.ts.map +1 -0
  127. package/dts/sparkline/sparkline-interactive/SparklineInteractivePanGestureHandler.d.ts +26 -0
  128. package/dts/sparkline/sparkline-interactive/SparklineInteractivePanGestureHandler.d.ts.map +1 -0
  129. package/dts/sparkline/sparkline-interactive/SparklineInteractivePaths.d.ts +25 -0
  130. package/dts/sparkline/sparkline-interactive/SparklineInteractivePaths.d.ts.map +1 -0
  131. package/dts/sparkline/sparkline-interactive/SparklineInteractivePeriodSelector.d.ts +25 -0
  132. package/dts/sparkline/sparkline-interactive/SparklineInteractivePeriodSelector.d.ts.map +1 -0
  133. package/dts/sparkline/sparkline-interactive/SparklineInteractiveProvider.d.ts +39 -0
  134. package/dts/sparkline/sparkline-interactive/SparklineInteractiveProvider.d.ts.map +1 -0
  135. package/dts/sparkline/sparkline-interactive/SparklineInteractiveTimeseriesPaths.d.ts +31 -0
  136. package/dts/sparkline/sparkline-interactive/SparklineInteractiveTimeseriesPaths.d.ts.map +1 -0
  137. package/dts/sparkline/sparkline-interactive/__figma__/SparklineInteractive.figma.d.ts +2 -0
  138. package/dts/sparkline/sparkline-interactive/__figma__/SparklineInteractive.figma.d.ts.map +1 -0
  139. package/dts/sparkline/sparkline-interactive/useInterruptiblePathAnimation.d.ts +13 -0
  140. package/dts/sparkline/sparkline-interactive/useInterruptiblePathAnimation.d.ts.map +1 -0
  141. package/dts/sparkline/sparkline-interactive/useMinMaxTransform.d.ts +16 -0
  142. package/dts/sparkline/sparkline-interactive/useMinMaxTransform.d.ts.map +1 -0
  143. package/dts/sparkline/sparkline-interactive/useOpacityAnimation.d.ts +6 -0
  144. package/dts/sparkline/sparkline-interactive/useOpacityAnimation.d.ts.map +1 -0
  145. package/dts/sparkline/sparkline-interactive/useSparklineInteractiveConstants.d.ts +22 -0
  146. package/dts/sparkline/sparkline-interactive/useSparklineInteractiveConstants.d.ts.map +1 -0
  147. package/dts/sparkline/sparkline-interactive/useSparklineInteractiveLineStyles.d.ts +34 -0
  148. package/dts/sparkline/sparkline-interactive/useSparklineInteractiveLineStyles.d.ts.map +1 -0
  149. package/dts/sparkline/sparkline-interactive-header/SparklineInteractiveHeader.d.ts +118 -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/dts/sparkline/sparkline-interactive-header/useSparklineInteractiveHeaderStyles.d.ts +29 -0
  154. package/dts/sparkline/sparkline-interactive-header/useSparklineInteractiveHeaderStyles.d.ts.map +1 -0
  155. package/esm/chart/CartesianChart.js +241 -0
  156. package/esm/chart/ChartProvider.js +10 -0
  157. package/esm/chart/Path.js +133 -0
  158. package/esm/chart/PeriodSelector.js +136 -0
  159. package/esm/chart/Point.js +111 -0
  160. package/esm/chart/__stories__/CartesianChart.stories.js +476 -0
  161. package/esm/chart/__stories__/Chart.stories.js +79 -0
  162. package/esm/chart/__stories__/PeriodSelector.stories.js +294 -0
  163. package/esm/chart/area/Area.js +85 -0
  164. package/esm/chart/area/AreaChart.js +146 -0
  165. package/esm/chart/area/DottedArea.js +128 -0
  166. package/esm/chart/area/GradientArea.js +110 -0
  167. package/esm/chart/area/SolidArea.js +24 -0
  168. package/esm/chart/area/__stories__/AreaChart.stories.js +100 -0
  169. package/esm/chart/area/index.js +7 -0
  170. package/esm/chart/axis/Axis.js +43 -0
  171. package/esm/chart/axis/XAxis.js +181 -0
  172. package/esm/chart/axis/YAxis.js +170 -0
  173. package/esm/chart/axis/__stories__/Axis.stories.js +277 -0
  174. package/esm/chart/axis/index.js +5 -0
  175. package/esm/chart/bar/Bar.js +67 -0
  176. package/esm/chart/bar/BarChart.js +147 -0
  177. package/esm/chart/bar/BarPlot.js +96 -0
  178. package/esm/chart/bar/BarStack.js +514 -0
  179. package/esm/chart/bar/BarStackGroup.js +89 -0
  180. package/esm/chart/bar/DefaultBar.js +78 -0
  181. package/esm/chart/bar/DefaultBarStack.js +82 -0
  182. package/esm/chart/bar/__stories__/BarChart.stories.js +282 -0
  183. package/esm/chart/bar/index.js +9 -0
  184. package/esm/chart/index.js +14 -0
  185. package/esm/chart/line/DottedLine.js +35 -0
  186. package/esm/chart/line/GradientLine.js +62 -0
  187. package/esm/chart/line/Line.js +139 -0
  188. package/esm/chart/line/LineChart.js +115 -0
  189. package/esm/chart/line/ReferenceLine.js +115 -0
  190. package/esm/chart/line/SolidLine.js +31 -0
  191. package/esm/chart/line/__stories__/LineChart.stories.js +2248 -0
  192. package/esm/chart/line/__stories__/ReferenceLine.stories.js +77 -0
  193. package/esm/chart/line/index.js +8 -0
  194. package/esm/chart/scrubber/Scrubber.js +186 -0
  195. package/esm/chart/scrubber/ScrubberBeacon.js +199 -0
  196. package/esm/chart/scrubber/ScrubberProvider.js +143 -0
  197. package/esm/chart/scrubber/index.js +2 -0
  198. package/esm/chart/text/ChartText.js +237 -0
  199. package/esm/chart/text/SmartChartTextGroup.js +210 -0
  200. package/esm/chart/text/index.js +4 -0
  201. package/esm/chart/utils/axis.js +592 -0
  202. package/esm/chart/utils/bar.js +24 -0
  203. package/esm/chart/utils/chart.js +229 -0
  204. package/esm/chart/utils/context.js +15 -0
  205. package/esm/chart/utils/index.js +9 -0
  206. package/esm/chart/utils/path.js +206 -0
  207. package/esm/chart/utils/point.js +118 -0
  208. package/esm/chart/utils/scale.js +48 -0
  209. package/esm/index.js +4 -0
  210. package/esm/sparkline/Counter.js +45 -0
  211. package/esm/sparkline/Sparkline.js +164 -0
  212. package/esm/sparkline/SparklineArea.js +19 -0
  213. package/esm/sparkline/SparklineAreaPattern.js +38 -0
  214. package/esm/sparkline/SparklineGradient.js +76 -0
  215. package/esm/sparkline/__figma__/Sparkline.figma.js +22 -0
  216. package/esm/sparkline/__stories__/Sparkline.stories.js +120 -0
  217. package/esm/sparkline/__stories__/SparklineGradient.stories.js +123 -0
  218. package/esm/sparkline/generateSparklineWithId.js +7 -0
  219. package/esm/sparkline/index.js +5 -0
  220. package/esm/sparkline/sparkline-interactive/SparklineAccessibleView.js +75 -0
  221. package/esm/sparkline/sparkline-interactive/SparklineInteractive.js +307 -0
  222. package/esm/sparkline/sparkline-interactive/SparklineInteractiveAnimatedPath.js +116 -0
  223. package/esm/sparkline/sparkline-interactive/SparklineInteractiveHoverDate.js +131 -0
  224. package/esm/sparkline/sparkline-interactive/SparklineInteractiveLineVertical.js +99 -0
  225. package/esm/sparkline/sparkline-interactive/SparklineInteractiveMarkerDates.js +82 -0
  226. package/esm/sparkline/sparkline-interactive/SparklineInteractiveMinMax.js +103 -0
  227. package/esm/sparkline/sparkline-interactive/SparklineInteractivePanGestureHandler.js +104 -0
  228. package/esm/sparkline/sparkline-interactive/SparklineInteractivePaths.js +57 -0
  229. package/esm/sparkline/sparkline-interactive/SparklineInteractivePeriodSelector.js +124 -0
  230. package/esm/sparkline/sparkline-interactive/SparklineInteractiveProvider.js +80 -0
  231. package/esm/sparkline/sparkline-interactive/SparklineInteractiveTimeseriesPaths.js +109 -0
  232. package/esm/sparkline/sparkline-interactive/__figma__/SparklineInteractive.figma.js +85 -0
  233. package/esm/sparkline/sparkline-interactive/__stories__/SparklineInteractive.stories.js +501 -0
  234. package/esm/sparkline/sparkline-interactive/useInterruptiblePathAnimation.js +58 -0
  235. package/esm/sparkline/sparkline-interactive/useInterruptiblePathAnimation.test.disable.js +37 -0
  236. package/esm/sparkline/sparkline-interactive/useMinMaxTransform.js +56 -0
  237. package/esm/sparkline/sparkline-interactive/useOpacityAnimation.js +23 -0
  238. package/esm/sparkline/sparkline-interactive/useSparklineInteractiveConstants.js +47 -0
  239. package/esm/sparkline/sparkline-interactive/useSparklineInteractiveLineStyles.js +34 -0
  240. package/esm/sparkline/sparkline-interactive-header/SparklineInteractiveHeader.js +233 -0
  241. package/esm/sparkline/sparkline-interactive-header/__figma__/SparklineInteractiveHeader.figma.js +104 -0
  242. package/esm/sparkline/sparkline-interactive-header/__stories__/SparklineInteractiveHeader.stories.js +555 -0
  243. package/esm/sparkline/sparkline-interactive-header/useSparklineInteractiveHeaderStyles.js +117 -0
  244. package/package.json +65 -6
  245. package/index.js +0 -1
@@ -0,0 +1,514 @@
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, useMemo } from 'react';
3
+ import { useTheme } from '@coinbase/cds-mobile/hooks/useTheme';
4
+ import { useCartesianChartContext } from '../ChartProvider';
5
+ import { Bar } from './Bar';
6
+ import { DefaultBarStack } from './DefaultBarStack';
7
+ import { jsx as _jsx } from "react/jsx-runtime";
8
+ /**
9
+ * BarStack component that renders a single stack of bars at a specific category index.
10
+ * Handles the stacking logic for bars within a single category.
11
+ */
12
+ export const BarStack = /*#__PURE__*/memo(_ref => {
13
+ let {
14
+ series,
15
+ categoryIndex,
16
+ x,
17
+ width,
18
+ yScale,
19
+ rect,
20
+ BarComponent: defaultBarComponent,
21
+ fillOpacity: defaultFillOpacity,
22
+ stroke: defaultStroke,
23
+ strokeWidth: defaultStrokeWidth,
24
+ borderRadius = 4,
25
+ BarStackComponent = DefaultBarStack,
26
+ stackGap,
27
+ barMinSize,
28
+ stackMinSize,
29
+ roundBaseline
30
+ } = _ref;
31
+ const theme = useTheme();
32
+ const {
33
+ getSeriesData,
34
+ getXAxis
35
+ } = useCartesianChartContext();
36
+ const xAxis = getXAxis();
37
+ const baseline = useMemo(() => {
38
+ var _yScale;
39
+ const domain = yScale.domain();
40
+ const [domainMin, domainMax] = domain;
41
+ const baselineValue = domainMin >= 0 ? domainMin : domainMax <= 0 ? domainMax : 0;
42
+ const baseline = (_yScale = yScale(baselineValue)) != null ? _yScale : rect.y + rect.height;
43
+ return Math.max(rect.y, Math.min(baseline, rect.y + rect.height));
44
+ }, [rect.height, rect.y, yScale]);
45
+
46
+ // Calculate bars for this specific category
47
+ const {
48
+ bars,
49
+ stackRect
50
+ } = useMemo(() => {
51
+ let allBars = [];
52
+
53
+ // Track how many bars we've stacked in each direction for gap calculation
54
+ let positiveBarCount = 0;
55
+ let negativeBarCount = 0;
56
+
57
+ // Track stack bounds for clipping
58
+ let minY = Infinity;
59
+ let maxY = -Infinity;
60
+
61
+ // Process each series in the stack
62
+ series.forEach(s => {
63
+ var _yScale2, _yScale3;
64
+ const data = getSeriesData(s.id);
65
+ if (!data) return;
66
+ const value = data[categoryIndex];
67
+ if (value === null || value === undefined) return;
68
+ const originalData = s.data;
69
+ const originalValue = originalData == null ? void 0 : originalData[categoryIndex];
70
+ // Only apply gap logic if the original data wasn't tuple format
71
+ const shouldApplyGap = !Array.isArray(originalValue);
72
+
73
+ // Sort to be in ascending order
74
+ const [bottom, top] = value.sort((a, b) => a - b);
75
+ const isAboveBaseline = bottom >= 0 && top !== bottom;
76
+ const isBelowBaseline = bottom <= 0 && bottom !== top;
77
+ const barBottom = (_yScale2 = yScale(bottom)) != null ? _yScale2 : baseline;
78
+ const barTop = (_yScale3 = yScale(top)) != null ? _yScale3 : baseline;
79
+
80
+ // Track bar counts for later gap calculations
81
+ if (shouldApplyGap) {
82
+ if (isAboveBaseline) {
83
+ positiveBarCount++;
84
+ } else if (isBelowBaseline) {
85
+ negativeBarCount++;
86
+ }
87
+ }
88
+
89
+ // Calculate height (remember SVG y coordinates are inverted)
90
+ const height = Math.abs(barBottom - barTop);
91
+ const y = Math.min(barBottom, barTop);
92
+
93
+ // Skip bars that would have zero or negative height
94
+ if (height <= 0) {
95
+ return;
96
+ }
97
+
98
+ // Update stack bounds
99
+ minY = Math.min(minY, y);
100
+ maxY = Math.max(maxY, y + height);
101
+ allBars.push({
102
+ seriesId: s.id,
103
+ x,
104
+ y,
105
+ width,
106
+ height,
107
+ dataY: value,
108
+ // Store the actual data value
109
+ // Use series-specific properties, falling back to defaults
110
+ BarComponent: s.BarComponent,
111
+ fill: s.fill || s.color || theme.color.fgPrimary,
112
+ fillOpacity: s.fillOpacity,
113
+ stroke: s.stroke,
114
+ strokeWidth: s.strokeWidth,
115
+ // Pass context data for custom components
116
+ roundTop: roundBaseline || barTop !== baseline,
117
+ roundBottom: roundBaseline || barBottom !== baseline,
118
+ shouldApplyGap
119
+ });
120
+ });
121
+
122
+ // Apply proportional gap distribution to maintain total stack height
123
+ if (stackGap && allBars.length > 1) {
124
+ // Separate bars by baseline side
125
+ const barsAboveBaseline = allBars.filter(bar => {
126
+ const [bottom, top] = bar.dataY.sort((a, b) => a - b);
127
+ return bottom >= 0 && top !== bottom && bar.shouldApplyGap;
128
+ });
129
+ const barsBelowBaseline = allBars.filter(bar => {
130
+ const [bottom, top] = bar.dataY.sort((a, b) => a - b);
131
+ return bottom <= 0 && bottom !== top && bar.shouldApplyGap;
132
+ });
133
+
134
+ // Apply proportional gaps to bars above baseline
135
+ if (barsAboveBaseline.length > 1) {
136
+ const totalGapSpace = stackGap * (barsAboveBaseline.length - 1);
137
+ const totalDataHeight = barsAboveBaseline.reduce((sum, bar) => sum + bar.height, 0);
138
+ const heightReduction = totalGapSpace / totalDataHeight;
139
+
140
+ // Sort bars by position (from baseline upward)
141
+ const sortedBars = barsAboveBaseline.sort((a, b) => b.y - a.y);
142
+ let currentY = baseline;
143
+ sortedBars.forEach((bar, index) => {
144
+ // Reduce bar height proportionally
145
+ const newHeight = bar.height * (1 - heightReduction);
146
+ const newY = currentY - newHeight;
147
+
148
+ // Update the bar in allBars array
149
+ const barIndex = allBars.findIndex(b => b.seriesId === bar.seriesId);
150
+ if (barIndex !== -1) {
151
+ allBars[barIndex] = _extends({}, allBars[barIndex], {
152
+ height: newHeight,
153
+ y: newY
154
+ });
155
+ }
156
+
157
+ // Move to next position (include gap for next bar)
158
+ currentY = newY - (index < sortedBars.length - 1 ? stackGap : 0);
159
+ });
160
+ }
161
+
162
+ // Apply proportional gaps to bars below baseline
163
+ if (barsBelowBaseline.length > 1) {
164
+ const totalGapSpace = stackGap * (barsBelowBaseline.length - 1);
165
+ const totalDataHeight = barsBelowBaseline.reduce((sum, bar) => sum + bar.height, 0);
166
+ const heightReduction = totalGapSpace / totalDataHeight;
167
+
168
+ // Sort bars by position (from baseline downward)
169
+ const sortedBars = barsBelowBaseline.sort((a, b) => a.y - b.y);
170
+ let currentY = baseline;
171
+ sortedBars.forEach((bar, index) => {
172
+ // Reduce bar height proportionally
173
+ const newHeight = bar.height * (1 - heightReduction);
174
+
175
+ // Update the bar in allBars array
176
+ const barIndex = allBars.findIndex(b => b.seriesId === bar.seriesId);
177
+ if (barIndex !== -1) {
178
+ allBars[barIndex] = _extends({}, allBars[barIndex], {
179
+ height: newHeight,
180
+ y: currentY
181
+ });
182
+ }
183
+
184
+ // Move to next position (include gap for next bar)
185
+ currentY = currentY + newHeight + (index < sortedBars.length - 1 ? stackGap : 0);
186
+ });
187
+ }
188
+
189
+ // Recalculate stack bounds after gap adjustments
190
+ if (allBars.length > 0) {
191
+ minY = Math.min(...allBars.map(bar => bar.y));
192
+ maxY = Math.max(...allBars.map(bar => bar.y + bar.height));
193
+ }
194
+ }
195
+
196
+ // Apply barMinSize constraints
197
+ if (barMinSize) {
198
+ // First, expand bars that need it and track the expansion
199
+ const expandedBars = allBars.map((bar, index) => {
200
+ if (bar.height < barMinSize) {
201
+ var _yScale4, _yScale5, _yScale6, _yScale7;
202
+ const heightIncrease = barMinSize - bar.height;
203
+ const bottom = 0;
204
+ const top = 0;
205
+
206
+ // Determine how to expand the bar
207
+ let newBottom = bottom;
208
+ let newTop = top;
209
+ const scaleUnit = Math.abs(((_yScale4 = yScale(1)) != null ? _yScale4 : 0) - ((_yScale5 = yScale(0)) != null ? _yScale5 : 0));
210
+ if (bottom === 0) {
211
+ // Expand away from baseline (upward for positive)
212
+ newTop = top + heightIncrease / scaleUnit;
213
+ } else if (top === 0) {
214
+ // Expand away from baseline (downward for negative)
215
+ newBottom = bottom - heightIncrease / scaleUnit;
216
+ } else {
217
+ // Expand in both directions
218
+ const halfIncrease = heightIncrease / scaleUnit / 2;
219
+ newBottom = bottom - halfIncrease;
220
+ newTop = top + halfIncrease;
221
+ }
222
+
223
+ // Recalculate bar position with new data values
224
+ const newBarBottom = (_yScale6 = yScale(newBottom)) != null ? _yScale6 : baseline;
225
+ const newBarTop = (_yScale7 = yScale(newTop)) != null ? _yScale7 : baseline;
226
+ const newHeight = Math.abs(newBarBottom - newBarTop);
227
+ const newY = Math.min(newBarBottom, newBarTop);
228
+ return _extends({}, bar, {
229
+ height: newHeight,
230
+ y: newY,
231
+ wasExpanded: true
232
+ });
233
+ }
234
+ return _extends({}, bar, {
235
+ wasExpanded: false
236
+ });
237
+ });
238
+
239
+ // Now reposition all bars to avoid overlaps, similar to stackMinSize logic
240
+
241
+ // Sort bars by position to maintain order
242
+ const sortedExpandedBars = [...expandedBars].sort((a, b) => a.y - b.y);
243
+
244
+ // Determine if we have bars above and below baseline
245
+ const barsAboveBaseline = sortedExpandedBars.filter(bar => bar.y + bar.height <= baseline);
246
+ const barsBelowBaseline = sortedExpandedBars.filter(bar => bar.y >= baseline);
247
+
248
+ // Create a map of new positions
249
+ const newPositions = new Map();
250
+
251
+ // Start positioning from the baseline and work outward
252
+ let currentYAbove = baseline; // Start at baseline, work upward (decreasing Y)
253
+ let currentYBelow = baseline; // Start at baseline, work downward (increasing Y)
254
+
255
+ // Position bars above baseline (positive values, decreasing Y)
256
+ for (let i = barsAboveBaseline.length - 1; i >= 0; i--) {
257
+ const bar = barsAboveBaseline[i];
258
+ const newY = currentYAbove - bar.height;
259
+ newPositions.set(bar.seriesId, {
260
+ y: newY,
261
+ height: bar.height
262
+ });
263
+
264
+ // Update currentYAbove for next bar (preserve gaps)
265
+ if (i > 0) {
266
+ const currentBar = barsAboveBaseline[i];
267
+ const nextBar = barsAboveBaseline[i - 1];
268
+ // Find original bars to get original gap
269
+ const originalCurrent = allBars.find(b => b.seriesId === currentBar.seriesId);
270
+ const originalNext = allBars.find(b => b.seriesId === nextBar.seriesId);
271
+ const originalGap = originalCurrent.y - (originalNext.y + originalNext.height);
272
+ currentYAbove = newY - originalGap;
273
+ }
274
+ }
275
+
276
+ // Position bars below baseline (negative values, increasing Y)
277
+ for (let i = 0; i < barsBelowBaseline.length; i++) {
278
+ const bar = barsBelowBaseline[i];
279
+ const newY = currentYBelow;
280
+ newPositions.set(bar.seriesId, {
281
+ y: newY,
282
+ height: bar.height
283
+ });
284
+
285
+ // Update currentYBelow for next bar (preserve gaps)
286
+ if (i < barsBelowBaseline.length - 1) {
287
+ const currentBar = barsBelowBaseline[i];
288
+ const nextBar = barsBelowBaseline[i + 1];
289
+ // Find original bars to get original gap
290
+ const originalCurrent = allBars.find(b => b.seriesId === currentBar.seriesId);
291
+ const originalNext = allBars.find(b => b.seriesId === nextBar.seriesId);
292
+ const originalGap = originalNext.y - (originalCurrent.y + originalCurrent.height);
293
+ currentYBelow = newY + bar.height + originalGap;
294
+ }
295
+ }
296
+
297
+ // Apply new positions to all bars
298
+ allBars = expandedBars.map(bar => {
299
+ const newPos = newPositions.get(bar.seriesId);
300
+ if (newPos) {
301
+ return _extends({}, bar, {
302
+ y: newPos.y,
303
+ height: newPos.height
304
+ });
305
+ }
306
+ return bar;
307
+ });
308
+
309
+ // Recalculate stack bounds after barMinSize expansion and repositioning
310
+ if (allBars.length > 0) {
311
+ minY = Math.min(...allBars.map(bar => bar.y));
312
+ maxY = Math.max(...allBars.map(bar => bar.y + bar.height));
313
+ }
314
+ }
315
+
316
+ // Apply border radius logic (will be reapplied after stackMinSize if needed)
317
+ const applyBorderRadiusLogic = bars => {
318
+ return bars.sort((a, b) => b.y - a.y).map((a, index) => {
319
+ const barBefore = index > 0 ? bars[index - 1] : null;
320
+ const barAfter = index < bars.length - 1 ? bars[index + 1] : null;
321
+ const shouldRoundTop = index === bars.length - 1 || a.shouldApplyGap && stackGap || !a.shouldApplyGap && barAfter && barAfter.y + barAfter.height !== a.y;
322
+ const shouldRoundBottom = index === 0 || a.shouldApplyGap && stackGap || !a.shouldApplyGap && barBefore && barBefore.y !== a.y + a.height;
323
+ return _extends({}, a, {
324
+ roundTop: Boolean(a.roundTop && shouldRoundTop),
325
+ roundBottom: Boolean(a.roundBottom && shouldRoundBottom)
326
+ });
327
+ });
328
+ };
329
+ allBars = applyBorderRadiusLogic(allBars);
330
+
331
+ // Calculate the bounding rect for the entire stack
332
+ let stackBounds = {
333
+ x,
334
+ y: minY === Infinity ? baseline : minY,
335
+ width,
336
+ height: maxY === -Infinity ? 0 : maxY - minY
337
+ };
338
+
339
+ // Apply stackMinSize constraints
340
+ if (stackMinSize) {
341
+ if (allBars.length === 1 && stackBounds.height < stackMinSize) {
342
+ var _yScale8, _yScale9, _yScale0, _yScale1;
343
+ // For single bars (non-stacked), treat stackMinSize like barMinSize
344
+
345
+ const bar = allBars[0];
346
+ const heightIncrease = stackMinSize - bar.height;
347
+ const bottom = 0;
348
+ const top = 0;
349
+
350
+ // Determine how to expand the bar (same logic as barMinSize)
351
+ let newBottom = bottom;
352
+ let newTop = top;
353
+ const scaleUnit = Math.abs(((_yScale8 = yScale(1)) != null ? _yScale8 : 0) - ((_yScale9 = yScale(0)) != null ? _yScale9 : 0));
354
+ if (bottom === 0) {
355
+ // Expand away from baseline (upward for positive)
356
+ newTop = top + heightIncrease / scaleUnit;
357
+ } else if (top === 0) {
358
+ // Expand away from baseline (downward for negative)
359
+ newBottom = bottom - heightIncrease / scaleUnit;
360
+ } else {
361
+ // Expand in both directions
362
+ const halfIncrease = heightIncrease / scaleUnit / 2;
363
+ newBottom = bottom - halfIncrease;
364
+ newTop = top + halfIncrease;
365
+ }
366
+
367
+ // Recalculate bar position with new data values
368
+ const newBarBottom = (_yScale0 = yScale(newBottom)) != null ? _yScale0 : baseline;
369
+ const newBarTop = (_yScale1 = yScale(newTop)) != null ? _yScale1 : baseline;
370
+ const newHeight = Math.abs(newBarBottom - newBarTop);
371
+ const newY = Math.min(newBarBottom, newBarTop);
372
+ allBars[0] = _extends({}, bar, {
373
+ height: newHeight,
374
+ y: newY
375
+ });
376
+
377
+ // Recalculate stack bounds
378
+ stackBounds = {
379
+ x,
380
+ y: newY,
381
+ width,
382
+ height: newHeight
383
+ };
384
+ } else if (allBars.length > 1 && stackBounds.height < stackMinSize) {
385
+ // For multiple bars (stacked), scale heights while preserving gaps
386
+
387
+ // Calculate total bar height (excluding gaps)
388
+ const totalBarHeight = allBars.reduce((sum, bar) => sum + bar.height, 0);
389
+ const totalGapHeight = stackBounds.height - totalBarHeight;
390
+
391
+ // Calculate how much we need to increase bar heights
392
+ const requiredBarHeight = stackMinSize - totalGapHeight;
393
+ const barScaleFactor = requiredBarHeight / totalBarHeight;
394
+
395
+ // Sort bars by position to maintain order
396
+ const sortedBars = [...allBars].sort((a, b) => a.y - b.y);
397
+
398
+ // Determine if we have bars above and below baseline
399
+ const barsAboveBaseline = sortedBars.filter(bar => bar.y + bar.height <= baseline);
400
+ const barsBelowBaseline = sortedBars.filter(bar => bar.y >= baseline);
401
+
402
+ // Create a map of new positions
403
+ const newPositions = new Map();
404
+
405
+ // Start positioning from the baseline and work outward
406
+ let currentYAbove = baseline; // Start at baseline, work upward (decreasing Y)
407
+ let currentYBelow = baseline; // Start at baseline, work downward (increasing Y)
408
+
409
+ // Position bars above baseline (positive values, decreasing Y)
410
+ for (let i = barsAboveBaseline.length - 1; i >= 0; i--) {
411
+ const bar = barsAboveBaseline[i];
412
+ const newHeight = bar.height * barScaleFactor;
413
+ const newY = currentYAbove - newHeight;
414
+ newPositions.set(bar.seriesId, {
415
+ y: newY,
416
+ height: newHeight
417
+ });
418
+
419
+ // Update currentYAbove for next bar (preserve gaps)
420
+ if (i > 0) {
421
+ const currentBar = barsAboveBaseline[i];
422
+ const nextBar = barsAboveBaseline[i - 1];
423
+ const originalGap = currentBar.y - (nextBar.y + nextBar.height);
424
+ currentYAbove = newY - originalGap;
425
+ }
426
+ }
427
+
428
+ // Position bars below baseline (negative values, increasing Y)
429
+ for (let i = 0; i < barsBelowBaseline.length; i++) {
430
+ const bar = barsBelowBaseline[i];
431
+ const newHeight = bar.height * barScaleFactor;
432
+ const newY = currentYBelow;
433
+ newPositions.set(bar.seriesId, {
434
+ y: newY,
435
+ height: newHeight
436
+ });
437
+
438
+ // Update currentYBelow for next bar (preserve gaps)
439
+ if (i < barsBelowBaseline.length - 1) {
440
+ const currentBar = barsBelowBaseline[i];
441
+ const nextBar = barsBelowBaseline[i + 1];
442
+ const originalGap = nextBar.y - (currentBar.y + currentBar.height);
443
+ currentYBelow = newY + newHeight + originalGap;
444
+ }
445
+ }
446
+
447
+ // Apply new positions to all bars
448
+ allBars = allBars.map(bar => {
449
+ const newPos = newPositions.get(bar.seriesId);
450
+ if (!newPos) return bar;
451
+ return _extends({}, bar, {
452
+ height: newPos.height,
453
+ y: newPos.y
454
+ });
455
+ });
456
+
457
+ // Recalculate stack bounds
458
+ const newMinY = Math.min(...allBars.map(bar => bar.y));
459
+ const newMaxY = Math.max(...allBars.map(bar => bar.y + bar.height));
460
+ stackBounds = {
461
+ x,
462
+ y: newMinY,
463
+ width,
464
+ height: newMaxY - newMinY
465
+ };
466
+ }
467
+
468
+ // Reapply border radius logic only if we actually scaled
469
+ if (stackBounds.height < stackMinSize) {
470
+ allBars = applyBorderRadiusLogic(allBars);
471
+ }
472
+ }
473
+ return {
474
+ bars: allBars,
475
+ stackRect: stackBounds
476
+ };
477
+ }, [series, x, width, getSeriesData, categoryIndex, roundBaseline, baseline, stackGap, barMinSize, stackMinSize, yScale, theme.color.fgPrimary]);
478
+ const xData = xAxis != null && xAxis.data && Array.isArray(xAxis.data) && typeof xAxis.data[0] === 'number' ? xAxis.data : undefined;
479
+ const dataX = xData ? xData[categoryIndex] : categoryIndex;
480
+ const barElements = bars.map((bar, index) => {
481
+ var _bar$fillOpacity, _bar$stroke, _bar$strokeWidth;
482
+ return /*#__PURE__*/_jsx(Bar, {
483
+ BarComponent: bar.BarComponent || defaultBarComponent,
484
+ borderRadius: borderRadius,
485
+ dataX: dataX,
486
+ dataY: bar.dataY,
487
+ fill: bar.fill,
488
+ fillOpacity: (_bar$fillOpacity = bar.fillOpacity) != null ? _bar$fillOpacity : defaultFillOpacity,
489
+ height: bar.height,
490
+ originY: baseline,
491
+ roundBottom: bar.roundBottom,
492
+ roundTop: bar.roundTop,
493
+ stroke: (_bar$stroke = bar.stroke) != null ? _bar$stroke : defaultStroke,
494
+ strokeWidth: (_bar$strokeWidth = bar.strokeWidth) != null ? _bar$strokeWidth : defaultStrokeWidth,
495
+ width: bar.width,
496
+ x: bar.x,
497
+ y: bar.y
498
+ }, bar.seriesId + "-" + categoryIndex + "-" + index);
499
+ });
500
+ const stackRoundBottom = roundBaseline || stackRect.y + stackRect.height !== baseline;
501
+ const stackRoundTop = roundBaseline || stackRect.y !== baseline;
502
+ return /*#__PURE__*/_jsx(BarStackComponent, {
503
+ borderRadius: borderRadius,
504
+ categoryIndex: categoryIndex,
505
+ height: stackRect.height,
506
+ roundBottom: stackRoundBottom,
507
+ roundTop: stackRoundTop,
508
+ width: stackRect.width,
509
+ x: stackRect.x,
510
+ y: stackRect.y,
511
+ yOrigin: baseline,
512
+ children: barElements
513
+ });
514
+ });
@@ -0,0 +1,89 @@
1
+ const _excluded = ["series", "yAxisId", "stackIndex", "totalStacks", "barPadding"];
2
+ 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); }
3
+ 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; }
4
+ import { memo, useMemo, createElement as _createElement } from 'react';
5
+ import { useCartesianChartContext } from '../ChartProvider';
6
+ import { defaultAxisId, getBarSizeAdjustment, isCategoricalScale } from '../utils';
7
+ import { BarStack } from './BarStack';
8
+ /**
9
+ * BarStackGroup component that renders a group of stacks across all categories.
10
+ * Delegates the actual stacking logic to BarStack for each category.
11
+ */
12
+ export const BarStackGroup = /*#__PURE__*/memo(_ref => {
13
+ let {
14
+ series,
15
+ yAxisId = defaultAxisId,
16
+ stackIndex,
17
+ totalStacks,
18
+ barPadding = 0.1
19
+ } = _ref,
20
+ props = _objectWithoutPropertiesLoose(_ref, _excluded);
21
+ const {
22
+ getSeriesData,
23
+ getXScale,
24
+ getYScale,
25
+ drawingArea
26
+ } = useCartesianChartContext();
27
+ const xScale = getXScale();
28
+ const yScale = getYScale(yAxisId);
29
+ const maxDataLength = useMemo(() => {
30
+ if (!series || series.length === 0) return 0;
31
+ let maxLength = 0;
32
+ series.forEach(s => {
33
+ const data = getSeriesData(s.id);
34
+ if (data && data.length > maxLength) {
35
+ maxLength = data.length;
36
+ }
37
+ });
38
+ return maxLength;
39
+ }, [series, getSeriesData]);
40
+ const stackConfigs = useMemo(() => {
41
+ if (!xScale || !yScale || !drawingArea || maxDataLength === 0) return [];
42
+ if (!isCategoricalScale(xScale)) {
43
+ return [];
44
+ }
45
+ const categoryWidth = xScale.bandwidth();
46
+
47
+ // Calculate width for each stack within a category
48
+ // Only apply barPadding when there are multiple stacks
49
+ const gapWidth = totalStacks > 1 ? categoryWidth * barPadding / (totalStacks - 1) : 0;
50
+ const barWidth = categoryWidth / totalStacks - getBarSizeAdjustment(totalStacks, gapWidth);
51
+ const configs = [];
52
+
53
+ // Calculate position for each category
54
+ for (let categoryIndex = 0; categoryIndex < maxDataLength; categoryIndex++) {
55
+ // Get x position for this category
56
+ const categoryX = xScale(categoryIndex);
57
+ if (categoryX !== undefined) {
58
+ // Calculate x position for this specific stack within the category
59
+ const stackX = categoryX + stackIndex * (barWidth + gapWidth);
60
+ configs.push({
61
+ categoryIndex,
62
+ x: stackX,
63
+ width: barWidth
64
+ });
65
+ }
66
+ }
67
+ return configs;
68
+ }, [xScale, yScale, drawingArea, maxDataLength, stackIndex, totalStacks, barPadding]);
69
+ if (xScale && !isCategoricalScale(xScale)) {
70
+ throw new Error('BarStackGroup requires a band scale for x-axis. See https://cds.coinbase.com/components/graphs/XAxis/#scale-type');
71
+ }
72
+ if (!yScale || !drawingArea || stackConfigs.length === 0) return;
73
+ return stackConfigs.map(_ref2 => {
74
+ let {
75
+ categoryIndex,
76
+ x,
77
+ width
78
+ } = _ref2;
79
+ return /*#__PURE__*/_createElement(BarStack, _extends({}, props, {
80
+ key: "stack-" + stackIndex + "-category-" + categoryIndex,
81
+ categoryIndex: categoryIndex,
82
+ rect: drawingArea,
83
+ series: series,
84
+ width: width,
85
+ x: x,
86
+ yScale: yScale
87
+ }));
88
+ });
89
+ });
@@ -0,0 +1,78 @@
1
+ import { memo, useCallback, useEffect, useMemo, useRef } from 'react';
2
+ import { runOnJS, useAnimatedReaction, useSharedValue, withTiming } from 'react-native-reanimated';
3
+ import { Path } from 'react-native-svg';
4
+ import { usePreviousValue } from '@coinbase/cds-common/hooks/usePreviousValue';
5
+ import { useTheme } from '@coinbase/cds-mobile/hooks/useTheme';
6
+ import * as interpolate from 'd3-interpolate-path';
7
+ import { useCartesianChartContext } from '../ChartProvider';
8
+ import { getBarPath } from '../utils';
9
+ import { jsx as _jsx } from "react/jsx-runtime";
10
+ /**
11
+ * Default bar component that renders a solid bar with animation.
12
+ */
13
+ export const DefaultBar = /*#__PURE__*/memo(_ref => {
14
+ let {
15
+ x,
16
+ y,
17
+ width,
18
+ height,
19
+ borderRadius,
20
+ roundTop,
21
+ roundBottom,
22
+ d,
23
+ fill,
24
+ fillOpacity = 1,
25
+ stroke,
26
+ strokeWidth
27
+ } = _ref;
28
+ const pathRef = useRef(null);
29
+ const {
30
+ animate
31
+ } = useCartesianChartContext();
32
+ const theme = useTheme();
33
+ const animationProgress = useSharedValue(0);
34
+ const targetPath = useMemo(() => {
35
+ return d || getBarPath(x, y, width, height, borderRadius != null ? borderRadius : 0, roundTop != null ? roundTop : true, roundBottom != null ? roundBottom : true);
36
+ }, [d, x, y, width, height, borderRadius, roundTop, roundBottom]);
37
+ const previousPath = usePreviousValue(targetPath);
38
+ const fromPath = useMemo(() => {
39
+ if (!animate) return targetPath;
40
+ return previousPath || targetPath;
41
+ }, [animate, previousPath, targetPath]);
42
+ const pathInterpolator = useMemo(() => interpolate.interpolatePath(fromPath, targetPath), [fromPath, targetPath]);
43
+ const updatePath = useCallback(progress => {
44
+ var _pathRef$current;
45
+ const val = Number(progress.toFixed(4));
46
+ (_pathRef$current = pathRef.current) == null || _pathRef$current.setNativeProps({
47
+ d: pathInterpolator(val)
48
+ });
49
+ }, [pathInterpolator]);
50
+ const defaultFill = fill || theme.color.fgPrimary;
51
+ useAnimatedReaction(() => animationProgress.value, progress => {
52
+ 'worklet';
53
+
54
+ runOnJS(updatePath)(progress);
55
+ }, [updatePath]);
56
+ useEffect(() => {
57
+ if (!pathRef.current) return;
58
+ if (!animate) {
59
+ pathRef.current.setNativeProps({
60
+ d: targetPath
61
+ });
62
+ animationProgress.value = 1;
63
+ return;
64
+ }
65
+ animationProgress.value = 0;
66
+ animationProgress.value = withTiming(1, {
67
+ duration: 200
68
+ });
69
+ }, [animate, animationProgress, targetPath]);
70
+ return /*#__PURE__*/_jsx(Path, {
71
+ ref: pathRef,
72
+ d: fromPath,
73
+ fill: defaultFill,
74
+ fillOpacity: fillOpacity,
75
+ stroke: stroke,
76
+ strokeWidth: strokeWidth
77
+ });
78
+ });