@coinbase/cds-web-visualization 3.4.0-beta.12 → 3.4.0-beta.14

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 (51) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dts/chart/CartesianChart.d.ts +18 -1
  3. package/dts/chart/CartesianChart.d.ts.map +1 -1
  4. package/dts/chart/area/AreaChart.d.ts.map +1 -1
  5. package/dts/chart/bar/Bar.d.ts +4 -0
  6. package/dts/chart/bar/Bar.d.ts.map +1 -1
  7. package/dts/chart/bar/BarChart.d.ts +4 -2
  8. package/dts/chart/bar/BarChart.d.ts.map +1 -1
  9. package/dts/chart/bar/BarStack.d.ts +11 -2
  10. package/dts/chart/bar/BarStack.d.ts.map +1 -1
  11. package/dts/chart/bar/DefaultBar.d.ts.map +1 -1
  12. package/dts/chart/index.d.ts +1 -0
  13. package/dts/chart/index.d.ts.map +1 -1
  14. package/dts/chart/legend/DefaultLegendEntry.d.ts +21 -0
  15. package/dts/chart/legend/DefaultLegendEntry.d.ts.map +1 -0
  16. package/dts/chart/legend/DefaultLegendShape.d.ts +7 -0
  17. package/dts/chart/legend/DefaultLegendShape.d.ts.map +1 -0
  18. package/dts/chart/legend/Legend.d.ts +169 -0
  19. package/dts/chart/legend/Legend.d.ts.map +1 -0
  20. package/dts/chart/legend/index.d.ts +4 -0
  21. package/dts/chart/legend/index.d.ts.map +1 -0
  22. package/dts/chart/line/LineChart.d.ts.map +1 -1
  23. package/dts/chart/scrubber/DefaultScrubberBeacon.d.ts +25 -1
  24. package/dts/chart/scrubber/DefaultScrubberBeacon.d.ts.map +1 -1
  25. package/dts/chart/scrubber/Scrubber.d.ts +31 -0
  26. package/dts/chart/scrubber/Scrubber.d.ts.map +1 -1
  27. package/dts/chart/scrubber/ScrubberBeaconGroup.d.ts +10 -0
  28. package/dts/chart/scrubber/ScrubberBeaconGroup.d.ts.map +1 -1
  29. package/dts/chart/utils/chart.d.ts +18 -0
  30. package/dts/chart/utils/chart.d.ts.map +1 -1
  31. package/esm/chart/CartesianChart.js +66 -34
  32. package/esm/chart/area/AreaChart.js +4 -2
  33. package/esm/chart/bar/Bar.js +2 -0
  34. package/esm/chart/bar/BarStack.js +7 -0
  35. package/esm/chart/bar/DefaultBar.js +2 -1
  36. package/esm/chart/index.js +1 -0
  37. package/esm/chart/legend/DefaultLegendEntry.css +1 -0
  38. package/esm/chart/legend/DefaultLegendEntry.js +50 -0
  39. package/esm/chart/legend/DefaultLegendShape.css +5 -0
  40. package/esm/chart/legend/DefaultLegendShape.js +47 -0
  41. package/esm/chart/legend/Legend.js +76 -0
  42. package/esm/chart/legend/index.js +3 -0
  43. package/esm/chart/line/LineChart.js +5 -3
  44. package/esm/chart/scrubber/DefaultScrubberBeacon.js +74 -66
  45. package/esm/chart/scrubber/Scrubber.js +4 -1
  46. package/esm/chart/scrubber/ScrubberBeaconGroup.js +11 -3
  47. package/esm/chart/utils/chart.js +13 -0
  48. package/esm/sparkline/__figma__/Sparkline.figma.js +1 -1
  49. package/esm/sparkline/sparkline-interactive/__figma__/SparklineInteractive.figma.js +1 -1
  50. package/esm/sparkline/sparkline-interactive-header/__figma__/SparklineInteractiveHeader.figma.js +1 -1
  51. package/package.json +5 -6
@@ -8,12 +8,13 @@ import { m as motion, useAnimate } from 'framer-motion';
8
8
  import { useCartesianChartContext } from '../ChartProvider';
9
9
  import { defaultTransition, projectPoint } from '../utils';
10
10
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
11
- const radius = 5;
12
- const strokeWidth = 2;
11
+ const defaultRadius = 5;
12
+ const defaultStrokeWidth = 2;
13
+ const defaultStroke = 'var(--color-bg)';
13
14
  const pulseOpacityStart = 0.5;
14
15
  const pulseOpacityEnd = 0;
15
- const pulseRadiusStart = 10;
16
- const pulseRadiusEnd = 15;
16
+ const pulseRadiusStartMultiplier = 2;
17
+ const pulseRadiusEndMultiplier = 3;
17
18
  const defaultPulseTransition = {
18
19
  duration: 1.6,
19
20
  ease: [0.0, 0.0, 0.0, 1.0]
@@ -27,19 +28,25 @@ export const DefaultScrubberBeacon = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((
27
28
  dataY,
28
29
  isIdle,
29
30
  idlePulse,
31
+ animate: animateProp,
30
32
  transitions,
31
33
  opacity = 1,
34
+ radius = defaultRadius,
35
+ stroke = defaultStroke,
36
+ strokeWidth = defaultStrokeWidth,
32
37
  className,
33
38
  style,
34
- testID
39
+ testID = "".concat(seriesId, "-beacon")
35
40
  } = _ref;
36
- const [scope, animate] = useAnimate();
41
+ const [scope, animateFn] = useAnimate();
37
42
  const {
43
+ animate: animateContext,
38
44
  getSeries,
39
45
  getXScale,
40
46
  getYScale,
41
47
  drawingArea
42
48
  } = useCartesianChartContext();
49
+ const animate = animateProp !== null && animateProp !== void 0 ? animateProp : animateContext;
43
50
  const targetSeries = getSeries(seriesId);
44
51
  const xScale = getXScale();
45
52
  const yScale = getYScale(targetSeries === null || targetSeries === void 0 ? void 0 : targetSeries.yAxisId);
@@ -68,17 +75,19 @@ export const DefaultScrubberBeacon = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((
68
75
  yScale
69
76
  });
70
77
  }, [dataX, dataY, xScale, yScale]);
78
+ const pulseRadiusStart = radius * pulseRadiusStartMultiplier;
79
+ const pulseRadiusEnd = radius * pulseRadiusEndMultiplier;
71
80
  useImperativeHandle(ref, () => ({
72
81
  pulse: () => {
73
82
  // Only pulse when idle and idlePulse is not enabled
74
83
  if (isIdle && !idlePulse && scope.current) {
75
- animate(scope.current, {
84
+ animateFn(scope.current, {
76
85
  opacity: [pulseOpacityStart, pulseOpacityEnd],
77
86
  r: [pulseRadiusStart, pulseRadiusEnd]
78
87
  }, pulseTransition);
79
88
  }
80
89
  }
81
- }), [isIdle, idlePulse, scope, animate, pulseTransition]);
90
+ }), [isIdle, idlePulse, scope, animateFn, pulseTransition, pulseRadiusStart, pulseRadiusEnd]);
82
91
 
83
92
  // Create continuous pulse transition by repeating the base pulse transition with delay
84
93
  const continuousPulseTransition = useMemo(() => _objectSpread(_objectSpread({}, pulseTransition), {}, {
@@ -91,65 +100,64 @@ export const DefaultScrubberBeacon = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((
91
100
  return pixelCoordinate.x >= drawingArea.x && pixelCoordinate.x <= drawingArea.x + drawingArea.width && pixelCoordinate.y >= drawingArea.y && pixelCoordinate.y <= drawingArea.y + drawingArea.height;
92
101
  }, [pixelCoordinate, drawingArea]);
93
102
  if (!pixelCoordinate) return;
94
- if (isIdle) {
95
- return /*#__PURE__*/_jsxs("g", {
96
- "data-testid": testID,
97
- opacity: isWithinDrawingArea ? opacity : 0,
98
- children: [/*#__PURE__*/_jsx(motion.g, {
99
- animate: {
100
- x: pixelCoordinate.x,
101
- y: pixelCoordinate.y
102
- },
103
- initial: false,
104
- transition: updateTransition,
105
- children: /*#__PURE__*/_jsx(motion.circle, {
106
- ref: scope,
107
- animate: shouldPulse ? {
108
- opacity: [pulseOpacityStart, pulseOpacityEnd],
109
- r: [pulseRadiusStart, pulseRadiusEnd],
110
- transition: continuousPulseTransition
111
- } : {
112
- opacity: pulseOpacityEnd,
113
- r: pulseRadiusStart
114
- },
115
- cx: 0,
116
- cy: 0,
117
- fill: color,
118
- initial: {
119
- opacity: shouldPulse ? pulseOpacityStart : pulseOpacityEnd,
120
- r: pulseRadiusStart
121
- }
122
- })
123
- }), /*#__PURE__*/_jsx(motion.circle, {
124
- animate: {
125
- cx: pixelCoordinate.x,
126
- cy: pixelCoordinate.y
127
- },
128
- className: className,
129
- cx: pixelCoordinate.x,
130
- cy: pixelCoordinate.y,
131
- fill: color,
132
- initial: false,
133
- r: radius,
134
- stroke: "var(--color-bg)",
135
- strokeWidth: strokeWidth,
136
- style: style,
137
- transition: updateTransition
138
- })]
139
- });
140
- }
141
- return /*#__PURE__*/_jsx("g", {
103
+ const pulseCircle = /*#__PURE__*/_jsx(motion.circle, {
104
+ ref: scope,
105
+ animate: shouldPulse ? {
106
+ opacity: [pulseOpacityStart, pulseOpacityEnd],
107
+ r: [pulseRadiusStart, pulseRadiusEnd],
108
+ transition: continuousPulseTransition
109
+ } : {
110
+ opacity: pulseOpacityEnd,
111
+ r: pulseRadiusStart
112
+ },
113
+ cx: 0,
114
+ cy: 0,
115
+ "data-testid": "".concat(testID, "-pulse"),
116
+ fill: color,
117
+ initial: {
118
+ opacity: shouldPulse ? pulseOpacityStart : pulseOpacityEnd,
119
+ r: pulseRadiusStart
120
+ }
121
+ });
122
+ const beaconCircle = isIdle && animate ? /*#__PURE__*/_jsx(motion.circle, {
123
+ animate: {
124
+ cx: pixelCoordinate.x,
125
+ cy: pixelCoordinate.y
126
+ },
127
+ className: className,
128
+ cx: pixelCoordinate.x,
129
+ cy: pixelCoordinate.y,
130
+ fill: color,
131
+ initial: false,
132
+ r: radius,
133
+ stroke: stroke,
134
+ strokeWidth: strokeWidth,
135
+ style: style,
136
+ transition: updateTransition
137
+ }) : /*#__PURE__*/_jsx("circle", {
138
+ className: className,
139
+ cx: pixelCoordinate.x,
140
+ cy: pixelCoordinate.y,
141
+ fill: color,
142
+ r: radius,
143
+ stroke: stroke,
144
+ strokeWidth: strokeWidth,
145
+ style: style
146
+ });
147
+ return /*#__PURE__*/_jsxs("g", {
142
148
  "data-testid": testID,
143
149
  opacity: isWithinDrawingArea ? opacity : 0,
144
- children: /*#__PURE__*/_jsx("circle", {
145
- className: className,
146
- cx: pixelCoordinate.x,
147
- cy: pixelCoordinate.y,
148
- fill: color,
149
- r: radius,
150
- stroke: "var(--color-bg)",
151
- strokeWidth: strokeWidth,
152
- style: style
153
- })
150
+ children: [isIdle && (animate ? /*#__PURE__*/_jsx(motion.g, {
151
+ animate: {
152
+ x: pixelCoordinate.x,
153
+ y: pixelCoordinate.y
154
+ },
155
+ initial: false,
156
+ transition: updateTransition,
157
+ children: pulseCircle
158
+ }) : /*#__PURE__*/_jsx("g", {
159
+ transform: "translate(".concat(pixelCoordinate.x, ", ").concat(pixelCoordinate.y, ")"),
160
+ children: pulseCircle
161
+ })), beaconCircle]
154
162
  });
155
163
  }));
@@ -19,6 +19,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
19
19
  export const Scrubber = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, ref) => {
20
20
  let {
21
21
  seriesIds,
22
+ hideBeaconLabels,
22
23
  hideLine,
23
24
  label,
24
25
  accessibilityLabel,
@@ -38,6 +39,7 @@ export const Scrubber = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, ref) =>
38
39
  testID,
39
40
  idlePulse,
40
41
  beaconTransitions,
42
+ beaconStroke,
41
43
  styles,
42
44
  classNames
43
45
  } = _ref;
@@ -175,10 +177,11 @@ export const Scrubber = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, ref) =>
175
177
  className: classNames === null || classNames === void 0 ? void 0 : classNames.beacon,
176
178
  idlePulse: idlePulse,
177
179
  seriesIds: filteredSeriesIds,
180
+ stroke: beaconStroke,
178
181
  style: styles === null || styles === void 0 ? void 0 : styles.beacon,
179
182
  testID: testID,
180
183
  transitions: beaconTransitions
181
- }), beaconLabels.length > 0 && /*#__PURE__*/_jsx(ScrubberBeaconLabelGroup, {
184
+ }), !hideBeaconLabels && beaconLabels.length > 0 && /*#__PURE__*/_jsx(ScrubberBeaconLabelGroup, {
182
185
  BeaconLabelComponent: BeaconLabelComponent,
183
186
  labelFont: beaconLabelFont,
184
187
  labelHorizontalOffset: beaconLabelHorizontalOffset,
@@ -13,11 +13,13 @@ const BeaconWithData = /*#__PURE__*/memo(_ref => {
13
13
  isIdle,
14
14
  BeaconComponent,
15
15
  idlePulse,
16
+ animate,
16
17
  transitions,
17
18
  className,
18
19
  style,
19
20
  testID,
20
- beaconRef
21
+ beaconRef,
22
+ stroke
21
23
  } = _ref;
22
24
  const {
23
25
  getSeries,
@@ -71,6 +73,7 @@ const BeaconWithData = /*#__PURE__*/memo(_ref => {
71
73
  if (dataY === undefined) return null;
72
74
  return /*#__PURE__*/_jsx(BeaconComponent, {
73
75
  ref: beaconRef,
76
+ animate: animate,
74
77
  className: className,
75
78
  color: color,
76
79
  dataX: dataX,
@@ -78,6 +81,7 @@ const BeaconWithData = /*#__PURE__*/memo(_ref => {
78
81
  idlePulse: idlePulse,
79
82
  isIdle: isIdle,
80
83
  seriesId: seriesId,
84
+ stroke: stroke,
81
85
  style: style,
82
86
  testID: testID,
83
87
  transitions: transitions
@@ -91,7 +95,8 @@ export const ScrubberBeaconGroup = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_r
91
95
  BeaconComponent = DefaultScrubberBeacon,
92
96
  className,
93
97
  style,
94
- testID
98
+ testID,
99
+ stroke
95
100
  } = _ref2;
96
101
  const ScrubberBeaconRefs = useRefMap();
97
102
  const {
@@ -101,7 +106,8 @@ export const ScrubberBeaconGroup = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_r
101
106
  getXScale,
102
107
  getXAxis,
103
108
  dataLength,
104
- series
109
+ series,
110
+ animate
105
111
  } = useCartesianChartContext();
106
112
 
107
113
  // Expose imperative handle with pulse method
@@ -152,6 +158,7 @@ export const ScrubberBeaconGroup = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_r
152
158
  if (dataX === undefined || dataIndex === undefined) return null;
153
159
  return filteredSeries.map(s => /*#__PURE__*/_jsx(BeaconWithData, {
154
160
  BeaconComponent: BeaconComponent,
161
+ animate: animate,
155
162
  beaconRef: createBeaconRef(s.id),
156
163
  className: className,
157
164
  dataIndex: dataIndex,
@@ -159,6 +166,7 @@ export const ScrubberBeaconGroup = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_r
159
166
  idlePulse: idlePulse,
160
167
  isIdle: isIdle,
161
168
  seriesId: s.id,
169
+ stroke: stroke,
162
170
  style: style,
163
171
  testID: testID ? "".concat(testID !== null && testID !== void 0 ? testID : 'beacon', "-").concat(s.id) : undefined,
164
172
  transitions: transitions
@@ -1,5 +1,18 @@
1
1
  import { stack as d3Stack, stackOffsetDiverging, stackOrderNone } from 'd3-shape';
2
2
  export const defaultStackId = 'DEFAULT_STACK_ID';
3
+
4
+ /**
5
+ * Shape variants available for legend items.
6
+ */
7
+
8
+ /**
9
+ * Shape for legend items. Can be a preset variant or a custom ReactNode.
10
+ */
11
+
12
+ /**
13
+ * Position of the legend relative to the chart.
14
+ */
15
+
3
16
  /**
4
17
  * Type guard to check if bounds are complete with both min and max values.
5
18
  * @param bounds - The bounds to validate
@@ -5,7 +5,7 @@ import { figma } from '@figma/code-connect';
5
5
  import { Sparkline } from '../Sparkline';
6
6
  import { jsx as _jsx } from "react/jsx-runtime";
7
7
  figma.connect(Sparkline, 'https://www.figma.com/design/k5CtyJccNQUGMI5bI4lJ2g/✨-CDS-Components?node-id=320-15040&m=dev', {
8
- imports: ["import { Sparkline } from '@coinbase/cds-web-visualization';", "import { useSparklinePath } from '@coinbase/cds-common/visualizations/useSparklinePath';"],
8
+ imports: ["import { Sparkline } from '@coinbase/cds-web-visualization'", "import { useSparklinePath } from '@coinbase/cds-common/visualizations/useSparklinePath'"],
9
9
  example: () => {
10
10
  const data = [20, 30, 5, 45, 0];
11
11
  // @ts-expect-error: useSparklinePath is not typed correctly
@@ -8,7 +8,7 @@ import { figma } from '@figma/code-connect';
8
8
  import { SparklineInteractive } from '../SparklineInteractive';
9
9
  import { jsx as _jsx } from "react/jsx-runtime";
10
10
  figma.connect(SparklineInteractive, 'https://www.figma.com/design/k5CtyJccNQUGMI5bI4lJ2g/✨-CDS-Components?node-id=320-14858&m=dev', {
11
- imports: ["import { SparklineInteractive } from '@coinbase/cds-web-visualization';"],
11
+ imports: ["import { SparklineInteractive } from '@coinbase/cds-web-visualization'"],
12
12
  props: {
13
13
  compact: figma.boolean('compact'),
14
14
  disableScrubbing: figma.boolean('scrubbing', {
@@ -9,7 +9,7 @@ import { SparklineInteractive } from '../../sparkline-interactive/SparklineInter
9
9
  import { SparklineInteractiveHeader } from '../SparklineInteractiveHeader';
10
10
  import { jsx as _jsx } from "react/jsx-runtime";
11
11
  figma.connect(SparklineInteractiveHeader, 'https://www.figma.com/design/k5CtyJccNQUGMI5bI4lJ2g/✨-CDS-Components?node-id=320-14931&m=dev', {
12
- imports: ["import { SparklineInteractiveHeader } from '@coinbase/cds-web-visualization';", "import { SparklineInteractive } from '@coinbase/cds-web-visualization';"],
12
+ imports: ["import { SparklineInteractiveHeader } from '@coinbase/cds-web-visualization'", "import { SparklineInteractive } from '@coinbase/cds-web-visualization'"],
13
13
  props: {
14
14
  compact: figma.boolean('compact'),
15
15
  disableScrubbing: figma.boolean('scrubbing', {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coinbase/cds-web-visualization",
3
- "version": "3.4.0-beta.12",
3
+ "version": "3.4.0-beta.14",
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.36.2",
41
+ "@coinbase/cds-common": "^8.38.6",
42
42
  "@coinbase/cds-lottie-files": "^3.3.4",
43
43
  "@coinbase/cds-utils": "^2.3.5",
44
- "@coinbase/cds-web": "^8.36.2",
44
+ "@coinbase/cds-web": "^8.38.6",
45
45
  "react": "^18.3.1",
46
46
  "react-dom": "^18.3.1"
47
47
  },
@@ -58,11 +58,10 @@
58
58
  "@babel/preset-env": "^7.28.0",
59
59
  "@babel/preset-react": "^7.27.1",
60
60
  "@babel/preset-typescript": "^7.27.1",
61
- "@coinbase/cds-common": "^8.36.2",
61
+ "@coinbase/cds-common": "^8.38.6",
62
62
  "@coinbase/cds-lottie-files": "^3.3.4",
63
63
  "@coinbase/cds-utils": "^2.3.5",
64
- "@coinbase/cds-web": "^8.36.2",
65
- "@figma/code-connect": "^1.3.4",
64
+ "@coinbase/cds-web": "^8.38.6",
66
65
  "@linaria/core": "^3.0.0-beta.22",
67
66
  "@types/react": "^18.3.12",
68
67
  "@types/react-dom": "^18.3.1"