@coinbase/cds-mobile-visualization 3.4.0-beta.11 → 3.4.0-beta.13
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 +18 -0
- package/dts/chart/scrubber/DefaultScrubberBeacon.d.ts +24 -2
- package/dts/chart/scrubber/DefaultScrubberBeacon.d.ts.map +1 -1
- package/dts/chart/scrubber/Scrubber.d.ts +20 -2
- package/dts/chart/scrubber/Scrubber.d.ts.map +1 -1
- package/dts/chart/scrubber/ScrubberBeaconGroup.d.ts +10 -0
- package/dts/chart/scrubber/ScrubberBeaconGroup.d.ts.map +1 -1
- package/esm/chart/line/__stories__/LineChart.stories.js +124 -2
- package/esm/chart/scrubber/DefaultScrubberBeacon.js +33 -29
- package/esm/chart/scrubber/Scrubber.js +3 -1
- package/esm/chart/scrubber/ScrubberBeaconGroup.js +6 -2
- package/esm/sparkline/__figma__/Sparkline.figma.js +1 -1
- package/esm/sparkline/sparkline-interactive/__figma__/SparklineInteractive.figma.js +1 -1
- package/esm/sparkline/sparkline-interactive-header/__figma__/SparklineInteractiveHeader.figma.js +1 -1
- package/package.json +5 -6
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,24 @@ 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.13 (1/20/2026 PST)
|
|
12
|
+
|
|
13
|
+
#### 🚀 Updates
|
|
14
|
+
|
|
15
|
+
- Feat: support styling default scrubber beacon. [[#315](https://github.com/coinbase/cds/pull/315)]
|
|
16
|
+
- Fix: idlePulse works on mobile even when Chart animation is off, matching web. [[#315](https://github.com/coinbase/cds/pull/315)]
|
|
17
|
+
|
|
18
|
+
#### 📘 Misc
|
|
19
|
+
|
|
20
|
+
- Internal: code connect file lint fixes. [[#311](https://github.com/coinbase/cds/pull/311)]
|
|
21
|
+
- Internal: update figma code connect config and some mapping files. [[#304](https://github.com/coinbase/cds/pull/304)]
|
|
22
|
+
|
|
23
|
+
## 3.4.0-beta.12 (1/8/2026 PST)
|
|
24
|
+
|
|
25
|
+
#### 🐞 Fixes
|
|
26
|
+
|
|
27
|
+
- Fix pulse with spread operator broken on new react-native architecture. [[#296](https://github.com/coinbase/cds/pull/296)]
|
|
28
|
+
|
|
11
29
|
## 3.4.0-beta.11 (1/7/2026 PST)
|
|
12
30
|
|
|
13
31
|
#### 🐞 Fixes
|
|
@@ -1,8 +1,30 @@
|
|
|
1
1
|
import type { ScrubberBeaconProps, ScrubberBeaconRef } from './Scrubber';
|
|
2
|
-
export type DefaultScrubberBeaconProps = ScrubberBeaconProps
|
|
2
|
+
export type DefaultScrubberBeaconProps = ScrubberBeaconProps & {
|
|
3
|
+
/**
|
|
4
|
+
* Radius of the beacon circle.
|
|
5
|
+
* @default 5
|
|
6
|
+
*/
|
|
7
|
+
radius?: number;
|
|
8
|
+
/**
|
|
9
|
+
* Stroke width of the beacon circle.
|
|
10
|
+
* @default 2
|
|
11
|
+
*/
|
|
12
|
+
strokeWidth?: number;
|
|
13
|
+
};
|
|
3
14
|
export declare const DefaultScrubberBeacon: import('react').MemoExoticComponent<
|
|
4
15
|
import('react').ForwardRefExoticComponent<
|
|
5
|
-
ScrubberBeaconProps &
|
|
16
|
+
ScrubberBeaconProps & {
|
|
17
|
+
/**
|
|
18
|
+
* Radius of the beacon circle.
|
|
19
|
+
* @default 5
|
|
20
|
+
*/
|
|
21
|
+
radius?: number;
|
|
22
|
+
/**
|
|
23
|
+
* Stroke width of the beacon circle.
|
|
24
|
+
* @default 2
|
|
25
|
+
*/
|
|
26
|
+
strokeWidth?: number;
|
|
27
|
+
} & import('react').RefAttributes<ScrubberBeaconRef>
|
|
6
28
|
>
|
|
7
29
|
>;
|
|
8
30
|
//# sourceMappingURL=DefaultScrubberBeacon.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DefaultScrubberBeacon.d.ts","sourceRoot":"","sources":["../../../src/chart/scrubber/DefaultScrubberBeacon.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"DefaultScrubberBeacon.d.ts","sourceRoot":"","sources":["../../../src/chart/scrubber/DefaultScrubberBeacon.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAkBzE,MAAM,MAAM,0BAA0B,GAAG,mBAAmB,GAAG;IAC7D;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,eAAO,MAAM,qBAAqB;IAZhC;;;OAGG;aACM,MAAM;IACf;;;OAGG;kBACW,MAAM;sDAiMrB,CAAC"}
|
|
@@ -43,11 +43,14 @@ export type ScrubberBeaconProps = {
|
|
|
43
43
|
isIdle: AnimatedProp<boolean>;
|
|
44
44
|
/**
|
|
45
45
|
* Pulse the beacon while it is at rest.
|
|
46
|
+
*
|
|
47
|
+
* @note Only has an effect when `isIdle` is `true`. Pulse animations work
|
|
48
|
+
* regardless of the chart's `animate` prop.
|
|
46
49
|
*/
|
|
47
50
|
idlePulse?: boolean;
|
|
48
51
|
/**
|
|
49
|
-
* Whether animations are enabled.
|
|
50
|
-
* @default
|
|
52
|
+
* Whether position animations are enabled.
|
|
53
|
+
* @default to ChartContext's animate value
|
|
51
54
|
*/
|
|
52
55
|
animate?: boolean;
|
|
53
56
|
/**
|
|
@@ -76,6 +79,11 @@ export type ScrubberBeaconProps = {
|
|
|
76
79
|
* @default 1
|
|
77
80
|
*/
|
|
78
81
|
opacity?: AnimatedProp<number>;
|
|
82
|
+
/**
|
|
83
|
+
* Stroke color of the beacon circle.
|
|
84
|
+
* @default theme.color.bg
|
|
85
|
+
*/
|
|
86
|
+
stroke?: string;
|
|
79
87
|
};
|
|
80
88
|
export type ScrubberBeaconComponent = React.FC<
|
|
81
89
|
ScrubberBeaconProps & {
|
|
@@ -159,6 +167,11 @@ export type ScrubberBaseProps = Pick<ScrubberBeaconGroupBaseProps, 'idlePulse'>
|
|
|
159
167
|
* Transition configuration for the scrubber beacon.
|
|
160
168
|
*/
|
|
161
169
|
beaconTransitions?: ScrubberBeaconProps['transitions'];
|
|
170
|
+
/**
|
|
171
|
+
* Stroke color of the scrubber beacon circle.
|
|
172
|
+
* @default theme.color.bg
|
|
173
|
+
*/
|
|
174
|
+
beaconStroke?: string;
|
|
162
175
|
};
|
|
163
176
|
export type ScrubberProps = ScrubberBaseProps;
|
|
164
177
|
export type ScrubberRef = ScrubberBeaconGroupRef;
|
|
@@ -227,6 +240,11 @@ export declare const Scrubber: React.MemoExoticComponent<
|
|
|
227
240
|
* Transition configuration for the scrubber beacon.
|
|
228
241
|
*/
|
|
229
242
|
beaconTransitions?: ScrubberBeaconProps['transitions'];
|
|
243
|
+
/**
|
|
244
|
+
* Stroke color of the scrubber beacon circle.
|
|
245
|
+
* @default theme.color.bg
|
|
246
|
+
*/
|
|
247
|
+
beaconStroke?: string;
|
|
230
248
|
} & React.RefAttributes<ScrubberBeaconGroupRef>
|
|
231
249
|
>
|
|
232
250
|
>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Scrubber.d.ts","sourceRoot":"","sources":["../../../src/chart/scrubber/Scrubber.tsx"],"names":[],"mappings":"AAAA,OAAO,KAON,MAAM,OAAO,CAAC;AAUf,OAAO,EAAE,KAAK,YAAY,EAAe,KAAK,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAG9F,OAAO,EAEL,KAAK,sBAAsB,EAC3B,KAAK,gCAAgC,EACtC,MAAM,SAAS,CAAC;AACjB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAC9C,OAAO,EAGL,KAAK,UAAU,EAEf,KAAK,MAAM,EAEZ,MAAM,UAAU,CAAC;AAClB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAItD,OAAO,EAEL,KAAK,4BAA4B,EACjC,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,EAC5B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAEL,KAAK,iCAAiC,EACtC,KAAK,6BAA6B,EACnC,MAAM,4BAA4B,CAAC;AAEpC,MAAM,MAAM,iBAAiB,GAAG;IAC9B;;;OAGG;IACH,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IACvB;;OAEG;IACH,KAAK,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;IAC7B;;OAEG;IACH,KAAK,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;IAC5B;;OAEG;IACH,KAAK,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC;IAC5B;;OAEG;IACH,MAAM,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC;IAC9B
|
|
1
|
+
{"version":3,"file":"Scrubber.d.ts","sourceRoot":"","sources":["../../../src/chart/scrubber/Scrubber.tsx"],"names":[],"mappings":"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"}
|
|
@@ -25,6 +25,11 @@ export type ScrubberBeaconGroupProps = ScrubberBeaconGroupBaseProps & {
|
|
|
25
25
|
* @default DefaultScrubberBeacon
|
|
26
26
|
*/
|
|
27
27
|
BeaconComponent?: ScrubberBeaconComponent;
|
|
28
|
+
/**
|
|
29
|
+
* Stroke color of the beacon circle.
|
|
30
|
+
* @default theme.color.bg
|
|
31
|
+
*/
|
|
32
|
+
stroke?: string;
|
|
28
33
|
};
|
|
29
34
|
export declare const ScrubberBeaconGroup: import('react').MemoExoticComponent<
|
|
30
35
|
import('react').ForwardRefExoticComponent<
|
|
@@ -38,6 +43,11 @@ export declare const ScrubberBeaconGroup: import('react').MemoExoticComponent<
|
|
|
38
43
|
* @default DefaultScrubberBeacon
|
|
39
44
|
*/
|
|
40
45
|
BeaconComponent?: ScrubberBeaconComponent;
|
|
46
|
+
/**
|
|
47
|
+
* Stroke color of the beacon circle.
|
|
48
|
+
* @default theme.color.bg
|
|
49
|
+
*/
|
|
50
|
+
stroke?: string;
|
|
41
51
|
} & import('react').RefAttributes<ScrubberBeaconGroupRef>
|
|
42
52
|
>
|
|
43
53
|
>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScrubberBeaconGroup.d.ts","sourceRoot":"","sources":["../../../src/chart/scrubber/ScrubberBeaconGroup.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,uBAAuB,EAAE,mBAAmB,EAAqB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"ScrubberBeaconGroup.d.ts","sourceRoot":"","sources":["../../../src/chart/scrubber/ScrubberBeaconGroup.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,uBAAuB,EAAE,mBAAmB,EAAqB,MAAM,YAAY,CAAC;AAmHlG,MAAM,MAAM,sBAAsB,GAAG;IACnC;;OAEG;IACH,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAAG;IACzC;;OAEG;IACH,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,wBAAwB,GAAG,4BAA4B,GAAG;IACpE;;OAEG;IACH,WAAW,CAAC,EAAE,mBAAmB,CAAC,aAAa,CAAC,CAAC;IACjD;;;OAGG;IACH,eAAe,CAAC,EAAE,uBAAuB,CAAC;IAC1C;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,eAAO,MAAM,mBAAmB;IAhB9B;;OAEG;kBACW,mBAAmB,CAAC,aAAa,CAAC;IAChD;;;OAGG;sBACe,uBAAuB;IACzC;;;OAGG;aACM,MAAM;2DAyEhB,CAAC"}
|
|
@@ -2014,6 +2014,122 @@ function HiddenScrubberWhenIdle() {
|
|
|
2014
2014
|
})
|
|
2015
2015
|
});
|
|
2016
2016
|
}
|
|
2017
|
+
function CustomBeaconStroke() {
|
|
2018
|
+
const theme = useTheme();
|
|
2019
|
+
const backgroundColor = "rgb(" + theme.spectrum.red40 + ")";
|
|
2020
|
+
const foregroundColor = "rgb(" + theme.spectrum.gray0 + ")";
|
|
2021
|
+
return /*#__PURE__*/_jsx(Box, {
|
|
2022
|
+
borderRadius: 300,
|
|
2023
|
+
padding: 2,
|
|
2024
|
+
style: {
|
|
2025
|
+
backgroundColor
|
|
2026
|
+
},
|
|
2027
|
+
children: /*#__PURE__*/_jsx(LineChart, {
|
|
2028
|
+
enableScrubbing: true,
|
|
2029
|
+
showArea: true,
|
|
2030
|
+
height: 150,
|
|
2031
|
+
series: [{
|
|
2032
|
+
id: 'prices',
|
|
2033
|
+
data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58],
|
|
2034
|
+
color: foregroundColor
|
|
2035
|
+
}],
|
|
2036
|
+
children: /*#__PURE__*/_jsx(Scrubber, {
|
|
2037
|
+
hideOverlay: true,
|
|
2038
|
+
idlePulse: true,
|
|
2039
|
+
beaconStroke: backgroundColor,
|
|
2040
|
+
lineStroke: foregroundColor
|
|
2041
|
+
})
|
|
2042
|
+
})
|
|
2043
|
+
});
|
|
2044
|
+
}
|
|
2045
|
+
function CustomBeaconSize() {
|
|
2046
|
+
const theme = useTheme();
|
|
2047
|
+
const dataCount = 14;
|
|
2048
|
+
const minDataValue = 0;
|
|
2049
|
+
const maxDataValue = 100;
|
|
2050
|
+
const minStepOffset = 5;
|
|
2051
|
+
const maxStepOffset = 20;
|
|
2052
|
+
const updateInterval = 2000;
|
|
2053
|
+
function generateNextValue(previousValue) {
|
|
2054
|
+
const range = maxStepOffset - minStepOffset;
|
|
2055
|
+
const offset = Math.random() * range + minStepOffset;
|
|
2056
|
+
let direction;
|
|
2057
|
+
if (previousValue >= maxDataValue) {
|
|
2058
|
+
direction = -1;
|
|
2059
|
+
} else if (previousValue <= minDataValue) {
|
|
2060
|
+
direction = 1;
|
|
2061
|
+
} else {
|
|
2062
|
+
direction = Math.random() < 0.5 ? -1 : 1;
|
|
2063
|
+
}
|
|
2064
|
+
const newValue = previousValue + offset * direction;
|
|
2065
|
+
return Math.max(minDataValue, Math.min(maxDataValue, newValue));
|
|
2066
|
+
}
|
|
2067
|
+
function generateInitialData() {
|
|
2068
|
+
const data = [];
|
|
2069
|
+
let previousValue = Math.random() * (maxDataValue - minDataValue) + minDataValue;
|
|
2070
|
+
data.push(previousValue);
|
|
2071
|
+
for (let i = 1; i < dataCount; i++) {
|
|
2072
|
+
const newValue = generateNextValue(previousValue);
|
|
2073
|
+
data.push(newValue);
|
|
2074
|
+
previousValue = newValue;
|
|
2075
|
+
}
|
|
2076
|
+
return data;
|
|
2077
|
+
}
|
|
2078
|
+
const InvertedBeacon = useMemo(() => props => /*#__PURE__*/_jsx(DefaultScrubberBeacon, _extends({}, props, {
|
|
2079
|
+
color: theme.color.bg,
|
|
2080
|
+
radius: 5,
|
|
2081
|
+
stroke: theme.color.fg,
|
|
2082
|
+
strokeWidth: 3
|
|
2083
|
+
})), [theme.color.fg, theme.color.bg]);
|
|
2084
|
+
const CustomBeaconSizeChart = /*#__PURE__*/memo(() => {
|
|
2085
|
+
const [data, setData] = useState(generateInitialData);
|
|
2086
|
+
useEffect(() => {
|
|
2087
|
+
const intervalId = setInterval(() => {
|
|
2088
|
+
setData(currentData => {
|
|
2089
|
+
var _currentData2;
|
|
2090
|
+
const lastValue = (_currentData2 = currentData[currentData.length - 1]) != null ? _currentData2 : 50;
|
|
2091
|
+
const newValue = generateNextValue(lastValue);
|
|
2092
|
+
return [...currentData.slice(1), newValue];
|
|
2093
|
+
});
|
|
2094
|
+
}, updateInterval);
|
|
2095
|
+
return () => clearInterval(intervalId);
|
|
2096
|
+
}, []);
|
|
2097
|
+
return /*#__PURE__*/_jsx(LineChart, {
|
|
2098
|
+
enableScrubbing: true,
|
|
2099
|
+
showArea: true,
|
|
2100
|
+
showYAxis: true,
|
|
2101
|
+
height: 150,
|
|
2102
|
+
series: [{
|
|
2103
|
+
id: 'prices',
|
|
2104
|
+
data,
|
|
2105
|
+
color: theme.color.fg
|
|
2106
|
+
}],
|
|
2107
|
+
xAxis: {
|
|
2108
|
+
range: _ref23 => {
|
|
2109
|
+
let {
|
|
2110
|
+
min,
|
|
2111
|
+
max
|
|
2112
|
+
} = _ref23;
|
|
2113
|
+
return {
|
|
2114
|
+
min,
|
|
2115
|
+
max: max - 16
|
|
2116
|
+
};
|
|
2117
|
+
}
|
|
2118
|
+
},
|
|
2119
|
+
yAxis: {
|
|
2120
|
+
showGrid: true,
|
|
2121
|
+
domain: {
|
|
2122
|
+
min: 0,
|
|
2123
|
+
max: 100
|
|
2124
|
+
}
|
|
2125
|
+
},
|
|
2126
|
+
children: /*#__PURE__*/_jsx(Scrubber, {
|
|
2127
|
+
BeaconComponent: InvertedBeacon
|
|
2128
|
+
})
|
|
2129
|
+
});
|
|
2130
|
+
});
|
|
2131
|
+
return /*#__PURE__*/_jsx(CustomBeaconSizeChart, {});
|
|
2132
|
+
}
|
|
2017
2133
|
function TwoLineScrubberLabel() {
|
|
2018
2134
|
const theme = useTheme();
|
|
2019
2135
|
const data = useMemo(() => [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58], []);
|
|
@@ -2260,11 +2376,11 @@ function ExampleNavigator() {
|
|
|
2260
2376
|
}],
|
|
2261
2377
|
xAxis: {
|
|
2262
2378
|
// Give space before the end of the chart for the scrubber
|
|
2263
|
-
range:
|
|
2379
|
+
range: _ref24 => {
|
|
2264
2380
|
let {
|
|
2265
2381
|
min,
|
|
2266
2382
|
max
|
|
2267
|
-
} =
|
|
2383
|
+
} = _ref24;
|
|
2268
2384
|
return {
|
|
2269
2385
|
min,
|
|
2270
2386
|
max: max - 24
|
|
@@ -2319,6 +2435,12 @@ function ExampleNavigator() {
|
|
|
2319
2435
|
}, {
|
|
2320
2436
|
title: 'Two-Line Scrubber Label',
|
|
2321
2437
|
component: /*#__PURE__*/_jsx(TwoLineScrubberLabel, {})
|
|
2438
|
+
}, {
|
|
2439
|
+
title: 'Custom Beacon Stroke',
|
|
2440
|
+
component: /*#__PURE__*/_jsx(CustomBeaconStroke, {})
|
|
2441
|
+
}, {
|
|
2442
|
+
title: 'Custom Beacon Size',
|
|
2443
|
+
component: /*#__PURE__*/_jsx(CustomBeaconSize, {})
|
|
2322
2444
|
}], [theme.color.fg, theme.color.fgPositive, theme.spectrum.gray50]);
|
|
2323
2445
|
const currentExample = examples[currentIndex];
|
|
2324
2446
|
const isFirstExample = currentIndex === 0;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import { cancelAnimation, Easing, useAnimatedReaction, useDerivedValue, useSharedValue, withRepeat, withSequence } from 'react-native-reanimated';
|
|
1
|
+
import { forwardRef, memo, useEffect, useImperativeHandle, useMemo } from 'react';
|
|
2
|
+
import { cancelAnimation, Easing, useAnimatedReaction, useDerivedValue, useSharedValue, withDelay, withRepeat, withSequence, withTiming } from 'react-native-reanimated';
|
|
4
3
|
import { useTheme } from '@coinbase/cds-mobile';
|
|
5
4
|
import { Circle, Group } from '@shopify/react-native-skia';
|
|
6
5
|
import { useCartesianChartContext } from '../ChartProvider';
|
|
@@ -8,12 +7,12 @@ import { unwrapAnimatedValue } from '../utils';
|
|
|
8
7
|
import { projectPointWithSerializableScale } from '../utils/point';
|
|
9
8
|
import { buildTransition, defaultTransition } from '../utils/transition';
|
|
10
9
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
|
-
const
|
|
12
|
-
const
|
|
10
|
+
const defaultRadius = 5;
|
|
11
|
+
const defaultStrokeWidth = 2;
|
|
13
12
|
const pulseOpacityStart = 0.5;
|
|
14
13
|
const pulseOpacityEnd = 0;
|
|
15
|
-
const
|
|
16
|
-
const
|
|
14
|
+
const pulseRadiusStartMultiplier = 2;
|
|
15
|
+
const pulseRadiusEndMultiplier = 3;
|
|
17
16
|
const defaultPulseTransition = {
|
|
18
17
|
type: 'timing',
|
|
19
18
|
duration: 1600,
|
|
@@ -30,7 +29,10 @@ export const DefaultScrubberBeacon = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((
|
|
|
30
29
|
idlePulse,
|
|
31
30
|
animate = true,
|
|
32
31
|
transitions,
|
|
33
|
-
opacity: opacityProp = 1
|
|
32
|
+
opacity: opacityProp = 1,
|
|
33
|
+
radius = defaultRadius,
|
|
34
|
+
stroke,
|
|
35
|
+
strokeWidth = defaultStrokeWidth
|
|
34
36
|
} = _ref;
|
|
35
37
|
const theme = useTheme();
|
|
36
38
|
const {
|
|
@@ -58,8 +60,18 @@ export const DefaultScrubberBeacon = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((
|
|
|
58
60
|
var _transitions$pulseRep;
|
|
59
61
|
return (_transitions$pulseRep = transitions == null ? void 0 : transitions.pulseRepeatDelay) != null ? _transitions$pulseRep : defaultPulseRepeatDelay;
|
|
60
62
|
}, [transitions == null ? void 0 : transitions.pulseRepeatDelay]);
|
|
63
|
+
const pulseRadiusStart = radius * pulseRadiusStartMultiplier;
|
|
64
|
+
const pulseRadiusEnd = radius * pulseRadiusEndMultiplier;
|
|
61
65
|
const pulseOpacity = useSharedValue(0);
|
|
62
66
|
const pulseRadius = useSharedValue(pulseRadiusStart);
|
|
67
|
+
|
|
68
|
+
// Convert idlePulse prop to SharedValue so useAnimatedReaction can detect changes.
|
|
69
|
+
// In the new React Native architecture, regular JS props are captured by value in worklets
|
|
70
|
+
// and won't update when the prop changes.
|
|
71
|
+
const idlePulseShared = useSharedValue(idlePulse != null ? idlePulse : false);
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
idlePulseShared.value = idlePulse != null ? idlePulse : false;
|
|
74
|
+
}, [idlePulse, idlePulseShared]);
|
|
63
75
|
const animatedX = useSharedValue(0);
|
|
64
76
|
const animatedY = useSharedValue(0);
|
|
65
77
|
|
|
@@ -103,41 +115,33 @@ export const DefaultScrubberBeacon = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((
|
|
|
103
115
|
useImperativeHandle(ref, () => ({
|
|
104
116
|
pulse: () => {
|
|
105
117
|
// Only trigger manual pulse when idlePulse is not enabled
|
|
106
|
-
if (!
|
|
118
|
+
if (!idlePulseShared.value) {
|
|
107
119
|
cancelAnimation(pulseOpacity);
|
|
108
120
|
cancelAnimation(pulseRadius);
|
|
109
121
|
|
|
110
122
|
// Manual pulse without delay
|
|
111
|
-
const immediatePulseTransition = _extends({}, pulseTransition, {
|
|
112
|
-
delay: 0
|
|
113
|
-
});
|
|
114
123
|
pulseOpacity.value = pulseOpacityStart;
|
|
115
124
|
pulseRadius.value = pulseRadiusStart;
|
|
116
|
-
pulseOpacity.value = buildTransition(pulseOpacityEnd,
|
|
117
|
-
pulseRadius.value = buildTransition(pulseRadiusEnd,
|
|
125
|
+
pulseOpacity.value = buildTransition(pulseOpacityEnd, pulseTransition);
|
|
126
|
+
pulseRadius.value = buildTransition(pulseRadiusEnd, pulseTransition);
|
|
118
127
|
}
|
|
119
128
|
}
|
|
120
|
-
}), [
|
|
129
|
+
}), [idlePulseShared, pulseOpacity, pulseRadius, pulseTransition, pulseRadiusStart, pulseRadiusEnd]);
|
|
121
130
|
|
|
122
131
|
// Watch idlePulse changes and control continuous pulse
|
|
123
|
-
useAnimatedReaction(() =>
|
|
124
|
-
if (!animate) return;
|
|
132
|
+
useAnimatedReaction(() => idlePulseShared.value, current => {
|
|
125
133
|
if (current) {
|
|
126
134
|
// Start continuous pulse when idlePulse is enabled
|
|
127
|
-
// Create instant transition to reset pulse after delay
|
|
128
|
-
const instantTransition = {
|
|
129
|
-
type: 'timing',
|
|
130
|
-
duration: 0
|
|
131
|
-
};
|
|
132
|
-
const resetWithDelay = _extends({}, instantTransition, {
|
|
133
|
-
delay: pulseRepeatDelay
|
|
134
|
-
});
|
|
135
135
|
pulseOpacity.value = pulseOpacityStart;
|
|
136
136
|
pulseRadius.value = pulseRadiusStart;
|
|
137
|
-
pulseOpacity.value = withRepeat(withSequence(buildTransition(pulseOpacityEnd, pulseTransition),
|
|
137
|
+
pulseOpacity.value = withRepeat(withSequence(buildTransition(pulseOpacityEnd, pulseTransition), withDelay(pulseRepeatDelay, withTiming(pulseOpacityStart, {
|
|
138
|
+
duration: 0
|
|
139
|
+
}))), -1,
|
|
138
140
|
// infinite loop
|
|
139
141
|
false);
|
|
140
|
-
pulseRadius.value = withRepeat(withSequence(buildTransition(pulseRadiusEnd, pulseTransition),
|
|
142
|
+
pulseRadius.value = withRepeat(withSequence(buildTransition(pulseRadiusEnd, pulseTransition), withDelay(pulseRepeatDelay, withTiming(pulseRadiusStart, {
|
|
143
|
+
duration: 0
|
|
144
|
+
}))), -1,
|
|
141
145
|
// infinite loop
|
|
142
146
|
false);
|
|
143
147
|
} else {
|
|
@@ -147,7 +151,7 @@ export const DefaultScrubberBeacon = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((
|
|
|
147
151
|
pulseOpacity.value = pulseOpacityEnd;
|
|
148
152
|
pulseRadius.value = pulseRadiusStart;
|
|
149
153
|
}
|
|
150
|
-
}, [
|
|
154
|
+
}, [pulseTransition, pulseRepeatDelay, pulseRadiusStart, pulseRadiusEnd]);
|
|
151
155
|
const pulseVisibility = useDerivedValue(() => {
|
|
152
156
|
// Never pulse when scrubbing
|
|
153
157
|
if (!unwrapAnimatedValue(isIdle)) return 0;
|
|
@@ -168,7 +172,7 @@ export const DefaultScrubberBeacon = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((
|
|
|
168
172
|
r: pulseRadius
|
|
169
173
|
}), /*#__PURE__*/_jsx(Circle, {
|
|
170
174
|
c: animatedPoint,
|
|
171
|
-
color: theme.color.bg,
|
|
175
|
+
color: stroke != null ? stroke : theme.color.bg,
|
|
172
176
|
r: radius + strokeWidth / 2
|
|
173
177
|
}), /*#__PURE__*/_jsx(Circle, {
|
|
174
178
|
c: animatedPoint,
|
|
@@ -32,7 +32,8 @@ export const Scrubber = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, ref) =>
|
|
|
32
32
|
labelBoundsInset,
|
|
33
33
|
beaconLabelFont,
|
|
34
34
|
idlePulse,
|
|
35
|
-
beaconTransitions
|
|
35
|
+
beaconTransitions,
|
|
36
|
+
beaconStroke
|
|
36
37
|
} = _ref;
|
|
37
38
|
const theme = useTheme();
|
|
38
39
|
const beaconGroupRef = React.useRef(null);
|
|
@@ -154,6 +155,7 @@ export const Scrubber = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref, ref) =>
|
|
|
154
155
|
BeaconComponent: BeaconComponent,
|
|
155
156
|
idlePulse: idlePulse,
|
|
156
157
|
seriesIds: filteredSeriesIds,
|
|
158
|
+
stroke: beaconStroke,
|
|
157
159
|
transitions: beaconTransitions
|
|
158
160
|
}), beaconLabels.length > 0 && /*#__PURE__*/_jsx(ScrubberBeaconLabelGroup, {
|
|
159
161
|
BeaconLabelComponent: BeaconLabelComponent,
|
|
@@ -18,7 +18,8 @@ const BeaconWithData = /*#__PURE__*/memo(_ref => {
|
|
|
18
18
|
idlePulse,
|
|
19
19
|
animate,
|
|
20
20
|
transitions,
|
|
21
|
-
beaconRef
|
|
21
|
+
beaconRef,
|
|
22
|
+
stroke
|
|
22
23
|
} = _ref;
|
|
23
24
|
const {
|
|
24
25
|
getSeries,
|
|
@@ -91,6 +92,7 @@ const BeaconWithData = /*#__PURE__*/memo(_ref => {
|
|
|
91
92
|
idlePulse: idlePulse,
|
|
92
93
|
isIdle: isIdle,
|
|
93
94
|
seriesId: seriesId,
|
|
95
|
+
stroke: stroke,
|
|
94
96
|
transitions: transitions
|
|
95
97
|
});
|
|
96
98
|
});
|
|
@@ -99,7 +101,8 @@ export const ScrubberBeaconGroup = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_r
|
|
|
99
101
|
seriesIds,
|
|
100
102
|
idlePulse,
|
|
101
103
|
transitions,
|
|
102
|
-
BeaconComponent = DefaultScrubberBeacon
|
|
104
|
+
BeaconComponent = DefaultScrubberBeacon,
|
|
105
|
+
stroke
|
|
103
106
|
} = _ref2;
|
|
104
107
|
const ScrubberBeaconRefs = useRefMap();
|
|
105
108
|
const {
|
|
@@ -156,6 +159,7 @@ export const ScrubberBeaconGroup = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_r
|
|
|
156
159
|
idlePulse: idlePulse,
|
|
157
160
|
isIdle: isIdle,
|
|
158
161
|
seriesId: s.id,
|
|
162
|
+
stroke: stroke,
|
|
159
163
|
transitions: transitions
|
|
160
164
|
}, s.id));
|
|
161
165
|
}));
|
|
@@ -4,7 +4,7 @@ import { figma } from '@figma/code-connect';
|
|
|
4
4
|
import { Sparkline } from '../Sparkline';
|
|
5
5
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
6
6
|
figma.connect(Sparkline, 'https://www.figma.com/design/k5CtyJccNQUGMI5bI4lJ2g/%E2%9C%A8-CDS-Components?node-id=320%3A15040', {
|
|
7
|
-
imports: ["import { Sparkline } from '@coinbase/cds-mobile-visualization'
|
|
7
|
+
imports: ["import { Sparkline } from '@coinbase/cds-mobile-visualization'", "import { useSparklinePath } from '@coinbase/cds-common/visualizations/useSparklinePath'"],
|
|
8
8
|
example: function Example() {
|
|
9
9
|
const data = [20, 30, 5, 45, 0];
|
|
10
10
|
const path = useSparklinePath({
|
|
@@ -4,7 +4,7 @@ import { figma } from '@figma/code-connect';
|
|
|
4
4
|
import { SparklineInteractive } from '../SparklineInteractive';
|
|
5
5
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
6
6
|
figma.connect(SparklineInteractive, 'https://www.figma.com/design/k5CtyJccNQUGMI5bI4lJ2g/%E2%9C%A8-CDS-Components?node-id=320-14858&m=dev', {
|
|
7
|
-
imports: ["import { SparklineInteractive } from '@coinbase/cds-
|
|
7
|
+
imports: ["import { SparklineInteractive } from '@coinbase/cds-mobile-visualization'"],
|
|
8
8
|
props: {
|
|
9
9
|
compact: figma.boolean('compact'),
|
|
10
10
|
disableScrubbing: figma.boolean('scrubbing', {
|
package/esm/sparkline/sparkline-interactive-header/__figma__/SparklineInteractiveHeader.figma.js
CHANGED
|
@@ -5,7 +5,7 @@ import { SparklineInteractive } from '../../sparkline-interactive/SparklineInter
|
|
|
5
5
|
import { SparklineInteractiveHeader } from '../SparklineInteractiveHeader';
|
|
6
6
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
7
7
|
figma.connect(SparklineInteractiveHeader, 'https://www.figma.com/design/k5CtyJccNQUGMI5bI4lJ2g/✨-CDS-Components?node-id=320-14931&m=dev', {
|
|
8
|
-
imports: ["import { SparklineInteractiveHeader } from '@coinbase/cds-
|
|
8
|
+
imports: ["import { SparklineInteractiveHeader } from '@coinbase/cds-mobile-visualization'", "import { SparklineInteractive } from '@coinbase/cds-mobile-visualization'"],
|
|
9
9
|
props: {
|
|
10
10
|
compact: figma.boolean('compact'),
|
|
11
11
|
disableScrubbing: figma.boolean('scrubbing', {
|
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.13",
|
|
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.38.1",
|
|
40
40
|
"@coinbase/cds-lottie-files": "^3.3.4",
|
|
41
|
-
"@coinbase/cds-mobile": "^8.
|
|
41
|
+
"@coinbase/cds-mobile": "^8.38.1",
|
|
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,11 +57,10 @@
|
|
|
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.38.1",
|
|
61
61
|
"@coinbase/cds-lottie-files": "^3.3.4",
|
|
62
|
-
"@coinbase/cds-mobile": "^8.
|
|
62
|
+
"@coinbase/cds-mobile": "^8.38.1",
|
|
63
63
|
"@coinbase/cds-utils": "^2.3.5",
|
|
64
|
-
"@figma/code-connect": "^1.3.4",
|
|
65
64
|
"@shopify/react-native-skia": "1.12.4",
|
|
66
65
|
"@types/react": "^18.3.12",
|
|
67
66
|
"react-native-gesture-handler": "2.16.2",
|