@coinbase/cds-web-visualization 3.4.0-beta.22 → 3.4.0-beta.23

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 (96) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dts/chart/CartesianChart.d.ts +23 -4
  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 +3 -3
  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 +10 -10
  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 -3
  19. package/dts/chart/bar/Bar.d.ts.map +1 -1
  20. package/dts/chart/bar/BarChart.d.ts +25 -5
  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 +47 -12
  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 +7 -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 +3 -3
  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/ScrubberBeaconGroup.d.ts.map +1 -1
  47. package/dts/chart/scrubber/ScrubberProvider.d.ts.map +1 -1
  48. package/dts/chart/utils/axis.d.ts +23 -8
  49. package/dts/chart/utils/axis.d.ts.map +1 -1
  50. package/dts/chart/utils/bar.d.ts +4 -3
  51. package/dts/chart/utils/bar.d.ts.map +1 -1
  52. package/dts/chart/utils/chart.d.ts +13 -0
  53. package/dts/chart/utils/chart.d.ts.map +1 -1
  54. package/dts/chart/utils/context.d.ts +20 -4
  55. package/dts/chart/utils/context.d.ts.map +1 -1
  56. package/dts/chart/utils/gradient.d.ts +3 -1
  57. package/dts/chart/utils/gradient.d.ts.map +1 -1
  58. package/dts/chart/utils/path.d.ts +20 -0
  59. package/dts/chart/utils/path.d.ts.map +1 -1
  60. package/dts/chart/utils/point.d.ts +7 -0
  61. package/dts/chart/utils/point.d.ts.map +1 -1
  62. package/esm/chart/CartesianChart.js +89 -57
  63. package/esm/chart/Path.js +15 -6
  64. package/esm/chart/area/Area.js +19 -9
  65. package/esm/chart/area/AreaChart.js +16 -14
  66. package/esm/chart/area/DottedArea.js +11 -6
  67. package/esm/chart/area/GradientArea.js +11 -6
  68. package/esm/chart/area/SolidArea.js +3 -1
  69. package/esm/chart/axis/XAxis.js +11 -12
  70. package/esm/chart/axis/YAxis.js +4 -4
  71. package/esm/chart/bar/Bar.js +11 -5
  72. package/esm/chart/bar/BarChart.js +34 -31
  73. package/esm/chart/bar/BarPlot.js +6 -3
  74. package/esm/chart/bar/BarStack.js +155 -356
  75. package/esm/chart/bar/BarStackGroup.js +36 -27
  76. package/esm/chart/bar/DefaultBar.js +26 -10
  77. package/esm/chart/bar/DefaultBarStack.js +27 -13
  78. package/esm/chart/gradient/Gradient.js +3 -2
  79. package/esm/chart/line/DottedLine.js +3 -1
  80. package/esm/chart/line/Line.js +29 -16
  81. package/esm/chart/line/LineChart.js +10 -8
  82. package/esm/chart/line/SolidLine.js +3 -1
  83. package/esm/chart/point/Point.js +3 -2
  84. package/esm/chart/scrubber/DefaultScrubberBeacon.js +1 -1
  85. package/esm/chart/scrubber/DefaultScrubberLabel.js +26 -8
  86. package/esm/chart/scrubber/Scrubber.js +34 -27
  87. package/esm/chart/scrubber/ScrubberBeaconGroup.js +49 -32
  88. package/esm/chart/scrubber/ScrubberProvider.js +44 -39
  89. package/esm/chart/utils/axis.js +44 -13
  90. package/esm/chart/utils/bar.js +5 -4
  91. package/esm/chart/utils/chart.js +18 -5
  92. package/esm/chart/utils/context.js +7 -0
  93. package/esm/chart/utils/gradient.js +6 -4
  94. package/esm/chart/utils/path.js +87 -61
  95. package/esm/chart/utils/point.js +30 -21
  96. package/package.json +5 -5
@@ -45,15 +45,16 @@ export const getChartDomain = (series, min, max) => {
45
45
  };
46
46
 
47
47
  /**
48
- * Creates a composite stack key that includes both stack ID and y-axis ID.
49
- * This ensures series with different y-scales don't get stacked together.
48
+ * Creates a composite stack key that includes stack ID and axis IDs.
49
+ * This ensures series with different scales don't get stacked together.
50
50
  */
51
51
  const createStackKey = series => {
52
52
  if (series.stackId === undefined) return undefined;
53
53
 
54
- // Include y-axis ID to prevent cross-scale stacking
54
+ // Include axis IDs to prevent cross-scale stacking
55
+ const xAxisId = series.xAxisId || 'default';
55
56
  const yAxisId = series.yAxisId || 'default';
56
- return "".concat(series.stackId, ":").concat(yAxisId);
57
+ return "".concat(series.stackId, ":").concat(xAxisId, ":").concat(yAxisId);
57
58
  };
58
59
 
59
60
  /**
@@ -224,12 +225,24 @@ export const getChartRange = (series, min, max) => {
224
225
  }
225
226
  return range;
226
227
  };
227
- export const defaultChartInset = {
228
+ export const defaultVerticalLayoutChartInset = {
228
229
  top: 32,
229
230
  left: 16,
230
231
  bottom: 16,
231
232
  right: 16
232
233
  };
234
+ export const defaultHorizontalLayoutChartInset = {
235
+ top: 16,
236
+ left: 16,
237
+ bottom: 16,
238
+ right: 48
239
+ };
240
+
241
+ /**
242
+ * @deprecated Use `defaultVerticalLayoutChartInset` for vertical layout charts or
243
+ * `defaultHorizontalLayoutChartInset` for horizontal layout charts.
244
+ */
245
+ export const defaultChartInset = defaultVerticalLayoutChartInset;
233
246
 
234
247
  /**
235
248
  * Normalize padding to include all sides with a value.
@@ -1,5 +1,12 @@
1
1
  import { createContext, useContext } from 'react';
2
2
 
3
+ /**
4
+ * Chart layout for Cartesian charts.
5
+ * Describes the direction bars/areas grow.
6
+ * - 'vertical': Bars grow vertically (up/down). X is category axis, Y is value axis.
7
+ * - 'horizontal': Bars grow horizontally (left/right). Y is category axis, X is value axis.
8
+ */
9
+
3
10
  /**
4
11
  * Context value for Cartesian (X/Y) coordinate charts.
5
12
  * Contains axis-specific methods and properties for rectangular coordinate systems.
@@ -214,9 +214,11 @@ export const getBaseline = function (axisBounds) {
214
214
  * @param fill - The color to use for the gradient
215
215
  * @param peakOpacity - Opacity at the peak of the gradient
216
216
  * @param baselineOpacity - Opacity at the baseline
217
- * @returns A gradient definition with y-axis stops in ascending order
217
+ * @param axis - The axis the gradient maps to ('y' for vertical, 'x' for horizontal layout)
218
+ * @returns A gradient definition with stops in ascending order
218
219
  */
219
- export const createGradient = (axisBounds, baselineValue, fill, peakOpacity, baselineOpacity) => {
220
+ export const createGradient = function (axisBounds, baselineValue, fill, peakOpacity, baselineOpacity) {
221
+ let axis = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : 'y';
220
222
  const {
221
223
  min,
222
224
  max
@@ -225,7 +227,7 @@ export const createGradient = (axisBounds, baselineValue, fill, peakOpacity, bas
225
227
  const upperBound = Math.max(min, max);
226
228
  if (lowerBound < baselineValue && baselineValue < upperBound) {
227
229
  return {
228
- axis: 'y',
230
+ axis,
229
231
  stops: [{
230
232
  offset: lowerBound,
231
233
  color: fill,
@@ -243,7 +245,7 @@ export const createGradient = (axisBounds, baselineValue, fill, peakOpacity, bas
243
245
  }
244
246
  const peakValue = Math.abs(min - baselineValue) > Math.abs(max - baselineValue) ? min : max;
245
247
  return {
246
- axis: 'y',
248
+ axis,
247
249
  stops: [{
248
250
  offset: peakValue,
249
251
  color: fill,
@@ -1,5 +1,5 @@
1
- import { area as d3Area, curveBumpX, curveCatmullRom, curveLinear, curveLinearClosed, curveMonotoneX, curveNatural, curveStep, curveStepAfter, curveStepBefore, line as d3Line } from 'd3-shape';
2
- import { projectPoint, projectPoints } from './point';
1
+ import { area as d3Area, curveBumpX, curveBumpY, curveCatmullRom, curveLinear, curveLinearClosed, curveMonotoneX, curveMonotoneY, curveNatural, curveStep, curveStepAfter, curveStepBefore, line as d3Line } from 'd3-shape';
2
+ import { getPointOnScale, projectPoints } from './point';
3
3
  import { isCategoricalScale } from './scale';
4
4
 
5
5
  /**
@@ -14,16 +14,19 @@ export const defaultPathEnterTransition = {
14
14
  * Get the d3 curve function for a path.
15
15
  * See https://d3js.org/d3-shape/curve
16
16
  * @param curve - The curve type. Defaults to 'linear'.
17
+ * @param layout - The chart layout. Defaults to 'vertical'.
17
18
  * @returns The d3 curve function.
18
19
  */
19
20
  export const getPathCurveFunction = function () {
20
21
  let curve = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'linear';
22
+ let layout = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'vertical';
21
23
  switch (curve) {
22
24
  case 'catmullRom':
23
25
  return curveCatmullRom;
24
26
  case 'monotone':
25
- // When we support layout="vertical" this should dynamically switch to curveMonotoneY
26
- return curveMonotoneX;
27
+ // For vertical layout, X is the independent axis (category/index), so use MonotoneX
28
+ // For horizontal layout, Y is the independent axis (category/index), so use MonotoneY
29
+ return layout !== 'horizontal' ? curveMonotoneX : curveMonotoneY;
27
30
  case 'natural':
28
31
  return curveNatural;
29
32
  case 'step':
@@ -33,8 +36,9 @@ export const getPathCurveFunction = function () {
33
36
  case 'stepAfter':
34
37
  return curveStepAfter;
35
38
  case 'bump':
36
- // When we support layout="vertical" this should dynamically switch to curveBumpY
37
- return curveBumpX;
39
+ // For vertical layout, X is the independent axis (category/index), so use BumpX
40
+ // For horizontal layout, Y is the independent axis (category/index), so use BumpY
41
+ return layout !== 'horizontal' ? curveBumpX : curveBumpY;
38
42
  case 'linearClosed':
39
43
  return curveLinearClosed;
40
44
  case 'linear':
@@ -60,17 +64,21 @@ export const getLinePath = _ref => {
60
64
  xScale,
61
65
  yScale,
62
66
  xData,
63
- connectNulls
67
+ yData,
68
+ connectNulls,
69
+ layout = 'vertical'
64
70
  } = _ref;
65
71
  if (data.length === 0) {
66
72
  return '';
67
73
  }
68
- const curveFunction = getPathCurveFunction(curve);
74
+ const curveFunction = getPathCurveFunction(curve, layout);
69
75
  const dataPoints = projectPoints({
70
76
  data,
71
77
  xScale,
72
78
  yScale,
73
- xData
79
+ xData,
80
+ yData,
81
+ layout
74
82
  });
75
83
 
76
84
  // When connectNulls is true, filter out null values before rendering
@@ -109,15 +117,21 @@ export const getAreaPath = _ref2 => {
109
117
  xScale,
110
118
  yScale,
111
119
  xData,
112
- connectNulls
120
+ yData,
121
+ connectNulls,
122
+ layout = 'vertical'
113
123
  } = _ref2;
114
124
  if (data.length === 0) {
115
125
  return '';
116
126
  }
117
- const curveFunction = getPathCurveFunction(curve);
118
- const yDomain = yScale.domain();
119
- const yMin = Math.min(...yDomain);
120
- const normalizedData = data.map((item, index) => {
127
+ const curveFunction = getPathCurveFunction(curve, layout);
128
+ const categoryAxisIsX = layout !== 'horizontal';
129
+
130
+ // Determine baseline from the value scale
131
+ const valueScale = categoryAxisIsX ? yScale : xScale;
132
+ const domain = valueScale.domain();
133
+ const min = Math.min(...domain);
134
+ const normalizedData = data.map(item => {
121
135
  if (item === null) {
122
136
  return null;
123
137
  }
@@ -128,7 +142,7 @@ export const getAreaPath = _ref2 => {
128
142
  return null;
129
143
  }
130
144
  if (typeof item === 'number') {
131
- return [yMin, item];
145
+ return [min, item];
132
146
  }
133
147
  return null;
134
148
  });
@@ -136,37 +150,28 @@ export const getAreaPath = _ref2 => {
136
150
  if (range === null) {
137
151
  return {
138
152
  x: 0,
153
+ y: 0,
139
154
  low: null,
140
155
  high: null,
141
156
  isValid: false
142
157
  };
143
158
  }
144
- let xValue = index;
145
- if (!isCategoricalScale(xScale) && xData && xData[index] !== undefined) {
146
- xValue = xData[index];
159
+
160
+ // Determine the position along the independent (index) axis
161
+ let indexValue = index;
162
+ const indexScale = categoryAxisIsX ? xScale : yScale;
163
+ const indexData = categoryAxisIsX ? xData : yData;
164
+ if (!isCategoricalScale(indexScale) && indexData && indexData[index] !== undefined) {
165
+ indexValue = indexData[index];
147
166
  }
148
- const xPoint = projectPoint({
149
- x: xValue,
150
- y: 0,
151
- xScale,
152
- yScale
153
- });
154
- const lowPoint = projectPoint({
155
- x: xValue,
156
- y: range[0],
157
- xScale,
158
- yScale
159
- });
160
- const highPoint = projectPoint({
161
- x: xValue,
162
- y: range[1],
163
- xScale,
164
- yScale
165
- });
167
+ const pos = getPointOnScale(indexValue, indexScale);
168
+ const low = getPointOnScale(range[0], valueScale);
169
+ const high = getPointOnScale(range[1], valueScale);
166
170
  return {
167
- x: xPoint.x,
168
- low: lowPoint.y,
169
- high: highPoint.y,
171
+ x: categoryAxisIsX ? pos : 0,
172
+ y: !categoryAxisIsX ? pos : 0,
173
+ low,
174
+ high,
170
175
  isValid: true
171
176
  };
172
177
  });
@@ -174,16 +179,25 @@ export const getAreaPath = _ref2 => {
174
179
  // When connectNulls is true, filter out invalid points before rendering
175
180
  // When false, use defined() to create gaps in the area
176
181
  const filteredPoints = connectNulls ? dataPoints.filter(d => d.isValid) : dataPoints;
177
- const areaGenerator = d3Area().x(d => d.x).y0(d => {
178
- var _d$low;
179
- return (_d$low = d.low) !== null && _d$low !== void 0 ? _d$low : 0;
180
- }) // Bottom boundary (low values), fallback to 0
181
- .y1(d => {
182
- var _d$high;
183
- return (_d$high = d.high) !== null && _d$high !== void 0 ? _d$high : 0;
184
- }) // Top boundary (high values), fallback to 0
185
- .curve(curveFunction).defined(d => connectNulls || d.isValid && d.low != null && d.high != null); // Only draw where both values exist
186
-
182
+ const areaGenerator = d3Area();
183
+ if (categoryAxisIsX) {
184
+ areaGenerator.x(d => d.x).y0(d => {
185
+ var _d$low;
186
+ return (_d$low = d.low) !== null && _d$low !== void 0 ? _d$low : 0;
187
+ }).y1(d => {
188
+ var _d$high;
189
+ return (_d$high = d.high) !== null && _d$high !== void 0 ? _d$high : 0;
190
+ });
191
+ } else {
192
+ areaGenerator.y(d => d.y).x0(d => {
193
+ var _d$low2;
194
+ return (_d$low2 = d.low) !== null && _d$low2 !== void 0 ? _d$low2 : 0;
195
+ }).x1(d => {
196
+ var _d$high2;
197
+ return (_d$high2 = d.high) !== null && _d$high2 !== void 0 ? _d$high2 : 0;
198
+ });
199
+ }
200
+ areaGenerator.curve(curveFunction).defined(d => connectNulls || d.isValid && d.low != null && d.high != null);
187
201
  const result = areaGenerator(filteredPoints);
188
202
  return result !== null && result !== void 0 ? result : '';
189
203
  };
@@ -215,22 +229,34 @@ export const lineToPath = (x1, y1, x2, y2) => {
215
229
  * const roundedPath = getBarPath(10, 20, 50, 100, 8, true, false);
216
230
  * ```
217
231
  */
218
- export const getBarPath = (x, y, width, height, radius, roundTop, roundBottom) => {
232
+ export const getBarPath = function (x, y, width, height, radius, roundTop, roundBottom) {
233
+ let layout = arguments.length > 7 && arguments[7] !== undefined ? arguments[7] : 'vertical';
219
234
  const roundBothSides = roundTop && roundBottom;
235
+ const barsGrowVertically = layout !== 'horizontal';
220
236
  const r = Math.min(radius, width / 2, roundBothSides ? height / 2 : height);
221
- const topR = roundTop ? r : 0;
222
- const bottomR = roundBottom ? r : 0;
237
+
238
+ // In vertical layout (bars grow up/down):
239
+ // - roundTop rounds the top face (min Y)
240
+ // - roundBottom rounds the bottom face (max Y)
241
+ // In horizontal layout (bars grow left/right):
242
+ // - roundTop rounds the right face (max X)
243
+ // - roundBottom rounds the left face (min X)
244
+
245
+ const rTL = barsGrowVertically ? roundTop ? r : 0 : roundBottom ? r : 0;
246
+ const rTR = barsGrowVertically ? roundTop ? r : 0 : roundTop ? r : 0;
247
+ const rBR = barsGrowVertically ? roundBottom ? r : 0 : roundTop ? r : 0;
248
+ const rBL = barsGrowVertically ? roundBottom ? r : 0 : roundBottom ? r : 0;
223
249
 
224
250
  // Build path with selective rounding
225
- let path = "M ".concat(x + (roundTop ? r : 0), " ").concat(y);
226
- path += " L ".concat(x + width - topR, " ").concat(y);
227
- path += " A ".concat(topR, " ").concat(topR, " 0 0 1 ").concat(x + width, " ").concat(y + topR);
228
- path += " L ".concat(x + width, " ").concat(y + height - bottomR);
229
- path += " A ".concat(bottomR, " ").concat(bottomR, " 0 0 1 ").concat(x + width - bottomR, " ").concat(y + height);
230
- path += " L ".concat(x + bottomR, " ").concat(y + height);
231
- path += " A ".concat(bottomR, " ").concat(bottomR, " 0 0 1 ").concat(x, " ").concat(y + height - bottomR);
232
- path += " L ".concat(x, " ").concat(y + topR);
233
- path += " A ".concat(topR, " ").concat(topR, " 0 0 1 ").concat(x + topR, " ").concat(y);
251
+ let path = "M ".concat(x + rTL, " ").concat(y);
252
+ path += " L ".concat(x + width - rTR, " ").concat(y);
253
+ path += " A ".concat(rTR, " ").concat(rTR, " 0 0 1 ").concat(x + width, " ").concat(y + rTR);
254
+ path += " L ".concat(x + width, " ").concat(y + height - rBR);
255
+ path += " A ".concat(rBR, " ").concat(rBR, " 0 0 1 ").concat(x + width - rBR, " ").concat(y + height);
256
+ path += " L ".concat(x + rBL, " ").concat(y + height);
257
+ path += " A ".concat(rBL, " ").concat(rBL, " 0 0 1 ").concat(x, " ").concat(y + height - rBL);
258
+ path += " L ".concat(x, " ").concat(y + rTL);
259
+ path += " A ".concat(rTL, " ").concat(rTL, " 0 0 1 ").concat(x + rTL, " ").concat(y);
234
260
  path += ' Z';
235
261
  return path;
236
262
  };
@@ -1,4 +1,4 @@
1
- import { isCategoricalScale, isLogScale, isNumericScale } from './scale';
1
+ import { isCategoricalScale, isLogScale } from './scale';
2
2
 
3
3
  /**
4
4
  * Position a label should be placed relative to the point
@@ -33,13 +33,12 @@ export const getPointOnScale = function (dataValue, scale) {
33
33
  return stepStart;
34
34
  case 'bandStart':
35
35
  return bandStart;
36
+ case 'middle':
37
+ return bandStart + bandwidth / 2;
36
38
  case 'bandEnd':
37
39
  return bandStart + bandwidth;
38
40
  case 'stepEnd':
39
41
  return stepStart + step;
40
- case 'middle':
41
- default:
42
- return bandStart + bandwidth / 2;
43
42
  }
44
43
  }
45
44
 
@@ -97,7 +96,8 @@ export const projectPoints = _ref2 => {
97
96
  xScale,
98
97
  yScale,
99
98
  xData,
100
- yData
99
+ yData,
100
+ layout = 'vertical'
101
101
  } = _ref2;
102
102
  if (data.length === 0) {
103
103
  return [];
@@ -115,28 +115,37 @@ export const projectPoints = _ref2 => {
115
115
  });
116
116
  }
117
117
 
118
- // For scales with axis data, determine the correct x value
119
- let xValue = index;
118
+ // Determine values/scales based on role (index vs value) and layout.
119
+ const categoryAxisIsX = layout !== 'horizontal';
120
+ const indexScale = categoryAxisIsX ? xScale : yScale;
121
+ const indexData = categoryAxisIsX ? xData : yData;
120
122
 
121
- // For band scales, always use the index
122
- if (!isCategoricalScale(xScale)) {
123
- // For numeric scales with axis data, use the axis data values instead of indices
124
- if (xData && Array.isArray(xData) && xData.length > 0) {
125
- // Check if it's numeric data
126
- if (typeof xData[0] === 'number') {
127
- var _numericXData$index;
128
- const numericXData = xData;
129
- xValue = (_numericXData$index = numericXData[index]) !== null && _numericXData$index !== void 0 ? _numericXData$index : index;
123
+ // 1. Calculate position along the index axis (categorical or numeric domain).
124
+ let indexValue = index;
125
+ if (!isCategoricalScale(indexScale)) {
126
+ if (indexData && Array.isArray(indexData) && indexData.length > 0) {
127
+ if (typeof indexData[0] === 'number') {
128
+ var _index;
129
+ indexValue = (_index = indexData[index]) !== null && _index !== void 0 ? _index : index;
130
130
  }
131
131
  }
132
132
  }
133
- let yValue = value;
134
- if (isNumericScale(yScale) && yData && Array.isArray(yData) && yData.length > 0 && typeof yData[0] === 'number' && typeof value === 'number') {
135
- yValue = value;
133
+
134
+ // 2. Calculate position along the value axis (measured magnitude).
135
+ const valueAsNumber = value;
136
+
137
+ // 3. Project final coordinates based on layout.
138
+ if (categoryAxisIsX) {
139
+ return projectPoint({
140
+ x: indexValue,
141
+ y: valueAsNumber,
142
+ xScale,
143
+ yScale
144
+ });
136
145
  }
137
146
  return projectPoint({
138
- x: xValue,
139
- y: yValue,
147
+ x: valueAsNumber,
148
+ y: indexValue,
140
149
  xScale,
141
150
  yScale
142
151
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coinbase/cds-web-visualization",
3
- "version": "3.4.0-beta.22",
3
+ "version": "3.4.0-beta.23",
4
4
  "description": "Coinbase Design System - Web Sparkline",
5
5
  "repository": {
6
6
  "type": "git",
@@ -38,10 +38,10 @@
38
38
  "CHANGELOG"
39
39
  ],
40
40
  "peerDependencies": {
41
- "@coinbase/cds-common": "^8.49.0",
41
+ "@coinbase/cds-common": "^8.52.0",
42
42
  "@coinbase/cds-lottie-files": "^3.3.4",
43
43
  "@coinbase/cds-utils": "^2.3.5",
44
- "@coinbase/cds-web": "^8.49.0",
44
+ "@coinbase/cds-web": "^8.52.0",
45
45
  "framer-motion": "^10.18.0",
46
46
  "react": "^18.3.1",
47
47
  "react-dom": "^18.3.1"
@@ -59,10 +59,10 @@
59
59
  "@babel/preset-env": "^7.28.0",
60
60
  "@babel/preset-react": "^7.27.1",
61
61
  "@babel/preset-typescript": "^7.27.1",
62
- "@coinbase/cds-common": "^8.49.0",
62
+ "@coinbase/cds-common": "^8.52.0",
63
63
  "@coinbase/cds-lottie-files": "^3.3.4",
64
64
  "@coinbase/cds-utils": "^2.3.5",
65
- "@coinbase/cds-web": "^8.49.0",
65
+ "@coinbase/cds-web": "^8.52.0",
66
66
  "@linaria/core": "^3.0.0-beta.22",
67
67
  "@types/react": "^18.3.12",
68
68
  "@types/react-dom": "^18.3.1",