@coinbase/cds-mobile-visualization 3.4.0-beta.1 → 3.4.0-beta.10

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 (184) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/dts/chart/CartesianChart.d.ts +57 -33
  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/Path.d.ts +77 -34
  7. package/dts/chart/Path.d.ts.map +1 -1
  8. package/dts/chart/PeriodSelector.d.ts +2 -2
  9. package/dts/chart/PeriodSelector.d.ts.map +1 -1
  10. package/dts/chart/area/Area.d.ts +42 -27
  11. package/dts/chart/area/Area.d.ts.map +1 -1
  12. package/dts/chart/area/AreaChart.d.ts +51 -10
  13. package/dts/chart/area/AreaChart.d.ts.map +1 -1
  14. package/dts/chart/area/DottedArea.d.ts +21 -2
  15. package/dts/chart/area/DottedArea.d.ts.map +1 -1
  16. package/dts/chart/area/GradientArea.d.ts +19 -13
  17. package/dts/chart/area/GradientArea.d.ts.map +1 -1
  18. package/dts/chart/area/SolidArea.d.ts +17 -2
  19. package/dts/chart/area/SolidArea.d.ts.map +1 -1
  20. package/dts/chart/axis/Axis.d.ts +68 -78
  21. package/dts/chart/axis/Axis.d.ts.map +1 -1
  22. package/dts/chart/axis/DefaultAxisTickLabel.d.ts +8 -0
  23. package/dts/chart/axis/DefaultAxisTickLabel.d.ts.map +1 -0
  24. package/dts/chart/axis/XAxis.d.ts +1 -1
  25. package/dts/chart/axis/XAxis.d.ts.map +1 -1
  26. package/dts/chart/axis/YAxis.d.ts +2 -2
  27. package/dts/chart/axis/YAxis.d.ts.map +1 -1
  28. package/dts/chart/axis/index.d.ts +1 -0
  29. package/dts/chart/axis/index.d.ts.map +1 -1
  30. package/dts/chart/bar/Bar.d.ts +16 -13
  31. package/dts/chart/bar/Bar.d.ts.map +1 -1
  32. package/dts/chart/bar/BarChart.d.ts +36 -20
  33. package/dts/chart/bar/BarChart.d.ts.map +1 -1
  34. package/dts/chart/bar/BarPlot.d.ts +2 -1
  35. package/dts/chart/bar/BarPlot.d.ts.map +1 -1
  36. package/dts/chart/bar/BarStack.d.ts +39 -48
  37. package/dts/chart/bar/BarStack.d.ts.map +1 -1
  38. package/dts/chart/bar/BarStackGroup.d.ts +1 -0
  39. package/dts/chart/bar/BarStackGroup.d.ts.map +1 -1
  40. package/dts/chart/bar/DefaultBar.d.ts +1 -1
  41. package/dts/chart/bar/DefaultBar.d.ts.map +1 -1
  42. package/dts/chart/bar/DefaultBarStack.d.ts.map +1 -1
  43. package/dts/chart/gradient/Gradient.d.ts +25 -0
  44. package/dts/chart/gradient/Gradient.d.ts.map +1 -0
  45. package/dts/chart/gradient/index.d.ts +2 -0
  46. package/dts/chart/gradient/index.d.ts.map +1 -0
  47. package/dts/chart/index.d.ts +3 -1
  48. package/dts/chart/index.d.ts.map +1 -1
  49. package/dts/chart/line/DefaultReferenceLineLabel.d.ts +9 -0
  50. package/dts/chart/line/DefaultReferenceLineLabel.d.ts.map +1 -0
  51. package/dts/chart/line/DottedLine.d.ts +13 -5
  52. package/dts/chart/line/DottedLine.d.ts.map +1 -1
  53. package/dts/chart/line/Line.d.ts +62 -25
  54. package/dts/chart/line/Line.d.ts.map +1 -1
  55. package/dts/chart/line/LineChart.d.ts +43 -9
  56. package/dts/chart/line/LineChart.d.ts.map +1 -1
  57. package/dts/chart/line/ReferenceLine.d.ts +68 -20
  58. package/dts/chart/line/ReferenceLine.d.ts.map +1 -1
  59. package/dts/chart/line/SolidLine.d.ts +8 -5
  60. package/dts/chart/line/SolidLine.d.ts.map +1 -1
  61. package/dts/chart/line/index.d.ts +1 -1
  62. package/dts/chart/line/index.d.ts.map +1 -1
  63. package/dts/chart/point/DefaultPointLabel.d.ts +10 -0
  64. package/dts/chart/point/DefaultPointLabel.d.ts.map +1 -0
  65. package/dts/chart/point/Point.d.ts +120 -0
  66. package/dts/chart/point/Point.d.ts.map +1 -0
  67. package/dts/chart/point/index.d.ts +3 -0
  68. package/dts/chart/point/index.d.ts.map +1 -0
  69. package/dts/chart/scrubber/DefaultScrubberBeacon.d.ts +8 -0
  70. package/dts/chart/scrubber/DefaultScrubberBeacon.d.ts.map +1 -0
  71. package/dts/chart/scrubber/DefaultScrubberBeaconLabel.d.ts +12 -0
  72. package/dts/chart/scrubber/DefaultScrubberBeaconLabel.d.ts.map +1 -0
  73. package/dts/chart/scrubber/DefaultScrubberLabel.d.ts +11 -0
  74. package/dts/chart/scrubber/DefaultScrubberLabel.d.ts.map +1 -0
  75. package/dts/chart/scrubber/Scrubber.d.ts +172 -43
  76. package/dts/chart/scrubber/Scrubber.d.ts.map +1 -1
  77. package/dts/chart/scrubber/ScrubberBeaconGroup.d.ts +44 -0
  78. package/dts/chart/scrubber/ScrubberBeaconGroup.d.ts.map +1 -0
  79. package/dts/chart/scrubber/ScrubberBeaconLabelGroup.d.ts +31 -0
  80. package/dts/chart/scrubber/ScrubberBeaconLabelGroup.d.ts.map +1 -0
  81. package/dts/chart/scrubber/ScrubberProvider.d.ts +6 -3
  82. package/dts/chart/scrubber/ScrubberProvider.d.ts.map +1 -1
  83. package/dts/chart/scrubber/index.d.ts +3 -0
  84. package/dts/chart/scrubber/index.d.ts.map +1 -1
  85. package/dts/chart/text/ChartText.d.ts +151 -77
  86. package/dts/chart/text/ChartText.d.ts.map +1 -1
  87. package/dts/chart/text/{SmartChartTextGroup.d.ts → ChartTextGroup.d.ts} +9 -3
  88. package/dts/chart/text/ChartTextGroup.d.ts.map +1 -0
  89. package/dts/chart/text/index.d.ts +1 -1
  90. package/dts/chart/text/index.d.ts.map +1 -1
  91. package/dts/chart/utils/chart.d.ts +34 -7
  92. package/dts/chart/utils/chart.d.ts.map +1 -1
  93. package/dts/chart/utils/context.d.ts +28 -7
  94. package/dts/chart/utils/context.d.ts.map +1 -1
  95. package/dts/chart/utils/gradient.d.ts +117 -0
  96. package/dts/chart/utils/gradient.d.ts.map +1 -0
  97. package/dts/chart/utils/index.d.ts +3 -0
  98. package/dts/chart/utils/index.d.ts.map +1 -1
  99. package/dts/chart/utils/path.d.ts +53 -0
  100. package/dts/chart/utils/path.d.ts.map +1 -1
  101. package/dts/chart/utils/point.d.ts +60 -1
  102. package/dts/chart/utils/point.d.ts.map +1 -1
  103. package/dts/chart/utils/scale.d.ts +91 -0
  104. package/dts/chart/utils/scale.d.ts.map +1 -1
  105. package/dts/chart/utils/scrubber.d.ts +39 -0
  106. package/dts/chart/utils/scrubber.d.ts.map +1 -0
  107. package/dts/chart/utils/transition.d.ts +140 -0
  108. package/dts/chart/utils/transition.d.ts.map +1 -0
  109. package/esm/chart/CartesianChart.js +164 -70
  110. package/esm/chart/ChartContextBridge.js +148 -0
  111. package/esm/chart/Path.js +198 -113
  112. package/esm/chart/PeriodSelector.js +2 -2
  113. package/esm/chart/__stories__/CartesianChart.stories.js +378 -131
  114. package/esm/chart/__stories__/Chart.stories.js +2 -4
  115. package/esm/chart/__stories__/PeriodSelector.stories.js +103 -75
  116. package/esm/chart/area/Area.js +25 -35
  117. package/esm/chart/area/AreaChart.js +17 -12
  118. package/esm/chart/area/DottedArea.js +61 -109
  119. package/esm/chart/area/GradientArea.js +35 -91
  120. package/esm/chart/area/SolidArea.js +22 -8
  121. package/esm/chart/area/__stories__/AreaChart.stories.js +1 -1
  122. package/esm/chart/axis/Axis.js +2 -0
  123. package/esm/chart/axis/DefaultAxisTickLabel.js +11 -0
  124. package/esm/chart/axis/XAxis.js +63 -56
  125. package/esm/chart/axis/YAxis.js +59 -52
  126. package/esm/chart/axis/__stories__/Axis.stories.js +0 -1
  127. package/esm/chart/axis/index.js +1 -0
  128. package/esm/chart/bar/Bar.js +3 -1
  129. package/esm/chart/bar/BarChart.js +15 -37
  130. package/esm/chart/bar/BarPlot.js +41 -35
  131. package/esm/chart/bar/BarStack.js +75 -38
  132. package/esm/chart/bar/BarStackGroup.js +6 -16
  133. package/esm/chart/bar/DefaultBar.js +26 -48
  134. package/esm/chart/bar/DefaultBarStack.js +23 -58
  135. package/esm/chart/bar/__stories__/BarChart.stories.js +463 -77
  136. package/esm/chart/gradient/Gradient.js +53 -0
  137. package/esm/chart/gradient/index.js +1 -0
  138. package/esm/chart/index.js +3 -1
  139. package/esm/chart/line/DefaultReferenceLineLabel.js +66 -0
  140. package/esm/chart/line/DottedLine.js +29 -14
  141. package/esm/chart/line/Line.js +106 -67
  142. package/esm/chart/line/LineChart.js +20 -14
  143. package/esm/chart/line/ReferenceLine.js +80 -63
  144. package/esm/chart/line/SolidLine.js +25 -10
  145. package/esm/chart/line/__stories__/LineChart.stories.js +2101 -1977
  146. package/esm/chart/line/__stories__/ReferenceLine.stories.js +83 -28
  147. package/esm/chart/line/index.js +1 -1
  148. package/esm/chart/point/DefaultPointLabel.js +39 -0
  149. package/esm/chart/point/Point.js +188 -0
  150. package/esm/chart/point/index.js +2 -0
  151. package/esm/chart/scrubber/DefaultScrubberBeacon.js +179 -0
  152. package/esm/chart/scrubber/DefaultScrubberBeaconLabel.js +43 -0
  153. package/esm/chart/scrubber/DefaultScrubberLabel.js +28 -0
  154. package/esm/chart/scrubber/Scrubber.js +126 -146
  155. package/esm/chart/scrubber/ScrubberBeaconGroup.js +161 -0
  156. package/esm/chart/scrubber/ScrubberBeaconLabelGroup.js +185 -0
  157. package/esm/chart/scrubber/ScrubberProvider.js +46 -54
  158. package/esm/chart/scrubber/index.js +3 -1
  159. package/esm/chart/text/ChartText.js +242 -174
  160. package/esm/chart/text/{SmartChartTextGroup.js → ChartTextGroup.js} +6 -5
  161. package/esm/chart/text/index.js +1 -1
  162. package/esm/chart/utils/chart.js +44 -3
  163. package/esm/chart/utils/gradient.js +305 -0
  164. package/esm/chart/utils/index.js +3 -0
  165. package/esm/chart/utils/path.js +76 -8
  166. package/esm/chart/utils/point.js +116 -5
  167. package/esm/chart/utils/scale.js +230 -1
  168. package/esm/chart/utils/scrubber.js +139 -0
  169. package/esm/chart/utils/transition.js +185 -0
  170. package/esm/sparkline/__stories__/Sparkline.stories.js +11 -7
  171. package/esm/sparkline/__stories__/SparklineGradient.stories.js +7 -4
  172. package/esm/sparkline/sparkline-interactive/__stories__/SparklineInteractive.stories.js +51 -26
  173. package/esm/sparkline/sparkline-interactive-header/__stories__/SparklineInteractiveHeader.stories.js +17 -9
  174. package/package.json +15 -9
  175. package/dts/chart/Point.d.ts +0 -103
  176. package/dts/chart/Point.d.ts.map +0 -1
  177. package/dts/chart/line/GradientLine.d.ts +0 -45
  178. package/dts/chart/line/GradientLine.d.ts.map +0 -1
  179. package/dts/chart/scrubber/ScrubberBeacon.d.ts +0 -75
  180. package/dts/chart/scrubber/ScrubberBeacon.d.ts.map +0 -1
  181. package/dts/chart/text/SmartChartTextGroup.d.ts.map +0 -1
  182. package/esm/chart/Point.js +0 -111
  183. package/esm/chart/line/GradientLine.js +0 -62
  184. package/esm/chart/scrubber/ScrubberBeacon.js +0 -199
@@ -1,110 +1,54 @@
1
- const _excluded = ["d", "fill", "fillOpacity", "peakColor", "baselineColor", "peakOpacity", "baselineOpacity", "baseline", "yAxisId", "clipRect"];
1
+ const _excluded = ["d", "fill", "fillOpacity", "gradient", "peakOpacity", "baselineOpacity", "baseline", "yAxisId", "animate", "transition"];
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
- import { memo, useId } from 'react';
5
- import { Defs, LinearGradient, Stop } from 'react-native-svg';
4
+ import { memo, useMemo } from 'react';
6
5
  import { useTheme } from '@coinbase/cds-mobile/hooks/useTheme';
7
6
  import { useCartesianChartContext } from '../ChartProvider';
7
+ import { Gradient } from '../gradient';
8
8
  import { Path } from '../Path';
9
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
9
+ import { createGradient, getBaseline } from '../utils';
10
+ import { jsx as _jsx } from "react/jsx-runtime";
10
11
  /**
11
- * A customizable gradient area component which uses Path.
12
+ * A customizable gradient area component.
13
+ * When no gradient is provided, renders a default gradient based
14
+ * on the fill color and peak/baseline opacities.
12
15
  */
13
16
  export const GradientArea = /*#__PURE__*/memo(_ref => {
14
17
  let {
15
18
  d,
16
- fill,
19
+ fill: fillProp,
17
20
  fillOpacity = 1,
18
- peakColor,
19
- baselineColor,
21
+ gradient: gradientProp,
20
22
  peakOpacity = 0.3,
21
23
  baselineOpacity = 0,
22
24
  baseline,
23
25
  yAxisId,
24
- clipRect
26
+ animate,
27
+ transition
25
28
  } = _ref,
26
29
  pathProps = _objectWithoutPropertiesLoose(_ref, _excluded);
27
- const context = useCartesianChartContext();
30
+ const {
31
+ getYAxis
32
+ } = useCartesianChartContext();
28
33
  const theme = useTheme();
29
- const patternId = useId();
30
-
31
- // Get the y-scale for the specified axis (or default)
32
- const yScale = context.getYScale(yAxisId);
33
- const yRange = yScale == null ? void 0 : yScale.range();
34
- const yDomain = yScale == null ? void 0 : yScale.domain();
35
-
36
- // Use chart range if available, otherwise fall back to percentage
37
- const useUserSpaceUnits = yRange !== undefined;
38
- const gradientY1 = useUserSpaceUnits && yRange ? String(yRange[1]) : '0%';
39
- const gradientY2 = useUserSpaceUnits && yRange ? String(yRange[0]) : '100%';
40
-
41
- // Auto-calculate baseline position based on domain
42
- let baselinePosition;
43
- let baselinePercentage;
44
- if (yScale && yDomain) {
45
- const [minValue, maxValue] = yDomain;
46
- let dataBaseline;
47
- if (minValue >= 0) {
48
- // All positive: baseline at min
49
- dataBaseline = minValue;
50
- } else if (maxValue <= 0) {
51
- // All negative: baseline at max
52
- dataBaseline = maxValue;
53
- } else {
54
- // Crosses zero: baseline at 0
55
- dataBaseline = 0;
56
- }
57
- if (useUserSpaceUnits && yRange) {
58
- // Get the actual y coordinate for the baseline
59
- const scaledValue = yScale(baseline != null ? baseline : dataBaseline);
60
- if (typeof scaledValue === 'number') {
61
- baselinePosition = scaledValue;
62
- }
63
- } else {
64
- // Calculate percentage position
65
- baselinePercentage = (maxValue - (baseline != null ? baseline : dataBaseline)) / (maxValue - minValue) * 100 + "%";
66
- }
67
- }
68
- const effectiveFill = fill != null ? fill : theme.color.fgPrimary;
69
- const effectivePeakColor = peakColor != null ? peakColor : effectiveFill;
70
- const effectiveBaselineColor = baselineColor != null ? baselineColor : effectiveFill;
71
- return /*#__PURE__*/_jsxs(_Fragment, {
72
- children: [/*#__PURE__*/_jsx(Defs, {
73
- children: /*#__PURE__*/_jsx(LinearGradient, {
74
- gradientUnits: useUserSpaceUnits ? 'userSpaceOnUse' : 'objectBoundingBox',
75
- id: patternId,
76
- x1: useUserSpaceUnits ? '0' : '0%',
77
- x2: useUserSpaceUnits ? '0' : '0%',
78
- y1: gradientY1,
79
- y2: gradientY2,
80
- children: baselinePosition !== undefined || baselinePercentage !== undefined ? /* Diverging gradient: peak opacity at extremes, baseline opacity at baseline */
81
- [/*#__PURE__*/_jsx(Stop, {
82
- offset: "0%",
83
- stopColor: effectivePeakColor,
84
- stopOpacity: peakOpacity
85
- }, "0"), /*#__PURE__*/_jsx(Stop, {
86
- offset: baselinePercentage != null ? baselinePercentage : (baselinePosition - yRange[1]) / (yRange[0] - yRange[1]) * 100 + "%",
87
- stopColor: effectiveBaselineColor,
88
- stopOpacity: baselineOpacity
89
- }, "1"), /*#__PURE__*/_jsx(Stop, {
90
- offset: "100%",
91
- stopColor: effectivePeakColor,
92
- stopOpacity: peakOpacity
93
- }, "2")] : /* Simple gradient from peak to baseline */
94
- [/*#__PURE__*/_jsx(Stop, {
95
- offset: "0%",
96
- stopColor: effectivePeakColor,
97
- stopOpacity: peakOpacity
98
- }, "0"), /*#__PURE__*/_jsx(Stop, {
99
- offset: "100%",
100
- stopColor: effectiveBaselineColor,
101
- stopOpacity: baselineOpacity
102
- }, "1")]
103
- })
104
- }), /*#__PURE__*/_jsx(Path, _extends({
105
- clipRect: clipRect,
106
- d: d,
107
- fill: "url(#" + patternId + ")"
108
- }, pathProps))]
109
- });
34
+ const yAxisConfig = getYAxis(yAxisId);
35
+ const fill = useMemo(() => fillProp != null ? fillProp : theme.color.fgPrimary, [fillProp, theme.color.fgPrimary]);
36
+ const gradient = useMemo(() => {
37
+ if (gradientProp) return gradientProp;
38
+ if (!yAxisConfig) return;
39
+ const baselineValue = getBaseline(yAxisConfig.domain, baseline);
40
+ return createGradient(yAxisConfig.domain, baselineValue, fill, peakOpacity, baselineOpacity);
41
+ }, [gradientProp, yAxisConfig, fill, baseline, peakOpacity, baselineOpacity]);
42
+ return /*#__PURE__*/_jsx(Path, _extends({
43
+ animate: animate,
44
+ d: d,
45
+ fill: fill,
46
+ fillOpacity: fillOpacity,
47
+ transition: transition
48
+ }, pathProps, {
49
+ children: gradient && /*#__PURE__*/_jsx(Gradient, {
50
+ gradient: gradient,
51
+ yAxisId: yAxisId
52
+ })
53
+ }));
110
54
  });
@@ -1,24 +1,38 @@
1
- const _excluded = ["d", "fill", "fillOpacity", "clipRect"];
1
+ const _excluded = ["d", "fill", "fillOpacity", "yAxisId", "animate", "transition", "gradient"];
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 { memo } from 'react';
5
+ import { useTheme } from '@coinbase/cds-mobile/hooks/useTheme';
6
+ import { Gradient } from '../gradient';
5
7
  import { Path } from '../Path';
6
8
  import { jsx as _jsx } from "react/jsx-runtime";
7
9
  /**
8
- * A customizable solid area component which uses Path.
10
+ * A customizable solid area component.
11
+ * When a gradient is provided, renders with gradient fill.
12
+ * Otherwise, renders with solid fill.
9
13
  */
10
14
  export const SolidArea = /*#__PURE__*/memo(_ref => {
11
15
  let {
12
16
  d,
13
17
  fill,
14
18
  fillOpacity = 1,
15
- clipRect
19
+ yAxisId,
20
+ animate,
21
+ transition,
22
+ gradient
16
23
  } = _ref,
17
- props = _objectWithoutPropertiesLoose(_ref, _excluded);
24
+ pathProps = _objectWithoutPropertiesLoose(_ref, _excluded);
25
+ const theme = useTheme();
18
26
  return /*#__PURE__*/_jsx(Path, _extends({
19
- clipRect: clipRect,
27
+ animate: animate,
20
28
  d: d,
21
- fill: fill,
22
- fillOpacity: fillOpacity
23
- }, props));
29
+ fill: fill != null ? fill : theme.color.fgPrimary,
30
+ fillOpacity: fillOpacity,
31
+ transition: transition
32
+ }, pathProps, {
33
+ children: gradient && /*#__PURE__*/_jsx(Gradient, {
34
+ gradient: gradient,
35
+ yAxisId: yAxisId
36
+ })
37
+ }));
24
38
  });
@@ -64,7 +64,7 @@ const AreaChartStories = () => {
64
64
  id: 'pageViews',
65
65
  data: [24, 13, -98, 39, 48, 38, 43]
66
66
  }],
67
- type: "gradient",
67
+ type: "solid",
68
68
  yAxis: {
69
69
  showGrid: true
70
70
  },
@@ -1,5 +1,7 @@
1
1
  /**
2
2
  * Animation variants for grouped axis tick labels - initial mount
3
+ * Note: Mobile currently doesn't use these variants. Axes render immediately without animation.
4
+ * Web uses similar variants with delay to match path enter animation timing.
3
5
  */
4
6
  export const axisTickLabelsInitialAnimationVariants = {
5
7
  initial: {
@@ -0,0 +1,11 @@
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 { memo } from 'react';
3
+ import { ChartText } from '../text';
4
+ import { jsx as _jsx } from "react/jsx-runtime";
5
+ /**
6
+ * DefaultAxisTickLabel is the default label component for axis tick labels.
7
+ * Provides standard styling for both X and Y axis tick labels.
8
+ */
9
+ export const DefaultAxisTickLabel = /*#__PURE__*/memo(props => {
10
+ return /*#__PURE__*/_jsx(ChartText, _extends({}, props));
11
+ });
@@ -1,17 +1,19 @@
1
- const _excluded = ["position", "showGrid", "requestedTickCount", "ticks", "tickLabelFormatter", "style", "className", "styles", "classNames", "GridLineComponent", "tickMarkLabelGap", "height", "minTickLabelGap", "showTickMarks", "showLine", "tickMarkSize", "tickInterval", "tickMinStep", "tickMaxStep"];
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); }
1
+ const _excluded = ["position", "showGrid", "requestedTickCount", "ticks", "tickLabelFormatter", "TickLabelComponent", "GridLineComponent", "LineComponent", "TickMarkLineComponent", "tickMarkLabelGap", "minTickLabelGap", "showTickMarks", "showLine", "tickMarkSize", "tickInterval", "tickMinStep", "tickMaxStep", "label", "labelGap", "height"];
3
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; }
4
3
  import { memo, useCallback, useEffect, useId, useMemo } from 'react';
5
- import Animated, { useAnimatedStyle, useSharedValue } from 'react-native-reanimated';
6
- import { G, Line } from 'react-native-svg';
7
4
  import { useTheme } from '@coinbase/cds-mobile/hooks/useTheme';
5
+ import { Group } from '@shopify/react-native-skia';
8
6
  import { useCartesianChartContext } from '../ChartProvider';
9
7
  import { DottedLine } from '../line/DottedLine';
10
8
  import { ReferenceLine } from '../line/ReferenceLine';
11
- import { SmartChartTextGroup } from '../text/SmartChartTextGroup';
12
- import { getAxisTicksData, isCategoricalScale } from '../utils';
9
+ import { SolidLine } from '../line/SolidLine';
10
+ import { ChartText } from '../text/ChartText';
11
+ import { ChartTextGroup } from '../text/ChartTextGroup';
12
+ import { getAxisTicksData, isCategoricalScale, lineToPath } from '../utils';
13
+ import { DefaultAxisTickLabel } from './DefaultAxisTickLabel';
13
14
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
- const AnimatedG = Animated.createAnimatedComponent(G);
15
+ const AXIS_HEIGHT = 32;
16
+ const LABEL_SIZE = 20;
15
17
  export const XAxis = /*#__PURE__*/memo(_ref => {
16
18
  let {
17
19
  position = 'bottom',
@@ -19,18 +21,21 @@ export const XAxis = /*#__PURE__*/memo(_ref => {
19
21
  requestedTickCount,
20
22
  ticks,
21
23
  tickLabelFormatter,
22
- styles,
23
- classNames,
24
+ TickLabelComponent = DefaultAxisTickLabel,
24
25
  GridLineComponent = DottedLine,
26
+ LineComponent = SolidLine,
27
+ TickMarkLineComponent = SolidLine,
25
28
  tickMarkLabelGap = 2,
26
- height = 32,
27
29
  minTickLabelGap = 4,
28
30
  showTickMarks,
29
31
  showLine,
30
32
  tickMarkSize = 4,
31
33
  tickInterval = 32,
32
34
  tickMinStep = 1,
33
- tickMaxStep
35
+ tickMaxStep,
36
+ label,
37
+ labelGap = 4,
38
+ height = label ? AXIS_HEIGHT + LABEL_SIZE : AXIS_HEIGHT
34
39
  } = _ref,
35
40
  props = _objectWithoutPropertiesLoose(_ref, _excluded);
36
41
  const theme = useTheme();
@@ -46,17 +51,10 @@ export const XAxis = /*#__PURE__*/memo(_ref => {
46
51
  const xScale = getXScale();
47
52
  const xAxis = getXAxis();
48
53
  const axisBounds = getAxisBounds(registrationId);
49
- const gridOpacity = useSharedValue(1);
50
- const axisLineProps = useMemo(() => ({
51
- stroke: theme.color.fg,
52
- strokeLinecap: 'square',
53
- strokeWidth: 1
54
- }), [theme.color.fg]);
55
- const axisTickMarkProps = useMemo(() => ({
56
- stroke: theme.color.fg,
57
- strokeLinecap: 'square',
58
- strokeWidth: 1
59
- }), [theme.color.fg]);
54
+
55
+ // Note: gridOpacity not currently used in Skia version
56
+ // const gridOpacity = useSharedValue(1);
57
+
60
58
  useEffect(() => {
61
59
  registerAxis(registrationId, position, height);
62
60
  return () => unregisterAxis(registrationId);
@@ -118,64 +116,73 @@ export const XAxis = /*#__PURE__*/memo(_ref => {
118
116
  if (!axisBounds) return null;
119
117
  return ticksData.map(tick => {
120
118
  const tickOffset = tickMarkLabelGap + (showTickMarks ? tickMarkSize : 0);
121
- const availableSpace = axisBounds.height - tickOffset;
119
+
120
+ // Use AXIS_HEIGHT for centering, not full axisBounds.height
121
+ // This ensures tick labels are centered in the axis area, not including label space
122
+ const availableSpace = AXIS_HEIGHT - tickOffset;
122
123
  const labelOffset = availableSpace / 2;
123
- const labelY = position === 'top' ? axisBounds.y + labelOffset - tickOffset : axisBounds.y + labelOffset + tickOffset;
124
+
125
+ // For bottom position: start at axisBounds.y
126
+ // For top position with label: start at axisBounds.y + LABEL_SIZE
127
+ const baseY = position === 'top' && label ? axisBounds.y + LABEL_SIZE : axisBounds.y;
128
+ const labelY = position === 'top' ? baseY + labelOffset - tickOffset : baseY + labelOffset + tickOffset;
124
129
  return {
125
130
  x: tick.position,
126
131
  y: labelY,
127
132
  label: String(formatTick(tick.tick)),
128
133
  chartTextProps: {
129
- className: classNames == null ? void 0 : classNames.tickLabel,
130
134
  color: theme.color.fgMuted,
131
135
  verticalAlignment: 'middle',
132
- style: styles == null ? void 0 : styles.tickLabel,
133
136
  horizontalAlignment: 'center'
134
137
  }
135
138
  };
136
139
  });
137
- }, [axisBounds, ticksData, theme.color.fgMuted, tickMarkLabelGap, showTickMarks, tickMarkSize, position, formatTick, classNames == null ? void 0 : classNames.tickLabel, styles == null ? void 0 : styles.tickLabel]);
138
- const gridAnimatedStyle = useAnimatedStyle(() => ({
139
- opacity: gridOpacity.value
140
- }));
141
- if (!xScale) return;
142
- return /*#__PURE__*/_jsxs(G, _extends({
143
- "data-axis": "x",
144
- "data-position": position
145
- }, props, {
146
- children: [showGrid && /*#__PURE__*/_jsx(AnimatedG, {
147
- animatedProps: gridAnimatedStyle,
140
+ }, [axisBounds, ticksData, theme.color.fgMuted, tickMarkLabelGap, showTickMarks, tickMarkSize, position, formatTick, label]);
141
+ if (!xScale || !axisBounds) return;
142
+ const labelX = axisBounds.x + axisBounds.width / 2;
143
+ const labelY = position === 'bottom' ? axisBounds.y + axisBounds.height - LABEL_SIZE / 2 : axisBounds.y + LABEL_SIZE / 2;
144
+ return /*#__PURE__*/_jsxs(Group, {
145
+ children: [showGrid && /*#__PURE__*/_jsx(Group, {
148
146
  children: ticksData.map((tick, index) => {
149
147
  const verticalLine = /*#__PURE__*/_jsx(ReferenceLine, {
150
148
  LineComponent: GridLineComponent,
151
149
  dataX: tick.tick
152
150
  });
153
- return /*#__PURE__*/_jsx(G, {
151
+ return /*#__PURE__*/_jsx(Group, {
154
152
  children: verticalLine
155
153
  }, "grid-" + tick.tick + "-" + index);
156
154
  })
157
- }), chartTextData && /*#__PURE__*/_jsx(SmartChartTextGroup, {
155
+ }), chartTextData && /*#__PURE__*/_jsx(ChartTextGroup, {
158
156
  prioritizeEndLabels: true,
157
+ LabelComponent: TickLabelComponent,
159
158
  labels: chartTextData,
160
159
  minGap: minTickLabelGap
161
- }), axisBounds && showTickMarks && /*#__PURE__*/_jsx(G, {
162
- "data-testid": "tick-marks",
160
+ }), axisBounds && showTickMarks && /*#__PURE__*/_jsx(Group, {
163
161
  children: ticksData.map((tick, index) => {
164
162
  const tickY = position === 'bottom' ? axisBounds.y : axisBounds.y + axisBounds.height;
165
- const tickMarkSizePixels = tickMarkSize;
166
- const tickY2 = position === 'bottom' ? axisBounds.y + tickMarkSizePixels : axisBounds.y + axisBounds.height - tickMarkSizePixels;
167
- return /*#__PURE__*/_jsx(Line, _extends({}, axisTickMarkProps, {
168
- x1: tick.position,
169
- x2: tick.position,
170
- y1: tickY,
171
- y2: tickY2
172
- }), "tick-mark-" + tick.tick + "-" + index);
163
+ const tickY2 = position === 'bottom' ? axisBounds.y + tickMarkSize : axisBounds.y + axisBounds.height - tickMarkSize;
164
+ return /*#__PURE__*/_jsx(TickMarkLineComponent, {
165
+ animate: false,
166
+ clipPath: null,
167
+ d: lineToPath(tick.position, tickY, tick.position, tickY2),
168
+ stroke: theme.color.fg,
169
+ strokeCap: "square",
170
+ strokeWidth: 1
171
+ }, "tick-mark-" + tick.tick + "-" + index);
173
172
  })
174
- }), axisBounds && showLine && /*#__PURE__*/_jsx(Line, _extends({}, axisLineProps, {
175
- x1: axisBounds.x,
176
- x2: axisBounds.x + axisBounds.width,
177
- y1: position === 'bottom' ? axisBounds.y : axisBounds.y + axisBounds.height,
178
- y2: position === 'bottom' ? axisBounds.y : axisBounds.y + axisBounds.height
179
- }))]
180
- }));
173
+ }), showLine && /*#__PURE__*/_jsx(LineComponent, {
174
+ animate: false,
175
+ clipPath: null,
176
+ d: lineToPath(axisBounds.x, position === 'bottom' ? axisBounds.y : axisBounds.y + axisBounds.height, axisBounds.x + axisBounds.width, position === 'bottom' ? axisBounds.y : axisBounds.y + axisBounds.height),
177
+ stroke: theme.color.fg,
178
+ strokeCap: "square",
179
+ strokeWidth: 1
180
+ }), label && /*#__PURE__*/_jsx(ChartText, {
181
+ horizontalAlignment: "center",
182
+ verticalAlignment: "middle",
183
+ x: labelX,
184
+ y: labelY,
185
+ children: label
186
+ })]
187
+ });
181
188
  });
@@ -1,17 +1,19 @@
1
- const _excluded = ["axisId", "position", "showGrid", "requestedTickCount", "ticks", "tickLabelFormatter", "style", "className", "styles", "classNames", "GridLineComponent", "tickMarkLabelGap", "width", "minTickLabelGap", "showTickMarks", "showLine", "tickMarkSize", "tickInterval"];
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); }
1
+ const _excluded = ["axisId", "position", "showGrid", "requestedTickCount", "ticks", "tickLabelFormatter", "TickLabelComponent", "GridLineComponent", "LineComponent", "TickMarkLineComponent", "tickMarkLabelGap", "minTickLabelGap", "showTickMarks", "showLine", "tickMarkSize", "tickInterval", "label", "labelGap", "width"];
3
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; }
4
3
  import { memo, useCallback, useEffect, useId, useMemo } from 'react';
5
- import Animated, { useAnimatedStyle, useSharedValue } from 'react-native-reanimated';
6
- import { G, Line } from 'react-native-svg';
7
4
  import { useTheme } from '@coinbase/cds-mobile/hooks/useTheme';
5
+ import { Group, vec } from '@shopify/react-native-skia';
8
6
  import { useCartesianChartContext } from '../ChartProvider';
9
7
  import { DottedLine } from '../line/DottedLine';
10
8
  import { ReferenceLine } from '../line/ReferenceLine';
11
- import { SmartChartTextGroup } from '../text/SmartChartTextGroup';
12
- import { getAxisTicksData, isCategoricalScale } from '../utils';
9
+ import { SolidLine } from '../line/SolidLine';
10
+ import { ChartText } from '../text/ChartText';
11
+ import { ChartTextGroup } from '../text/ChartTextGroup';
12
+ import { getAxisTicksData, isCategoricalScale, lineToPath } from '../utils';
13
+ import { DefaultAxisTickLabel } from './DefaultAxisTickLabel';
13
14
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
14
- const AnimatedG = Animated.createAnimatedComponent(G);
15
+ const AXIS_WIDTH = 44;
16
+ const LABEL_SIZE = 20;
15
17
  export const YAxis = /*#__PURE__*/memo(_ref => {
16
18
  let {
17
19
  axisId,
@@ -20,16 +22,19 @@ export const YAxis = /*#__PURE__*/memo(_ref => {
20
22
  requestedTickCount = 5,
21
23
  ticks,
22
24
  tickLabelFormatter,
23
- styles,
24
- classNames,
25
+ TickLabelComponent = DefaultAxisTickLabel,
25
26
  GridLineComponent = DottedLine,
27
+ LineComponent = SolidLine,
28
+ TickMarkLineComponent = SolidLine,
26
29
  tickMarkLabelGap = 8,
27
- width = 44,
28
30
  minTickLabelGap = 0,
29
31
  showTickMarks,
30
32
  showLine,
31
33
  tickMarkSize = 4,
32
- tickInterval
34
+ tickInterval,
35
+ label,
36
+ labelGap = 4,
37
+ width = label ? AXIS_WIDTH + LABEL_SIZE : AXIS_WIDTH
33
38
  } = _ref,
34
39
  props = _objectWithoutPropertiesLoose(_ref, _excluded);
35
40
  const theme = useTheme();
@@ -45,17 +50,10 @@ export const YAxis = /*#__PURE__*/memo(_ref => {
45
50
  const yScale = getYScale(axisId);
46
51
  const yAxis = getYAxis(axisId);
47
52
  const axisBounds = getAxisBounds(registrationId);
48
- const gridOpacity = useSharedValue(1);
49
- const axisLineProps = useMemo(() => ({
50
- stroke: theme.color.fg,
51
- strokeLinecap: 'square',
52
- strokeWidth: 1
53
- }), [theme.color.fg]);
54
- const axisTickMarkProps = useMemo(() => ({
55
- stroke: theme.color.fg,
56
- strokeLinecap: 'square',
57
- strokeWidth: 1
58
- }), [theme.color.fg]);
53
+
54
+ // Note: gridOpacity not currently used in Skia version
55
+ // const gridOpacity = useSharedValue(1);
56
+
59
57
  useEffect(() => {
60
58
  registerAxis(registrationId, position, width);
61
59
  return () => unregisterAxis(registrationId);
@@ -114,57 +112,66 @@ export const YAxis = /*#__PURE__*/memo(_ref => {
114
112
  y: tick.position,
115
113
  label: String(formatTick(tick.tick)),
116
114
  chartTextProps: {
117
- className: classNames == null ? void 0 : classNames.tickLabel,
118
115
  color: theme.color.fgMuted,
119
116
  verticalAlignment: 'middle',
120
- style: styles == null ? void 0 : styles.tickLabel,
121
117
  horizontalAlignment: position === 'left' ? 'right' : 'left'
122
118
  }
123
119
  };
124
120
  });
125
- }, [axisBounds, ticksData, theme.color.fgMuted, tickMarkLabelGap, showTickMarks, tickMarkSize, position, formatTick, classNames == null ? void 0 : classNames.tickLabel, styles == null ? void 0 : styles.tickLabel]);
126
- const gridAnimatedStyle = useAnimatedStyle(() => ({
127
- opacity: gridOpacity.value
128
- }));
129
- if (!yScale) return;
130
- return /*#__PURE__*/_jsxs(G, _extends({
131
- "data-axis": "y",
132
- "data-position": position
133
- }, props, {
134
- children: [showGrid && /*#__PURE__*/_jsx(AnimatedG, {
135
- animatedProps: gridAnimatedStyle,
121
+ }, [axisBounds, ticksData, tickMarkLabelGap, showTickMarks, tickMarkSize, position, formatTick, theme.color.fgMuted]);
122
+ if (!yScale || !axisBounds) return;
123
+ const labelX = position === 'left' ? axisBounds.x + LABEL_SIZE / 2 : axisBounds.x + axisBounds.width - LABEL_SIZE / 2;
124
+ const labelY = axisBounds.y + axisBounds.height / 2;
125
+ return /*#__PURE__*/_jsxs(Group, {
126
+ children: [showGrid && /*#__PURE__*/_jsx(Group, {
136
127
  children: ticksData.map((tick, index) => {
137
128
  const horizontalLine = /*#__PURE__*/_jsx(ReferenceLine, {
138
129
  LineComponent: GridLineComponent,
139
130
  dataY: tick.tick,
140
131
  yAxisId: axisId
141
132
  });
142
- return /*#__PURE__*/_jsx(G, {
133
+ return /*#__PURE__*/_jsx(Group, {
143
134
  children: horizontalLine
144
135
  }, "grid-" + tick.tick + "-" + index);
145
136
  })
146
- }), chartTextData && /*#__PURE__*/_jsx(SmartChartTextGroup, {
137
+ }), chartTextData && /*#__PURE__*/_jsx(ChartTextGroup, {
147
138
  prioritizeEndLabels: true,
139
+ LabelComponent: TickLabelComponent,
148
140
  labels: chartTextData,
149
141
  minGap: minTickLabelGap
150
- }), axisBounds && showTickMarks && /*#__PURE__*/_jsx(G, {
151
- "data-testid": "tick-marks",
142
+ }), axisBounds && showTickMarks && /*#__PURE__*/_jsx(Group, {
152
143
  children: ticksData.map((tick, index) => {
153
144
  const tickX = position === 'left' ? axisBounds.x + axisBounds.width : axisBounds.x;
154
145
  const tickMarkSizePixels = tickMarkSize;
155
146
  const tickX2 = position === 'left' ? axisBounds.x + axisBounds.width - tickMarkSizePixels : axisBounds.x + tickMarkSizePixels;
156
- return /*#__PURE__*/_jsx(Line, _extends({}, axisTickMarkProps, {
157
- x1: tickX,
158
- x2: tickX2,
159
- y1: tick.position,
160
- y2: tick.position
161
- }), "tick-mark-" + tick.tick + "-" + index);
147
+ return /*#__PURE__*/_jsx(TickMarkLineComponent, {
148
+ animate: false,
149
+ clipPath: null,
150
+ d: lineToPath(tickX, tick.position, tickX2, tick.position),
151
+ stroke: theme.color.fg,
152
+ strokeCap: "square",
153
+ strokeWidth: 1
154
+ }, "tick-mark-" + tick.tick + "-" + index);
155
+ })
156
+ }), showLine && /*#__PURE__*/_jsx(LineComponent, {
157
+ animate: false,
158
+ clipPath: null,
159
+ d: lineToPath(position === 'left' ? axisBounds.x + axisBounds.width : axisBounds.x, axisBounds.y, position === 'left' ? axisBounds.x + axisBounds.width : axisBounds.x, axisBounds.y + axisBounds.height),
160
+ stroke: theme.color.fg,
161
+ strokeCap: "square",
162
+ strokeWidth: 1
163
+ }), label && /*#__PURE__*/_jsx(Group, {
164
+ origin: vec(labelX, labelY),
165
+ transform: [{
166
+ rotate: position === 'left' ? -Math.PI / 2 : Math.PI / 2
167
+ }],
168
+ children: /*#__PURE__*/_jsx(ChartText, {
169
+ horizontalAlignment: "center",
170
+ verticalAlignment: "middle",
171
+ x: labelX,
172
+ y: labelY,
173
+ children: label
162
174
  })
163
- }), axisBounds && showLine && /*#__PURE__*/_jsx(Line, _extends({}, axisLineProps, {
164
- x1: position === 'left' ? axisBounds.x + axisBounds.width : axisBounds.x,
165
- x2: position === 'left' ? axisBounds.x + axisBounds.width : axisBounds.x,
166
- y1: axisBounds.y,
167
- y2: axisBounds.y + axisBounds.height
168
- }))]
169
- }));
175
+ })]
176
+ });
170
177
  });
@@ -118,7 +118,6 @@ const TimeOfDayAxesExample = () => {
118
118
  }, [timeData]);
119
119
  return /*#__PURE__*/_jsxs(LineChart, {
120
120
  enableScrubbing: true,
121
- curve: "monotone",
122
121
  height: defaultChartHeight,
123
122
  series: [{
124
123
  id: 'lineA',
@@ -1,5 +1,6 @@
1
1
  // codegen:start {preset: barrel, include: ./*.tsx, exclude: ./__stories__/*.tsx}
2
2
  export * from './Axis';
3
+ export * from './DefaultAxisTickLabel';
3
4
  export * from './XAxis';
4
5
  export * from './YAxis';
5
6
  // codegen:end
@@ -31,7 +31,8 @@ export const Bar = /*#__PURE__*/memo(_ref => {
31
31
  strokeWidth,
32
32
  borderRadius = 4,
33
33
  roundTop = true,
34
- roundBottom = true
34
+ roundBottom = true,
35
+ transition
35
36
  } = _ref;
36
37
  const theme = useTheme();
37
38
 
@@ -60,6 +61,7 @@ export const Bar = /*#__PURE__*/memo(_ref => {
60
61
  roundTop: roundTop,
61
62
  stroke: stroke,
62
63
  strokeWidth: strokeWidth,
64
+ transition: transition,
63
65
  width: width,
64
66
  x: x,
65
67
  y: y