@coinbase/cds-mobile-visualization 3.4.0-beta.22 → 3.4.0-beta.24

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 (106) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dts/chart/CartesianChart.d.ts +58 -7
  3. package/dts/chart/CartesianChart.d.ts.map +1 -1
  4. package/dts/chart/Path.d.ts.map +1 -1
  5. package/dts/chart/area/Area.d.ts +7 -0
  6. package/dts/chart/area/Area.d.ts.map +1 -1
  7. package/dts/chart/area/AreaChart.d.ts +5 -5
  8. package/dts/chart/area/AreaChart.d.ts.map +1 -1
  9. package/dts/chart/area/DottedArea.d.ts.map +1 -1
  10. package/dts/chart/area/GradientArea.d.ts.map +1 -1
  11. package/dts/chart/area/SolidArea.d.ts.map +1 -1
  12. package/dts/chart/axis/Axis.d.ts +3 -1
  13. package/dts/chart/axis/Axis.d.ts.map +1 -1
  14. package/dts/chart/axis/XAxis.d.ts +6 -0
  15. package/dts/chart/axis/XAxis.d.ts.map +1 -1
  16. package/dts/chart/axis/YAxis.d.ts +1 -0
  17. package/dts/chart/axis/YAxis.d.ts.map +1 -1
  18. package/dts/chart/bar/Bar.d.ts +4 -2
  19. package/dts/chart/bar/Bar.d.ts.map +1 -1
  20. package/dts/chart/bar/BarChart.d.ts +49 -9
  21. package/dts/chart/bar/BarChart.d.ts.map +1 -1
  22. package/dts/chart/bar/BarPlot.d.ts.map +1 -1
  23. package/dts/chart/bar/BarStack.d.ts +30 -9
  24. package/dts/chart/bar/BarStack.d.ts.map +1 -1
  25. package/dts/chart/bar/BarStackGroup.d.ts +1 -1
  26. package/dts/chart/bar/BarStackGroup.d.ts.map +1 -1
  27. package/dts/chart/bar/DefaultBar.d.ts.map +1 -1
  28. package/dts/chart/bar/DefaultBarStack.d.ts.map +1 -1
  29. package/dts/chart/gradient/Gradient.d.ts +5 -0
  30. package/dts/chart/gradient/Gradient.d.ts.map +1 -1
  31. package/dts/chart/line/DottedLine.d.ts.map +1 -1
  32. package/dts/chart/line/Line.d.ts +7 -0
  33. package/dts/chart/line/Line.d.ts.map +1 -1
  34. package/dts/chart/line/LineChart.d.ts +22 -8
  35. package/dts/chart/line/LineChart.d.ts.map +1 -1
  36. package/dts/chart/line/ReferenceLine.d.ts +1 -0
  37. package/dts/chart/line/ReferenceLine.d.ts.map +1 -1
  38. package/dts/chart/line/SolidLine.d.ts.map +1 -1
  39. package/dts/chart/point/Point.d.ts +7 -0
  40. package/dts/chart/point/Point.d.ts.map +1 -1
  41. package/dts/chart/scrubber/DefaultScrubberBeacon.d.ts.map +1 -1
  42. package/dts/chart/scrubber/DefaultScrubberLabel.d.ts +2 -1
  43. package/dts/chart/scrubber/DefaultScrubberLabel.d.ts.map +1 -1
  44. package/dts/chart/scrubber/Scrubber.d.ts +8 -0
  45. package/dts/chart/scrubber/Scrubber.d.ts.map +1 -1
  46. package/dts/chart/scrubber/ScrubberAccessibilityView.d.ts +12 -0
  47. package/dts/chart/scrubber/ScrubberAccessibilityView.d.ts.map +1 -0
  48. package/dts/chart/scrubber/ScrubberBeaconGroup.d.ts.map +1 -1
  49. package/dts/chart/scrubber/ScrubberProvider.d.ts.map +1 -1
  50. package/dts/chart/utils/axis.d.ts +20 -9
  51. package/dts/chart/utils/axis.d.ts.map +1 -1
  52. package/dts/chart/utils/bar.d.ts +4 -3
  53. package/dts/chart/utils/bar.d.ts.map +1 -1
  54. package/dts/chart/utils/chart.d.ts +13 -0
  55. package/dts/chart/utils/chart.d.ts.map +1 -1
  56. package/dts/chart/utils/context.d.ts +21 -6
  57. package/dts/chart/utils/context.d.ts.map +1 -1
  58. package/dts/chart/utils/gradient.d.ts +3 -1
  59. package/dts/chart/utils/gradient.d.ts.map +1 -1
  60. package/dts/chart/utils/path.d.ts +20 -0
  61. package/dts/chart/utils/path.d.ts.map +1 -1
  62. package/dts/chart/utils/point.d.ts +7 -0
  63. package/dts/chart/utils/point.d.ts.map +1 -1
  64. package/esm/chart/CartesianChart.js +145 -81
  65. package/esm/chart/Path.js +10 -7
  66. package/esm/chart/__stories__/CartesianChart.stories.js +10 -0
  67. package/esm/chart/__stories__/ChartAccessibility.stories.js +721 -0
  68. package/esm/chart/area/Area.js +19 -9
  69. package/esm/chart/area/AreaChart.js +11 -9
  70. package/esm/chart/area/DottedArea.js +11 -6
  71. package/esm/chart/area/GradientArea.js +11 -6
  72. package/esm/chart/area/SolidArea.js +3 -1
  73. package/esm/chart/area/__stories__/AreaChart.stories.js +47 -5
  74. package/esm/chart/axis/XAxis.js +14 -21
  75. package/esm/chart/axis/YAxis.js +4 -3
  76. package/esm/chart/axis/__stories__/Axis.stories.js +65 -48
  77. package/esm/chart/bar/Bar.js +9 -5
  78. package/esm/chart/bar/BarChart.js +34 -31
  79. package/esm/chart/bar/BarPlot.js +7 -5
  80. package/esm/chart/bar/BarStack.js +176 -36
  81. package/esm/chart/bar/BarStackGroup.js +37 -27
  82. package/esm/chart/bar/DefaultBar.js +24 -8
  83. package/esm/chart/bar/DefaultBarStack.js +24 -10
  84. package/esm/chart/bar/__stories__/BarChart.stories.js +105 -3
  85. package/esm/chart/gradient/Gradient.js +2 -1
  86. package/esm/chart/line/DottedLine.js +3 -1
  87. package/esm/chart/line/Line.js +32 -19
  88. package/esm/chart/line/LineChart.js +31 -9
  89. package/esm/chart/line/SolidLine.js +3 -1
  90. package/esm/chart/line/__stories__/LineChart.stories.js +115 -46
  91. package/esm/chart/point/Point.js +2 -1
  92. package/esm/chart/scrubber/DefaultScrubberBeacon.js +1 -1
  93. package/esm/chart/scrubber/DefaultScrubberLabel.js +26 -10
  94. package/esm/chart/scrubber/Scrubber.js +47 -21
  95. package/esm/chart/scrubber/ScrubberAccessibilityView.js +177 -0
  96. package/esm/chart/scrubber/ScrubberBeaconGroup.js +24 -20
  97. package/esm/chart/scrubber/ScrubberProvider.js +29 -24
  98. package/esm/chart/scrubber/__stories__/Scrubber.stories.js +192 -6
  99. package/esm/chart/utils/axis.js +42 -14
  100. package/esm/chart/utils/bar.js +5 -4
  101. package/esm/chart/utils/chart.js +18 -5
  102. package/esm/chart/utils/context.js +7 -0
  103. package/esm/chart/utils/gradient.js +8 -4
  104. package/esm/chart/utils/path.js +90 -61
  105. package/esm/chart/utils/point.js +28 -18
  106. package/package.json +5 -5
@@ -22,23 +22,39 @@ export const DefaultBar = /*#__PURE__*/memo(_ref => {
22
22
  fillOpacity = 1,
23
23
  stroke,
24
24
  strokeWidth,
25
- originY,
25
+ origin,
26
26
  transitions,
27
27
  transition
28
28
  } = _ref;
29
29
  const {
30
30
  animate,
31
- drawingArea
31
+ drawingArea,
32
+ layout
32
33
  } = useCartesianChartContext();
33
34
  const theme = useTheme();
34
35
  const defaultFill = fill || theme.color.fgPrimary;
35
- const normalizedX = useMemo(() => drawingArea.width > 0 ? (x - drawingArea.x) / drawingArea.width : 0, [x, drawingArea.x, drawingArea.width]);
36
- const enterTransition = useMemo(() => withStaggerDelayTransition(getTransition(transitions == null ? void 0 : transitions.enter, animate, defaultBarEnterTransition), normalizedX), [transitions == null ? void 0 : transitions.enter, animate, normalizedX]);
37
- const updateTransition = useMemo(() => withStaggerDelayTransition(getTransition((transitions == null ? void 0 : transitions.update) !== undefined ? transitions.update : transition, animate, defaultTransition), normalizedX), [transitions == null ? void 0 : transitions.update, transition, animate, normalizedX]);
36
+
37
+ // For vertical layout, stagger by x (category axis). For horizontal, stagger by y (category axis).
38
+ const normalizedStagger = useMemo(() => {
39
+ const barsGrowVertically = layout !== 'horizontal';
40
+ if (barsGrowVertically) {
41
+ return drawingArea.width > 0 ? (x - drawingArea.x) / drawingArea.width : 0;
42
+ }
43
+ return drawingArea.height > 0 ? (y - drawingArea.y) / drawingArea.height : 0;
44
+ }, [layout, x, y, drawingArea.x, drawingArea.y, drawingArea.width, drawingArea.height]);
45
+ const enterTransition = useMemo(() => withStaggerDelayTransition(getTransition(transitions == null ? void 0 : transitions.enter, animate, defaultBarEnterTransition), normalizedStagger), [transitions == null ? void 0 : transitions.enter, animate, normalizedStagger]);
46
+ const updateTransition = useMemo(() => withStaggerDelayTransition(getTransition((transitions == null ? void 0 : transitions.update) !== undefined ? transitions.update : transition, animate, defaultTransition), normalizedStagger), [transitions == null ? void 0 : transitions.update, transition, animate, normalizedStagger]);
38
47
  const initialPath = useMemo(() => {
39
- const baselineY = originY != null ? originY : y + height;
40
- return getBarPath(x, baselineY, width, 1, borderRadius, !!roundTop, !!roundBottom);
41
- }, [x, originY, y, height, width, borderRadius, roundTop, roundBottom]);
48
+ if (!animate) return undefined;
49
+ const minSize = 1;
50
+ const barsGrowVertically = layout !== 'horizontal';
51
+ const baseline = origin != null ? origin : barsGrowVertically ? y + height : x;
52
+ const initialX = barsGrowVertically ? x : baseline;
53
+ const initialY = barsGrowVertically ? baseline : y;
54
+ const initialWidth = barsGrowVertically ? width : minSize;
55
+ const initialHeight = barsGrowVertically ? minSize : height;
56
+ return getBarPath(initialX, initialY, initialWidth, initialHeight, borderRadius, !!roundTop, !!roundBottom, layout);
57
+ }, [animate, layout, x, y, origin, width, height, borderRadius, roundTop, roundBottom]);
42
58
  return /*#__PURE__*/_jsx(Path, {
43
59
  animate: animate,
44
60
  clipPath: null,
@@ -24,24 +24,38 @@ export const DefaultBarStack = /*#__PURE__*/memo(_ref => {
24
24
  } = _ref;
25
25
  const {
26
26
  animate,
27
- drawingArea
27
+ drawingArea,
28
+ layout
28
29
  } = useCartesianChartContext();
29
30
 
30
- // Compute normalized x position for stagger delay calculation
31
- const normalizedX = useMemo(() => drawingArea.width > 0 ? (x - drawingArea.x) / drawingArea.width : 0, [x, drawingArea.x, drawingArea.width]);
32
- const enterTransition = useMemo(() => withStaggerDelayTransition(getTransition(transitions == null ? void 0 : transitions.enter, animate, defaultBarEnterTransition), normalizedX), [animate, transitions == null ? void 0 : transitions.enter, normalizedX]);
33
- const updateTransition = useMemo(() => withStaggerDelayTransition(getTransition((transitions == null ? void 0 : transitions.update) !== undefined ? transitions.update : transition, animate, defaultTransition), normalizedX), [animate, transitions == null ? void 0 : transitions.update, transition, normalizedX]);
31
+ // For vertical layout, stagger by x (category axis). For horizontal, stagger by y (category axis).
32
+ const normalizedStagger = useMemo(() => {
33
+ const barsGrowVertically = layout !== 'horizontal';
34
+ if (barsGrowVertically) {
35
+ return drawingArea.width > 0 ? (x - drawingArea.x) / drawingArea.width : 0;
36
+ }
37
+ return drawingArea.height > 0 ? (y - drawingArea.y) / drawingArea.height : 0;
38
+ }, [layout, x, y, drawingArea.x, drawingArea.y, drawingArea.width, drawingArea.height]);
39
+ const enterTransition = useMemo(() => withStaggerDelayTransition(getTransition(transitions == null ? void 0 : transitions.enter, animate, defaultBarEnterTransition), normalizedStagger), [animate, transitions == null ? void 0 : transitions.enter, normalizedStagger]);
40
+ const updateTransition = useMemo(() => withStaggerDelayTransition(getTransition((transitions == null ? void 0 : transitions.update) !== undefined ? transitions.update : transition, animate, defaultTransition), normalizedStagger), [animate, transitions == null ? void 0 : transitions.update, transition, normalizedStagger]);
34
41
 
35
42
  // Generate target clip path (full bar)
36
43
  const targetPath = useMemo(() => {
37
- return getBarPath(x, y, width, height, borderRadius, roundTop, roundBottom);
38
- }, [x, y, width, height, borderRadius, roundTop, roundBottom]);
44
+ return getBarPath(x, y, width, height, borderRadius, roundTop, roundBottom, layout);
45
+ }, [x, y, width, height, borderRadius, roundTop, roundBottom, layout]);
39
46
 
40
47
  // Initial clip path for entry animation (bar at baseline with minimal height)
41
48
  const initialPath = useMemo(() => {
42
- const baselineY = yOrigin != null ? yOrigin : y + height;
43
- return getBarPath(x, baselineY, width, 1, borderRadius, roundTop, roundBottom);
44
- }, [x, yOrigin, y, height, width, borderRadius, roundTop, roundBottom]);
49
+ if (!animate) return undefined;
50
+ const barsGrowVertically = layout !== 'horizontal';
51
+ const baseline = yOrigin != null ? yOrigin : barsGrowVertically ? y + height : x;
52
+ const minSize = 1;
53
+ const initialX = barsGrowVertically ? x : baseline;
54
+ const initialY = barsGrowVertically ? baseline : y;
55
+ const initialWidth = barsGrowVertically ? width : minSize;
56
+ const initialHeight = barsGrowVertically ? minSize : height;
57
+ return getBarPath(initialX, initialY, initialWidth, initialHeight, borderRadius, roundTop, roundBottom, layout);
58
+ }, [animate, layout, x, yOrigin, y, height, width, borderRadius, roundTop, roundBottom]);
45
59
  const animatedClipPath = usePathTransition({
46
60
  currentPath: targetPath,
47
61
  initialPath,
@@ -1,6 +1,6 @@
1
1
  const _excluded = ["children"],
2
2
  _excluded2 = ["animate"],
3
- _excluded3 = ["x", "y", "width", "height", "originY", "dataX"],
3
+ _excluded3 = ["x", "y", "width", "height", "dataX"],
4
4
  _excluded4 = ["data", "height"];
5
5
  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; }
6
6
  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); }
@@ -114,7 +114,7 @@ const CustomBarStackComponent = /*#__PURE__*/memo(_ref => {
114
114
  borderRadius: 1000,
115
115
  fill: theme.color.bgTertiary,
116
116
  height: diameter,
117
- originY: props.y,
117
+ origin: props.y,
118
118
  width: diameter,
119
119
  x: props.x,
120
120
  y: props.y - diameter
@@ -801,11 +801,17 @@ const CandlesticksChart = /*#__PURE__*/memo(_ref8 => {
801
801
  day: 'numeric'
802
802
  });
803
803
  }, []);
804
+ const getScrubberAccessibilityLabel = useCallback(index => {
805
+ const candle = candlestickStockData[index];
806
+ return formatTime(index) + ": O " + formatThousandsPriceNumber(parseFloat(candle.open)) + " H " + formatThousandsPriceNumber(parseFloat(candle.high)) + " L " + formatThousandsPriceNumber(parseFloat(candle.low)) + " C " + formatThousandsPriceNumber(parseFloat(candle.close));
807
+ }, [formatTime, formatThousandsPriceNumber]);
804
808
  return /*#__PURE__*/_jsxs(CartesianChart, {
805
809
  enableScrubbing: true,
810
+ accessibilityLabel: "Candlestick chart with " + candlesData.length + " data points. Swipe to navigate.",
806
811
  animate: false,
807
812
  "aria-labelledby": infoTextId,
808
813
  borderRadius: 0,
814
+ getScrubberAccessibilityLabel: getScrubberAccessibilityLabel,
809
815
  height: 150,
810
816
  inset: {
811
817
  top: 8,
@@ -975,7 +981,7 @@ const SunlightChartInner = /*#__PURE__*/memo(_ref10 => {
975
981
  type: 'spring',
976
982
  stiffness: 700,
977
983
  damping: 40,
978
- staggerDelay: 1
984
+ staggerDelay: 1000
979
985
  }
980
986
  }
981
987
  })]
@@ -1029,6 +1035,96 @@ const PriceRange = () => {
1029
1035
  }
1030
1036
  });
1031
1037
  };
1038
+ const HorizontalBarChart = () => {
1039
+ const labels = ['BTC', 'ETH', 'SOL', 'ADA'];
1040
+ const allocation = [42, 28, 18, 12];
1041
+ return /*#__PURE__*/_jsx(BarChart, {
1042
+ showXAxis: true,
1043
+ showYAxis: true,
1044
+ height: 220,
1045
+ layout: "horizontal",
1046
+ series: [{
1047
+ id: 'allocation',
1048
+ data: allocation,
1049
+ color: assets.btc.color
1050
+ }],
1051
+ xAxis: {
1052
+ domain: {
1053
+ min: 0,
1054
+ max: 50
1055
+ },
1056
+ tickLabelFormatter: value => value + "%"
1057
+ },
1058
+ yAxis: {
1059
+ data: labels,
1060
+ scaleType: 'band'
1061
+ }
1062
+ });
1063
+ };
1064
+ const PopulationPyramid = () => {
1065
+ const theme = useTheme();
1066
+ const ageGroups = ['100+ yrs', '95-99 yrs', '90-94 yrs', '85-89 yrs', '80-84 yrs', '75-79 yrs', '70-74 yrs', '65-69 yrs', '60-64 yrs', '55-59 yrs', '50-54 yrs', '45-49 yrs', '40-44 yrs', '35-39 yrs', '30-34 yrs', '25-29 yrs', '20-24 yrs', '15-19 yrs', '10-14 yrs', '5-9 yrs', '0-4 yrs'];
1067
+ const malePopulation = [14587, 48604, 83560, 128957, 184152, 248505, 498683, 706420, 852333, 939629, 1002195, 1001264, 960282, 1161371, 1105023, 1061755, 1019343, 1023264, 1026330, 984773, 944071];
1068
+ const femalePopulation = [14122, 46974, 80768, 124663, 178043, 240293, 482271, 683270, 824525, 909115, 969807, 969070, 929571, 1122380, 1068050, 1026356, 985483, 989404, 992505, 952453, 913222];
1069
+ const numberWithSuffixFormatter = useMemo(() => new Intl.NumberFormat('en-US', {
1070
+ notation: 'compact'
1071
+ }), []);
1072
+ const tickLabelFormatter = useCallback(value => numberWithSuffixFormatter.format(Math.abs(value)), [numberWithSuffixFormatter]);
1073
+ const domainSymmetric = useCallback(bounds => {
1074
+ const extremum = Math.max(-bounds.min, bounds.max);
1075
+ const roundedExtremum = Math.ceil(extremum / 100000) * 100000;
1076
+ return {
1077
+ min: -roundedExtremum,
1078
+ max: roundedExtremum
1079
+ };
1080
+ }, []);
1081
+ const series = [{
1082
+ id: 'male',
1083
+ label: 'Male',
1084
+ data: malePopulation.map(population => -population),
1085
+ color: "rgb(" + theme.spectrum.blue40 + ")",
1086
+ stackId: 'population'
1087
+ }, {
1088
+ id: 'female',
1089
+ label: 'Female',
1090
+ data: femalePopulation,
1091
+ color: "rgb(" + theme.spectrum.pink40 + ")",
1092
+ stackId: 'population'
1093
+ }];
1094
+ return /*#__PURE__*/_jsx(VStack, {
1095
+ gap: 2,
1096
+ children: /*#__PURE__*/_jsx(BarChart, {
1097
+ showXAxis: true,
1098
+ showYAxis: true,
1099
+ stacked: true,
1100
+ borderRadius: 2,
1101
+ height: 550,
1102
+ inset: 0,
1103
+ layout: "horizontal",
1104
+ series: series,
1105
+ xAxis: {
1106
+ domain: domainSymmetric,
1107
+ GridLineComponent: ThinSolidLine,
1108
+ showGrid: true,
1109
+ showLine: true,
1110
+ showTickMarks: true,
1111
+ tickLabelFormatter
1112
+ },
1113
+ yAxis: {
1114
+ bandTickMarkPlacement: 'edges',
1115
+ data: ageGroups,
1116
+ position: 'left',
1117
+ showLine: true,
1118
+ showTickMarks: true,
1119
+ width: 80
1120
+ },
1121
+ children: /*#__PURE__*/_jsx(ReferenceLine, {
1122
+ LineComponent: SolidLine,
1123
+ dataX: 0
1124
+ })
1125
+ })
1126
+ });
1127
+ };
1032
1128
  function ExampleNavigator() {
1033
1129
  const [currentIndex, setCurrentIndex] = useState(0);
1034
1130
  const examples = useMemo(() => [{
@@ -1093,6 +1189,12 @@ function ExampleNavigator() {
1093
1189
  }, {
1094
1190
  title: 'Price Range',
1095
1191
  component: /*#__PURE__*/_jsx(PriceRange, {})
1192
+ }, {
1193
+ title: 'Horizontal Layout',
1194
+ component: /*#__PURE__*/_jsx(HorizontalBarChart, {})
1195
+ }, {
1196
+ title: 'Population Pyramid',
1197
+ component: /*#__PURE__*/_jsx(PopulationPyramid, {})
1096
1198
  }], []);
1097
1199
  const currentExample = examples[currentIndex];
1098
1200
  const handlePrevious = useCallback(() => {
@@ -16,10 +16,11 @@ export const Gradient = /*#__PURE__*/memo(_ref => {
16
16
  var _gradient$axis;
17
17
  let {
18
18
  gradient,
19
+ xAxisId,
19
20
  yAxisId
20
21
  } = _ref;
21
22
  const context = useCartesianChartContext();
22
- const xScale = context.getXScale();
23
+ const xScale = context.getXScale(xAxisId);
23
24
  const yScale = context.getYScale(yAxisId);
24
25
  const axis = (_gradient$axis = gradient.axis) != null ? _gradient$axis : 'y';
25
26
  const scale = axis === 'x' ? xScale : yScale;
@@ -1,4 +1,4 @@
1
- const _excluded = ["fill", "stroke", "dashIntervals", "strokeCap", "strokeJoin", "strokeOpacity", "strokeWidth", "gradient", "yAxisId", "d", "animate", "transitions", "transition"];
1
+ const _excluded = ["fill", "stroke", "dashIntervals", "strokeCap", "strokeJoin", "strokeOpacity", "strokeWidth", "gradient", "xAxisId", "yAxisId", "d", "animate", "transitions", "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
4
  import { memo } from 'react';
@@ -21,6 +21,7 @@ export const DottedLine = /*#__PURE__*/memo(_ref => {
21
21
  strokeOpacity = 1,
22
22
  strokeWidth = 2,
23
23
  gradient,
24
+ xAxisId,
24
25
  yAxisId,
25
26
  d,
26
27
  animate,
@@ -46,6 +47,7 @@ export const DottedLine = /*#__PURE__*/memo(_ref => {
46
47
  intervals: dashIntervals
47
48
  }), gradient && /*#__PURE__*/_jsx(Gradient, {
48
49
  gradient: gradient,
50
+ xAxisId: xAxisId,
49
51
  yAxisId: yAxisId
50
52
  })]
51
53
  }));
@@ -36,36 +36,47 @@ export const Line = /*#__PURE__*/memo(_ref => {
36
36
  props = _objectWithoutPropertiesLoose(_ref, _excluded);
37
37
  const theme = useTheme();
38
38
  const {
39
+ layout,
39
40
  animate,
40
41
  getSeries,
41
42
  getSeriesData,
42
43
  getXScale,
43
44
  getYScale,
44
- getXAxis
45
+ getXAxis,
46
+ getYAxis
45
47
  } = useCartesianChartContext();
46
48
  const matchedSeries = useMemo(() => getSeries(seriesId), [getSeries, seriesId]);
47
49
  const gradient = useMemo(() => gradientProp != null ? gradientProp : matchedSeries == null ? void 0 : matchedSeries.gradient, [gradientProp, matchedSeries == null ? void 0 : matchedSeries.gradient]);
48
50
  const sourceData = useMemo(() => getSeriesData(seriesId), [getSeriesData, seriesId]);
49
- const xAxis = useMemo(() => getXAxis(), [getXAxis]);
50
- const xScale = useMemo(() => getXScale(), [getXScale]);
51
+ const xAxis = useMemo(() => getXAxis(matchedSeries == null ? void 0 : matchedSeries.xAxisId), [getXAxis, matchedSeries == null ? void 0 : matchedSeries.xAxisId]);
52
+ const xScale = useMemo(() => getXScale(matchedSeries == null ? void 0 : matchedSeries.xAxisId), [getXScale, matchedSeries == null ? void 0 : matchedSeries.xAxisId]);
51
53
  const yScale = useMemo(() => getYScale(matchedSeries == null ? void 0 : matchedSeries.yAxisId), [getYScale, matchedSeries == null ? void 0 : matchedSeries.yAxisId]);
54
+ const yAxis = useMemo(() => getYAxis(matchedSeries == null ? void 0 : matchedSeries.yAxisId), [getYAxis, matchedSeries == null ? void 0 : matchedSeries.yAxisId]);
52
55
 
53
56
  // Convert sourceData to number array (line only supports numbers, not tuples)
54
57
  const chartData = useMemo(() => getLineData(sourceData), [sourceData]);
58
+ const categoryAxisIsX = useMemo(() => {
59
+ return layout !== 'horizontal';
60
+ }, [layout]);
61
+ const categoryAxis = useMemo(() => {
62
+ return categoryAxisIsX ? xAxis : yAxis;
63
+ }, [categoryAxisIsX, xAxis, yAxis]);
55
64
  const path = useMemo(() => {
56
65
  if (!xScale || !yScale || chartData.length === 0) return '';
57
66
 
58
- // Get numeric x-axis data if available
59
- const xData = xAxis != null && xAxis.data && Array.isArray(xAxis.data) && typeof xAxis.data[0] === 'number' ? xAxis.data : undefined;
67
+ // Get numeric category-axis data if available.
68
+ const indexData = categoryAxis != null && categoryAxis.data && Array.isArray(categoryAxis.data) && typeof categoryAxis.data[0] === 'number' ? categoryAxis.data : undefined;
60
69
  return getLinePath({
61
70
  data: chartData,
62
71
  xScale,
63
72
  yScale,
64
73
  curve,
65
- xData,
66
- connectNulls
74
+ xData: categoryAxisIsX ? indexData : undefined,
75
+ yData: !categoryAxisIsX ? indexData : undefined,
76
+ connectNulls,
77
+ layout
67
78
  });
68
- }, [chartData, xScale, yScale, curve, xAxis == null ? void 0 : xAxis.data, connectNulls]);
79
+ }, [xScale, yScale, chartData, categoryAxis, curve, categoryAxisIsX, connectNulls, layout]);
69
80
  const LineComponent = useMemo(() => {
70
81
  if (SelectedLineComponent) {
71
82
  return SelectedLineComponent;
@@ -80,10 +91,10 @@ export const Line = /*#__PURE__*/memo(_ref => {
80
91
 
81
92
  // Get series color for stroke
82
93
  const stroke = (_ref2 = strokeProp != null ? strokeProp : matchedSeries == null ? void 0 : matchedSeries.color) != null ? _ref2 : theme.color.fgPrimary;
83
- const xData = useMemo(() => {
84
- const data = xAxis == null ? void 0 : xAxis.data;
94
+ const categoryData = useMemo(() => {
95
+ const data = categoryAxis == null ? void 0 : categoryAxis.data;
85
96
  return data && Array.isArray(data) && data.length > 0 && typeof data[0] === 'number' ? data : null;
86
- }, [xAxis == null ? void 0 : xAxis.data]);
97
+ }, [categoryAxis]);
87
98
  const gradientConfig = useMemo(() => {
88
99
  if (!gradient || !xScale || !yScale) return;
89
100
  const gradientScale = gradient.axis === 'x' ? xScale : yScale;
@@ -120,17 +131,18 @@ export const Line = /*#__PURE__*/memo(_ref => {
120
131
  strokeOpacity: strokeOpacity != null ? strokeOpacity : opacity,
121
132
  transition: transition,
122
133
  transitions: transitions,
134
+ xAxisId: matchedSeries == null ? void 0 : matchedSeries.xAxisId,
123
135
  yAxisId: matchedSeries == null ? void 0 : matchedSeries.yAxisId
124
136
  }, props)), points && /*#__PURE__*/_jsx(Group, {
125
137
  children: chartData.map((value, index) => {
126
138
  if (value === null) return;
127
- const xValue = xData && xData[index] !== undefined ? xData[index] : index;
139
+ const indexValue = categoryData && categoryData[index] !== undefined ? categoryData[index] : index;
128
140
  let pointFill = stroke;
129
141
  if (gradientConfig && gradient) {
130
142
  var _gradient$axis;
131
- // Use the appropriate data value based on gradient axis
132
- const axis = (_gradient$axis = gradient.axis) != null ? _gradient$axis : 'y';
133
- const dataValue = axis === 'x' ? xValue : value;
143
+ // Match gradient sampling to the chart axis roles for each layout.
144
+ const gradientAxis = (_gradient$axis = gradient.axis) != null ? _gradient$axis : 'y';
145
+ const dataValue = gradientAxis === 'x' ? categoryAxisIsX ? indexValue : value : categoryAxisIsX ? value : indexValue;
134
146
  const evaluatedColor = evaluateGradientAtValue(gradientConfig.stops, dataValue, gradientConfig.scale);
135
147
  if (evaluatedColor) {
136
148
  // Apply gradient color to fill if not explicitly set
@@ -140,9 +152,10 @@ export const Line = /*#__PURE__*/memo(_ref => {
140
152
 
141
153
  // Build defaults that would be passed to Point
142
154
  const defaults = {
143
- dataX: xValue,
144
- dataY: value,
155
+ dataX: categoryAxisIsX ? indexValue : value,
156
+ dataY: categoryAxisIsX ? value : indexValue,
145
157
  fill: pointFill,
158
+ xAxisId: matchedSeries == null ? void 0 : matchedSeries.xAxisId,
146
159
  yAxisId: matchedSeries == null ? void 0 : matchedSeries.yAxisId,
147
160
  opacity
148
161
  };
@@ -152,7 +165,7 @@ export const Line = /*#__PURE__*/memo(_ref => {
152
165
  return /*#__PURE__*/_jsx(Point, _extends({
153
166
  transition: transition,
154
167
  transitions: transitions
155
- }, defaults), seriesId + "-" + xValue);
168
+ }, defaults), seriesId + "-" + index);
156
169
  }
157
170
 
158
171
  // Call the function with defaults
@@ -162,7 +175,7 @@ export const Line = /*#__PURE__*/memo(_ref => {
162
175
  return /*#__PURE__*/_jsx(Point, _extends({
163
176
  transition: transition,
164
177
  transitions: transitions
165
- }, defaults, pointConfig), seriesId + "-" + xValue);
178
+ }, defaults, pointConfig), seriesId + "-" + index);
166
179
  })
167
180
  })]
168
181
  });
@@ -1,16 +1,22 @@
1
- const _excluded = ["series", "showArea", "areaType", "type", "LineComponent", "AreaComponent", "curve", "points", "strokeWidth", "strokeOpacity", "connectNulls", "transition", "transitions", "opacity", "showXAxis", "showYAxis", "xAxis", "yAxis", "inset", "children"],
2
- _excluded2 = ["scaleType", "data", "categoryPadding", "domain", "domainLimit", "range"],
1
+ const _excluded = ["series", "showArea", "areaType", "type", "LineComponent", "AreaComponent", "curve", "points", "strokeWidth", "strokeOpacity", "connectNulls", "transition", "transitions", "opacity", "showXAxis", "showYAxis", "xAxis", "yAxis", "inset", "scrubberAccessibilityLabelStep", "layout", "children"],
2
+ _excluded2 = ["scaleType", "data", "categoryPadding", "domain", "domainLimit", "range", "id"],
3
3
  _excluded3 = ["scaleType", "data", "categoryPadding", "domain", "domainLimit", "range", "id"],
4
- _excluded4 = ["id", "data", "label", "color", "yAxisId"];
4
+ _excluded4 = ["id", "data", "label", "color", "xAxisId", "yAxisId"];
5
5
  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); }
6
6
  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; }
7
7
  import { forwardRef, memo, useMemo } from 'react';
8
8
  import { XAxis } from '../axis/XAxis';
9
9
  import { YAxis } from '../axis/YAxis';
10
10
  import { CartesianChart } from '../CartesianChart';
11
- import { defaultChartInset, getChartInset } from '../utils';
12
11
  import { Line } from './Line';
13
12
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
+ const getDefaultScrubberAccessibilityStep = function (dataLength, sampleCount) {
14
+ if (sampleCount === void 0) {
15
+ sampleCount = 10;
16
+ }
17
+ if (dataLength <= 0) return 1;
18
+ return Math.max(1, Math.ceil(dataLength / sampleCount));
19
+ };
14
20
  export const LineChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, ref) => {
15
21
  let {
16
22
  series,
@@ -32,11 +38,11 @@ export const LineChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, ref) =
32
38
  xAxis,
33
39
  yAxis,
34
40
  inset,
41
+ scrubberAccessibilityLabelStep,
42
+ layout = 'vertical',
35
43
  children
36
44
  } = _ref,
37
45
  chartProps = _objectWithoutPropertiesLoose(_ref, _excluded);
38
- const calculatedInset = useMemo(() => getChartInset(inset, defaultChartInset), [inset]);
39
-
40
46
  // Convert LineSeries to Series for Chart context
41
47
  const chartSeries = useMemo(() => {
42
48
  return series == null ? void 0 : series.map(s => ({
@@ -44,6 +50,7 @@ export const LineChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, ref) =
44
50
  data: s.data,
45
51
  label: s.label,
46
52
  color: s.color,
53
+ xAxisId: s.xAxisId,
47
54
  yAxisId: s.yAxisId,
48
55
  stackId: s.stackId,
49
56
  gradient: s.gradient,
@@ -59,7 +66,8 @@ export const LineChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, ref) =
59
66
  categoryPadding: xCategoryPadding,
60
67
  domain: xDomain,
61
68
  domainLimit: xDomainLimit,
62
- range: xRange
69
+ range: xRange,
70
+ id: xAxisId
63
71
  } = _ref2,
64
72
  xAxisVisualProps = _objectWithoutPropertiesLoose(_ref2, _excluded2);
65
73
  const _ref3 = yAxis || {},
@@ -89,13 +97,27 @@ export const LineChart = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, ref) =
89
97
  domainLimit: yDomainLimit,
90
98
  range: yRange
91
99
  };
100
+ const categoryAxisData = layout === 'horizontal' ? yData : xData;
101
+ const lineChartDataLength = useMemo(() => {
102
+ if (categoryAxisData && categoryAxisData.length > 0) return categoryAxisData.length;
103
+ if (!series || series.length === 0) return 0;
104
+ return series.reduce((max, s) => {
105
+ var _s$data$length, _s$data;
106
+ return Math.max(max, (_s$data$length = (_s$data = s.data) == null ? void 0 : _s$data.length) != null ? _s$data$length : 0);
107
+ }, 0);
108
+ }, [categoryAxisData, series]);
109
+ const resolvedScrubberAccessibilityLabelStep = useMemo(() => scrubberAccessibilityLabelStep != null ? scrubberAccessibilityLabelStep : getDefaultScrubberAccessibilityStep(lineChartDataLength), [scrubberAccessibilityLabelStep, lineChartDataLength]);
92
110
  return /*#__PURE__*/_jsxs(CartesianChart, _extends({}, chartProps, {
93
111
  ref: ref,
94
- inset: calculatedInset,
112
+ inset: inset,
113
+ layout: layout,
114
+ scrubberAccessibilityLabelStep: resolvedScrubberAccessibilityLabelStep,
95
115
  series: chartSeries,
96
116
  xAxis: xAxisConfig,
97
117
  yAxis: yAxisConfig,
98
- children: [showXAxis && /*#__PURE__*/_jsx(XAxis, _extends({}, xAxisVisualProps)), showYAxis && /*#__PURE__*/_jsx(YAxis, _extends({
118
+ children: [showXAxis && /*#__PURE__*/_jsx(XAxis, _extends({
119
+ axisId: xAxisId
120
+ }, xAxisVisualProps)), showYAxis && /*#__PURE__*/_jsx(YAxis, _extends({
99
121
  axisId: yAxisId
100
122
  }, yAxisVisualProps)), series == null ? void 0 : series.map(_ref4 => {
101
123
  let {
@@ -1,4 +1,4 @@
1
- const _excluded = ["fill", "stroke", "strokeCap", "strokeJoin", "strokeOpacity", "strokeWidth", "gradient", "yAxisId", "d", "animate", "transitions", "transition"];
1
+ const _excluded = ["fill", "stroke", "strokeCap", "strokeJoin", "strokeOpacity", "strokeWidth", "gradient", "xAxisId", "yAxisId", "d", "animate", "transitions", "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
4
  import { memo } from 'react';
@@ -19,6 +19,7 @@ export const SolidLine = /*#__PURE__*/memo(_ref => {
19
19
  strokeOpacity = 1,
20
20
  strokeWidth = 2,
21
21
  gradient,
22
+ xAxisId,
22
23
  yAxisId,
23
24
  d,
24
25
  animate,
@@ -42,6 +43,7 @@ export const SolidLine = /*#__PURE__*/memo(_ref => {
42
43
  }, props, {
43
44
  children: gradient && /*#__PURE__*/_jsx(Gradient, {
44
45
  gradient: gradient,
46
+ xAxisId: xAxisId,
45
47
  yAxisId: yAxisId
46
48
  })
47
49
  }));