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

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 +122 -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 +220 -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,178 @@
1
+ import {
2
+ type ExtrapolationType,
3
+ type SharedValue,
4
+ type WithSpringConfig,
5
+ type WithTimingConfig,
6
+ } from 'react-native-reanimated';
7
+ import { type SkPath } from '@shopify/react-native-skia';
8
+ /**
9
+ * Transition for animations.
10
+ * Supports timing and spring animation types.
11
+ * Used for paths, positions, opacity, and any other animated properties.
12
+ *
13
+ * @example
14
+ * // Spring animation
15
+ * { type: 'spring', damping: 10, stiffness: 100 }
16
+ *
17
+ * @example
18
+ * // Timing animation
19
+ * { type: 'timing', duration: 500, easing: Easing.inOut(Easing.ease) }
20
+ */
21
+ export type Transition = (
22
+ | ({
23
+ type: 'timing';
24
+ } & WithTimingConfig)
25
+ | ({
26
+ type: 'spring';
27
+ } & WithSpringConfig)
28
+ ) & {
29
+ /**
30
+ * Delay in milliseconds (ms) before the animation starts.
31
+ *
32
+ * @example
33
+ * // Wait 2 seconds before animating
34
+ * { type: 'timing', duration: 500, delay: 2000 }
35
+ */
36
+ delay?: number;
37
+ };
38
+ /**
39
+ * Default update transition used across all chart components.
40
+ * `{ type: 'spring', stiffness: 900, damping: 120 }`
41
+ */
42
+ export declare const defaultTransition: Transition;
43
+ /**
44
+ * Instant transition that completes immediately with no animation.
45
+ * Used when a transition is set to `null`.
46
+ */
47
+ export declare const instantTransition: Transition;
48
+ /**
49
+ * Duration in milliseconds for accessory elements to fade in.
50
+ */
51
+ export declare const accessoryFadeTransitionDuration = 150;
52
+ /**
53
+ * Delay in milliseconds before accessory elements fade in.
54
+ */
55
+ export declare const accessoryFadeTransitionDelay = 350;
56
+ /**
57
+ * Default enter transition for accessory elements (Point, Scrubber beacons).
58
+ * `{ type: 'timing', duration: 150, delay: 350 }`
59
+ */
60
+ export declare const defaultAccessoryEnterTransition: Transition;
61
+ /**
62
+ * Resolves a transition value based on the animation state and a default.
63
+ * @note Passing in null will disable an animation.
64
+ * @note Passing in undefined will use the provided default.
65
+ */
66
+ export declare const getTransition: (
67
+ value: Transition | null | undefined,
68
+ animate: boolean,
69
+ defaultValue: Transition,
70
+ ) => Transition;
71
+ /**
72
+ * @worklet
73
+ */
74
+ type Interpolator<T> = (
75
+ value: number,
76
+ input: number[],
77
+ output: T[],
78
+ options: ExtrapolationType,
79
+ result: T,
80
+ ) => T;
81
+ export declare const useInterpolator: <T>(
82
+ factory: () => T,
83
+ value: SharedValue<number>,
84
+ interpolator: Interpolator<T>,
85
+ input: number[],
86
+ output: T[],
87
+ options?: ExtrapolationType,
88
+ ) => SharedValue<T>;
89
+ /**
90
+ * Builds a react-native-reanimated animation based on the configuration.
91
+ *
92
+ * @param targetValue - The target value to animate to
93
+ * @param config - The transition configuration
94
+ * @returns The animation value to assign to a shared value
95
+ *
96
+ * @example
97
+ * // Use directly for animation
98
+ * progress.value = 0;
99
+ * progress.value = buildTransition(1, { type: 'spring', damping: 10, stiffness: 100 });
100
+ *
101
+ * @example
102
+ * // Coordinate animations
103
+ * animatedX.value = buildTransition(100, { type: 'spring', damping: 10, stiffness: 100 });
104
+ * animatedY.value = buildTransition(200, { type: 'spring', damping: 10, stiffness: 100 });
105
+ *
106
+ * @example
107
+ * // Timing animation
108
+ * progress.value = buildTransition(1, { type: 'timing', duration: 500 });
109
+ */
110
+ export declare const buildTransition: (targetValue: number, transition: Transition) => number;
111
+ /**
112
+ * Hook for path animation state and transitions.
113
+ *
114
+ * @param currentPath - Current target path to animate to
115
+ * @param initialPath - Initial path for enter animation. When provided, the first animation will go from initialPath to currentPath.
116
+ * @param transitions - Transition configuration for enter and update animations
117
+ * @returns Animated SkPath as a shared value
118
+ *
119
+ * @example
120
+ * // Simple path transition
121
+ * const path = usePathTransition({
122
+ * currentPath: d ?? '',
123
+ * transitions: {
124
+ * update: { type: 'timing', duration: 3000 },
125
+ * },
126
+ * });
127
+ *
128
+ * @example
129
+ * // Enter animation with different initial config (like DefaultBar)
130
+ * const path = usePathTransition({
131
+ * currentPath: targetPath,
132
+ * initialPath: baselinePath,
133
+ * transitions: {
134
+ * enter: { type: 'tween', duration: 500 },
135
+ * update: { type: 'spring', stiffness: 900, damping: 120 },
136
+ * },
137
+ * });
138
+ */
139
+ export declare const usePathTransition: ({
140
+ currentPath,
141
+ initialPath,
142
+ transitions,
143
+ transition,
144
+ }: {
145
+ /**
146
+ * Current target path to animate to.
147
+ */
148
+ currentPath: string;
149
+ /**
150
+ * Initial path for enter animation.
151
+ * When provided, the first animation will go from initialPath to currentPath.
152
+ * If not provided, defaults to currentPath (no enter animation).
153
+ */
154
+ initialPath?: string;
155
+ /**
156
+ * Transition configuration for enter and update animations.
157
+ */
158
+ transitions?: {
159
+ /**
160
+ * Transition for the initial enter animation (initialPath → currentPath).
161
+ * Only used when `initialPath` is provided.
162
+ * If not provided, falls back to `update`.
163
+ */
164
+ enter?: Transition;
165
+ /**
166
+ * Transition for subsequent data update animations.
167
+ * @default defaultTransition
168
+ */
169
+ update?: Transition;
170
+ };
171
+ /**
172
+ * Transition for updates.
173
+ * @deprecated Use `transitions.update` instead.
174
+ */
175
+ transition?: Transition;
176
+ }) => SharedValue<SkPath>;
177
+ export {};
178
+ //# sourceMappingURL=transition.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transition.d.ts","sourceRoot":"","sources":["../../../src/chart/utils/transition.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAKhB,KAAK,gBAAgB,EAErB,KAAK,gBAAgB,EACtB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAsB,KAAK,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAG7E;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,UAAU,GAAG,CACrB,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAAG,gBAAgB,CAAC,GACvC,CAAC;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAAG,gBAAgB,CAAC,CAC1C,GAAG;IACF;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,UAI/B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,UAG/B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,+BAA+B,MAAM,CAAC;AAEnD;;GAEG;AACH,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAEhD;;;GAGG;AACH,eAAO,MAAM,+BAA+B,EAAE,UAI7C,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,aAAa,GACxB,OAAO,UAAU,GAAG,IAAI,GAAG,SAAS,EACpC,SAAS,OAAO,EAChB,cAAc,UAAU,KACvB,UAGF,CAAC;AAGF;;GAEG;AACH,KAAK,YAAY,CAAC,CAAC,IAAI,CACrB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EAAE,EACf,MAAM,EAAE,CAAC,EAAE,EACX,OAAO,EAAE,iBAAiB,EAC1B,MAAM,EAAE,CAAC,KACN,CAAC,CAAC;AAEP,eAAO,MAAM,eAAe,GAAI,CAAC,EAC/B,SAAS,MAAM,CAAC,EAChB,OAAO,WAAW,CAAC,MAAM,CAAC,EAC1B,cAAc,YAAY,CAAC,CAAC,CAAC,EAC7B,OAAO,MAAM,EAAE,EACf,QAAQ,CAAC,EAAE,EACX,UAAU,iBAAiB,mBAc5B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,eAAe,GAAI,aAAa,MAAM,EAAE,YAAY,UAAU,KAAG,MAyB7E,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,eAAO,MAAM,iBAAiB,GAAI,wDAK/B;IACD;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,WAAW,CAAC,EAAE;QACZ;;;;WAIG;QACH,KAAK,CAAC,EAAE,UAAU,CAAC;QACnB;;;WAGG;QACH,MAAM,CAAC,EAAE,UAAU,CAAC;KACrB,CAAC;IACF;;;OAGG;IACH,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB,KAAG,WAAW,CAAC,MAAM,CAoErB,CAAC"}
@@ -1,40 +1,67 @@
1
- const _excluded = ["series", "animate", "enableScrubbing", "xAxis", "yAxis", "inset", "onScrubberPositionChange", "children", "width", "height", "style", "allowOverflowGestures"];
1
+ const _excluded = ["series", "children", "animate", "enableScrubbing", "xAxis", "yAxis", "inset", "onScrubberPositionChange", "legend", "legendPosition", "legendAccessibilityLabel", "width", "height", "style", "styles", "allowOverflowGestures", "fontFamilies", "fontProvider", "collapsable"];
2
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
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
4
  import React, { forwardRef, memo, useCallback, useMemo } from 'react';
5
- import { Svg } from 'react-native-svg';
6
5
  import { useLayout } from '@coinbase/cds-mobile/hooks/useLayout';
7
6
  import { Box } from '@coinbase/cds-mobile/layout';
7
+ import { Canvas, Skia } from '@shopify/react-native-skia';
8
8
  import { ScrubberProvider } from './scrubber/ScrubberProvider';
9
+ import { convertToSerializableScale } from './utils/scale';
10
+ import { useChartContextBridge } from './ChartContextBridge';
9
11
  import { CartesianChartProvider } from './ChartProvider';
12
+ import { Legend } from './legend';
10
13
  import { defaultAxisId, defaultChartInset, getAxisConfig, getAxisDomain, getAxisRange, getAxisScale, getChartInset, getStackedSeriesData as calculateStackedSeriesData, useTotalAxisPadding } from './utils';
11
- import { jsx as _jsx } from "react/jsx-runtime";
12
- export const CartesianChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, ref) => {
14
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
15
+ const ChartCanvas = /*#__PURE__*/memo(_ref => {
16
+ let {
17
+ children,
18
+ style
19
+ } = _ref;
20
+ const ContextBridge = useChartContextBridge();
21
+ return /*#__PURE__*/_jsx(Canvas, {
22
+ style: [{
23
+ width: '100%',
24
+ height: '100%'
25
+ }, style],
26
+ children: /*#__PURE__*/_jsx(ContextBridge, {
27
+ children: children
28
+ })
29
+ });
30
+ });
31
+ export const CartesianChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref2, ref) => {
13
32
  let {
14
33
  series,
34
+ children,
15
35
  animate = true,
16
36
  enableScrubbing,
17
- xAxis: xAxisConfigInput,
18
- yAxis: yAxisConfigInput,
19
- inset: insetInput,
37
+ xAxis: xAxisConfigProp,
38
+ yAxis: yAxisConfigProp,
39
+ inset,
20
40
  onScrubberPositionChange,
21
- children,
41
+ legend,
42
+ legendPosition = 'bottom',
43
+ legendAccessibilityLabel,
22
44
  width = '100%',
23
45
  height = '100%',
24
46
  style,
25
- allowOverflowGestures
26
- } = _ref,
27
- props = _objectWithoutPropertiesLoose(_ref, _excluded);
47
+ styles,
48
+ allowOverflowGestures,
49
+ fontFamilies,
50
+ fontProvider: fontProviderProp,
51
+ // React Native will collapse views by default when only used
52
+ // to group children, which interferes with gesture-handler
53
+ // https://docs.swmansion.com/react-native-gesture-handler/docs/gestures/gesture-detector/#:~:text=%7B%0A%20%20return%20%3C-,View,-collapsable%3D%7B
54
+ collapsable = false
55
+ } = _ref2,
56
+ props = _objectWithoutPropertiesLoose(_ref2, _excluded);
28
57
  const [containerLayout, onContainerLayout] = useLayout();
29
- const chartWidth = typeof width === 'number' ? width : containerLayout.width;
30
- const chartHeight = typeof height === 'number' ? height : containerLayout.height;
31
- const userInset = useMemo(() => {
32
- return getChartInset(insetInput, defaultChartInset);
33
- }, [insetInput]);
58
+ const chartWidth = containerLayout.width;
59
+ const chartHeight = containerLayout.height;
60
+ const calculatedInset = useMemo(() => getChartInset(inset, defaultChartInset), [inset]);
34
61
 
35
62
  // there can only be one x axis but the helper function always returns an array
36
- const xAxisConfig = useMemo(() => getAxisConfig('x', xAxisConfigInput)[0], [xAxisConfigInput]);
37
- const yAxisConfig = useMemo(() => getAxisConfig('y', yAxisConfigInput), [yAxisConfigInput]);
63
+ const xAxisConfig = useMemo(() => getAxisConfig('x', xAxisConfigProp)[0], [xAxisConfigProp]);
64
+ const yAxisConfig = useMemo(() => getAxisConfig('y', yAxisConfigProp), [yAxisConfigProp]);
38
65
  const {
39
66
  renderedAxes,
40
67
  registerAxis,
@@ -42,11 +69,11 @@ export const CartesianChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, r
42
69
  axisPadding
43
70
  } = useTotalAxisPadding();
44
71
  const totalInset = useMemo(() => ({
45
- top: userInset.top + axisPadding.top,
46
- right: userInset.right + axisPadding.right,
47
- bottom: userInset.bottom + axisPadding.bottom,
48
- left: userInset.left + axisPadding.left
49
- }), [userInset, axisPadding]);
72
+ top: calculatedInset.top + axisPadding.top,
73
+ right: calculatedInset.right + axisPadding.right,
74
+ bottom: calculatedInset.bottom + axisPadding.bottom,
75
+ left: calculatedInset.left + axisPadding.left
76
+ }), [calculatedInset, axisPadding]);
50
77
  const chartRect = useMemo(() => {
51
78
  if (chartWidth <= 0 || chartHeight <= 0) return {
52
79
  x: 0,
@@ -63,8 +90,14 @@ export const CartesianChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, r
63
90
  height: availableHeight > 0 ? availableHeight : 0
64
91
  };
65
92
  }, [chartHeight, chartWidth, totalInset]);
66
- const xAxis = useMemo(() => {
67
- if (!chartRect || chartRect.width <= 0 || chartRect.height <= 0) return undefined;
93
+ const {
94
+ xAxis,
95
+ xScale
96
+ } = useMemo(() => {
97
+ if (!chartRect || chartRect.width <= 0 || chartRect.height <= 0) return {
98
+ xAxis: undefined,
99
+ xScale: undefined
100
+ };
68
101
  const domain = getAxisDomain(xAxisConfig, series != null ? series : [], 'x');
69
102
  const range = getAxisRange(xAxisConfig, chartRect, 'x');
70
103
  const axisConfig = {
@@ -75,11 +108,47 @@ export const CartesianChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, r
75
108
  categoryPadding: xAxisConfig.categoryPadding,
76
109
  domainLimit: xAxisConfig.domainLimit
77
110
  };
78
- return axisConfig;
111
+
112
+ // Create the scale
113
+ const scale = getAxisScale({
114
+ config: axisConfig,
115
+ type: 'x',
116
+ range: axisConfig.range,
117
+ dataDomain: axisConfig.domain
118
+ });
119
+ if (!scale) return {
120
+ xAxis: undefined,
121
+ xScale: undefined
122
+ };
123
+
124
+ // Update axis config with actual scale domain (after .nice() or other adjustments)
125
+ const scaleDomain = scale.domain();
126
+ const actualDomain = Array.isArray(scaleDomain) && scaleDomain.length === 2 ? {
127
+ min: scaleDomain[0],
128
+ max: scaleDomain[1]
129
+ } : axisConfig.domain;
130
+ const finalAxisConfig = _extends({}, axisConfig, {
131
+ domain: actualDomain
132
+ });
133
+ return {
134
+ xAxis: finalAxisConfig,
135
+ xScale: scale
136
+ };
79
137
  }, [xAxisConfig, series, chartRect]);
80
- const yAxes = useMemo(() => {
138
+ const xSerializableScale = useMemo(() => {
139
+ if (!xScale) return;
140
+ return convertToSerializableScale(xScale);
141
+ }, [xScale]);
142
+ const {
143
+ yAxes,
144
+ yScales
145
+ } = useMemo(() => {
81
146
  const axes = new Map();
82
- if (!chartRect || chartRect.width <= 0 || chartRect.height <= 0) return axes;
147
+ const scales = new Map();
148
+ if (!chartRect || chartRect.width <= 0 || chartRect.height <= 0) return {
149
+ yAxes: axes,
150
+ yScales: scales
151
+ };
83
152
  yAxisConfig.forEach(axisParam => {
84
153
  var _axisParam$id, _series$filter, _axisParam$domainLimi;
85
154
  const axisId = (_axisParam$id = axisParam.id) != null ? _axisParam$id : defaultAxisId;
@@ -90,33 +159,19 @@ export const CartesianChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, r
90
159
  return ((_s$yAxisId = s.yAxisId) != null ? _s$yAxisId : defaultAxisId) === axisId;
91
160
  })) != null ? _series$filter : [];
92
161
 
93
- // Calculate domain and range in one pass
94
- const domain = getAxisDomain(axisParam, relevantSeries, 'y');
162
+ // Calculate domain and range
163
+ const dataDomain = getAxisDomain(axisParam, relevantSeries, 'y');
95
164
  const range = getAxisRange(axisParam, chartRect, 'y');
96
- axes.set(axisId, {
165
+ const axisConfig = {
97
166
  scaleType: axisParam.scaleType,
98
- domain,
167
+ domain: dataDomain,
99
168
  range,
100
169
  data: axisParam.data,
101
170
  categoryPadding: axisParam.categoryPadding,
102
171
  domainLimit: (_axisParam$domainLimi = axisParam.domainLimit) != null ? _axisParam$domainLimi : 'nice'
103
- });
104
- });
105
- return axes;
106
- }, [yAxisConfig, series, chartRect]);
107
- const xScale = useMemo(() => {
108
- if (!chartRect || chartRect.width <= 0 || chartRect.height <= 0 || xAxis === undefined) return undefined;
109
- return getAxisScale({
110
- config: xAxis,
111
- type: 'x',
112
- range: xAxis.range,
113
- dataDomain: xAxis.domain
114
- });
115
- }, [chartRect, xAxis]);
116
- const yScales = useMemo(() => {
117
- const scales = new Map();
118
- if (!chartRect || chartRect.width <= 0 || chartRect.height <= 0) return scales;
119
- yAxes.forEach((axisConfig, axisId) => {
172
+ };
173
+
174
+ // Create the scale
120
175
  const scale = getAxisScale({
121
176
  config: axisConfig,
122
177
  type: 'y',
@@ -125,17 +180,42 @@ export const CartesianChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, r
125
180
  });
126
181
  if (scale) {
127
182
  scales.set(axisId, scale);
183
+
184
+ // Update axis config with actual scale domain (after .nice() or other adjustments)
185
+ const scaleDomain = scale.domain();
186
+ const actualDomain = Array.isArray(scaleDomain) && scaleDomain.length === 2 ? {
187
+ min: scaleDomain[0],
188
+ max: scaleDomain[1]
189
+ } : axisConfig.domain;
190
+ axes.set(axisId, _extends({}, axisConfig, {
191
+ domain: actualDomain
192
+ }));
128
193
  }
129
194
  });
130
- return scales;
131
- }, [chartRect, yAxes]);
195
+ return {
196
+ yAxes: axes,
197
+ yScales: scales
198
+ };
199
+ }, [yAxisConfig, series, chartRect]);
200
+
201
+ // We need a set of serialized scales usable in UI thread
202
+ const ySerializableScales = useMemo(() => {
203
+ const serializableScales = new Map();
204
+ yScales.forEach((scale, id) => {
205
+ const serializableScale = convertToSerializableScale(scale);
206
+ if (serializableScale) {
207
+ serializableScales.set(id, serializableScale);
208
+ }
209
+ });
210
+ return serializableScales;
211
+ }, [yScales]);
132
212
  const getXAxis = useCallback(() => xAxis, [xAxis]);
133
213
  const getYAxis = useCallback(id => yAxes.get(id != null ? id : defaultAxisId), [yAxes]);
134
214
  const getXScale = useCallback(() => xScale, [xScale]);
135
215
  const getYScale = useCallback(id => yScales.get(id != null ? id : defaultAxisId), [yScales]);
216
+ const getXSerializableScale = useCallback(() => xSerializableScale, [xSerializableScale]);
217
+ const getYSerializableScale = useCallback(id => ySerializableScales.get(id != null ? id : defaultAxisId), [ySerializableScales]);
136
218
  const getSeries = useCallback(seriesId => series == null ? void 0 : series.find(s => s.id === seriesId), [series]);
137
-
138
- // Compute stacked data for series with stack properties
139
219
  const stackedDataMap = useMemo(() => {
140
220
  if (!series) return new Map();
141
221
  return calculateStackedSeriesData(series);
@@ -144,6 +224,20 @@ export const CartesianChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, r
144
224
  if (!seriesId) return undefined;
145
225
  return stackedDataMap.get(seriesId);
146
226
  }, [stackedDataMap]);
227
+ const dataLength = useMemo(() => {
228
+ // If xAxis has categorical data, use that length
229
+ if (xAxisConfig.data && xAxisConfig.data.length > 0) {
230
+ return xAxisConfig.data.length;
231
+ }
232
+
233
+ // Otherwise, find the longest series
234
+ if (!series || series.length === 0) return 0;
235
+ return series.reduce((max, s) => {
236
+ var _seriesData$length;
237
+ const seriesData = getStackedSeriesData(s.id);
238
+ return Math.max(max, (_seriesData$length = seriesData == null ? void 0 : seriesData.length) != null ? _seriesData$length : 0);
239
+ }, 0);
240
+ }, [xAxisConfig.data, series, getStackedSeriesData]);
147
241
  const getAxisBounds = useCallback(axisId => {
148
242
  const axis = renderedAxes.get(axisId);
149
243
  if (!axis || !chartRect) return;
@@ -155,7 +249,7 @@ export const CartesianChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, r
155
249
  const offsetFromPreviousAxes = axesAtPosition.slice(0, axisIndex).reduce((sum, a) => sum + a.size, 0);
156
250
  if (axis.position === 'top') {
157
251
  // Position above the chart rect, accounting for user inset
158
- const startY = userInset.top + offsetFromPreviousAxes;
252
+ const startY = calculatedInset.top + offsetFromPreviousAxes;
159
253
  return {
160
254
  x: chartRect.x,
161
255
  y: startY,
@@ -173,7 +267,7 @@ export const CartesianChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, r
173
267
  };
174
268
  } else if (axis.position === 'left') {
175
269
  // Position to the left of the chart rect, accounting for user inset
176
- const startX = userInset.left + offsetFromPreviousAxes;
270
+ const startX = calculatedInset.left + offsetFromPreviousAxes;
177
271
  return {
178
272
  x: startX,
179
273
  y: chartRect.y,
@@ -190,7 +284,11 @@ export const CartesianChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, r
190
284
  height: chartRect.height
191
285
  };
192
286
  }
193
- }, [renderedAxes, chartRect, userInset]);
287
+ }, [renderedAxes, chartRect, calculatedInset]);
288
+ const fontProvider = useMemo(() => {
289
+ if (fontProviderProp) return fontProviderProp;
290
+ return Skia.TypefaceFontProvider.Make();
291
+ }, [fontProviderProp]);
194
292
  const contextValue = useMemo(() => ({
195
293
  series: series != null ? series : [],
196
294
  getSeries,
@@ -198,41 +296,67 @@ export const CartesianChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, r
198
296
  animate,
199
297
  width: chartWidth,
200
298
  height: chartHeight,
299
+ fontFamilies,
300
+ fontProvider,
201
301
  getXAxis,
202
302
  getYAxis,
203
303
  getXScale,
204
304
  getYScale,
305
+ getXSerializableScale,
306
+ getYSerializableScale,
205
307
  drawingArea: chartRect,
308
+ dataLength,
206
309
  registerAxis,
207
310
  unregisterAxis,
208
311
  getAxisBounds
209
- }), [series, getSeries, getStackedSeriesData, animate, chartWidth, chartHeight, getXAxis, getYAxis, getXScale, getYScale, chartRect, registerAxis, unregisterAxis, getAxisBounds]);
210
- const containerStyles = useMemo(() => {
211
- const dynamicStyles = {};
212
- if (typeof width === 'string') {
213
- dynamicStyles.width = width;
214
- }
215
- if (typeof height === 'string') {
216
- dynamicStyles.height = height;
312
+ }), [series, getSeries, getStackedSeriesData, animate, chartWidth, chartHeight, fontFamilies, fontProvider, getXAxis, getYAxis, getXScale, getYScale, getXSerializableScale, getYSerializableScale, chartRect, dataLength, registerAxis, unregisterAxis, getAxisBounds]);
313
+ const rootStyles = useMemo(() => {
314
+ return [style, styles == null ? void 0 : styles.root];
315
+ }, [style, styles == null ? void 0 : styles.root]);
316
+ const legendElement = useMemo(() => {
317
+ if (!legend) return;
318
+ if (legend === true) {
319
+ const isHorizontal = legendPosition === 'top' || legendPosition === 'bottom';
320
+ const flexDirection = isHorizontal ? 'row' : 'column';
321
+ return /*#__PURE__*/_jsx(Legend, {
322
+ accessibilityLabel: legendAccessibilityLabel,
323
+ flexDirection: flexDirection
324
+ });
217
325
  }
218
- return [style, dynamicStyles];
219
- }, [style, width, height]);
326
+ return legend;
327
+ }, [legend, legendAccessibilityLabel, legendPosition]);
328
+ const rootBoxProps = useMemo(() => _extends({
329
+ ref,
330
+ accessibilityLiveRegion: 'polite',
331
+ accessibilityRole: 'image',
332
+ height,
333
+ style: rootStyles,
334
+ width
335
+ }, props), [ref, height, rootStyles, width, props]);
220
336
  return /*#__PURE__*/_jsx(CartesianChartProvider, {
221
337
  value: contextValue,
222
338
  children: /*#__PURE__*/_jsx(ScrubberProvider, {
223
339
  allowOverflowGestures: allowOverflowGestures,
224
340
  enableScrubbing: enableScrubbing,
225
341
  onScrubberPositionChange: onScrubberPositionChange,
226
- children: /*#__PURE__*/_jsx(Box, _extends({
227
- ref: ref,
228
- accessibilityLiveRegion: "polite",
229
- accessibilityRole: "image",
342
+ children: legend ? /*#__PURE__*/_jsxs(Box, _extends({}, rootBoxProps, {
343
+ flexDirection: legendPosition === 'top' || legendPosition === 'bottom' ? 'column' : 'row',
344
+ children: [(legendPosition === 'top' || legendPosition === 'left') && legendElement, /*#__PURE__*/_jsx(Box, {
345
+ collapsable: collapsable,
346
+ onLayout: onContainerLayout,
347
+ style: {
348
+ flex: 1
349
+ },
350
+ children: /*#__PURE__*/_jsx(ChartCanvas, {
351
+ style: styles == null ? void 0 : styles.chart,
352
+ children: children
353
+ })
354
+ }), (legendPosition === 'bottom' || legendPosition === 'right') && legendElement]
355
+ })) : /*#__PURE__*/_jsx(Box, _extends({}, rootBoxProps, {
356
+ collapsable: collapsable,
230
357
  onLayout: onContainerLayout,
231
- style: containerStyles
232
- }, props, {
233
- children: /*#__PURE__*/_jsx(Svg, {
234
- height: chartHeight,
235
- width: chartWidth,
358
+ children: /*#__PURE__*/_jsx(ChartCanvas, {
359
+ style: styles == null ? void 0 : styles.chart,
236
360
  children: children
237
361
  })
238
362
  }))