@coinbase/cds-mcp-server 8.47.4 → 8.48.1

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.
package/CHANGELOG.md CHANGED
@@ -8,6 +8,14 @@ All notable changes to this project will be documented in this file.
8
8
 
9
9
  <!-- template-start -->
10
10
 
11
+ ## 8.48.1 ((2/25/2026, 01:30 PM PST))
12
+
13
+ This is an artificial version bump with no new change.
14
+
15
+ ## 8.48.0 ((2/24/2026, 10:33 AM PST))
16
+
17
+ This is an artificial version bump with no new change.
18
+
11
19
  ## 8.47.4 ((2/23/2026, 03:04 PM PST))
12
20
 
13
21
  This is an artificial version bump with no new change.
@@ -143,6 +143,479 @@ You can have different area styles for each series.
143
143
  />
144
144
  ```
145
145
 
146
+ ### Animations
147
+
148
+ You can configure chart transitions using the `transitions` prop on individual chart elements, or use the `animate` prop to toggle animations entirely.
149
+
150
+ #### Customized Transitions
151
+
152
+ You can pass in a custom spring or timing based transition to your chart for custom update animations. Use `CartesianChart` with `Area` and `Line` components directly to configure `transitions` per element.
153
+
154
+ ```jsx
155
+ function AnimatedStackedAreas() {
156
+ const theme = useTheme();
157
+ const dataCount = 20;
158
+ const minYValue = 5000;
159
+ const maxDataOffset = 15000;
160
+ const minStepOffset = 2500;
161
+ const maxStepOffset = 10000;
162
+ const updateInterval = 500;
163
+ const seriesSpacing = 2000;
164
+ const myTransition = {
165
+ update: { type: 'spring', stiffness: 700, damping: 20 },
166
+ };
167
+
168
+ const seriesConfig = [
169
+ { id: 'red', label: 'Red', color: `rgb(${theme.spectrum.red40})` },
170
+ { id: 'orange', label: 'Orange', color: `rgb(${theme.spectrum.orange40})` },
171
+ { id: 'yellow', label: 'Yellow', color: `rgb(${theme.spectrum.yellow40})` },
172
+ { id: 'green', label: 'Green', color: `rgb(${theme.spectrum.green40})` },
173
+ { id: 'blue', label: 'Blue', color: `rgb(${theme.spectrum.blue40})` },
174
+ { id: 'indigo', label: 'Indigo', color: `rgb(${theme.spectrum.indigo40})` },
175
+ { id: 'purple', label: 'Purple', color: `rgb(${theme.spectrum.purple40})` },
176
+ ];
177
+
178
+ const domainLimit = maxDataOffset + seriesConfig.length * seriesSpacing;
179
+
180
+ function generateNextValue(previousValue) {
181
+ const range = maxStepOffset - minStepOffset;
182
+ const offset = Math.random() * range + minStepOffset;
183
+
184
+ let direction;
185
+ if (previousValue >= maxDataOffset) {
186
+ direction = -1;
187
+ } else if (previousValue <= minYValue) {
188
+ direction = 1;
189
+ } else {
190
+ direction = Math.random() < 0.5 ? -1 : 1;
191
+ }
192
+
193
+ let newValue = previousValue + offset * direction;
194
+ newValue = Math.max(minYValue, Math.min(maxDataOffset, newValue));
195
+ return newValue;
196
+ }
197
+
198
+ function generateInitialData() {
199
+ const data = [];
200
+
201
+ let previousValue = minYValue + Math.random() * (maxDataOffset - minYValue);
202
+ data.push(previousValue);
203
+
204
+ for (let i = 1; i < dataCount; i++) {
205
+ const newValue = generateNextValue(previousValue);
206
+ data.push(newValue);
207
+ previousValue = newValue;
208
+ }
209
+
210
+ return data;
211
+ }
212
+
213
+ const MemoizedDottedArea = memo((props) => (
214
+ <DottedArea {...props} baselineOpacity={1} peakOpacity={1} />
215
+ ));
216
+
217
+ function AnimatedChart() {
218
+ const [data, setData] = useState(generateInitialData);
219
+
220
+ useEffect(() => {
221
+ const intervalId = setInterval(() => {
222
+ setData((currentData) => {
223
+ const lastValue = currentData[currentData.length - 1] ?? 0;
224
+ const newValue = generateNextValue(lastValue);
225
+
226
+ return [...currentData.slice(1), newValue];
227
+ });
228
+ }, updateInterval);
229
+
230
+ return () => clearInterval(intervalId);
231
+ }, []);
232
+
233
+ const series = seriesConfig.map((config, index) => ({
234
+ id: config.id,
235
+ label: config.label,
236
+ color: config.color,
237
+ data: index === 0 ? data : Array(dataCount).fill(seriesSpacing),
238
+ }));
239
+
240
+ return (
241
+ <AreaChart
242
+ stacked
243
+ height={300}
244
+ series={series}
245
+ type="dotted"
246
+ showLines
247
+ AreaComponent={MemoizedDottedArea}
248
+ transition={myTransition.update}
249
+ inset={0}
250
+ showYAxis
251
+ yAxis={{
252
+ showGrid: true,
253
+ width: 0,
254
+ tickLabelFormatter: () => '',
255
+ domain: { min: 0, max: domainLimit },
256
+ }}
257
+ />
258
+ );
259
+ }
260
+
261
+ return <AnimatedChart />;
262
+ }
263
+ ```
264
+
265
+ #### Disable Animations
266
+
267
+ You can also disable animations by setting the `animate` prop to `false`.
268
+
269
+ ```jsx
270
+ function AnimatedStackedAreas() {
271
+ const theme = useTheme();
272
+ const dataCount = 20;
273
+ const minYValue = 5000;
274
+ const maxDataOffset = 15000;
275
+ const minStepOffset = 2500;
276
+ const maxStepOffset = 10000;
277
+ const updateInterval = 500;
278
+ const seriesSpacing = 2000;
279
+
280
+ const seriesConfig = [
281
+ { id: 'red', label: 'Red', color: `rgb(${theme.spectrum.red40})` },
282
+ { id: 'orange', label: 'Orange', color: `rgb(${theme.spectrum.orange40})` },
283
+ { id: 'yellow', label: 'Yellow', color: `rgb(${theme.spectrum.yellow40})` },
284
+ { id: 'green', label: 'Green', color: `rgb(${theme.spectrum.green40})` },
285
+ { id: 'blue', label: 'Blue', color: `rgb(${theme.spectrum.blue40})` },
286
+ { id: 'indigo', label: 'Indigo', color: `rgb(${theme.spectrum.indigo40})` },
287
+ { id: 'purple', label: 'Purple', color: `rgb(${theme.spectrum.purple40})` },
288
+ ];
289
+
290
+ const domainLimit = maxDataOffset + seriesConfig.length * seriesSpacing;
291
+
292
+ function generateNextValue(previousValue) {
293
+ const range = maxStepOffset - minStepOffset;
294
+ const offset = Math.random() * range + minStepOffset;
295
+
296
+ let direction;
297
+ if (previousValue >= maxDataOffset) {
298
+ direction = -1;
299
+ } else if (previousValue <= minYValue) {
300
+ direction = 1;
301
+ } else {
302
+ direction = Math.random() < 0.5 ? -1 : 1;
303
+ }
304
+
305
+ let newValue = previousValue + offset * direction;
306
+ newValue = Math.max(minYValue, Math.min(maxDataOffset, newValue));
307
+ return newValue;
308
+ }
309
+
310
+ function generateInitialData() {
311
+ const data = [];
312
+
313
+ let previousValue = minYValue + Math.random() * (maxDataOffset - minYValue);
314
+ data.push(previousValue);
315
+
316
+ for (let i = 1; i < dataCount; i++) {
317
+ const newValue = generateNextValue(previousValue);
318
+ data.push(newValue);
319
+ previousValue = newValue;
320
+ }
321
+
322
+ return data;
323
+ }
324
+
325
+ const MemoizedDottedArea = memo((props) => (
326
+ <DottedArea {...props} baselineOpacity={1} peakOpacity={1} />
327
+ ));
328
+
329
+ function AnimatedChart() {
330
+ const [data, setData] = useState(generateInitialData);
331
+
332
+ useEffect(() => {
333
+ const intervalId = setInterval(() => {
334
+ setData((currentData) => {
335
+ const lastValue = currentData[currentData.length - 1] ?? 0;
336
+ const newValue = generateNextValue(lastValue);
337
+
338
+ return [...currentData.slice(1), newValue];
339
+ });
340
+ }, updateInterval);
341
+
342
+ return () => clearInterval(intervalId);
343
+ }, []);
344
+
345
+ const series = seriesConfig.map((config, index) => ({
346
+ id: config.id,
347
+ label: config.label,
348
+ color: config.color,
349
+ data: index === 0 ? data : Array(dataCount).fill(seriesSpacing),
350
+ }));
351
+
352
+ return (
353
+ <AreaChart
354
+ animate={false}
355
+ stacked
356
+ height={300}
357
+ series={series}
358
+ type="dotted"
359
+ showLines
360
+ AreaComponent={MemoizedDottedArea}
361
+ inset={0}
362
+ showYAxis
363
+ yAxis={{
364
+ showGrid: true,
365
+ width: 0,
366
+ tickLabelFormatter: () => '',
367
+ domain: { min: 0, max: domainLimit },
368
+ }}
369
+ />
370
+ );
371
+ }
372
+
373
+ return <AnimatedChart />;
374
+ }
375
+ ```
376
+
377
+ ### Gradients
378
+
379
+ You can use the `gradient` prop on `series` to enable gradients.
380
+
381
+ Each stop requires an `offset`, which is based on the data within the x/y scale and `color`, with an optional `opacity` (defaults to 1).
382
+
383
+ Values in between stops will be interpolated smoothly.
384
+
385
+ ```jsx
386
+ function ContinuousGradient() {
387
+ const theme = useTheme();
388
+ const spectrumColors = [
389
+ 'blue',
390
+ 'green',
391
+ 'orange',
392
+ 'yellow',
393
+ 'gray',
394
+ 'indigo',
395
+ 'pink',
396
+ 'purple',
397
+ 'red',
398
+ 'teal',
399
+ 'chartreuse',
400
+ ];
401
+ const data = [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58];
402
+
403
+ const [currentSpectrumColor, setCurrentSpectrumColor] = useState('pink');
404
+
405
+ return (
406
+ <VStack gap={2}>
407
+ <HStack flexWrap="wrap" gap={1} justifyContent="flex-end">
408
+ {spectrumColors.map((color) => (
409
+ <Pressable
410
+ key={color}
411
+ accessibilityLabel={`Select ${color}`}
412
+ height={16}
413
+ onPress={() => setCurrentSpectrumColor(color)}
414
+ style={{
415
+ backgroundColor: `rgb(${theme.spectrum[`${color}20`]})`,
416
+ borderColor: `rgb(${theme.spectrum[`${color}50`]})`,
417
+ borderWidth: 2,
418
+ borderRadius: 1000,
419
+ }}
420
+ width={16}
421
+ />
422
+ ))}
423
+ </HStack>
424
+ <AreaChart
425
+ enableScrubbing
426
+ height={250}
427
+ series={[
428
+ {
429
+ id: 'prices',
430
+ data: data,
431
+ gradient: {
432
+ stops: ({ min, max }) => [
433
+ { offset: min, color: `rgb(${theme.spectrum[`${currentSpectrumColor}80`]})` },
434
+ { offset: max, color: `rgb(${theme.spectrum[`${currentSpectrumColor}20`]})` },
435
+ ],
436
+ },
437
+ },
438
+ ]}
439
+ showYAxis
440
+ yAxis={{
441
+ showGrid: true,
442
+ }}
443
+ >
444
+ <Scrubber />
445
+ </AreaChart>
446
+ </VStack>
447
+ );
448
+ }
449
+ ```
450
+
451
+ #### Discrete
452
+
453
+ You can set multiple stops at the same offset to create a discrete gradient.
454
+
455
+ ```jsx
456
+ function DiscreteGradient() {
457
+ const theme = useTheme();
458
+ const spectrumColors = [
459
+ 'blue',
460
+ 'green',
461
+ 'orange',
462
+ 'yellow',
463
+ 'gray',
464
+ 'indigo',
465
+ 'pink',
466
+ 'purple',
467
+ 'red',
468
+ 'teal',
469
+ 'chartreuse',
470
+ ];
471
+ const data = [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58];
472
+
473
+ const [currentSpectrumColor, setCurrentSpectrumColor] = useState('pink');
474
+
475
+ return (
476
+ <VStack gap={2}>
477
+ <HStack flexWrap="wrap" gap={1} justifyContent="flex-end">
478
+ {spectrumColors.map((color) => (
479
+ <Pressable
480
+ key={color}
481
+ accessibilityLabel={`Select ${color}`}
482
+ height={16}
483
+ onPress={() => setCurrentSpectrumColor(color)}
484
+ style={{
485
+ backgroundColor: `rgb(${theme.spectrum[`${color}20`]})`,
486
+ borderColor: `rgb(${theme.spectrum[`${color}50`]})`,
487
+ borderWidth: 2,
488
+ borderRadius: 1000,
489
+ }}
490
+ width={16}
491
+ />
492
+ ))}
493
+ </HStack>
494
+ <AreaChart
495
+ enableScrubbing
496
+ height={250}
497
+ series={[
498
+ {
499
+ id: 'prices',
500
+ data: data,
501
+ gradient: {
502
+ stops: ({ min, max }) => [
503
+ { offset: min, color: `rgb(${theme.spectrum[`${currentSpectrumColor}80`]})` },
504
+ {
505
+ offset: min + (max - min) / 3,
506
+ color: `rgb(${theme.spectrum[`${currentSpectrumColor}80`]})`,
507
+ },
508
+ {
509
+ offset: min + (max - min) / 3,
510
+ color: `rgb(${theme.spectrum[`${currentSpectrumColor}50`]})`,
511
+ },
512
+ {
513
+ offset: min + ((max - min) / 3) * 2,
514
+ color: `rgb(${theme.spectrum[`${currentSpectrumColor}50`]})`,
515
+ },
516
+ {
517
+ offset: min + ((max - min) / 3) * 2,
518
+ color: `rgb(${theme.spectrum[`${currentSpectrumColor}20`]})`,
519
+ },
520
+ { offset: max, color: `rgb(${theme.spectrum[`${currentSpectrumColor}20`]})` },
521
+ ],
522
+ },
523
+ },
524
+ ]}
525
+ showLines
526
+ strokeWidth={4}
527
+ showYAxis
528
+ yAxis={{
529
+ showGrid: true,
530
+ }}
531
+ fillOpacity={0.5}
532
+ >
533
+ <Scrubber />
534
+ </AreaChart>
535
+ </VStack>
536
+ );
537
+ }
538
+ ```
539
+
540
+ #### Axes
541
+
542
+ By default, gradients will be applied to the y-axis. You can apply a gradient to the x-axis by setting `axis` to `x` in the gradient definition.
543
+
544
+ ```jsx
545
+ function XAxisGradient() {
546
+ const theme = useTheme();
547
+ const spectrumColors = [
548
+ 'blue',
549
+ 'green',
550
+ 'orange',
551
+ 'yellow',
552
+ 'gray',
553
+ 'indigo',
554
+ 'pink',
555
+ 'purple',
556
+ 'red',
557
+ 'teal',
558
+ 'chartreuse',
559
+ ];
560
+ const data = [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58];
561
+
562
+ const [currentSpectrumColor, setCurrentSpectrumColor] = useState('pink');
563
+
564
+ return (
565
+ <VStack gap={2}>
566
+ <HStack flexWrap="wrap" gap={1} justifyContent="flex-end">
567
+ {spectrumColors.map((color) => (
568
+ <Pressable
569
+ key={color}
570
+ accessibilityLabel={`Select ${color}`}
571
+ height={16}
572
+ onPress={() => setCurrentSpectrumColor(color)}
573
+ style={{
574
+ backgroundColor: `rgb(${theme.spectrum[`${color}20`]})`,
575
+ borderColor: `rgb(${theme.spectrum[`${color}50`]})`,
576
+ borderWidth: 2,
577
+ borderRadius: 1000,
578
+ }}
579
+ width={16}
580
+ />
581
+ ))}
582
+ </HStack>
583
+ <AreaChart
584
+ enableScrubbing
585
+ height={250}
586
+ series={[
587
+ {
588
+ id: 'prices',
589
+ data: data,
590
+ gradient: {
591
+ axis: 'x',
592
+ stops: ({ min, max }) => [
593
+ {
594
+ offset: min,
595
+ color: `rgb(${theme.spectrum[`${currentSpectrumColor}80`]})`,
596
+ opacity: 0,
597
+ },
598
+ {
599
+ offset: max,
600
+ color: `rgb(${theme.spectrum[`${currentSpectrumColor}20`]})`,
601
+ opacity: 1,
602
+ },
603
+ ],
604
+ },
605
+ },
606
+ ]}
607
+ showYAxis
608
+ yAxis={{
609
+ showGrid: true,
610
+ }}
611
+ >
612
+ <Scrubber />
613
+ </AreaChart>
614
+ </VStack>
615
+ );
616
+ }
617
+ ```
618
+
146
619
  ## Props
147
620
 
148
621
  | Prop | Type | Required | Default | Description |
@@ -259,7 +732,7 @@ You can have different area styles for each series.
259
732
  | `textTransform` | `none \| capitalize \| uppercase \| lowercase` | No | `-` | - |
260
733
  | `top` | `string \| number` | No | `-` | - |
261
734
  | `transform` | `string \| (({ perspective: AnimatableNumericValue; } & { rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ rotate: AnimatableStringValue; } & { perspective?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ rotateX: AnimatableStringValue; } & { perspective?: undefined; rotate?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ rotateY: AnimatableStringValue; } & { perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateZ?: undefined; scale?: undefined; scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ rotateZ: AnimatableStringValue; } & { perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; scale?: undefined; scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ scale: AnimatableNumericValue; } & { perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ scaleX: AnimatableNumericValue; } & { perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ scaleY: AnimatableNumericValue; } & { perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; scaleX?: undefined; translateX?: undefined; translateY?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ translateX: AnimatableNumericValue \| ${number}%; } & { perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; scaleX?: undefined; scaleY?: undefined; translateY?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ translateY: AnimatableNumericValue \| ${number}%; } & { perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; scaleX?: undefined; scaleY?: undefined; translateX?: undefined; skewX?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ skewX: AnimatableStringValue; } & { perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; skewY?: undefined; matrix?: undefined; }) \| ({ skewY: AnimatableStringValue; } & { perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; skewX?: undefined; matrix?: undefined; }) \| ({ matrix: AnimatableNumericValue[]; } & { perspective?: undefined; rotate?: undefined; rotateX?: undefined; rotateY?: undefined; rotateZ?: undefined; scale?: undefined; scaleX?: undefined; scaleY?: undefined; translateX?: undefined; translateY?: undefined; skewX?: undefined; skewY?: undefined; }))[]` | No | `-` | - |
262
- | `transition` | `{ type: timing; } & TimingConfig \| { type: spring; } & { stiffness?: number \| undefined; overshootClamping?: boolean \| undefined; restDisplacementThreshold?: number \| undefined; restSpeedThreshold?: number \| undefined; velocity?: number \| undefined; reduceMotion?: ReduceMotion \| undefined; } & { mass?: number \| undefined; damping?: number \| undefined; duration?: undefined; dampingRatio?: undefined; clamp?: undefined; } \| { type: spring; } & { stiffness?: number \| undefined; overshootClamping?: boolean \| undefined; restDisplacementThreshold?: number \| undefined; restSpeedThreshold?: number \| undefined; velocity?: number \| undefined; reduceMotion?: ReduceMotion \| undefined; } & { mass?: undefined; damping?: undefined; duration?: number \| undefined; dampingRatio?: number \| undefined; clamp?: { min?: number \| undefined; max?: number \| undefined; } \| undefined; }` | No | `-` | Transition configuration for path animations. |
735
+ | `transition` | `{ type: timing; } & TimingConfig & { delay?: number \| undefined; } \| { type: spring; } & { stiffness?: number \| undefined; overshootClamping?: boolean \| undefined; restDisplacementThreshold?: number \| undefined; restSpeedThreshold?: number \| undefined; velocity?: number \| undefined; reduceMotion?: ReduceMotion \| undefined; } & { mass?: number \| undefined; damping?: number \| undefined; duration?: undefined; dampingRatio?: undefined; clamp?: undefined; } & { delay?: number \| undefined; } \| { type: spring; } & { stiffness?: number \| undefined; overshootClamping?: boolean \| undefined; restDisplacementThreshold?: number \| undefined; restSpeedThreshold?: number \| undefined; velocity?: number \| undefined; reduceMotion?: ReduceMotion \| undefined; } & { mass?: undefined; damping?: undefined; duration?: number \| undefined; dampingRatio?: number \| undefined; clamp?: { min?: number \| undefined; max?: number \| undefined; } \| undefined; } & { delay?: number \| undefined; }` | No | `-` | Transition for updates. |
263
736
  | `type` | `solid \| dotted \| gradient` | No | `'solid'` | The type of area to render. |
264
737
  | `userSelect` | `none \| auto \| text \| contain \| all` | No | `-` | - |
265
738
  | `width` | `string \| number` | No | `-` | - |