@coinbase/cds-mobile-visualization 3.4.0-beta.19 → 3.4.0-beta.20
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 +10 -0
- package/dts/chart/PeriodSelector.d.ts +4 -11
- package/dts/chart/PeriodSelector.d.ts.map +1 -1
- package/esm/chart/ChartProvider.js +1 -1
- package/esm/chart/__stories__/PeriodSelector.stories.js +75 -1
- package/esm/chart/bar/BarStackGroup.js +1 -1
- package/esm/chart/bar/__stories__/BarChart.stories.js +39 -0
- package/esm/chart/utils/axis.js +2 -2
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,16 @@ All notable changes to this project will be documented in this file.
|
|
|
8
8
|
|
|
9
9
|
<!-- template-start -->
|
|
10
10
|
|
|
11
|
+
## 3.4.0-beta.20 (2/27/2026 PST)
|
|
12
|
+
|
|
13
|
+
#### 🚀 Updates
|
|
14
|
+
|
|
15
|
+
- Add styles props to PeriodSelector. [[#438](https://github.com/coinbase/cds/pull/438/)]
|
|
16
|
+
|
|
17
|
+
#### 📘 Misc
|
|
18
|
+
|
|
19
|
+
- Update outdated doc links. [[#440](https://github.com/coinbase/cds/pull/440)]
|
|
20
|
+
|
|
11
21
|
## 3.4.0-beta.19 (2/20/2026 PST)
|
|
12
22
|
|
|
13
23
|
#### 🚀 Updates
|
|
@@ -62,23 +62,16 @@ export declare const LiveTabLabel: React.MemoExoticComponent<
|
|
|
62
62
|
} & React.RefAttributes<View>
|
|
63
63
|
>
|
|
64
64
|
>;
|
|
65
|
-
export type PeriodSelectorProps = SegmentedTabsProps
|
|
65
|
+
export type PeriodSelectorProps = Omit<SegmentedTabsProps, 'styles'> &
|
|
66
|
+
Pick<SegmentedTabsProps, 'styles'>;
|
|
66
67
|
/**
|
|
67
68
|
* PeriodSelector is a specialized version of SegmentedTabs optimized for chart period selection.
|
|
68
69
|
* It provides transparent background, primary wash active state, and full-width layout by default.
|
|
69
70
|
*/
|
|
70
71
|
export declare const PeriodSelector: React.MemoExoticComponent<
|
|
71
72
|
React.ForwardRefExoticComponent<
|
|
72
|
-
|
|
73
|
-
Pick<
|
|
74
|
-
import('@coinbase/cds-mobile/tabs').TabsProps<string>,
|
|
75
|
-
'TabComponent' | 'TabsActiveIndicatorComponent'
|
|
76
|
-
>
|
|
77
|
-
> &
|
|
78
|
-
Omit<
|
|
79
|
-
import('@coinbase/cds-mobile/tabs').TabsProps<string>,
|
|
80
|
-
'TabComponent' | 'TabsActiveIndicatorComponent'
|
|
81
|
-
> &
|
|
73
|
+
Omit<SegmentedTabsProps, 'styles'> &
|
|
74
|
+
Pick<SegmentedTabsProps, 'styles'> &
|
|
82
75
|
React.RefAttributes<any>
|
|
83
76
|
>
|
|
84
77
|
>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PeriodSelector.d.ts","sourceRoot":"","sources":["../../src/chart/PeriodSelector.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoC,MAAM,OAAO,CAAC;AACzD,OAAO,EAAc,IAAI,EAAkB,MAAM,cAAc,CAAC;AAGhE,OAAO,EAEL,KAAK,kBAAkB,EAEvB,KAAK,wBAAwB,EAC9B,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAAQ,KAAK,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAG3E,eAAO,MAAM,6BAA6B,GAAI,wDAK3C,wBAAwB,wDAmD1B,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,aAAa,GAAG;IAClD;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,KAAK,CAAC,EAAE,GAAG,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,qBAAqB,CAAC;AAStD,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;IAxBvB;;;OAGG;YACK,MAAM;IACd;;OAEG;cACO,OAAO;IACjB;;OAEG;YACK,GAAG;+BAyCZ,CAAC;AASF,MAAM,MAAM,mBAAmB,GAAG,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"PeriodSelector.d.ts","sourceRoot":"","sources":["../../src/chart/PeriodSelector.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoC,MAAM,OAAO,CAAC;AACzD,OAAO,EAAc,IAAI,EAAkB,MAAM,cAAc,CAAC;AAGhE,OAAO,EAEL,KAAK,kBAAkB,EAEvB,KAAK,wBAAwB,EAC9B,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAAQ,KAAK,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAG3E,eAAO,MAAM,6BAA6B,GAAI,wDAK3C,wBAAwB,wDAmD1B,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG,aAAa,GAAG;IAClD;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;OAEG;IACH,KAAK,CAAC,EAAE,GAAG,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,qBAAqB,CAAC;AAStD,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;IAxBvB;;;OAGG;YACK,MAAM;IACd;;OAEG;cACO,OAAO;IACjB;;OAEG;YACK,GAAG;+BAyCZ,CAAC;AASF,MAAM,MAAM,mBAAmB,GAAG,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAC,GAClE,IAAI,CAAC,kBAAkB,EAAE,QAAQ,CAAC,CAAC;AAErC;;;GAGG;AACH,eAAO,MAAM,cAAc,gKA0B1B,CAAC"}
|
|
@@ -3,7 +3,7 @@ export const CartesianChartContext = /*#__PURE__*/createContext(undefined);
|
|
|
3
3
|
export const useCartesianChartContext = () => {
|
|
4
4
|
const context = useContext(CartesianChartContext);
|
|
5
5
|
if (!context) {
|
|
6
|
-
throw new Error('useCartesianChartContext must be used within a CartesianChart component. See
|
|
6
|
+
throw new Error('useCartesianChartContext must be used within a CartesianChart component. See https://cds.coinbase.com/components/charts/CartesianChart.');
|
|
7
7
|
}
|
|
8
8
|
return context;
|
|
9
9
|
};
|
|
@@ -2,15 +2,18 @@ const _excluded = ["label"],
|
|
|
2
2
|
_excluded2 = ["label", "font", "hideDot", "style"];
|
|
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
|
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); }
|
|
5
|
-
import { forwardRef, memo, useMemo, useState } from 'react';
|
|
5
|
+
import { forwardRef, memo, useCallback, useEffect, useMemo, useState } from 'react';
|
|
6
6
|
import { ScrollView, View } from 'react-native';
|
|
7
|
+
import { interpolateColor, runOnJS, useAnimatedReaction, useSharedValue, withSpring } from 'react-native-reanimated';
|
|
7
8
|
import { assets } from '@coinbase/cds-common/internal/data/assets';
|
|
8
9
|
import { useTabsContext } from '@coinbase/cds-common/tabs/TabsContext';
|
|
9
10
|
import { IconButton } from '@coinbase/cds-mobile/buttons';
|
|
10
11
|
import { Example, ExampleScreen } from '@coinbase/cds-mobile/examples/ExampleScreen';
|
|
11
12
|
import { useTheme } from '@coinbase/cds-mobile/hooks/useTheme';
|
|
13
|
+
import { Icon } from '@coinbase/cds-mobile/icons';
|
|
12
14
|
import { HStack } from '@coinbase/cds-mobile/layout';
|
|
13
15
|
import { SegmentedTab } from '@coinbase/cds-mobile/tabs/SegmentedTab';
|
|
16
|
+
import { tabsSpringConfig } from '@coinbase/cds-mobile/tabs/Tabs';
|
|
14
17
|
import { Text } from '@coinbase/cds-mobile/typography';
|
|
15
18
|
import { LiveTabLabel, PeriodSelector, PeriodSelectorActiveIndicator } from '../PeriodSelector';
|
|
16
19
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
@@ -318,6 +321,74 @@ const ColoredExcludingLivePeriodSelectorExample = () => {
|
|
|
318
321
|
tabs: tabs
|
|
319
322
|
});
|
|
320
323
|
};
|
|
324
|
+
const ColoredIcon = /*#__PURE__*/memo(_ref3 => {
|
|
325
|
+
let {
|
|
326
|
+
tabId,
|
|
327
|
+
name
|
|
328
|
+
} = _ref3;
|
|
329
|
+
const {
|
|
330
|
+
activeTab
|
|
331
|
+
} = useTabsContext();
|
|
332
|
+
const isActive = (activeTab == null ? void 0 : activeTab.id) === tabId;
|
|
333
|
+
const theme = useTheme();
|
|
334
|
+
const progress = useSharedValue(isActive ? 1 : 0);
|
|
335
|
+
const [color, setColor] = useState(isActive ? theme.color.fgPrimary : theme.color.fg);
|
|
336
|
+
useEffect(() => {
|
|
337
|
+
progress.value = withSpring(isActive ? 1 : 0, tabsSpringConfig);
|
|
338
|
+
}, [isActive, progress]);
|
|
339
|
+
useAnimatedReaction(() => interpolateColor(progress.value, [0, 1], [theme.color.fg, theme.color.fgPrimary]), newColor => {
|
|
340
|
+
runOnJS(setColor)(newColor);
|
|
341
|
+
});
|
|
342
|
+
return /*#__PURE__*/_jsx(Icon, {
|
|
343
|
+
active: true,
|
|
344
|
+
name: name,
|
|
345
|
+
size: "s",
|
|
346
|
+
styles: {
|
|
347
|
+
icon: {
|
|
348
|
+
color
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
});
|
|
352
|
+
});
|
|
353
|
+
function IconsPeriodSelectorExample() {
|
|
354
|
+
const theme = useTheme();
|
|
355
|
+
const tabs = [{
|
|
356
|
+
id: 'buy',
|
|
357
|
+
label: /*#__PURE__*/_jsx(ColoredIcon, {
|
|
358
|
+
name: "chartLine",
|
|
359
|
+
tabId: "buy"
|
|
360
|
+
})
|
|
361
|
+
}, {
|
|
362
|
+
id: 'sell',
|
|
363
|
+
label: /*#__PURE__*/_jsx(ColoredIcon, {
|
|
364
|
+
name: "chartCandles",
|
|
365
|
+
tabId: "sell"
|
|
366
|
+
})
|
|
367
|
+
}, {
|
|
368
|
+
id: 'convert',
|
|
369
|
+
label: /*#__PURE__*/_jsx(ColoredIcon, {
|
|
370
|
+
name: "chartBar",
|
|
371
|
+
tabId: "convert"
|
|
372
|
+
})
|
|
373
|
+
}];
|
|
374
|
+
const [activeTab, updateActiveTab] = useState(tabs[0]);
|
|
375
|
+
const handleChange = useCallback(activeTab => updateActiveTab(activeTab), []);
|
|
376
|
+
return /*#__PURE__*/_jsx(PeriodSelector, {
|
|
377
|
+
accessibilityLabel: "Switch token action views",
|
|
378
|
+
activeTab: activeTab,
|
|
379
|
+
borderRadius: 300,
|
|
380
|
+
gap: 0.5,
|
|
381
|
+
onChange: handleChange,
|
|
382
|
+
padding: 0.5,
|
|
383
|
+
styles: {
|
|
384
|
+
activeIndicator: {
|
|
385
|
+
borderRadius: theme.borderRadius[200]
|
|
386
|
+
}
|
|
387
|
+
},
|
|
388
|
+
tabs: tabs,
|
|
389
|
+
width: "fit-content"
|
|
390
|
+
});
|
|
391
|
+
}
|
|
321
392
|
export default function All() {
|
|
322
393
|
return /*#__PURE__*/_jsxs(ExampleScreen, {
|
|
323
394
|
children: [/*#__PURE__*/_jsx(Example, {
|
|
@@ -341,6 +412,9 @@ export default function All() {
|
|
|
341
412
|
}), /*#__PURE__*/_jsx(Example, {
|
|
342
413
|
title: "With Padding",
|
|
343
414
|
children: /*#__PURE__*/_jsx(PaddedPeriodSelectorExample, {})
|
|
415
|
+
}), /*#__PURE__*/_jsx(Example, {
|
|
416
|
+
title: "With Icons",
|
|
417
|
+
children: /*#__PURE__*/_jsx(IconsPeriodSelectorExample, {})
|
|
344
418
|
})]
|
|
345
419
|
});
|
|
346
420
|
}
|
|
@@ -57,7 +57,7 @@ export const BarStackGroup = /*#__PURE__*/memo(_ref => {
|
|
|
57
57
|
return configs;
|
|
58
58
|
}, [xScale, yScale, drawingArea, dataLength, stackIndex, totalStacks, barPadding]);
|
|
59
59
|
if (xScale && !isCategoricalScale(xScale)) {
|
|
60
|
-
throw new Error('BarStackGroup requires a band scale for x-axis. See https://cds.coinbase.com/components/
|
|
60
|
+
throw new Error('BarStackGroup requires a band scale for x-axis. See https://cds.coinbase.com/components/charts/XAxis/#scale-type');
|
|
61
61
|
}
|
|
62
62
|
if (!yScale || !drawingArea || stackConfigs.length === 0) return;
|
|
63
63
|
return stackConfigs.map(_ref2 => {
|
|
@@ -6,6 +6,7 @@ function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var 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); }
|
|
7
7
|
import { memo, useCallback, useEffect, useId, useMemo, useState } from 'react';
|
|
8
8
|
import { useDerivedValue } from 'react-native-reanimated';
|
|
9
|
+
import { assets } from '@coinbase/cds-common/internal/data/assets';
|
|
9
10
|
import { candles as btcCandles } from '@coinbase/cds-common/internal/data/candles';
|
|
10
11
|
import { Button, IconButton } from '@coinbase/cds-mobile/buttons';
|
|
11
12
|
import { ExampleScreen } from '@coinbase/cds-mobile/examples/ExampleScreen';
|
|
@@ -993,6 +994,41 @@ const SunlightChart = () => {
|
|
|
993
994
|
})]
|
|
994
995
|
});
|
|
995
996
|
};
|
|
997
|
+
const PriceRange = () => {
|
|
998
|
+
const candles = btcCandles.slice(0, 180).reverse();
|
|
999
|
+
const data = useMemo(() => candles.map(candle => [parseFloat(candle.low), parseFloat(candle.high)]), [candles]);
|
|
1000
|
+
const min = useMemo(() => Math.min(...data.map(_ref13 => {
|
|
1001
|
+
let [low] = _ref13;
|
|
1002
|
+
return low;
|
|
1003
|
+
})), [data]);
|
|
1004
|
+
const max = useMemo(() => Math.max(...data.map(_ref14 => {
|
|
1005
|
+
let [, high] = _ref14;
|
|
1006
|
+
return high;
|
|
1007
|
+
})), [data]);
|
|
1008
|
+
const tickFormatter = useCallback(value => new Intl.NumberFormat('en-US', {
|
|
1009
|
+
style: 'currency',
|
|
1010
|
+
currency: 'USD',
|
|
1011
|
+
notation: 'compact',
|
|
1012
|
+
maximumFractionDigits: 0
|
|
1013
|
+
}).format(value), []);
|
|
1014
|
+
return /*#__PURE__*/_jsx(BarChart, {
|
|
1015
|
+
showYAxis: true,
|
|
1016
|
+
height: 150,
|
|
1017
|
+
series: [{
|
|
1018
|
+
id: 'prices',
|
|
1019
|
+
data,
|
|
1020
|
+
color: assets.btc.color
|
|
1021
|
+
}],
|
|
1022
|
+
yAxis: {
|
|
1023
|
+
domain: {
|
|
1024
|
+
min,
|
|
1025
|
+
max
|
|
1026
|
+
},
|
|
1027
|
+
showGrid: true,
|
|
1028
|
+
tickLabelFormatter: tickFormatter
|
|
1029
|
+
}
|
|
1030
|
+
});
|
|
1031
|
+
};
|
|
996
1032
|
function ExampleNavigator() {
|
|
997
1033
|
const [currentIndex, setCurrentIndex] = useState(0);
|
|
998
1034
|
const examples = useMemo(() => [{
|
|
@@ -1054,6 +1090,9 @@ function ExampleNavigator() {
|
|
|
1054
1090
|
}, {
|
|
1055
1091
|
title: 'Monthly Sunlight',
|
|
1056
1092
|
component: /*#__PURE__*/_jsx(SunlightChart, {})
|
|
1093
|
+
}, {
|
|
1094
|
+
title: 'Price Range',
|
|
1095
|
+
component: /*#__PURE__*/_jsx(PriceRange, {})
|
|
1057
1096
|
}], []);
|
|
1058
1097
|
const currentExample = examples[currentIndex];
|
|
1059
1098
|
const handlePrevious = useCallback(() => {
|
package/esm/chart/utils/axis.js
CHANGED
|
@@ -83,7 +83,7 @@ export const getAxisScale = _ref => {
|
|
|
83
83
|
max: (_config$domain$max = config.domain.max) != null ? _config$domain$max : dataDomain.max
|
|
84
84
|
};
|
|
85
85
|
}
|
|
86
|
-
if (!isValidBounds(adjustedDomain)) throw new Error('Invalid domain bounds. See https://cds.coinbase.com/
|
|
86
|
+
if (!isValidBounds(adjustedDomain)) throw new Error('Invalid domain bounds. See https://cds.coinbase.com/components/charts/XAxis/#domain');
|
|
87
87
|
if (scaleType === 'band') {
|
|
88
88
|
var _config$categoryPaddi;
|
|
89
89
|
return getCategoricalScale({
|
|
@@ -137,7 +137,7 @@ export const getAxisConfig = function (type, axes, defaultId, defaultScaleType)
|
|
|
137
137
|
} = _ref2;
|
|
138
138
|
return id === undefined;
|
|
139
139
|
})) {
|
|
140
|
-
throw new Error('When defining multiple axes, each must have a unique id. See https://cds.coinbase.com/components/
|
|
140
|
+
throw new Error('When defining multiple axes, each must have a unique id. See https://cds.coinbase.com/components/charts/YAxis/#multiple-y-axes.');
|
|
141
141
|
}
|
|
142
142
|
return axes.map(_ref3 => {
|
|
143
143
|
let {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coinbase/cds-mobile-visualization",
|
|
3
|
-
"version": "3.4.0-beta.
|
|
3
|
+
"version": "3.4.0-beta.20",
|
|
4
4
|
"description": "Coinbase Design System - Mobile Visualization Native",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -36,9 +36,9 @@
|
|
|
36
36
|
"CHANGELOG"
|
|
37
37
|
],
|
|
38
38
|
"peerDependencies": {
|
|
39
|
-
"@coinbase/cds-common": "^8.
|
|
39
|
+
"@coinbase/cds-common": "^8.49.0",
|
|
40
40
|
"@coinbase/cds-lottie-files": "^3.3.4",
|
|
41
|
-
"@coinbase/cds-mobile": "^8.
|
|
41
|
+
"@coinbase/cds-mobile": "^8.49.0",
|
|
42
42
|
"@coinbase/cds-utils": "^2.3.5",
|
|
43
43
|
"@shopify/react-native-skia": "^1.12.4 || ^2.0.0",
|
|
44
44
|
"react": "^18.3.1",
|
|
@@ -57,9 +57,9 @@
|
|
|
57
57
|
"@babel/preset-env": "^7.28.0",
|
|
58
58
|
"@babel/preset-react": "^7.27.1",
|
|
59
59
|
"@babel/preset-typescript": "^7.27.1",
|
|
60
|
-
"@coinbase/cds-common": "^8.
|
|
60
|
+
"@coinbase/cds-common": "^8.49.0",
|
|
61
61
|
"@coinbase/cds-lottie-files": "^3.3.4",
|
|
62
|
-
"@coinbase/cds-mobile": "^8.
|
|
62
|
+
"@coinbase/cds-mobile": "^8.49.0",
|
|
63
63
|
"@coinbase/cds-utils": "^2.3.5",
|
|
64
64
|
"@shopify/react-native-skia": "1.12.4",
|
|
65
65
|
"@types/react": "^18.3.12",
|