@coinbase/cds-mcp-server 8.21.7 → 8.22.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 +12 -0
- package/mcp-docs/mobile/components/AreaChart.txt +39 -37
- package/mcp-docs/mobile/components/Avatar.txt +18 -18
- package/mcp-docs/mobile/components/AvatarButton.txt +19 -19
- package/mcp-docs/mobile/components/Banner.txt +63 -24
- package/mcp-docs/mobile/components/BarChart.txt +37 -35
- package/mcp-docs/mobile/components/Box.txt +18 -18
- package/mcp-docs/mobile/components/BrowserBar.txt +18 -18
- package/mcp-docs/mobile/components/Button.txt +19 -19
- package/mcp-docs/mobile/components/Carousel.txt +18 -18
- package/mcp-docs/mobile/components/CartesianChart.txt +75 -44
- package/mcp-docs/mobile/components/CheckboxCell.txt +19 -19
- package/mcp-docs/mobile/components/Chip.txt +20 -20
- package/mcp-docs/mobile/components/Coachmark.txt +18 -18
- package/mcp-docs/mobile/components/ContentCard.txt +18 -18
- package/mcp-docs/mobile/components/ContentCardBody.txt +18 -18
- package/mcp-docs/mobile/components/ContentCardFooter.txt +18 -18
- package/mcp-docs/mobile/components/ContentCardHeader.txt +18 -18
- package/mcp-docs/mobile/components/ContentCell.txt +18 -18
- package/mcp-docs/mobile/components/ControlGroup.txt +18 -18
- package/mcp-docs/mobile/components/DatePicker.txt +1 -1
- package/mcp-docs/mobile/components/Divider.txt +18 -18
- package/mcp-docs/mobile/components/DotCount.txt +1 -1
- package/mcp-docs/mobile/components/DotSymbol.txt +2 -2
- package/mcp-docs/mobile/components/Fallback.txt +18 -18
- package/mcp-docs/mobile/components/HStack.txt +18 -18
- package/mcp-docs/mobile/components/Icon.txt +6 -0
- package/mcp-docs/mobile/components/IconButton.txt +19 -19
- package/mcp-docs/mobile/components/InputChip.txt +20 -20
- package/mcp-docs/mobile/components/Interactable.txt +19 -19
- package/mcp-docs/mobile/components/LineChart.txt +1608 -898
- package/mcp-docs/mobile/components/Link.txt +18 -18
- package/mcp-docs/mobile/components/ListCell.txt +37 -19
- package/mcp-docs/mobile/components/Lottie.txt +18 -18
- package/mcp-docs/mobile/components/MediaChip.txt +20 -20
- package/mcp-docs/mobile/components/MultiContentModule.txt +18 -18
- package/mcp-docs/mobile/components/NavigationTitle.txt +18 -18
- package/mcp-docs/mobile/components/NavigationTitleSelect.txt +18 -18
- package/mcp-docs/mobile/components/Numpad.txt +18 -18
- package/mcp-docs/mobile/components/Overlay.txt +18 -18
- package/mcp-docs/mobile/components/PageFooter.txt +17 -17
- package/mcp-docs/mobile/components/PageHeader.txt +17 -17
- package/mcp-docs/mobile/components/PeriodSelector.txt +26 -26
- package/mcp-docs/mobile/components/Point.txt +203 -98
- package/mcp-docs/mobile/components/Pressable.txt +19 -19
- package/mcp-docs/mobile/components/ProgressBar.txt +1 -1
- package/mcp-docs/mobile/components/ProgressBarWithFixedLabels.txt +1 -1
- package/mcp-docs/mobile/components/ProgressBarWithFloatLabel.txt +1 -1
- package/mcp-docs/mobile/components/ProgressCircle.txt +1 -1
- package/mcp-docs/mobile/components/RadioCell.txt +19 -19
- package/mcp-docs/mobile/components/ReferenceLine.txt +197 -54
- package/mcp-docs/mobile/components/RollingNumber.txt +18 -18
- package/mcp-docs/mobile/components/Scrubber.txt +597 -79
- package/mcp-docs/mobile/components/SegmentedTabs.txt +18 -18
- package/mcp-docs/mobile/components/SelectAlpha.txt +1 -1
- package/mcp-docs/mobile/components/SelectChip.txt +20 -20
- package/mcp-docs/mobile/components/SlideButton.txt +19 -19
- package/mcp-docs/mobile/components/Spacer.txt +6 -6
- package/mcp-docs/mobile/components/SparklineInteractive.txt +3 -3
- package/mcp-docs/mobile/components/Spinner.txt +1 -1
- package/mcp-docs/mobile/components/Stepper.txt +18 -18
- package/mcp-docs/mobile/components/TabLabel.txt +18 -18
- package/mcp-docs/mobile/components/TabNavigation.txt +18 -18
- package/mcp-docs/mobile/components/TabbedChips.txt +18 -18
- package/mcp-docs/mobile/components/TabbedChipsAlpha.txt +1 -1
- package/mcp-docs/mobile/components/Tabs.txt +18 -18
- package/mcp-docs/mobile/components/Tag.txt +18 -18
- package/mcp-docs/mobile/components/Text.txt +18 -18
- package/mcp-docs/mobile/components/Toast.txt +18 -18
- package/mcp-docs/mobile/components/Tooltip.txt +17 -1
- package/mcp-docs/mobile/components/TopNavBar.txt +18 -18
- package/mcp-docs/mobile/components/VStack.txt +18 -18
- package/mcp-docs/mobile/components/XAxis.txt +86 -24
- package/mcp-docs/mobile/components/YAxis.txt +75 -17
- package/mcp-docs/mobile/routes.txt +1 -1
- package/mcp-docs/web/components/AreaChart.txt +523 -301
- package/mcp-docs/web/components/Avatar.txt +27 -27
- package/mcp-docs/web/components/AvatarButton.txt +28 -28
- package/mcp-docs/web/components/Banner.txt +72 -33
- package/mcp-docs/web/components/BarChart.txt +182 -313
- package/mcp-docs/web/components/Box.txt +28 -28
- package/mcp-docs/web/components/Button.txt +28 -28
- package/mcp-docs/web/components/Calendar.txt +27 -27
- package/mcp-docs/web/components/Carousel.txt +27 -27
- package/mcp-docs/web/components/CartesianChart.txt +62 -309
- package/mcp-docs/web/components/CheckboxCell.txt +25 -25
- package/mcp-docs/web/components/Chip.txt +27 -27
- package/mcp-docs/web/components/Coachmark.txt +27 -27
- package/mcp-docs/web/components/ContainedAssetCard.txt +27 -27
- package/mcp-docs/web/components/ContentCard.txt +28 -28
- package/mcp-docs/web/components/ContentCardBody.txt +28 -28
- package/mcp-docs/web/components/ContentCardFooter.txt +28 -28
- package/mcp-docs/web/components/ContentCardHeader.txt +28 -28
- package/mcp-docs/web/components/ContentCell.txt +28 -28
- package/mcp-docs/web/components/ControlGroup.txt +27 -27
- package/mcp-docs/web/components/Divider.txt +27 -27
- package/mcp-docs/web/components/Fallback.txt +28 -28
- package/mcp-docs/web/components/FloatingAssetCard.txt +27 -27
- package/mcp-docs/web/components/Grid.txt +28 -28
- package/mcp-docs/web/components/GridColumn.txt +27 -27
- package/mcp-docs/web/components/HStack.txt +28 -28
- package/mcp-docs/web/components/Icon.txt +27 -27
- package/mcp-docs/web/components/IconButton.txt +28 -28
- package/mcp-docs/web/components/InputChip.txt +27 -27
- package/mcp-docs/web/components/Interactable.txt +28 -28
- package/mcp-docs/web/components/LineChart.txt +1598 -1116
- package/mcp-docs/web/components/Link.txt +28 -28
- package/mcp-docs/web/components/ListCell.txt +48 -30
- package/mcp-docs/web/components/Lottie.txt +27 -27
- package/mcp-docs/web/components/MediaChip.txt +27 -27
- package/mcp-docs/web/components/Modal.txt +27 -27
- package/mcp-docs/web/components/ModalBody.txt +27 -27
- package/mcp-docs/web/components/ModalFooter.txt +27 -27
- package/mcp-docs/web/components/ModalHeader.txt +27 -27
- package/mcp-docs/web/components/MultiContentModule.txt +28 -28
- package/mcp-docs/web/components/NavigationBar.txt +5 -5
- package/mcp-docs/web/components/NudgeCard.txt +27 -27
- package/mcp-docs/web/components/Overlay.txt +27 -27
- package/mcp-docs/web/components/PageFooter.txt +26 -26
- package/mcp-docs/web/components/PageHeader.txt +26 -26
- package/mcp-docs/web/components/Pagination.txt +27 -27
- package/mcp-docs/web/components/PeriodSelector.txt +49 -49
- package/mcp-docs/web/components/Point.txt +228 -79
- package/mcp-docs/web/components/Pressable.txt +28 -28
- package/mcp-docs/web/components/RadioCell.txt +25 -25
- package/mcp-docs/web/components/ReferenceLine.txt +208 -60
- package/mcp-docs/web/components/RemoteImage.txt +26 -26
- package/mcp-docs/web/components/RollingNumber.txt +28 -28
- package/mcp-docs/web/components/Scrubber.txt +463 -68
- package/mcp-docs/web/components/SectionHeader.txt +27 -27
- package/mcp-docs/web/components/SegmentedTabs.txt +27 -27
- package/mcp-docs/web/components/SelectChip.txt +27 -27
- package/mcp-docs/web/components/SelectOption.txt +27 -27
- package/mcp-docs/web/components/Sidebar.txt +27 -27
- package/mcp-docs/web/components/SidebarItem.txt +27 -27
- package/mcp-docs/web/components/Spacer.txt +34 -34
- package/mcp-docs/web/components/SparklineInteractive.txt +1 -1
- package/mcp-docs/web/components/Spinner.txt +27 -27
- package/mcp-docs/web/components/Stepper.txt +27 -27
- package/mcp-docs/web/components/TabLabel.txt +27 -27
- package/mcp-docs/web/components/TabNavigation.txt +26 -26
- package/mcp-docs/web/components/TabbedChips.txt +26 -26
- package/mcp-docs/web/components/TabbedChipsAlpha.txt +1 -1
- package/mcp-docs/web/components/Tabs.txt +27 -27
- package/mcp-docs/web/components/Tag.txt +27 -27
- package/mcp-docs/web/components/Text.txt +28 -28
- package/mcp-docs/web/components/TileButton.txt +28 -28
- package/mcp-docs/web/components/Toast.txt +27 -27
- package/mcp-docs/web/components/Tooltip.txt +17 -1
- package/mcp-docs/web/components/VStack.txt +28 -28
- package/mcp-docs/web/components/XAxis.txt +86 -22
- package/mcp-docs/web/components/YAxis.txt +133 -89
- package/package.json +1 -1
|
@@ -10,9 +10,9 @@ import { Scrubber } from '@coinbase/cds-mobile-visualization'
|
|
|
10
10
|
|
|
11
11
|
## Examples
|
|
12
12
|
|
|
13
|
-
###
|
|
13
|
+
### Basics
|
|
14
14
|
|
|
15
|
-
Scrubber can be used to provide horizontal interaction with a chart. As
|
|
15
|
+
Scrubber can be used to provide horizontal interaction with a chart. As you drag over the chart, you will see a line and scrubber beacon following.
|
|
16
16
|
|
|
17
17
|
```jsx
|
|
18
18
|
<LineChart
|
|
@@ -24,20 +24,17 @@ Scrubber can be used to provide horizontal interaction with a chart. As your mou
|
|
|
24
24
|
data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58],
|
|
25
25
|
},
|
|
26
26
|
]}
|
|
27
|
-
curve="monotone"
|
|
28
27
|
showYAxis
|
|
29
28
|
showArea
|
|
30
29
|
yAxis={{
|
|
31
30
|
showGrid: true,
|
|
32
31
|
}}
|
|
33
32
|
>
|
|
34
|
-
<Scrubber />
|
|
33
|
+
<Scrubber idlePulse />
|
|
35
34
|
</LineChart>
|
|
36
35
|
```
|
|
37
36
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
All series will be scrubbed by default. You can set the `seriesIds` prop to restrict the scrubbing to specific series.
|
|
37
|
+
All series will be scrubbed by default. You can set `seriesIds` to show only specific series.
|
|
41
38
|
|
|
42
39
|
```jsx
|
|
43
40
|
<LineChart
|
|
@@ -48,38 +45,41 @@ All series will be scrubbed by default. You can set the `seriesIds` prop to rest
|
|
|
48
45
|
id: 'top',
|
|
49
46
|
data: [15, 28, 32, 44, 46, 36, 40, 45, 48, 38],
|
|
50
47
|
},
|
|
51
|
-
{
|
|
52
|
-
id: 'upperMiddle',
|
|
53
|
-
data: [12, 23, 21, 29, 34, 28, 31, 38, 42, 35],
|
|
54
|
-
color: '#ef4444',
|
|
55
|
-
type: 'dotted',
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
id: 'lowerMiddle',
|
|
59
|
-
data: [8, 15, 14, 25, 20, 18, 22, 28, 24, 30],
|
|
60
|
-
color: '#f59e0b',
|
|
61
|
-
curve: 'natural',
|
|
62
|
-
LineComponent: (props) => (
|
|
63
|
-
<GradientLine {...props} endColor="#F7931A" startColor="#E3D74D" strokeWidth={4} />
|
|
64
|
-
),
|
|
65
|
-
},
|
|
66
48
|
{
|
|
67
49
|
id: 'bottom',
|
|
68
50
|
data: [4, 8, 11, 15, 16, 14, 16, 10, 12, 14],
|
|
69
|
-
color: '#800080',
|
|
70
|
-
curve: 'step',
|
|
71
|
-
AreaComponent: DottedArea,
|
|
72
|
-
showArea: true,
|
|
73
51
|
},
|
|
74
52
|
]}
|
|
75
53
|
>
|
|
76
|
-
<Scrubber seriesIds={['top'
|
|
54
|
+
<Scrubber seriesIds={['top']} />
|
|
55
|
+
</LineChart>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Labels
|
|
59
|
+
|
|
60
|
+
Setting `label` on a series will display a label to the side of the scrubber beacon, and
|
|
61
|
+
setting `label` on Scrubber displays a label above the scrubber line.
|
|
62
|
+
|
|
63
|
+
```jsx
|
|
64
|
+
<LineChart
|
|
65
|
+
enableScrubbing
|
|
66
|
+
height={150}
|
|
67
|
+
series={[
|
|
68
|
+
{
|
|
69
|
+
id: 'prices',
|
|
70
|
+
data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58],
|
|
71
|
+
label: 'Price',
|
|
72
|
+
},
|
|
73
|
+
]}
|
|
74
|
+
showArea
|
|
75
|
+
>
|
|
76
|
+
<Scrubber label={(dataIndex: number) => `Day ${dataIndex + 1}`} />
|
|
77
77
|
</LineChart>
|
|
78
78
|
```
|
|
79
79
|
|
|
80
80
|
### Pulsing
|
|
81
81
|
|
|
82
|
-
Setting
|
|
82
|
+
Setting `idlePulse` to `true` will cause the scrubber beacons to pulse when the user is not actively scrubbing.
|
|
83
83
|
|
|
84
84
|
```jsx
|
|
85
85
|
<LineChart
|
|
@@ -89,22 +89,24 @@ Setting the `idlePulse` prop will cause the scrubber heads to pulse when the use
|
|
|
89
89
|
{
|
|
90
90
|
id: 'prices',
|
|
91
91
|
data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58],
|
|
92
|
+
color: 'var(--color-fgPositive)',
|
|
92
93
|
},
|
|
93
94
|
]}
|
|
94
|
-
curve="monotone"
|
|
95
95
|
showArea
|
|
96
96
|
>
|
|
97
|
+
<ReferenceLine
|
|
98
|
+
LineComponent={(props) => <DottedLine {...props} dashIntervals={[0, 16]} strokeWidth={3} />}
|
|
99
|
+
dataY={10}
|
|
100
|
+
stroke="var(--color-fg)"
|
|
101
|
+
/>
|
|
97
102
|
<Scrubber idlePulse />
|
|
98
103
|
</LineChart>
|
|
99
104
|
```
|
|
100
105
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
You can also use the imperative handle to pulse the scrubber heads programmatically.
|
|
106
|
+
You can also use the imperative handle to pulse the scrubber beacons programmatically.
|
|
104
107
|
|
|
105
108
|
```jsx
|
|
106
109
|
function ImperativeHandle() {
|
|
107
|
-
const theme = useTheme();
|
|
108
110
|
const scrubberRef = useRef(null);
|
|
109
111
|
return (
|
|
110
112
|
<VStack gap={2}>
|
|
@@ -113,70 +115,579 @@ function ImperativeHandle() {
|
|
|
113
115
|
height={150}
|
|
114
116
|
series={[
|
|
115
117
|
{
|
|
116
|
-
id: '
|
|
117
|
-
data: [
|
|
118
|
-
color: theme.color.accentBoldBlue,
|
|
119
|
-
curve: 'natural',
|
|
120
|
-
},
|
|
121
|
-
{
|
|
122
|
-
id: 'priceB',
|
|
123
|
-
data: [2000, 2491, 4501, 6049, 5019, 4930, 5910],
|
|
124
|
-
color: theme.color.accentBoldGreen,
|
|
125
|
-
curve: 'natural',
|
|
126
|
-
},
|
|
127
|
-
{
|
|
128
|
-
id: 'priceC',
|
|
129
|
-
data: [1000, 4910, 2300, 5910, 3940, 2940, 1940],
|
|
130
|
-
color: theme.color.accentBoldPurple,
|
|
131
|
-
curve: 'natural',
|
|
132
|
-
},
|
|
133
|
-
{
|
|
134
|
-
id: 'priceD',
|
|
135
|
-
data: [4810, 2030, 5810, 3940, 2940, 1940, 940],
|
|
136
|
-
color: theme.color.accentBoldYellow,
|
|
137
|
-
curve: 'natural',
|
|
118
|
+
id: 'prices',
|
|
119
|
+
data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58],
|
|
138
120
|
},
|
|
139
121
|
]}
|
|
122
|
+
showYAxis
|
|
123
|
+
showArea
|
|
140
124
|
xAxis={{
|
|
141
|
-
|
|
125
|
+
/* Give space between the scrubber and the axis */
|
|
126
|
+
range: ({ min, max }) => ({ min, max: max - 8 }),
|
|
142
127
|
}}
|
|
143
|
-
showYAxis
|
|
144
128
|
yAxis={{
|
|
145
|
-
domain: {
|
|
146
|
-
min: 0,
|
|
147
|
-
},
|
|
148
129
|
showGrid: true,
|
|
149
|
-
tickLabelFormatter: (value) => value.toLocaleString(),
|
|
150
130
|
}}
|
|
151
131
|
>
|
|
152
132
|
<Scrubber ref={scrubberRef} />
|
|
153
133
|
</LineChart>
|
|
154
|
-
<Button
|
|
134
|
+
<Button onPress={() => scrubberRef.current?.pulse()}>Pulse</Button>
|
|
155
135
|
</VStack>
|
|
156
136
|
);
|
|
157
137
|
}
|
|
158
138
|
```
|
|
159
139
|
|
|
160
|
-
###
|
|
140
|
+
### Styling
|
|
141
|
+
|
|
142
|
+
#### Beacons
|
|
143
|
+
|
|
144
|
+
You can use `BeaconComponent` to customize the visual appearance of scrubber beacons.
|
|
145
|
+
|
|
146
|
+
```jsx
|
|
147
|
+
function OutlineBeacon() {
|
|
148
|
+
// Simple outline beacon with no pulse animation
|
|
149
|
+
const OutlineBeaconComponent = memo(({ dataX, dataY, seriesId, isIdle, animate = true }: ScrubberBeaconProps) => {
|
|
150
|
+
const theme = useTheme();
|
|
151
|
+
const { getSeries, getXSerializableScale, getYSerializableScale } = useCartesianChartContext();
|
|
152
|
+
|
|
153
|
+
const targetSeries = useMemo(() => getSeries(seriesId), [getSeries, seriesId]);
|
|
154
|
+
const xScale = useMemo(() => getXSerializableScale(), [getXSerializableScale]);
|
|
155
|
+
const yScale = useMemo(
|
|
156
|
+
() => getYSerializableScale(targetSeries?.yAxisId),
|
|
157
|
+
[getYSerializableScale, targetSeries?.yAxisId],
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
const color = useMemo(
|
|
161
|
+
() => targetSeries?.color ?? theme.color.fgPrimary,
|
|
162
|
+
[targetSeries?.color, theme.color.fgPrimary],
|
|
163
|
+
);
|
|
164
|
+
|
|
165
|
+
const animatedX = useSharedValue(0);
|
|
166
|
+
const animatedY = useSharedValue(0);
|
|
167
|
+
|
|
168
|
+
// Calculate the target point position - project data to pixels
|
|
169
|
+
const targetPoint = useDerivedValue(() => {
|
|
170
|
+
if (!xScale || !yScale) return { x: 0, y: 0 };
|
|
171
|
+
return projectPointWithSerializableScale({
|
|
172
|
+
x: unwrapAnimatedValue(dataX),
|
|
173
|
+
y: unwrapAnimatedValue(dataY),
|
|
174
|
+
xScale,
|
|
175
|
+
yScale,
|
|
176
|
+
});
|
|
177
|
+
}, [dataX, dataY, xScale, yScale]);
|
|
178
|
+
|
|
179
|
+
useAnimatedReaction(
|
|
180
|
+
() => {
|
|
181
|
+
return { point: targetPoint.value, isIdle: unwrapAnimatedValue(isIdle) };
|
|
182
|
+
},
|
|
183
|
+
(current, previous) => {
|
|
184
|
+
// When animation is disabled, on initial render, or when we are starting,
|
|
185
|
+
// continuing, or finishing scrubbing we should immediately transition
|
|
186
|
+
if (!animate || previous === null || !previous.isIdle || !current.isIdle) {
|
|
187
|
+
animatedX.value = current.point.x;
|
|
188
|
+
animatedY.value = current.point.y;
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
animatedX.value = buildTransition(current.point.x, defaultTransition);
|
|
193
|
+
animatedY.value = buildTransition(current.point.y, defaultTransition);
|
|
194
|
+
},
|
|
195
|
+
[animate],
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
// Create animated point using the animated values
|
|
199
|
+
const animatedPoint = useDerivedValue(() => {
|
|
200
|
+
return { x: animatedX.value, y: animatedY.value };
|
|
201
|
+
}, [animatedX, animatedY]);
|
|
202
|
+
|
|
203
|
+
return (
|
|
204
|
+
<>
|
|
205
|
+
<Circle c={animatedPoint} color={color} r={6} />
|
|
206
|
+
<Circle c={animatedPoint} color={theme.color.bg} r={3} />
|
|
207
|
+
</>
|
|
208
|
+
);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
const dataCount = 14;
|
|
212
|
+
const minDataValue = 0;
|
|
213
|
+
const maxDataValue = 100;
|
|
214
|
+
const minStepOffset = 5;
|
|
215
|
+
const maxStepOffset = 20;
|
|
216
|
+
const updateInterval = 2000;
|
|
217
|
+
|
|
218
|
+
function generateNextValue(previousValue: number) {
|
|
219
|
+
const range = maxStepOffset - minStepOffset;
|
|
220
|
+
const offset = Math.random() * range + minStepOffset;
|
|
221
|
+
|
|
222
|
+
let direction;
|
|
223
|
+
if (previousValue >= maxDataValue) {
|
|
224
|
+
direction = -1;
|
|
225
|
+
} else if (previousValue <= minDataValue) {
|
|
226
|
+
direction = 1;
|
|
227
|
+
} else {
|
|
228
|
+
direction = Math.random() < 0.5 ? -1 : 1;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const newValue = previousValue + offset * direction;
|
|
232
|
+
return Math.max(minDataValue, Math.min(maxDataValue, newValue));
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function generateInitialData() {
|
|
236
|
+
const data = [];
|
|
237
|
+
let previousValue = Math.random() * (maxDataValue - minDataValue) + minDataValue;
|
|
238
|
+
data.push(previousValue);
|
|
239
|
+
|
|
240
|
+
for (let i = 1; i < dataCount; i++) {
|
|
241
|
+
const newValue = generateNextValue(previousValue);
|
|
242
|
+
data.push(newValue);
|
|
243
|
+
previousValue = newValue;
|
|
244
|
+
}
|
|
245
|
+
return data;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
const OutlineBeaconChart = memo(() => {
|
|
250
|
+
const [data, setData] = useState(generateInitialData);
|
|
251
|
+
|
|
252
|
+
useEffect(() => {
|
|
253
|
+
const intervalId = setInterval(() => {
|
|
254
|
+
setData((currentData) => {
|
|
255
|
+
const lastValue = currentData[currentData.length - 1] ?? 50;
|
|
256
|
+
const newValue = generateNextValue(lastValue);
|
|
257
|
+
return [...currentData.slice(1), newValue];
|
|
258
|
+
});
|
|
259
|
+
}, updateInterval);
|
|
260
|
+
|
|
261
|
+
return () => clearInterval(intervalId);
|
|
262
|
+
}, []);
|
|
263
|
+
|
|
264
|
+
return (
|
|
265
|
+
<LineChart
|
|
266
|
+
enableScrubbing
|
|
267
|
+
showArea
|
|
268
|
+
showYAxis
|
|
269
|
+
height={150}
|
|
270
|
+
series={[
|
|
271
|
+
{
|
|
272
|
+
id: 'prices',
|
|
273
|
+
data,
|
|
274
|
+
color: 'var(--color-fg)',
|
|
275
|
+
},
|
|
276
|
+
]}
|
|
277
|
+
xAxis={{
|
|
278
|
+
range: ({ min, max }) => ({ min, max: max - 16 }),
|
|
279
|
+
}}
|
|
280
|
+
yAxis={{
|
|
281
|
+
showGrid: true,
|
|
282
|
+
domain: { min: 0, max: 100 }
|
|
283
|
+
}}
|
|
284
|
+
>
|
|
285
|
+
<Scrubber BeaconComponent={OutlineBeaconComponent} />
|
|
286
|
+
</LineChart>
|
|
287
|
+
);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
return <OutlineBeaconChart />;
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
#### Labels
|
|
161
295
|
|
|
162
|
-
|
|
296
|
+
You can use `BeaconLabelComponent` to customize the labels for each scrubber beacon.
|
|
163
297
|
|
|
164
298
|
```jsx
|
|
299
|
+
function CustomBeaconLabel() {
|
|
300
|
+
const theme = useTheme();
|
|
301
|
+
// This custom component label shows the percentage value of the data at the scrubber position.
|
|
302
|
+
const MyScrubberBeaconLabel = memo(
|
|
303
|
+
({ seriesId, color, label, ...props }: ScrubberBeaconLabelProps) => {
|
|
304
|
+
const { getSeriesData, dataLength } = useCartesianChartContext();
|
|
305
|
+
const { scrubberPosition } = useScrubberContext();
|
|
306
|
+
|
|
307
|
+
const seriesData = useMemo(
|
|
308
|
+
() => getLineData(getSeriesData(seriesId)),
|
|
309
|
+
[getSeriesData, seriesId],
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
const dataIndex = useDerivedValue(() => {
|
|
313
|
+
return scrubberPosition.value ?? Math.max(0, dataLength - 1);
|
|
314
|
+
}, [scrubberPosition, dataLength]);
|
|
315
|
+
|
|
316
|
+
const percentageLabel = useDerivedValue(() => {
|
|
317
|
+
if (seriesData !== undefined) {
|
|
318
|
+
const dataAtPosition = seriesData[dataIndex.value];
|
|
319
|
+
return `${unwrapAnimatedValue(label)} · ${dataAtPosition}%`;
|
|
320
|
+
}
|
|
321
|
+
return unwrapAnimatedValue(label);
|
|
322
|
+
}, [label, seriesData, dataIndex]);
|
|
323
|
+
|
|
324
|
+
return (
|
|
325
|
+
<DefaultScrubberBeaconLabel
|
|
326
|
+
{...props}
|
|
327
|
+
background={color}
|
|
328
|
+
color={theme.color.bg}
|
|
329
|
+
label={percentageLabel}
|
|
330
|
+
seriesId={seriesId}
|
|
331
|
+
/>
|
|
332
|
+
);
|
|
333
|
+
},
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
return (
|
|
337
|
+
<LineChart
|
|
338
|
+
enableScrubbing
|
|
339
|
+
showArea
|
|
340
|
+
showYAxis
|
|
341
|
+
areaType="dotted"
|
|
342
|
+
height={150}
|
|
343
|
+
series={[
|
|
344
|
+
{
|
|
345
|
+
id: 'Boston',
|
|
346
|
+
data: [25, 30, 35, 45, 60, 100],
|
|
347
|
+
color: `rgb(${theme.spectrum.green40})`,
|
|
348
|
+
label: 'Boston',
|
|
349
|
+
},
|
|
350
|
+
{
|
|
351
|
+
id: 'Miami',
|
|
352
|
+
data: [20, 25, 30, 35, 20, 0],
|
|
353
|
+
color: `rgb(${theme.spectrum.blue40})`,
|
|
354
|
+
label: 'Miami',
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
id: 'Denver',
|
|
358
|
+
data: [10, 15, 20, 25, 40, 0],
|
|
359
|
+
color: `rgb(${theme.spectrum.orange40})`,
|
|
360
|
+
label: 'Denver',
|
|
361
|
+
},
|
|
362
|
+
{
|
|
363
|
+
id: 'Phoenix',
|
|
364
|
+
data: [15, 10, 5, 0, 0, 0],
|
|
365
|
+
color: `rgb(${theme.spectrum.red40})`,
|
|
366
|
+
label: 'Phoenix',
|
|
367
|
+
},
|
|
368
|
+
]}
|
|
369
|
+
yAxis={{
|
|
370
|
+
showGrid: true,
|
|
371
|
+
}}
|
|
372
|
+
>
|
|
373
|
+
<Scrubber BeaconLabelComponent={MyScrubberBeaconLabel} />
|
|
374
|
+
</LineChart>
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
Using `labelElevated` will elevate the Scrubber's reference line label with a shadow.
|
|
380
|
+
|
|
381
|
+
```jsx live
|
|
165
382
|
<LineChart
|
|
166
383
|
enableScrubbing
|
|
167
|
-
height={
|
|
384
|
+
height={200}
|
|
168
385
|
series={[
|
|
169
386
|
{
|
|
170
387
|
id: 'prices',
|
|
171
388
|
data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58],
|
|
172
389
|
},
|
|
173
390
|
]}
|
|
174
|
-
curve="monotone"
|
|
175
|
-
showYAxis
|
|
176
391
|
showArea
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
}}
|
|
392
|
+
inset={{ top: 60 }}
|
|
393
|
+
>
|
|
394
|
+
<Scrubber label={(dataIndex: number) => `Day ${dataIndex + 1}`} labelElevated />
|
|
395
|
+
</LineChart>
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
You can use `LabelComponent` to customize this label even further.
|
|
399
|
+
|
|
400
|
+
```jsx
|
|
401
|
+
function CustomLabelComponent() {
|
|
402
|
+
const CustomLabelComponent = memo((props: ScrubberLabelProps) => {
|
|
403
|
+
const theme = useTheme();
|
|
404
|
+
const { drawingArea } = useCartesianChartContext();
|
|
405
|
+
|
|
406
|
+
if (!drawingArea) return;
|
|
407
|
+
|
|
408
|
+
return (
|
|
409
|
+
<DefaultScrubberLabel
|
|
410
|
+
{...props}
|
|
411
|
+
background={theme.color.bgPrimary}
|
|
412
|
+
color={theme.color.bgPrimaryWash}
|
|
413
|
+
dy={32}
|
|
414
|
+
elevated
|
|
415
|
+
fontWeight={FontWeight.Bold}
|
|
416
|
+
y={drawingArea.y + drawingArea.height}
|
|
417
|
+
/>
|
|
418
|
+
);
|
|
419
|
+
});
|
|
420
|
+
return (
|
|
421
|
+
<LineChart
|
|
422
|
+
enableScrubbing
|
|
423
|
+
showArea
|
|
424
|
+
height={200}
|
|
425
|
+
inset={{ top: 16, bottom: 64 }}
|
|
426
|
+
series={[
|
|
427
|
+
{
|
|
428
|
+
id: 'prices',
|
|
429
|
+
data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58],
|
|
430
|
+
},
|
|
431
|
+
]}
|
|
432
|
+
>
|
|
433
|
+
<Scrubber
|
|
434
|
+
LabelComponent={CustomLabelComponent}
|
|
435
|
+
label={(dataIndex: number) => `Day ${dataIndex + 1}`}
|
|
436
|
+
/>
|
|
437
|
+
</LineChart>
|
|
438
|
+
);
|
|
439
|
+
}
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
##### Multi-line Centered Text
|
|
443
|
+
|
|
444
|
+
You can create custom multi-line centered labels using Skia's `ParagraphBuilder` with `TextAlign.Center`. Set `paragraphAlignment={TextAlign.Center}` on your custom label component to ensure proper positioning.
|
|
445
|
+
|
|
446
|
+
```jsx
|
|
447
|
+
function TwoLineCenteredLabel() {
|
|
448
|
+
const theme = useTheme();
|
|
449
|
+
const data = useMemo(() => [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58], []);
|
|
450
|
+
|
|
451
|
+
const fontMgr = useMemo(() => Skia.TypefaceFontProvider.Make(), []);
|
|
452
|
+
|
|
453
|
+
const formatPrice = useCallback((price: number) => {
|
|
454
|
+
return new Intl.NumberFormat('en-US', {
|
|
455
|
+
style: 'currency',
|
|
456
|
+
currency: 'USD',
|
|
457
|
+
minimumFractionDigits: 2,
|
|
458
|
+
maximumFractionDigits: 2,
|
|
459
|
+
}).format(price);
|
|
460
|
+
}, []);
|
|
461
|
+
|
|
462
|
+
const scrubberLabel = useCallback(
|
|
463
|
+
(index: number) => {
|
|
464
|
+
const price = formatPrice(data[index]);
|
|
465
|
+
const day = `Day ${index + 1}`;
|
|
466
|
+
|
|
467
|
+
const priceStyle: SkTextStyle = {
|
|
468
|
+
fontFamilies: ['Inter'],
|
|
469
|
+
fontSize: 16,
|
|
470
|
+
fontStyle: { weight: FontWeight.Bold },
|
|
471
|
+
color: Skia.Color(theme.color.fg),
|
|
472
|
+
};
|
|
473
|
+
|
|
474
|
+
const dayStyle: SkTextStyle = {
|
|
475
|
+
fontFamilies: ['Inter'],
|
|
476
|
+
fontSize: 14,
|
|
477
|
+
fontStyle: { weight: FontWeight.Normal },
|
|
478
|
+
color: Skia.Color(theme.color.fgMuted),
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
const builder = Skia.ParagraphBuilder.Make({ textAlign: TextAlign.Center }, fontMgr);
|
|
482
|
+
|
|
483
|
+
builder.pushStyle(priceStyle);
|
|
484
|
+
builder.addText(price);
|
|
485
|
+
builder.addText('\n');
|
|
486
|
+
|
|
487
|
+
builder.pushStyle(dayStyle);
|
|
488
|
+
builder.addText(day);
|
|
489
|
+
|
|
490
|
+
const para = builder.build();
|
|
491
|
+
para.layout(384);
|
|
492
|
+
return para;
|
|
493
|
+
},
|
|
494
|
+
[data, formatPrice, theme.color.fg, theme.color.fgMuted, fontMgr],
|
|
495
|
+
);
|
|
496
|
+
|
|
497
|
+
// Custom label component that sets paragraphAlignment to center
|
|
498
|
+
const CenteredScrubberLabel = memo((props: ScrubberLabelProps) => (
|
|
499
|
+
<DefaultScrubberLabel {...props} paragraphAlignment={TextAlign.Center} />
|
|
500
|
+
));
|
|
501
|
+
|
|
502
|
+
return (
|
|
503
|
+
<LineChart
|
|
504
|
+
enableScrubbing
|
|
505
|
+
showArea
|
|
506
|
+
height={200}
|
|
507
|
+
inset={{ top: 64 }}
|
|
508
|
+
series={[
|
|
509
|
+
{
|
|
510
|
+
id: 'prices',
|
|
511
|
+
data: data,
|
|
512
|
+
color: theme.color.accentBoldBlue,
|
|
513
|
+
},
|
|
514
|
+
]}
|
|
515
|
+
>
|
|
516
|
+
<Scrubber
|
|
517
|
+
idlePulse
|
|
518
|
+
labelElevated
|
|
519
|
+
LabelComponent={CenteredScrubberLabel}
|
|
520
|
+
label={scrubberLabel}
|
|
521
|
+
/>
|
|
522
|
+
</LineChart>
|
|
523
|
+
);
|
|
524
|
+
}
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
##### Fonts
|
|
528
|
+
|
|
529
|
+
You can use `labelFont` to customize the font of the scrubber line label and `beaconLabelFont` to customize the font of the beacon labels.
|
|
530
|
+
|
|
531
|
+
```jsx
|
|
532
|
+
function CustomLabelFonts() {
|
|
533
|
+
const theme = useTheme();
|
|
534
|
+
|
|
535
|
+
return (
|
|
536
|
+
<LineChart
|
|
537
|
+
enableScrubbing
|
|
538
|
+
showArea
|
|
539
|
+
showYAxis
|
|
540
|
+
height={200}
|
|
541
|
+
series={[
|
|
542
|
+
{
|
|
543
|
+
id: 'btc',
|
|
544
|
+
data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58],
|
|
545
|
+
label: 'BTC',
|
|
546
|
+
color: assets.btc.color,
|
|
547
|
+
},
|
|
548
|
+
{
|
|
549
|
+
id: 'eth',
|
|
550
|
+
data: [5, 15, 18, 30, 65, 30, 15, 35, 15, 2, 45, 12, 15, 40],
|
|
551
|
+
label: 'ETH',
|
|
552
|
+
color: assets.eth.color,
|
|
553
|
+
},
|
|
554
|
+
]}
|
|
555
|
+
yAxis={{
|
|
556
|
+
showGrid: true,
|
|
557
|
+
}}
|
|
558
|
+
>
|
|
559
|
+
<Scrubber
|
|
560
|
+
label={(dataIndex: number) => `Day ${dataIndex + 1}`}
|
|
561
|
+
labelFont="legal"
|
|
562
|
+
beaconLabelFont="legal"
|
|
563
|
+
/>
|
|
564
|
+
</LineChart>
|
|
565
|
+
);
|
|
566
|
+
}
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
##### Bounds
|
|
570
|
+
|
|
571
|
+
Use `labelBoundsInset` to prevent the scrubber line label from getting too close to chart edges.
|
|
572
|
+
|
|
573
|
+
```jsx
|
|
574
|
+
function WithoutBoundsExample() {
|
|
575
|
+
return (
|
|
576
|
+
<LineChart
|
|
577
|
+
enableScrubbing
|
|
578
|
+
showArea
|
|
579
|
+
height={150}
|
|
580
|
+
inset={{ left: 0, right: 0 }}
|
|
581
|
+
series={[
|
|
582
|
+
{
|
|
583
|
+
id: 'prices',
|
|
584
|
+
data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58],
|
|
585
|
+
},
|
|
586
|
+
]}
|
|
587
|
+
>
|
|
588
|
+
<Scrubber label="Without bounds - text touches edge" labelBoundsInset={0} />
|
|
589
|
+
</LineChart>
|
|
590
|
+
);
|
|
591
|
+
}
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
```jsx
|
|
595
|
+
function WithBoundsExample() {
|
|
596
|
+
return (
|
|
597
|
+
<LineChart
|
|
598
|
+
enableScrubbing
|
|
599
|
+
showArea
|
|
600
|
+
height={150}
|
|
601
|
+
inset={{ left: 0, right: 0 }}
|
|
602
|
+
series={[
|
|
603
|
+
{
|
|
604
|
+
id: 'prices',
|
|
605
|
+
data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58],
|
|
606
|
+
},
|
|
607
|
+
]}
|
|
608
|
+
>
|
|
609
|
+
<Scrubber
|
|
610
|
+
label="With bounds inset - text has space"
|
|
611
|
+
labelBoundsInset={{ left: 12, right: 12 }}
|
|
612
|
+
/>
|
|
613
|
+
</LineChart>
|
|
614
|
+
);
|
|
615
|
+
}
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
#### Line
|
|
619
|
+
|
|
620
|
+
You can use `LineComponent` to customize Scrubber's line. In this case, as a user scrubs, they will see a solid line instead of dotted.
|
|
621
|
+
|
|
622
|
+
```jsx
|
|
623
|
+
<LineChart
|
|
624
|
+
enableScrubbing
|
|
625
|
+
height={150}
|
|
626
|
+
series={[
|
|
627
|
+
{
|
|
628
|
+
id: 'prices',
|
|
629
|
+
data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58],
|
|
630
|
+
},
|
|
631
|
+
]}
|
|
632
|
+
showArea
|
|
633
|
+
>
|
|
634
|
+
<Scrubber LineComponent={SolidLine} />
|
|
635
|
+
</LineChart>
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
#### Opacity
|
|
639
|
+
|
|
640
|
+
You can use `BeaconComponent` and `BeaconLabelComponent` with the `opacity` prop to hide scrubber beacons and labels when idle.
|
|
641
|
+
|
|
642
|
+
```jsx
|
|
643
|
+
function HiddenScrubberWhenIdle() {
|
|
644
|
+
const MyScrubberBeacon = memo((props: ScrubberBeaconProps) => {
|
|
645
|
+
const { scrubberPosition } = useScrubberContext();
|
|
646
|
+
const beaconOpacity = useDerivedValue(
|
|
647
|
+
() => (scrubberPosition.value !== undefined ? 1 : 0),
|
|
648
|
+
[scrubberPosition],
|
|
649
|
+
);
|
|
650
|
+
|
|
651
|
+
return <DefaultScrubberBeacon {...props} opacity={beaconOpacity} />;
|
|
652
|
+
});
|
|
653
|
+
|
|
654
|
+
const MyScrubberBeaconLabel = memo((props: ScrubberBeaconLabelProps) => {
|
|
655
|
+
const { scrubberPosition } = useScrubberContext();
|
|
656
|
+
const labelOpacity = useDerivedValue(
|
|
657
|
+
() => (scrubberPosition.value !== undefined ? 1 : 0),
|
|
658
|
+
[scrubberPosition],
|
|
659
|
+
);
|
|
660
|
+
|
|
661
|
+
return <DefaultScrubberBeaconLabel {...props} opacity={labelOpacity} />;
|
|
662
|
+
});
|
|
663
|
+
|
|
664
|
+
return (
|
|
665
|
+
<LineChart
|
|
666
|
+
enableScrubbing
|
|
667
|
+
showArea
|
|
668
|
+
height={150}
|
|
669
|
+
series={[
|
|
670
|
+
{
|
|
671
|
+
id: 'prices',
|
|
672
|
+
data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58],
|
|
673
|
+
label: 'Price',
|
|
674
|
+
},
|
|
675
|
+
]}
|
|
676
|
+
>
|
|
677
|
+
<Scrubber BeaconComponent={MyScrubberBeacon} BeaconLabelComponent={MyScrubberBeaconLabel} />
|
|
678
|
+
</LineChart>
|
|
679
|
+
);
|
|
680
|
+
}
|
|
681
|
+
```
|
|
682
|
+
|
|
683
|
+
#### Overlay
|
|
684
|
+
|
|
685
|
+
By default, Scrubber will show an overlay to de-emphasize future data. You can hide this by setting `hideOverlay` to `true`.
|
|
686
|
+
|
|
687
|
+
```jsx
|
|
688
|
+
<LineChart
|
|
689
|
+
enableScrubbing
|
|
690
|
+
...
|
|
180
691
|
>
|
|
181
692
|
<Scrubber hideOverlay />
|
|
182
693
|
</LineChart>
|
|
@@ -186,18 +697,25 @@ By default, the scrubber will show an overlay to de-emphasize future data. You c
|
|
|
186
697
|
|
|
187
698
|
| Prop | Type | Required | Default | Description |
|
|
188
699
|
| --- | --- | --- | --- | --- |
|
|
189
|
-
| `BeaconComponent` | `
|
|
190
|
-
| `
|
|
700
|
+
| `BeaconComponent` | `ScrubberBeaconComponent` | No | `DefaultScrubberBeacon` | Custom component for the scrubber beacon. |
|
|
701
|
+
| `BeaconLabelComponent` | `ScrubberBeaconLabelComponent` | No | `DefaultScrubberBeaconLabel` | Custom component to render as a scrubber beacon label. |
|
|
702
|
+
| `LabelComponent` | `ReferenceLineLabelComponent` | No | `DefaultReferenceLineLabel` | Component to render the label. |
|
|
703
|
+
| `LineComponent` | `LineComponent` | No | `DottedLine` | Component to render the line. |
|
|
704
|
+
| `beaconLabelFont` | `display1 \| display2 \| display3 \| title1 \| title2 \| title3 \| title4 \| headline \| body \| label1 \| label2 \| caption \| legal` | No | `-` | Font style for the beacon labels. |
|
|
705
|
+
| `beaconLabelHorizontalOffset` | `number` | No | `-` | Horizontal offset for beacon labels from their beacon position. Measured in pixels. |
|
|
706
|
+
| `beaconLabelMinGap` | `number` | No | `-` | Minimum gap between beacon labels to prevent overlap. Measured in pixels. |
|
|
707
|
+
| `beaconTransitions` | `{ update?: Transition; pulse?: Transition \| undefined; pulseRepeatDelay?: number \| undefined; } \| undefined` | No | `-` | Transition configuration for the scrubber beacon. |
|
|
191
708
|
| `hideLine` | `boolean` | No | `-` | Hides the scrubber line |
|
|
192
|
-
| `hideOverlay` | `boolean` | No | `-` |
|
|
193
|
-
| `idlePulse` | `boolean` | No | `-` | Pulse the
|
|
709
|
+
| `hideOverlay` | `boolean` | No | `-` | Hides the overlay rect which obscures data beyond the scrubber position. |
|
|
710
|
+
| `idlePulse` | `boolean` | No | `-` | Pulse the beacons while at rest. |
|
|
194
711
|
| `key` | `Key \| null` | No | `-` | - |
|
|
195
|
-
| `label` | `
|
|
196
|
-
| `
|
|
712
|
+
| `label` | `string \| SkParagraph \| ((dataIndex: number) => string \| SkParagraph)` | No | `-` | Label text displayed above the scrubber line. Can be a static string or a function that receives the current dataIndex. |
|
|
713
|
+
| `labelBoundsInset` | `number \| ChartInset` | No | `{ top: 4, bottom: 20, left: 12, right: 12 } when labelElevated is true, otherwise none` | Bounds inset for the scrubber line label to prevent cutoff at chart edges. |
|
|
714
|
+
| `labelElevated` | `boolean` | No | `-` | Whether to elevate the label with a shadow. When true, applies elevation and automatically adds bounds to keep label within chart area. |
|
|
715
|
+
| `labelFont` | `display1 \| display2 \| display3 \| title1 \| title2 \| title3 \| title4 \| headline \| body \| label1 \| label2 \| caption \| legal` | No | `-` | Font style for the scrubber line label. |
|
|
197
716
|
| `lineStroke` | `string` | No | `-` | Stroke color for the scrubber line. |
|
|
198
717
|
| `overlayOffset` | `number` | No | `2` | Offset of the overlay rect relative to the drawing area. Useful for when scrubbing over lines, where the stroke width would cause part of the line to be visible. |
|
|
199
|
-
| `ref` | `((instance:
|
|
200
|
-
| `seriesIds` | `string[]` | No | `-` |
|
|
201
|
-
| `testID` | `string` | No | `-` | Used to locate this element in unit and end-to-end tests. Under the hood, testID translates to data-testid on Web. On Mobile, testID stays the same - testID |
|
|
718
|
+
| `ref` | `((instance: ScrubberBeaconGroupRef \| null) => void) \| RefObject<ScrubberBeaconGroupRef> \| null` | No | `-` | - |
|
|
719
|
+
| `seriesIds` | `string[]` | No | `-` | Array of series IDs to highlight when scrubbing with scrubber beacons. By default, all series will be highlighted. |
|
|
202
720
|
|
|
203
721
|
|