@coinbase/cds-mobile-visualization 3.4.0-beta.5 → 3.4.0-beta.6
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 +9 -0
- package/dts/chart/CartesianChart.d.ts +57 -33
- package/dts/chart/CartesianChart.d.ts.map +1 -1
- package/dts/chart/ChartContextBridge.d.ts +28 -0
- package/dts/chart/ChartContextBridge.d.ts.map +1 -0
- package/dts/chart/Path.d.ts +77 -34
- package/dts/chart/Path.d.ts.map +1 -1
- package/dts/chart/PeriodSelector.d.ts +1 -1
- package/dts/chart/PeriodSelector.d.ts.map +1 -1
- package/dts/chart/area/Area.d.ts +42 -27
- package/dts/chart/area/Area.d.ts.map +1 -1
- package/dts/chart/area/AreaChart.d.ts +51 -10
- package/dts/chart/area/AreaChart.d.ts.map +1 -1
- package/dts/chart/area/DottedArea.d.ts +21 -2
- package/dts/chart/area/DottedArea.d.ts.map +1 -1
- package/dts/chart/area/GradientArea.d.ts +19 -13
- package/dts/chart/area/GradientArea.d.ts.map +1 -1
- package/dts/chart/area/SolidArea.d.ts +17 -2
- package/dts/chart/area/SolidArea.d.ts.map +1 -1
- package/dts/chart/axis/Axis.d.ts +68 -78
- package/dts/chart/axis/Axis.d.ts.map +1 -1
- package/dts/chart/axis/DefaultAxisTickLabel.d.ts +8 -0
- package/dts/chart/axis/DefaultAxisTickLabel.d.ts.map +1 -0
- package/dts/chart/axis/XAxis.d.ts +1 -1
- package/dts/chart/axis/XAxis.d.ts.map +1 -1
- package/dts/chart/axis/YAxis.d.ts +2 -2
- package/dts/chart/axis/YAxis.d.ts.map +1 -1
- package/dts/chart/axis/index.d.ts +1 -0
- package/dts/chart/axis/index.d.ts.map +1 -1
- package/dts/chart/bar/Bar.d.ts +16 -13
- package/dts/chart/bar/Bar.d.ts.map +1 -1
- package/dts/chart/bar/BarChart.d.ts +36 -20
- package/dts/chart/bar/BarChart.d.ts.map +1 -1
- package/dts/chart/bar/BarPlot.d.ts +2 -1
- package/dts/chart/bar/BarPlot.d.ts.map +1 -1
- package/dts/chart/bar/BarStack.d.ts +39 -48
- package/dts/chart/bar/BarStack.d.ts.map +1 -1
- package/dts/chart/bar/BarStackGroup.d.ts +1 -0
- package/dts/chart/bar/BarStackGroup.d.ts.map +1 -1
- package/dts/chart/bar/DefaultBar.d.ts +1 -1
- package/dts/chart/bar/DefaultBar.d.ts.map +1 -1
- package/dts/chart/bar/DefaultBarStack.d.ts.map +1 -1
- package/dts/chart/gradient/Gradient.d.ts +25 -0
- package/dts/chart/gradient/Gradient.d.ts.map +1 -0
- package/dts/chart/gradient/index.d.ts +2 -0
- package/dts/chart/gradient/index.d.ts.map +1 -0
- package/dts/chart/index.d.ts +3 -1
- package/dts/chart/index.d.ts.map +1 -1
- package/dts/chart/line/DefaultReferenceLineLabel.d.ts +9 -0
- package/dts/chart/line/DefaultReferenceLineLabel.d.ts.map +1 -0
- package/dts/chart/line/DottedLine.d.ts +13 -5
- package/dts/chart/line/DottedLine.d.ts.map +1 -1
- package/dts/chart/line/Line.d.ts +62 -25
- package/dts/chart/line/Line.d.ts.map +1 -1
- package/dts/chart/line/LineChart.d.ts +43 -9
- package/dts/chart/line/LineChart.d.ts.map +1 -1
- package/dts/chart/line/ReferenceLine.d.ts +65 -22
- package/dts/chart/line/ReferenceLine.d.ts.map +1 -1
- package/dts/chart/line/SolidLine.d.ts +8 -5
- package/dts/chart/line/SolidLine.d.ts.map +1 -1
- package/dts/chart/line/index.d.ts +1 -1
- package/dts/chart/line/index.d.ts.map +1 -1
- package/dts/chart/point/DefaultPointLabel.d.ts +10 -0
- package/dts/chart/point/DefaultPointLabel.d.ts.map +1 -0
- package/dts/chart/point/Point.d.ts +120 -0
- package/dts/chart/point/Point.d.ts.map +1 -0
- package/dts/chart/point/index.d.ts +3 -0
- package/dts/chart/point/index.d.ts.map +1 -0
- package/dts/chart/scrubber/DefaultScrubberBeacon.d.ts +8 -0
- package/dts/chart/scrubber/DefaultScrubberBeacon.d.ts.map +1 -0
- package/dts/chart/scrubber/DefaultScrubberBeaconLabel.d.ts +12 -0
- package/dts/chart/scrubber/DefaultScrubberBeaconLabel.d.ts.map +1 -0
- package/dts/chart/scrubber/DefaultScrubberLabel.d.ts +11 -0
- package/dts/chart/scrubber/DefaultScrubberLabel.d.ts.map +1 -0
- package/dts/chart/scrubber/Scrubber.d.ts +168 -41
- package/dts/chart/scrubber/Scrubber.d.ts.map +1 -1
- package/dts/chart/scrubber/ScrubberBeaconGroup.d.ts +44 -0
- package/dts/chart/scrubber/ScrubberBeaconGroup.d.ts.map +1 -0
- package/dts/chart/scrubber/ScrubberBeaconLabelGroup.d.ts +31 -0
- package/dts/chart/scrubber/ScrubberBeaconLabelGroup.d.ts.map +1 -0
- package/dts/chart/scrubber/ScrubberProvider.d.ts +6 -3
- package/dts/chart/scrubber/ScrubberProvider.d.ts.map +1 -1
- package/dts/chart/scrubber/index.d.ts +3 -0
- package/dts/chart/scrubber/index.d.ts.map +1 -1
- package/dts/chart/text/ChartText.d.ts +151 -77
- package/dts/chart/text/ChartText.d.ts.map +1 -1
- package/dts/chart/text/{SmartChartTextGroup.d.ts → ChartTextGroup.d.ts} +9 -3
- package/dts/chart/text/ChartTextGroup.d.ts.map +1 -0
- package/dts/chart/text/index.d.ts +1 -1
- package/dts/chart/text/index.d.ts.map +1 -1
- package/dts/chart/utils/chart.d.ts +34 -7
- package/dts/chart/utils/chart.d.ts.map +1 -1
- package/dts/chart/utils/context.d.ts +28 -7
- package/dts/chart/utils/context.d.ts.map +1 -1
- package/dts/chart/utils/gradient.d.ts +117 -0
- package/dts/chart/utils/gradient.d.ts.map +1 -0
- package/dts/chart/utils/index.d.ts +3 -0
- package/dts/chart/utils/index.d.ts.map +1 -1
- package/dts/chart/utils/path.d.ts +53 -0
- package/dts/chart/utils/path.d.ts.map +1 -1
- package/dts/chart/utils/point.d.ts +60 -1
- package/dts/chart/utils/point.d.ts.map +1 -1
- package/dts/chart/utils/scale.d.ts +91 -0
- package/dts/chart/utils/scale.d.ts.map +1 -1
- package/dts/chart/utils/scrubber.d.ts +39 -0
- package/dts/chart/utils/scrubber.d.ts.map +1 -0
- package/dts/chart/utils/transition.d.ts +140 -0
- package/dts/chart/utils/transition.d.ts.map +1 -0
- package/esm/chart/CartesianChart.js +164 -70
- package/esm/chart/ChartContextBridge.js +148 -0
- package/esm/chart/Path.js +196 -113
- package/esm/chart/PeriodSelector.js +1 -1
- package/esm/chart/__stories__/CartesianChart.stories.js +371 -129
- package/esm/chart/__stories__/Chart.stories.js +2 -4
- package/esm/chart/area/Area.js +25 -35
- package/esm/chart/area/AreaChart.js +17 -12
- package/esm/chart/area/DottedArea.js +61 -109
- package/esm/chart/area/GradientArea.js +35 -91
- package/esm/chart/area/SolidArea.js +22 -8
- package/esm/chart/area/__stories__/AreaChart.stories.js +1 -1
- package/esm/chart/axis/Axis.js +2 -0
- package/esm/chart/axis/DefaultAxisTickLabel.js +11 -0
- package/esm/chart/axis/XAxis.js +62 -56
- package/esm/chart/axis/YAxis.js +58 -52
- package/esm/chart/axis/__stories__/Axis.stories.js +0 -1
- package/esm/chart/axis/index.js +1 -0
- package/esm/chart/bar/Bar.js +3 -1
- package/esm/chart/bar/BarChart.js +15 -37
- package/esm/chart/bar/BarPlot.js +41 -35
- package/esm/chart/bar/BarStack.js +75 -38
- package/esm/chart/bar/BarStackGroup.js +6 -16
- package/esm/chart/bar/DefaultBar.js +26 -48
- package/esm/chart/bar/DefaultBarStack.js +23 -58
- package/esm/chart/bar/__stories__/BarChart.stories.js +463 -77
- package/esm/chart/gradient/Gradient.js +53 -0
- package/esm/chart/gradient/index.js +1 -0
- package/esm/chart/index.js +3 -1
- package/esm/chart/line/DefaultReferenceLineLabel.js +66 -0
- package/esm/chart/line/DottedLine.js +29 -14
- package/esm/chart/line/Line.js +106 -67
- package/esm/chart/line/LineChart.js +20 -14
- package/esm/chart/line/ReferenceLine.js +73 -62
- package/esm/chart/line/SolidLine.js +25 -10
- package/esm/chart/line/__stories__/LineChart.stories.js +2098 -1975
- package/esm/chart/line/__stories__/ReferenceLine.stories.js +83 -28
- package/esm/chart/line/index.js +1 -1
- package/esm/chart/point/DefaultPointLabel.js +39 -0
- package/esm/chart/point/Point.js +188 -0
- package/esm/chart/point/index.js +2 -0
- package/esm/chart/scrubber/DefaultScrubberBeacon.js +179 -0
- package/esm/chart/scrubber/DefaultScrubberBeaconLabel.js +43 -0
- package/esm/chart/scrubber/DefaultScrubberLabel.js +28 -0
- package/esm/chart/scrubber/Scrubber.js +130 -148
- package/esm/chart/scrubber/ScrubberBeaconGroup.js +161 -0
- package/esm/chart/scrubber/ScrubberBeaconLabelGroup.js +185 -0
- package/esm/chart/scrubber/ScrubberProvider.js +46 -54
- package/esm/chart/scrubber/index.js +3 -1
- package/esm/chart/text/ChartText.js +242 -174
- package/esm/chart/text/{SmartChartTextGroup.js → ChartTextGroup.js} +6 -5
- package/esm/chart/text/index.js +1 -1
- package/esm/chart/utils/chart.js +44 -3
- package/esm/chart/utils/gradient.js +305 -0
- package/esm/chart/utils/index.js +3 -0
- package/esm/chart/utils/path.js +76 -8
- package/esm/chart/utils/point.js +116 -5
- package/esm/chart/utils/scale.js +230 -1
- package/esm/chart/utils/scrubber.js +139 -0
- package/esm/chart/utils/transition.js +221 -0
- package/package.json +7 -5
- package/dts/chart/Point.d.ts +0 -103
- package/dts/chart/Point.d.ts.map +0 -1
- package/dts/chart/line/GradientLine.d.ts +0 -45
- package/dts/chart/line/GradientLine.d.ts.map +0 -1
- package/dts/chart/scrubber/ScrubberBeacon.d.ts +0 -75
- package/dts/chart/scrubber/ScrubberBeacon.d.ts.map +0 -1
- package/dts/chart/text/SmartChartTextGroup.d.ts.map +0 -1
- package/esm/chart/Point.js +0 -111
- package/esm/chart/line/GradientLine.js +0 -62
- package/esm/chart/scrubber/ScrubberBeacon.js +0 -199
|
@@ -1,905 +1,918 @@
|
|
|
1
|
-
const _excluded = ["
|
|
1
|
+
const _excluded = ["dataX", "dataY"],
|
|
2
2
|
_excluded2 = ["label"],
|
|
3
3
|
_excluded3 = ["style"],
|
|
4
|
-
_excluded4 = ["dataX"]
|
|
5
|
-
|
|
4
|
+
_excluded4 = ["x", "y", "width", "height", "originY", "dataX"],
|
|
5
|
+
_excluded5 = ["seriesId", "color", "label"];
|
|
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
|
-
|
|
8
|
-
import {
|
|
7
|
+
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; }
|
|
8
|
+
import { forwardRef, memo, useCallback, useEffect, useId, useMemo, useRef, useState } from 'react';
|
|
9
|
+
import { useAnimatedReaction, useDerivedValue, useSharedValue, withDelay, withTiming } from 'react-native-reanimated';
|
|
9
10
|
import { assets } from '@coinbase/cds-common/internal/data/assets';
|
|
10
11
|
import { candles as btcCandles } from '@coinbase/cds-common/internal/data/candles';
|
|
11
12
|
import { prices } from '@coinbase/cds-common/internal/data/prices';
|
|
12
13
|
import { sparklineInteractiveData } from '@coinbase/cds-common/internal/visualizations/SparklineInteractiveData';
|
|
13
14
|
import { useTabsContext } from '@coinbase/cds-common/tabs/TabsContext';
|
|
14
15
|
import { useTheme } from '@coinbase/cds-mobile';
|
|
15
|
-
import { Button } from '@coinbase/cds-mobile/buttons';
|
|
16
|
-
import {
|
|
16
|
+
import { Button, IconButton } from '@coinbase/cds-mobile/buttons';
|
|
17
|
+
import { ListCell } from '@coinbase/cds-mobile/cells';
|
|
18
|
+
import { ExampleScreen } from '@coinbase/cds-mobile/examples/ExampleScreen';
|
|
17
19
|
import { Box, HStack, VStack } from '@coinbase/cds-mobile/layout';
|
|
18
|
-
import { RemoteImage } from '@coinbase/cds-mobile/media';
|
|
20
|
+
import { Avatar, RemoteImage } from '@coinbase/cds-mobile/media';
|
|
19
21
|
import { SectionHeader } from '@coinbase/cds-mobile/section-header/SectionHeader';
|
|
20
|
-
import {
|
|
22
|
+
import { Pressable } from '@coinbase/cds-mobile/system';
|
|
21
23
|
import { SegmentedTab } from '@coinbase/cds-mobile/tabs/SegmentedTab';
|
|
22
24
|
import { TextLabel1 } from '@coinbase/cds-mobile/typography';
|
|
23
25
|
import { Text } from '@coinbase/cds-mobile/typography/Text';
|
|
24
|
-
import {
|
|
25
|
-
import {
|
|
26
|
+
import { Circle, FontWeight, Group, Line as SkiaLine, Rect, Skia, TextAlign } from '@shopify/react-native-skia';
|
|
27
|
+
import { Area, DottedArea } from '../../area';
|
|
28
|
+
import { DefaultAxisTickLabel, XAxis, YAxis } from '../../axis';
|
|
29
|
+
import { BarPlot } from '../../bar';
|
|
26
30
|
import { CartesianChart } from '../../CartesianChart';
|
|
27
31
|
import { useCartesianChartContext } from '../../ChartProvider';
|
|
28
32
|
import { PeriodSelector, PeriodSelectorActiveIndicator } from '../../PeriodSelector';
|
|
29
|
-
import { Point } from '../../
|
|
30
|
-
import { Scrubber } from '../../scrubber';
|
|
31
|
-
import {
|
|
33
|
+
import { Point } from '../../point';
|
|
34
|
+
import { DefaultScrubberBeacon, DefaultScrubberBeaconLabel, DefaultScrubberLabel, Scrubber } from '../../scrubber';
|
|
35
|
+
import { buildTransition, defaultTransition, getLineData, getPointOnSerializableScale, projectPointWithSerializableScale, unwrapAnimatedValue, useScrubberContext } from '../../utils';
|
|
36
|
+
import { DottedLine, Line, LineChart, ReferenceLine, SolidLine } from '..';
|
|
32
37
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
});
|
|
53
|
-
case 'week':
|
|
54
|
-
case 'month':
|
|
55
|
-
case '1W':
|
|
56
|
-
case '1M':
|
|
57
|
-
return date.toLocaleDateString('en-US', {
|
|
58
|
-
month: 'short',
|
|
59
|
-
day: 'numeric',
|
|
60
|
-
year: 'numeric'
|
|
61
|
-
});
|
|
62
|
-
case 'year':
|
|
63
|
-
case 'all':
|
|
64
|
-
case '1Y':
|
|
65
|
-
case 'All':
|
|
66
|
-
return date.toLocaleDateString('en-US', {
|
|
67
|
-
month: 'short',
|
|
68
|
-
year: 'numeric'
|
|
69
|
-
});
|
|
70
|
-
default:
|
|
71
|
-
return date.toLocaleDateString('en-US');
|
|
72
|
-
}
|
|
73
|
-
};
|
|
74
|
-
const calculateTrendData = (scrubberPosition, currentData, currentTimestamps, startPrice, currentPrice, activeTimeframe) => {
|
|
75
|
-
if (scrubberPosition !== undefined) {
|
|
76
|
-
// When hovering, show trend relative to START of time period (not previous point)
|
|
77
|
-
const hoverIndex = scrubberPosition;
|
|
78
|
-
const hoverPrice = currentData[hoverIndex];
|
|
79
|
-
const hoverPriceChange = hoverPrice - startPrice; // Fixed: relative to start price
|
|
80
|
-
const hoverTimestamp = currentTimestamps[hoverIndex];
|
|
81
|
-
return {
|
|
82
|
-
trendPrice: hoverPrice,
|
|
83
|
-
trendPreviousPrice: startPrice,
|
|
84
|
-
// Fixed: always use start price
|
|
85
|
-
trendDirection: hoverPriceChange > 0 ? 'up' : hoverPriceChange < 0 ? 'down' : 'neutral',
|
|
86
|
-
displayDate: formatChartDate(hoverTimestamp, activeTimeframe)
|
|
87
|
-
};
|
|
88
|
-
} else {
|
|
89
|
-
// When not hovering, show current trend relative to start
|
|
90
|
-
const latestTimestamp = currentTimestamps[currentTimestamps.length - 1];
|
|
91
|
-
const priceChange = currentPrice - startPrice;
|
|
92
|
-
return {
|
|
93
|
-
trendPrice: currentPrice,
|
|
94
|
-
trendPreviousPrice: startPrice,
|
|
95
|
-
trendDirection: priceChange > 0 ? 'up' : priceChange < 0 ? 'down' : 'neutral',
|
|
96
|
-
displayDate: formatChartDate(latestTimestamp, activeTimeframe)
|
|
97
|
-
};
|
|
98
|
-
}
|
|
99
|
-
};
|
|
100
|
-
export const BasicLineChart = () => {
|
|
101
|
-
const chartData = [65, 78, 45, 88, 92, 73, 69];
|
|
38
|
+
function MultipleLine() {
|
|
39
|
+
const theme = useTheme();
|
|
40
|
+
const [scrubberPosition, setScrubberPosition] = useState();
|
|
41
|
+
const pages = useMemo(() => ['Page A', 'Page B', 'Page C', 'Page D', 'Page E', 'Page F', 'Page G'], []);
|
|
42
|
+
const pageViews = useMemo(() => [2400, 1398, 9800, 3908, 4800, 3800, 4300], []);
|
|
43
|
+
const uniqueVisitors = useMemo(() => [4000, 3000, 2000, 2780, 1890, 2390, 3490], []);
|
|
44
|
+
const chartAccessibilityLabel = "Website visitors across " + pageViews.length + " pages.";
|
|
45
|
+
const scrubberAccessibilityLabel = useCallback(index => {
|
|
46
|
+
return pages[index] + " has " + pageViews[index] + " views and " + uniqueVisitors[index] + " unique visitors.";
|
|
47
|
+
}, [pages, pageViews, uniqueVisitors]);
|
|
48
|
+
const numberFormatter = useCallback(value => new Intl.NumberFormat('en-US', {
|
|
49
|
+
maximumFractionDigits: 0
|
|
50
|
+
}).format(value), []);
|
|
51
|
+
const accessibilityLabel = useMemo(() => {
|
|
52
|
+
if (scrubberPosition !== undefined) {
|
|
53
|
+
return scrubberAccessibilityLabel(scrubberPosition);
|
|
54
|
+
}
|
|
55
|
+
return chartAccessibilityLabel;
|
|
56
|
+
}, [scrubberPosition, chartAccessibilityLabel, scrubberAccessibilityLabel]);
|
|
102
57
|
return /*#__PURE__*/_jsx(LineChart, {
|
|
103
58
|
enableScrubbing: true,
|
|
59
|
+
showArea: true,
|
|
60
|
+
showXAxis: true,
|
|
104
61
|
showYAxis: true,
|
|
105
|
-
|
|
106
|
-
|
|
62
|
+
accessibilityLabel: accessibilityLabel,
|
|
63
|
+
height: 200,
|
|
64
|
+
onScrubberPositionChange: setScrubberPosition,
|
|
107
65
|
series: [{
|
|
108
|
-
id: '
|
|
109
|
-
data:
|
|
110
|
-
|
|
111
|
-
|
|
66
|
+
id: 'pageViews',
|
|
67
|
+
data: pageViews,
|
|
68
|
+
color: theme.color.accentBoldGreen,
|
|
69
|
+
// Label will render next to scrubber beacon
|
|
70
|
+
label: 'Page Views'
|
|
71
|
+
}, {
|
|
72
|
+
id: 'uniqueVisitors',
|
|
73
|
+
data: uniqueVisitors,
|
|
74
|
+
color: theme.color.accentBoldPurple,
|
|
75
|
+
label: 'Unique Visitors',
|
|
76
|
+
// Default area is gradient
|
|
77
|
+
areaType: 'dotted'
|
|
112
78
|
}],
|
|
79
|
+
xAxis: {
|
|
80
|
+
// Used on the x-axis to provide context for each index from the series data array
|
|
81
|
+
data: pages
|
|
82
|
+
},
|
|
113
83
|
yAxis: {
|
|
114
|
-
|
|
115
|
-
tickLabelFormatter:
|
|
116
|
-
showGrid: true
|
|
84
|
+
showGrid: true,
|
|
85
|
+
tickLabelFormatter: numberFormatter
|
|
117
86
|
},
|
|
118
87
|
children: /*#__PURE__*/_jsx(Scrubber, {})
|
|
119
88
|
});
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const
|
|
123
|
-
|
|
89
|
+
}
|
|
90
|
+
function DataFormat() {
|
|
91
|
+
const [scrubberPosition, setScrubberPosition] = useState();
|
|
92
|
+
const yData = useMemo(() => [2, 5.5, 2, 8.5, 1.5, 5], []);
|
|
93
|
+
const xData = useMemo(() => [1, 2, 3, 5, 8, 10], []);
|
|
94
|
+
const chartAccessibilityLabel = "Chart with custom X and Y data. " + yData.length + " data points";
|
|
95
|
+
const scrubberAccessibilityLabel = useCallback(index => {
|
|
96
|
+
return "Point " + (index + 1) + ": X value " + xData[index] + ", Y value " + yData[index];
|
|
97
|
+
}, [xData, yData]);
|
|
98
|
+
const accessibilityLabel = useMemo(() => {
|
|
99
|
+
if (scrubberPosition !== undefined) {
|
|
100
|
+
return scrubberAccessibilityLabel(scrubberPosition);
|
|
101
|
+
}
|
|
102
|
+
return chartAccessibilityLabel;
|
|
103
|
+
}, [scrubberPosition, chartAccessibilityLabel, scrubberAccessibilityLabel]);
|
|
104
|
+
return /*#__PURE__*/_jsx(LineChart, {
|
|
105
|
+
enableScrubbing: true,
|
|
106
|
+
points: true,
|
|
107
|
+
showArea: true,
|
|
108
|
+
showXAxis: true,
|
|
124
109
|
showYAxis: true,
|
|
125
|
-
|
|
126
|
-
|
|
110
|
+
accessibilityLabel: accessibilityLabel,
|
|
111
|
+
curve: "natural",
|
|
112
|
+
height: 200,
|
|
113
|
+
inset: {
|
|
114
|
+
top: 16,
|
|
115
|
+
right: 16,
|
|
116
|
+
bottom: 0,
|
|
117
|
+
left: 0
|
|
118
|
+
},
|
|
119
|
+
onScrubberPositionChange: setScrubberPosition,
|
|
127
120
|
series: [{
|
|
128
|
-
id: '
|
|
129
|
-
data:
|
|
130
|
-
label: 'Monthly Growth',
|
|
131
|
-
color: '#2ca02c'
|
|
121
|
+
id: 'line',
|
|
122
|
+
data: yData
|
|
132
123
|
}],
|
|
124
|
+
xAxis: {
|
|
125
|
+
data: xData,
|
|
126
|
+
showLine: true,
|
|
127
|
+
showTickMarks: true,
|
|
128
|
+
showGrid: true
|
|
129
|
+
},
|
|
133
130
|
yAxis: {
|
|
134
|
-
|
|
135
|
-
|
|
131
|
+
domain: {
|
|
132
|
+
min: 0
|
|
133
|
+
},
|
|
134
|
+
position: 'left',
|
|
135
|
+
showLine: true,
|
|
136
|
+
showTickMarks: true,
|
|
136
137
|
showGrid: true
|
|
137
138
|
},
|
|
138
|
-
children:
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
139
|
+
children: /*#__PURE__*/_jsx(Scrubber, {
|
|
140
|
+
hideOverlay: true
|
|
141
|
+
})
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
function LiveUpdates() {
|
|
145
|
+
const scrubberRef = useRef(null);
|
|
146
|
+
const initialData = useMemo(() => {
|
|
147
|
+
return sparklineInteractiveData.hour.map(d => d.value);
|
|
148
|
+
}, []);
|
|
149
|
+
const [priceData, setPriceData] = useState(initialData);
|
|
150
|
+
const lastDataPointTimeRef = useRef(Date.now());
|
|
151
|
+
const updateCountRef = useRef(0);
|
|
152
|
+
const intervalSeconds = 3600 / initialData.length;
|
|
153
|
+
const maxPercentChange = Math.abs(initialData[initialData.length - 1] - initialData[0]) * 0.05;
|
|
154
|
+
useEffect(() => {
|
|
155
|
+
const priceUpdateInterval = setInterval(() => {
|
|
156
|
+
var _scrubberRef$current;
|
|
157
|
+
setPriceData(currentData => {
|
|
158
|
+
const newData = [...currentData];
|
|
159
|
+
const lastPrice = newData[newData.length - 1];
|
|
160
|
+
const priceChange = (Math.random() - 0.5) * maxPercentChange;
|
|
161
|
+
const newPrice = Math.round((lastPrice + priceChange) * 100) / 100;
|
|
162
|
+
|
|
163
|
+
// Check if we should roll over to a new data point
|
|
164
|
+
const currentTime = Date.now();
|
|
165
|
+
const timeSinceLastPoint = (currentTime - lastDataPointTimeRef.current) / 1000;
|
|
166
|
+
if (timeSinceLastPoint >= intervalSeconds) {
|
|
167
|
+
// Time for a new data point - remove first, add new at end
|
|
168
|
+
lastDataPointTimeRef.current = currentTime;
|
|
169
|
+
newData.shift(); // Remove oldest data point
|
|
170
|
+
newData.push(newPrice); // Add new data point
|
|
171
|
+
updateCountRef.current = 0;
|
|
172
|
+
} else {
|
|
173
|
+
// Just update the last data point
|
|
174
|
+
newData[newData.length - 1] = newPrice;
|
|
175
|
+
updateCountRef.current++;
|
|
176
|
+
}
|
|
177
|
+
return newData;
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
// Pulse the scrubber on each update
|
|
181
|
+
(_scrubberRef$current = scrubberRef.current) == null || _scrubberRef$current.pulse();
|
|
182
|
+
}, 2000 + Math.random() * 1000);
|
|
183
|
+
return () => clearInterval(priceUpdateInterval);
|
|
184
|
+
}, [intervalSeconds, maxPercentChange]);
|
|
185
|
+
return /*#__PURE__*/_jsx(LineChart, {
|
|
186
|
+
enableScrubbing: true,
|
|
187
|
+
showArea: true,
|
|
188
|
+
height: 200,
|
|
189
|
+
inset: {
|
|
190
|
+
right: 64
|
|
191
|
+
},
|
|
192
|
+
series: [{
|
|
193
|
+
id: 'btc',
|
|
194
|
+
data: priceData,
|
|
195
|
+
color: assets.btc.color
|
|
196
|
+
}],
|
|
197
|
+
children: /*#__PURE__*/_jsx(Scrubber, {
|
|
198
|
+
ref: scrubberRef
|
|
199
|
+
})
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
function MissingData() {
|
|
203
|
+
const theme = useTheme();
|
|
204
|
+
const pages = ['Page A', 'Page B', 'Page C', 'Page D', 'Page E', 'Page F', 'Page G'];
|
|
205
|
+
const pageViews = [2400, 1398, null, 3908, 4800, 3800, 4300];
|
|
206
|
+
const uniqueVisitors = [4000, 3000, null, 2780, 1890, 2390, 3490];
|
|
207
|
+
const numberFormatter = useCallback(value => new Intl.NumberFormat('en-US', {
|
|
208
|
+
maximumFractionDigits: 0
|
|
209
|
+
}).format(value), []);
|
|
210
|
+
return /*#__PURE__*/_jsx(LineChart, {
|
|
211
|
+
enableScrubbing: true,
|
|
212
|
+
points: true,
|
|
213
|
+
showArea: true,
|
|
214
|
+
showXAxis: true,
|
|
215
|
+
showYAxis: true,
|
|
216
|
+
height: 200,
|
|
217
|
+
series: [{
|
|
218
|
+
id: 'pageViews',
|
|
219
|
+
data: pageViews,
|
|
220
|
+
color: theme.color.accentBoldGreen,
|
|
221
|
+
// Label will render next to scrubber beacon
|
|
222
|
+
label: 'Page Views',
|
|
223
|
+
connectNulls: true
|
|
224
|
+
}, {
|
|
225
|
+
id: 'uniqueVisitors',
|
|
226
|
+
data: uniqueVisitors,
|
|
227
|
+
color: theme.color.accentBoldPurple,
|
|
228
|
+
label: 'Unique Visitors'
|
|
229
|
+
}],
|
|
230
|
+
xAxis: {
|
|
231
|
+
// Used on the x-axis to provide context for each index from the series data array
|
|
232
|
+
data: pages
|
|
233
|
+
},
|
|
234
|
+
yAxis: {
|
|
235
|
+
showGrid: true,
|
|
236
|
+
tickLabelFormatter: numberFormatter
|
|
237
|
+
},
|
|
238
|
+
children: /*#__PURE__*/_jsx(Scrubber, {
|
|
239
|
+
overlayOffset: 6
|
|
240
|
+
})
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
function Interaction() {
|
|
244
|
+
const [scrubberPosition, setScrubberPosition] = useState();
|
|
245
|
+
return /*#__PURE__*/_jsxs(VStack, {
|
|
246
|
+
gap: 2,
|
|
247
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
248
|
+
font: "label1",
|
|
249
|
+
children: scrubberPosition !== undefined ? "Scrubber position: " + scrubberPosition : 'Not scrubbing'
|
|
250
|
+
}), /*#__PURE__*/_jsx(LineChart, {
|
|
251
|
+
enableScrubbing: true,
|
|
252
|
+
showArea: true,
|
|
253
|
+
height: 200,
|
|
254
|
+
onScrubberPositionChange: setScrubberPosition,
|
|
255
|
+
series: [{
|
|
256
|
+
id: 'prices',
|
|
257
|
+
data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58]
|
|
258
|
+
}],
|
|
259
|
+
children: /*#__PURE__*/_jsx(Scrubber, {})
|
|
260
|
+
})]
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
function Points() {
|
|
264
|
+
const theme = useTheme();
|
|
265
|
+
const keyMarketShiftIndices = [4, 6, 7, 9, 10];
|
|
266
|
+
const data = [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58];
|
|
267
|
+
return /*#__PURE__*/_jsxs(CartesianChart, {
|
|
268
|
+
height: 200,
|
|
269
|
+
series: [{
|
|
270
|
+
id: 'prices',
|
|
271
|
+
data: data
|
|
272
|
+
}],
|
|
273
|
+
children: [/*#__PURE__*/_jsx(Area, {
|
|
274
|
+
fill: "rgb(" + theme.spectrum.blue5 + ")",
|
|
275
|
+
seriesId: "prices"
|
|
276
|
+
}), /*#__PURE__*/_jsx(Line, {
|
|
277
|
+
points: _ref => {
|
|
278
|
+
let {
|
|
279
|
+
dataX,
|
|
280
|
+
dataY
|
|
281
|
+
} = _ref,
|
|
282
|
+
props = _objectWithoutPropertiesLoose(_ref, _excluded);
|
|
283
|
+
return keyMarketShiftIndices.includes(dataX) ? _extends({}, props, {
|
|
284
|
+
strokeWidth: 2,
|
|
285
|
+
stroke: theme.color.bg,
|
|
286
|
+
radius: 5,
|
|
287
|
+
onClick: () => alert("You have clicked a key market shift at position " + (dataX + 1) + " with value " + dataY + "!"),
|
|
288
|
+
accessibilityLabel: "Key market shift point at position " + (dataX + 1) + ", value " + dataY + ". Click to view details."
|
|
289
|
+
}) : false;
|
|
147
290
|
},
|
|
148
|
-
|
|
149
|
-
radius: 6,
|
|
150
|
-
stroke: "purple",
|
|
151
|
-
strokeWidth: 7
|
|
152
|
-
}), /*#__PURE__*/_jsx(ReferenceLine, {
|
|
153
|
-
dataX: 2,
|
|
154
|
-
label: "testing 123",
|
|
155
|
-
labelProps: {
|
|
156
|
-
color: '#10b981',
|
|
157
|
-
inset: 0,
|
|
158
|
-
verticalAlignment: 'middle'
|
|
159
|
-
}
|
|
160
|
-
}), /*#__PURE__*/_jsx(ReferenceLine, {
|
|
161
|
-
dataY: 60,
|
|
162
|
-
label: "testing 123",
|
|
163
|
-
labelProps: {
|
|
164
|
-
horizontalAlignment: 'left'
|
|
165
|
-
}
|
|
166
|
-
}), /*#__PURE__*/_jsx(Point, {
|
|
167
|
-
dataX: 5,
|
|
168
|
-
dataY: 50,
|
|
169
|
-
fill: "orange",
|
|
170
|
-
radius: 5
|
|
291
|
+
seriesId: "prices"
|
|
171
292
|
})]
|
|
172
293
|
});
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const
|
|
176
|
-
const
|
|
177
|
-
const
|
|
178
|
-
const
|
|
179
|
-
const
|
|
180
|
-
const
|
|
181
|
-
const
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
294
|
+
}
|
|
295
|
+
function Transitions() {
|
|
296
|
+
const theme = useTheme();
|
|
297
|
+
const dataCount = 20;
|
|
298
|
+
const maxDataOffset = 15000;
|
|
299
|
+
const minStepOffset = 2500;
|
|
300
|
+
const maxStepOffset = 10000;
|
|
301
|
+
const domainLimit = 20000;
|
|
302
|
+
const updateInterval = 500;
|
|
303
|
+
const myTransitionConfig = {
|
|
304
|
+
type: 'spring',
|
|
305
|
+
stiffness: 700,
|
|
306
|
+
damping: 20
|
|
307
|
+
};
|
|
308
|
+
const negativeColor = "rgb(" + theme.spectrum.gray15 + ")";
|
|
309
|
+
const positiveColor = theme.color.fgPositive;
|
|
310
|
+
function generateNextValue(previousValue) {
|
|
311
|
+
const range = maxStepOffset - minStepOffset;
|
|
312
|
+
const offset = Math.random() * range + minStepOffset;
|
|
313
|
+
let direction;
|
|
314
|
+
if (previousValue >= maxDataOffset) {
|
|
315
|
+
direction = -1;
|
|
316
|
+
} else if (previousValue <= -maxDataOffset) {
|
|
317
|
+
direction = 1;
|
|
318
|
+
} else {
|
|
319
|
+
direction = Math.random() < 0.5 ? -1 : 1;
|
|
320
|
+
}
|
|
321
|
+
let newValue = previousValue + offset * direction;
|
|
322
|
+
newValue = Math.max(-maxDataOffset, Math.min(maxDataOffset, newValue));
|
|
323
|
+
return newValue;
|
|
324
|
+
}
|
|
325
|
+
function generateInitialData() {
|
|
326
|
+
const data = [];
|
|
327
|
+
let previousValue = Math.random() * 2 * maxDataOffset - maxDataOffset;
|
|
328
|
+
data.push(previousValue);
|
|
329
|
+
for (let i = 1; i < dataCount; i++) {
|
|
330
|
+
const newValue = generateNextValue(previousValue);
|
|
331
|
+
data.push(newValue);
|
|
332
|
+
previousValue = newValue;
|
|
333
|
+
}
|
|
334
|
+
return data;
|
|
335
|
+
}
|
|
336
|
+
const MyGradient = /*#__PURE__*/memo(props => {
|
|
337
|
+
const areaGradient = {
|
|
338
|
+
stops: _ref2 => {
|
|
339
|
+
let {
|
|
340
|
+
min,
|
|
341
|
+
max
|
|
342
|
+
} = _ref2;
|
|
343
|
+
return [{
|
|
344
|
+
offset: min,
|
|
345
|
+
color: negativeColor,
|
|
346
|
+
opacity: 1
|
|
347
|
+
}, {
|
|
348
|
+
offset: 0,
|
|
349
|
+
color: negativeColor,
|
|
350
|
+
opacity: 0
|
|
351
|
+
}, {
|
|
352
|
+
offset: 0,
|
|
353
|
+
color: positiveColor,
|
|
354
|
+
opacity: 0
|
|
355
|
+
}, {
|
|
356
|
+
offset: max,
|
|
357
|
+
color: positiveColor,
|
|
358
|
+
opacity: 1
|
|
359
|
+
}];
|
|
360
|
+
}
|
|
361
|
+
};
|
|
362
|
+
return /*#__PURE__*/_jsx(DottedArea, _extends({}, props, {
|
|
363
|
+
gradient: areaGradient
|
|
364
|
+
}));
|
|
365
|
+
});
|
|
366
|
+
function CustomTransitionsChart() {
|
|
367
|
+
const [data, setData] = useState(generateInitialData);
|
|
368
|
+
useEffect(() => {
|
|
369
|
+
const intervalId = setInterval(() => {
|
|
370
|
+
setData(currentData => {
|
|
371
|
+
var _currentData;
|
|
372
|
+
const lastValue = (_currentData = currentData[currentData.length - 1]) != null ? _currentData : 0;
|
|
373
|
+
const newValue = generateNextValue(lastValue);
|
|
374
|
+
return [...currentData.slice(1), newValue];
|
|
375
|
+
});
|
|
376
|
+
}, updateInterval);
|
|
377
|
+
return () => clearInterval(intervalId);
|
|
378
|
+
}, []);
|
|
379
|
+
const tickLabelFormatter = useCallback(value => new Intl.NumberFormat('en-US', {
|
|
197
380
|
style: 'currency',
|
|
198
|
-
currency: 'USD'
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
// Calculate trend information
|
|
203
|
-
const trendInfo = useMemo(() => {
|
|
204
|
-
const currentPrice = isHovering && typeof highlightedItemIndex === 'number' ? parseFloat(prices[highlightedItemIndex]) : parseFloat(prices[prices.length - 1]);
|
|
205
|
-
const startPrice = parseFloat(prices[0]);
|
|
206
|
-
const priceChange = currentPrice - startPrice;
|
|
207
|
-
const percentChange = priceChange / startPrice * 100;
|
|
208
|
-
const trendDirection = priceChange > 0 ? 'up' : priceChange < 0 ? 'down' : 'neutral';
|
|
209
|
-
const formattedPriceChange = new Intl.NumberFormat('en-US', {
|
|
381
|
+
currency: 'USD',
|
|
382
|
+
maximumFractionDigits: 0
|
|
383
|
+
}).format(value), []);
|
|
384
|
+
const valueAtIndexFormatter = useCallback(dataIndex => new Intl.NumberFormat('en-US', {
|
|
210
385
|
style: 'currency',
|
|
211
386
|
currency: 'USD'
|
|
212
|
-
}).format(
|
|
213
|
-
const
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
387
|
+
}).format(data[dataIndex]), [data]);
|
|
388
|
+
const lineGradient = {
|
|
389
|
+
stops: [{
|
|
390
|
+
offset: 0,
|
|
391
|
+
color: negativeColor
|
|
392
|
+
}, {
|
|
393
|
+
offset: 0,
|
|
394
|
+
color: positiveColor
|
|
395
|
+
}]
|
|
217
396
|
};
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
children: /*#__PURE__*/_jsxs(LineChart, {
|
|
222
|
-
showArea: true,
|
|
223
|
-
height: defaultChartHeight,
|
|
397
|
+
return /*#__PURE__*/_jsxs(CartesianChart, {
|
|
398
|
+
enableScrubbing: true,
|
|
399
|
+
height: 200,
|
|
224
400
|
inset: {
|
|
225
|
-
top:
|
|
226
|
-
bottom:
|
|
227
|
-
left:
|
|
228
|
-
right:
|
|
401
|
+
top: 32,
|
|
402
|
+
bottom: 32,
|
|
403
|
+
left: 16,
|
|
404
|
+
right: 16
|
|
229
405
|
},
|
|
230
|
-
onScrubberPositionChange: onScrubberPositionChange,
|
|
231
406
|
series: [{
|
|
232
|
-
id: '
|
|
233
|
-
data:
|
|
234
|
-
|
|
407
|
+
id: 'prices',
|
|
408
|
+
data: data,
|
|
409
|
+
gradient: lineGradient
|
|
235
410
|
}],
|
|
236
|
-
|
|
411
|
+
yAxis: {
|
|
237
412
|
domain: {
|
|
238
|
-
min:
|
|
239
|
-
max:
|
|
413
|
+
min: -domainLimit,
|
|
414
|
+
max: domainLimit
|
|
240
415
|
}
|
|
241
416
|
},
|
|
242
|
-
children: [/*#__PURE__*/_jsx(
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
417
|
+
children: [/*#__PURE__*/_jsx(YAxis, {
|
|
418
|
+
showGrid: true,
|
|
419
|
+
requestedTickCount: 2,
|
|
420
|
+
tickLabelFormatter: tickLabelFormatter
|
|
421
|
+
}), /*#__PURE__*/_jsx(Line, {
|
|
422
|
+
showArea: true,
|
|
423
|
+
AreaComponent: MyGradient,
|
|
424
|
+
seriesId: "prices",
|
|
425
|
+
strokeWidth: 3,
|
|
426
|
+
transition: myTransitionConfig
|
|
427
|
+
}), /*#__PURE__*/_jsx(Scrubber, {
|
|
428
|
+
hideOverlay: true,
|
|
429
|
+
beaconTransitions: {
|
|
430
|
+
update: myTransitionConfig
|
|
431
|
+
},
|
|
432
|
+
label: valueAtIndexFormatter
|
|
247
433
|
})]
|
|
248
|
-
})
|
|
249
|
-
}
|
|
250
|
-
};
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
const
|
|
254
|
-
const
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
return /*#__PURE__*/_jsx(CustomTransitionsChart, {});
|
|
437
|
+
}
|
|
438
|
+
function BasicAccessible() {
|
|
439
|
+
const [scrubberPosition, setScrubberPosition] = useState();
|
|
440
|
+
const data = useMemo(() => [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58], []);
|
|
441
|
+
|
|
442
|
+
// Chart-level accessibility label provides overview
|
|
443
|
+
const chartAccessibilityLabel = useMemo(() => {
|
|
444
|
+
const currentPrice = data[data.length - 1];
|
|
445
|
+
return "Price chart showing trend over " + data.length + " data points. Current value: " + currentPrice + ". Use arrow keys to adjust view";
|
|
446
|
+
}, [data]);
|
|
447
|
+
|
|
448
|
+
// Scrubber-level accessibility label provides specific position info
|
|
449
|
+
const scrubberAccessibilityLabel = useCallback(index => {
|
|
450
|
+
return "Price at position " + (index + 1) + " of " + data.length + ": " + data[index];
|
|
451
|
+
}, [data]);
|
|
452
|
+
const accessibilityLabel = useMemo(() => {
|
|
453
|
+
if (scrubberPosition !== undefined) {
|
|
454
|
+
return scrubberAccessibilityLabel(scrubberPosition);
|
|
455
|
+
}
|
|
456
|
+
return chartAccessibilityLabel;
|
|
457
|
+
}, [scrubberPosition, chartAccessibilityLabel, scrubberAccessibilityLabel]);
|
|
458
|
+
return /*#__PURE__*/_jsx(LineChart, {
|
|
459
|
+
enableScrubbing: true,
|
|
460
|
+
showArea: true,
|
|
461
|
+
showYAxis: true,
|
|
462
|
+
accessibilityLabel: accessibilityLabel,
|
|
463
|
+
height: 200,
|
|
464
|
+
onScrubberPositionChange: setScrubberPosition,
|
|
258
465
|
series: [{
|
|
259
|
-
id: '
|
|
260
|
-
data:
|
|
261
|
-
}, {
|
|
262
|
-
id: 'upperMiddle',
|
|
263
|
-
data: upperMiddleChartData,
|
|
264
|
-
color: '#ef4444'
|
|
265
|
-
}, {
|
|
266
|
-
id: 'lowerMiddle',
|
|
267
|
-
data: lowerMiddleChartData,
|
|
268
|
-
color: '#f59e0b'
|
|
269
|
-
}, {
|
|
270
|
-
id: 'bottom',
|
|
271
|
-
data: bottomChartData,
|
|
272
|
-
color: '#800080'
|
|
466
|
+
id: 'prices',
|
|
467
|
+
data: data
|
|
273
468
|
}],
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
type: "dotted"
|
|
279
|
-
}), /*#__PURE__*/_jsx(Line, {
|
|
280
|
-
LineComponent: props => /*#__PURE__*/_jsx(GradientLine, _extends({}, props, {
|
|
281
|
-
endColor: "#F7931A",
|
|
282
|
-
startColor: "#E3D74D",
|
|
283
|
-
strokeWidth: 4
|
|
284
|
-
})),
|
|
285
|
-
curve: "natural",
|
|
286
|
-
seriesId: "lowerMiddle"
|
|
287
|
-
}), /*#__PURE__*/_jsx(Line, {
|
|
288
|
-
showArea: true,
|
|
289
|
-
AreaComponent: DottedArea,
|
|
290
|
-
curve: "step",
|
|
291
|
-
seriesId: "bottom"
|
|
292
|
-
})]
|
|
469
|
+
yAxis: {
|
|
470
|
+
showGrid: true
|
|
471
|
+
},
|
|
472
|
+
children: /*#__PURE__*/_jsx(Scrubber, {})
|
|
293
473
|
});
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
const
|
|
298
|
-
const
|
|
299
|
-
|
|
300
|
-
label: 'Linear'
|
|
301
|
-
}, {
|
|
302
|
-
id: 'log',
|
|
303
|
-
label: 'Log'
|
|
304
|
-
}];
|
|
305
|
-
const [selectedScaleType, setSelectedScaleType] = useState(scaleTypes[0]);
|
|
474
|
+
}
|
|
475
|
+
function Gradients() {
|
|
476
|
+
const theme = useTheme();
|
|
477
|
+
const spectrumColors = ['blue', 'green', 'orange', 'yellow', 'gray', 'indigo', 'pink', 'purple', 'red', 'teal', 'chartreuse'];
|
|
478
|
+
const data = [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58];
|
|
479
|
+
const [currentSpectrumColor, setCurrentSpectrumColor] = useState('pink');
|
|
306
480
|
return /*#__PURE__*/_jsxs(VStack, {
|
|
307
|
-
gap:
|
|
308
|
-
children: [/*#__PURE__*/_jsx(
|
|
309
|
-
|
|
310
|
-
gap:
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
})
|
|
481
|
+
gap: 2,
|
|
482
|
+
children: [/*#__PURE__*/_jsx(HStack, {
|
|
483
|
+
flexWrap: "wrap",
|
|
484
|
+
gap: 1,
|
|
485
|
+
justifyContent: "flex-end",
|
|
486
|
+
children: spectrumColors.map(color => /*#__PURE__*/_jsx(Pressable, {
|
|
487
|
+
accessibilityLabel: "Select " + color,
|
|
488
|
+
height: 16,
|
|
489
|
+
onPress: () => setCurrentSpectrumColor(color),
|
|
490
|
+
style: {
|
|
491
|
+
backgroundColor: "rgb(" + theme.spectrum[color + "20"] + ")",
|
|
492
|
+
borderColor: "rgb(" + theme.spectrum[color + "50"] + ")",
|
|
493
|
+
borderWidth: 2
|
|
494
|
+
},
|
|
495
|
+
width: 16
|
|
496
|
+
}, color))
|
|
323
497
|
}), /*#__PURE__*/_jsx(LineChart, {
|
|
324
|
-
|
|
498
|
+
points: true,
|
|
325
499
|
showYAxis: true,
|
|
326
|
-
|
|
327
|
-
height: defaultChartHeight,
|
|
500
|
+
height: 200,
|
|
328
501
|
series: [{
|
|
329
|
-
id: '
|
|
330
|
-
data:
|
|
331
|
-
|
|
502
|
+
id: 'continuousGradient',
|
|
503
|
+
data: data,
|
|
504
|
+
gradient: {
|
|
505
|
+
stops: [{
|
|
506
|
+
offset: 0,
|
|
507
|
+
color: "rgb(" + theme.spectrum[currentSpectrumColor + "80"] + ")"
|
|
508
|
+
}, {
|
|
509
|
+
offset: Math.max(...data),
|
|
510
|
+
color: "rgb(" + theme.spectrum[currentSpectrumColor + "20"] + ")"
|
|
511
|
+
}]
|
|
512
|
+
}
|
|
513
|
+
}, {
|
|
514
|
+
id: 'discreteGradient',
|
|
515
|
+
data: data.map(d => d + 50),
|
|
516
|
+
// You can create a "discrete" gradient by having multiple stops at the same offset
|
|
517
|
+
gradient: {
|
|
518
|
+
stops: _ref3 => {
|
|
519
|
+
let {
|
|
520
|
+
min,
|
|
521
|
+
max
|
|
522
|
+
} = _ref3;
|
|
523
|
+
return [
|
|
524
|
+
// Allows a function which accepts min/max or direct array
|
|
525
|
+
{
|
|
526
|
+
offset: min,
|
|
527
|
+
color: "rgb(" + theme.spectrum[currentSpectrumColor + "80"] + ")"
|
|
528
|
+
}, {
|
|
529
|
+
offset: min + (max - min) / 3,
|
|
530
|
+
color: "rgb(" + theme.spectrum[currentSpectrumColor + "80"] + ")"
|
|
531
|
+
}, {
|
|
532
|
+
offset: min + (max - min) / 3,
|
|
533
|
+
color: "rgb(" + theme.spectrum[currentSpectrumColor + "50"] + ")"
|
|
534
|
+
}, {
|
|
535
|
+
offset: min + (max - min) / 3 * 2,
|
|
536
|
+
color: "rgb(" + theme.spectrum[currentSpectrumColor + "50"] + ")"
|
|
537
|
+
}, {
|
|
538
|
+
offset: min + (max - min) / 3 * 2,
|
|
539
|
+
color: "rgb(" + theme.spectrum[currentSpectrumColor + "20"] + ")"
|
|
540
|
+
}, {
|
|
541
|
+
offset: max,
|
|
542
|
+
color: "rgb(" + theme.spectrum[currentSpectrumColor + "20"] + ")"
|
|
543
|
+
}];
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
}, {
|
|
547
|
+
id: 'xAxisGradient',
|
|
548
|
+
data: data.map(d => d + 100),
|
|
549
|
+
gradient: {
|
|
550
|
+
// You can also configure by the x-axis.
|
|
551
|
+
axis: 'x',
|
|
552
|
+
stops: _ref4 => {
|
|
553
|
+
let {
|
|
554
|
+
min,
|
|
555
|
+
max
|
|
556
|
+
} = _ref4;
|
|
557
|
+
return [{
|
|
558
|
+
offset: min,
|
|
559
|
+
color: "rgb(" + theme.spectrum[currentSpectrumColor + "80"] + ")",
|
|
560
|
+
opacity: 0
|
|
561
|
+
}, {
|
|
562
|
+
offset: max,
|
|
563
|
+
color: "rgb(" + theme.spectrum[currentSpectrumColor + "20"] + ")",
|
|
564
|
+
opacity: 1
|
|
565
|
+
}];
|
|
566
|
+
}
|
|
567
|
+
}
|
|
332
568
|
}],
|
|
569
|
+
strokeWidth: 4,
|
|
333
570
|
yAxis: {
|
|
334
|
-
|
|
335
|
-
requestedTickCount: 5,
|
|
336
|
-
tickLabelFormatter: value => value.toLocaleString(),
|
|
337
|
-
showGrid: true,
|
|
338
|
-
width: 70
|
|
571
|
+
showGrid: true
|
|
339
572
|
}
|
|
340
573
|
})]
|
|
341
574
|
});
|
|
342
|
-
}
|
|
343
|
-
|
|
575
|
+
}
|
|
576
|
+
function GainLossChart() {
|
|
344
577
|
const theme = useTheme();
|
|
345
|
-
const [
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
'1M': 'month',
|
|
354
|
-
'1Y': 'year',
|
|
355
|
-
All: 'all'
|
|
356
|
-
};
|
|
357
|
-
const currentPriceData = activeTab ? sparklineInteractiveData[tabConversion[activeTab.id]] : sparklineInteractiveData.hour;
|
|
358
|
-
const currentData = useMemo(() => [...currentPriceData.map(price => price.value)], [currentPriceData]);
|
|
359
|
-
const currentTimestamps = useMemo(() => [...currentPriceData.map(price => price.date.toISOString())], [currentPriceData]);
|
|
360
|
-
const startPrice = currentData[0];
|
|
361
|
-
const currentPrice = currentData[currentData.length - 1];
|
|
362
|
-
const priceChange = currentPrice - startPrice;
|
|
363
|
-
|
|
364
|
-
// Determine colors based on trend
|
|
365
|
-
const trendColor = useMemo(() => {
|
|
366
|
-
return priceChange >= 0 ? theme.color.fgPositive : theme.color.fgNegative;
|
|
367
|
-
}, [priceChange, theme.color.fgPositive, theme.color.fgNegative]);
|
|
368
|
-
const activeBackground = useMemo(() => {
|
|
369
|
-
return priceChange >= 0 ? 'bgPositiveWash' : 'bgNegativeWash';
|
|
370
|
-
}, [priceChange]);
|
|
371
|
-
const formatPrice = useCallback(price => {
|
|
372
|
-
return "$" + price.toLocaleString('en-US', {
|
|
373
|
-
minimumFractionDigits: 2,
|
|
374
|
-
maximumFractionDigits: 2
|
|
375
|
-
});
|
|
376
|
-
}, []);
|
|
377
|
-
const scrubberLabel = useCallback(index => {
|
|
378
|
-
const timestamp = currentTimestamps[index];
|
|
379
|
-
return formatChartDate(timestamp, (activeTab == null ? void 0 : activeTab.id) || '1H');
|
|
380
|
-
}, [activeTab == null ? void 0 : activeTab.id, currentTimestamps]);
|
|
578
|
+
const data = useMemo(() => [-40, -28, -21, -5, 48, -5, -28, 2, -29, -46, 16, -30, -29, 8], []);
|
|
579
|
+
const negativeColor = "rgb(" + theme.spectrum.gray15 + ")";
|
|
580
|
+
const positiveColor = theme.color.fgPositive;
|
|
581
|
+
const tickLabelFormatter = useCallback(value => new Intl.NumberFormat('en-US', {
|
|
582
|
+
style: 'currency',
|
|
583
|
+
currency: 'USD',
|
|
584
|
+
maximumFractionDigits: 0
|
|
585
|
+
}).format(value), []);
|
|
381
586
|
|
|
382
|
-
//
|
|
383
|
-
const
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
color: trendColor,
|
|
392
|
-
font: "label1",
|
|
393
|
-
label: label
|
|
394
|
-
}, props));
|
|
395
|
-
})), [trendColor]);
|
|
396
|
-
const tabs = useMemo(() => [{
|
|
397
|
-
id: '1H',
|
|
398
|
-
label: '1H'
|
|
399
|
-
}, {
|
|
400
|
-
id: '1D',
|
|
401
|
-
label: '1D'
|
|
402
|
-
}, {
|
|
403
|
-
id: '1W',
|
|
404
|
-
label: '1W'
|
|
405
|
-
}, {
|
|
406
|
-
id: '1M',
|
|
407
|
-
label: '1M'
|
|
408
|
-
}, {
|
|
409
|
-
id: '1Y',
|
|
410
|
-
label: '1Y'
|
|
411
|
-
}, {
|
|
412
|
-
id: 'All',
|
|
413
|
-
label: 'All'
|
|
414
|
-
}], []);
|
|
415
|
-
return /*#__PURE__*/_jsx(Box, {
|
|
416
|
-
style: {
|
|
417
|
-
marginLeft: -16,
|
|
418
|
-
marginRight: -16
|
|
419
|
-
},
|
|
420
|
-
children: /*#__PURE__*/_jsxs(VStack, {
|
|
421
|
-
gap: 3,
|
|
422
|
-
width: "100%",
|
|
423
|
-
children: [/*#__PURE__*/_jsxs(LineChart, {
|
|
424
|
-
enableScrubbing: true,
|
|
425
|
-
showArea: true,
|
|
426
|
-
showXAxis: true,
|
|
427
|
-
height: defaultChartHeight,
|
|
428
|
-
inset: {
|
|
429
|
-
left: 0,
|
|
430
|
-
right: 24,
|
|
431
|
-
bottom: 0
|
|
432
|
-
},
|
|
433
|
-
series: [{
|
|
434
|
-
id: 'price',
|
|
435
|
-
data: currentData,
|
|
436
|
-
color: trendColor
|
|
437
|
-
}],
|
|
438
|
-
children: [/*#__PURE__*/_jsx(Scrubber, {
|
|
439
|
-
idlePulse: true,
|
|
440
|
-
label: scrubberLabel
|
|
441
|
-
}), /*#__PURE__*/_jsx(ReferenceLine, {
|
|
442
|
-
dataY: startPrice,
|
|
443
|
-
label: formatPrice(startPrice),
|
|
444
|
-
labelProps: {
|
|
445
|
-
horizontalAlignment: 'right',
|
|
446
|
-
inset: 4,
|
|
447
|
-
borderRadius: 4,
|
|
448
|
-
dx: -8,
|
|
449
|
-
color: theme.color.fgInverse,
|
|
450
|
-
background: priceChange >= 0 ? theme.color.bgPositive : theme.color.bgNegative
|
|
451
|
-
},
|
|
452
|
-
stroke: priceChange >= 0 ? theme.color.bgPositive : theme.color.bgNegative
|
|
453
|
-
})]
|
|
454
|
-
}), /*#__PURE__*/_jsx(PeriodSelector, {
|
|
455
|
-
TabComponent: ColorShiftTab,
|
|
456
|
-
activeBackground: activeBackground,
|
|
457
|
-
activeTab: activeTab,
|
|
458
|
-
onChange: setActiveTab,
|
|
459
|
-
tabs: tabs
|
|
460
|
-
})]
|
|
461
|
-
})
|
|
462
|
-
});
|
|
463
|
-
};
|
|
464
|
-
export const PriceChart = () => {
|
|
465
|
-
const {
|
|
466
|
-
latestPrice,
|
|
467
|
-
formattedPrice
|
|
468
|
-
} = useMemo(() => {
|
|
469
|
-
const latestPrice = sparklineInteractiveData.hour[sparklineInteractiveData.hour.length - 1].value;
|
|
470
|
-
return {
|
|
471
|
-
latestPrice,
|
|
472
|
-
formattedPrice: "$" + latestPrice.toLocaleString('en-US', {
|
|
473
|
-
minimumFractionDigits: 2,
|
|
474
|
-
maximumFractionDigits: 2
|
|
475
|
-
})
|
|
476
|
-
};
|
|
477
|
-
}, []);
|
|
478
|
-
const tabs = useMemo(() => [{
|
|
479
|
-
id: '1H',
|
|
480
|
-
label: '1H'
|
|
481
|
-
}, {
|
|
482
|
-
id: '1D',
|
|
483
|
-
label: '1D'
|
|
484
|
-
}, {
|
|
485
|
-
id: '1W',
|
|
486
|
-
label: '1W'
|
|
487
|
-
}, {
|
|
488
|
-
id: '1M',
|
|
489
|
-
label: '1M'
|
|
490
|
-
}, {
|
|
491
|
-
id: '1Y',
|
|
492
|
-
label: '1Y'
|
|
493
|
-
}, {
|
|
494
|
-
id: 'All',
|
|
495
|
-
label: 'All'
|
|
496
|
-
}], []);
|
|
497
|
-
const [activeTab, setActiveTab] = useState(tabs[0]);
|
|
498
|
-
const isLive = useMemo(() => (activeTab == null ? void 0 : activeTab.id) === '1H', [activeTab]);
|
|
499
|
-
const activeBackground = useMemo(() => !isLive ? 'bgPrimaryWash' : 'bgNegativeWash', [isLive]);
|
|
500
|
-
const [isHovering, setIsHovering] = useState(false);
|
|
501
|
-
const tabConversion = {
|
|
502
|
-
'1H': 'hour',
|
|
503
|
-
'1D': 'day',
|
|
504
|
-
'1W': 'week',
|
|
505
|
-
'1M': 'month',
|
|
506
|
-
'1Y': 'year',
|
|
507
|
-
All: 'all'
|
|
587
|
+
// Line gradient: hard color change at 0 (full opacity for line)
|
|
588
|
+
const lineGradient = {
|
|
589
|
+
stops: [{
|
|
590
|
+
offset: 0,
|
|
591
|
+
color: negativeColor
|
|
592
|
+
}, {
|
|
593
|
+
offset: 0,
|
|
594
|
+
color: positiveColor
|
|
595
|
+
}]
|
|
508
596
|
};
|
|
509
|
-
const
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
if (currentData[i] > maxPrice) {
|
|
534
|
-
maxPrice = currentData[i];
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
// Second pass: find all indices where min and max occur
|
|
539
|
-
const lowestPriceIndices = [];
|
|
540
|
-
const highestPriceIndices = [];
|
|
541
|
-
for (let i = 0; i < currentData.length; i++) {
|
|
542
|
-
if (currentData[i] === minPrice) {
|
|
543
|
-
lowestPriceIndices.push(i);
|
|
544
|
-
}
|
|
545
|
-
if (currentData[i] === maxPrice) {
|
|
546
|
-
highestPriceIndices.push(i);
|
|
597
|
+
const GradientDottedArea = /*#__PURE__*/memo(props => /*#__PURE__*/_jsx(DottedArea, _extends({}, props, {
|
|
598
|
+
gradient: {
|
|
599
|
+
stops: _ref5 => {
|
|
600
|
+
let {
|
|
601
|
+
min,
|
|
602
|
+
max
|
|
603
|
+
} = _ref5;
|
|
604
|
+
return [{
|
|
605
|
+
offset: min,
|
|
606
|
+
color: negativeColor,
|
|
607
|
+
opacity: 0.4
|
|
608
|
+
}, {
|
|
609
|
+
offset: 0,
|
|
610
|
+
color: negativeColor,
|
|
611
|
+
opacity: 0
|
|
612
|
+
}, {
|
|
613
|
+
offset: 0,
|
|
614
|
+
color: positiveColor,
|
|
615
|
+
opacity: 0
|
|
616
|
+
}, {
|
|
617
|
+
offset: max,
|
|
618
|
+
color: positiveColor,
|
|
619
|
+
opacity: 0.4
|
|
620
|
+
}];
|
|
547
621
|
}
|
|
548
622
|
}
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
const
|
|
574
|
-
const
|
|
575
|
-
const
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
maximumFractionDigits: 2
|
|
581
|
-
}) + "%)";
|
|
582
|
-
const scrubberLabel = useCallback(item => {
|
|
583
|
-
if (item === undefined) return null;
|
|
584
|
-
const timestamp = currentTimestamps[item];
|
|
585
|
-
const price = currentData[item];
|
|
586
|
-
const formattedPrice = price.toLocaleString('en-US', {
|
|
587
|
-
minimumFractionDigits: 2,
|
|
588
|
-
maximumFractionDigits: 2
|
|
589
|
-
}) + ' USD';
|
|
590
|
-
const formattedDate = formatChartDate(timestamp, (activeTab == null ? void 0 : activeTab.id) || '1H');
|
|
591
|
-
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
592
|
-
children: [/*#__PURE__*/_jsx("tspan", {
|
|
593
|
-
style: {
|
|
594
|
-
fontWeight: 'bold',
|
|
595
|
-
display: 'inline-block'
|
|
596
|
-
},
|
|
597
|
-
children: formattedPrice
|
|
598
|
-
}), /*#__PURE__*/_jsxs("tspan", {
|
|
599
|
-
style: {
|
|
600
|
-
display: 'inline-block'
|
|
601
|
-
},
|
|
602
|
-
children: [" ", formattedDate]
|
|
603
|
-
})]
|
|
604
|
-
});
|
|
605
|
-
}, [currentTimestamps, currentData, activeTab == null ? void 0 : activeTab.id]);
|
|
606
|
-
const formatPrice = useCallback(value => {
|
|
607
|
-
return "$" + value.toLocaleString('en-US', {
|
|
623
|
+
})));
|
|
624
|
+
return /*#__PURE__*/_jsxs(CartesianChart, {
|
|
625
|
+
enableScrubbing: true,
|
|
626
|
+
height: 200,
|
|
627
|
+
series: [{
|
|
628
|
+
id: 'prices',
|
|
629
|
+
data: data,
|
|
630
|
+
gradient: lineGradient
|
|
631
|
+
}],
|
|
632
|
+
children: [/*#__PURE__*/_jsx(YAxis, {
|
|
633
|
+
showGrid: true,
|
|
634
|
+
requestedTickCount: 2,
|
|
635
|
+
tickLabelFormatter: tickLabelFormatter
|
|
636
|
+
}), /*#__PURE__*/_jsx(Line, {
|
|
637
|
+
showArea: true,
|
|
638
|
+
AreaComponent: GradientDottedArea,
|
|
639
|
+
seriesId: "prices",
|
|
640
|
+
strokeWidth: 3
|
|
641
|
+
}), /*#__PURE__*/_jsx(Scrubber, {
|
|
642
|
+
hideOverlay: true
|
|
643
|
+
})]
|
|
644
|
+
});
|
|
645
|
+
}
|
|
646
|
+
function HighLowPrice() {
|
|
647
|
+
const data = [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58];
|
|
648
|
+
const minPrice = Math.min(...data);
|
|
649
|
+
const maxPrice = Math.max(...data);
|
|
650
|
+
const minPriceIndex = data.indexOf(minPrice);
|
|
651
|
+
const maxPriceIndex = data.indexOf(maxPrice);
|
|
652
|
+
const formatPrice = useCallback(price => {
|
|
653
|
+
return "$" + price.toLocaleString('en-US', {
|
|
608
654
|
minimumFractionDigits: 2,
|
|
609
655
|
maximumFractionDigits: 2
|
|
610
656
|
});
|
|
611
657
|
}, []);
|
|
612
|
-
return /*#__PURE__*/_jsxs(
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
renderPoints: _ref2 => {
|
|
630
|
-
let {
|
|
631
|
-
dataX: index
|
|
632
|
-
} = _ref2;
|
|
633
|
-
if (highestPriceIndices.includes(index)) {
|
|
634
|
-
return {
|
|
635
|
-
opacity: 0,
|
|
636
|
-
label: formatPrice(currentData[index]),
|
|
637
|
-
labelProps: {
|
|
638
|
-
position: 'top',
|
|
639
|
-
dy: -16
|
|
640
|
-
}
|
|
641
|
-
};
|
|
642
|
-
}
|
|
643
|
-
if (lowestPriceIndices.includes(index)) {
|
|
644
|
-
return {
|
|
645
|
-
opacity: 0,
|
|
646
|
-
label: formatPrice(currentData[index]),
|
|
647
|
-
labelProps: {
|
|
648
|
-
position: 'bottom',
|
|
649
|
-
dy: 16
|
|
650
|
-
}
|
|
651
|
-
};
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
}],
|
|
655
|
-
yAxis: {
|
|
656
|
-
domainLimit: 'strict'
|
|
657
|
-
},
|
|
658
|
-
children: /*#__PURE__*/_jsx(Scrubber, {})
|
|
659
|
-
}), /*#__PURE__*/_jsx(PeriodSelector, {
|
|
660
|
-
activeTab: activeTab,
|
|
661
|
-
onChange: tab => setActiveTab(tab),
|
|
662
|
-
tabs: tabs
|
|
658
|
+
return /*#__PURE__*/_jsxs(LineChart, {
|
|
659
|
+
showArea: true,
|
|
660
|
+
height: 200,
|
|
661
|
+
series: [{
|
|
662
|
+
id: 'prices',
|
|
663
|
+
data: data
|
|
664
|
+
}],
|
|
665
|
+
children: [/*#__PURE__*/_jsx(Point, {
|
|
666
|
+
dataX: minPriceIndex,
|
|
667
|
+
dataY: minPrice,
|
|
668
|
+
label: formatPrice(minPrice),
|
|
669
|
+
labelPosition: "bottom"
|
|
670
|
+
}), /*#__PURE__*/_jsx(Point, {
|
|
671
|
+
dataX: maxPriceIndex,
|
|
672
|
+
dataY: maxPrice,
|
|
673
|
+
label: formatPrice(maxPrice),
|
|
674
|
+
labelPosition: "top"
|
|
663
675
|
})]
|
|
664
676
|
});
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
const
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
}));
|
|
675
|
-
};
|
|
676
|
-
const historicalData = useMemo(() => getDataFromSparkline(new Date('2019-01-01')), []);
|
|
677
|
-
const annualGrowthRate = 10;
|
|
678
|
-
const generateForecastData = useCallback((lastDate, lastPrice, growthRate) => {
|
|
679
|
-
const dailyGrowthRate = Math.pow(1 + growthRate / 100, 1 / 365) - 1;
|
|
680
|
-
const forecastData = [];
|
|
681
|
-
const fiveYearsFromNow = new Date(lastDate);
|
|
682
|
-
fiveYearsFromNow.setFullYear(fiveYearsFromNow.getFullYear() + 5);
|
|
683
|
-
|
|
684
|
-
// Generate daily forecast points for 5 years
|
|
685
|
-
const currentDate = new Date(lastDate);
|
|
686
|
-
let currentPrice = lastPrice;
|
|
687
|
-
while (currentDate <= fiveYearsFromNow) {
|
|
688
|
-
currentPrice = currentPrice * (1 + dailyGrowthRate * 10);
|
|
689
|
-
forecastData.push({
|
|
690
|
-
date: new Date(currentDate),
|
|
691
|
-
value: Math.round(currentPrice)
|
|
692
|
-
});
|
|
693
|
-
currentDate.setDate(currentDate.getDate() + 10);
|
|
694
|
-
}
|
|
695
|
-
return forecastData;
|
|
696
|
-
}, []);
|
|
697
|
-
const forecastData = useMemo(() => {
|
|
698
|
-
if (historicalData.length === 0) return [];
|
|
699
|
-
const lastPoint = historicalData[historicalData.length - 1];
|
|
700
|
-
return generateForecastData(lastPoint.date, lastPoint.value, annualGrowthRate);
|
|
701
|
-
}, [generateForecastData, historicalData, annualGrowthRate]);
|
|
702
|
-
|
|
703
|
-
// Combine all data points with dates converted to timestamps for x-axis
|
|
704
|
-
const allDataPoints = useMemo(() => [...historicalData, ...forecastData], [historicalData, forecastData]);
|
|
705
|
-
const formatPrice = useCallback(price => {
|
|
706
|
-
return new Intl.NumberFormat('en-US', {
|
|
707
|
-
style: 'currency',
|
|
708
|
-
currency: 'USD',
|
|
709
|
-
minimumFractionDigits: 0,
|
|
710
|
-
maximumFractionDigits: 0
|
|
711
|
-
}).format(price);
|
|
712
|
-
}, []);
|
|
713
|
-
|
|
714
|
-
// Format x-axis labels to show years
|
|
715
|
-
const formatXAxisLabel = useCallback(timestamp => {
|
|
716
|
-
return new Date(timestamp).getFullYear().toString();
|
|
717
|
-
}, []);
|
|
677
|
+
}
|
|
678
|
+
function StylingScrubber() {
|
|
679
|
+
const theme = useTheme();
|
|
680
|
+
const pages = ['Page A', 'Page B', 'Page C', 'Page D', 'Page E', 'Page F', 'Page G'];
|
|
681
|
+
const pageViews = [2400, 1398, 9800, 3908, 4800, 3800, 4300];
|
|
682
|
+
const uniqueVisitors = [4000, 3000, 2000, 2780, 1890, 2390, 3490];
|
|
683
|
+
const numberFormatter = useCallback(value => new Intl.NumberFormat('en-US', {
|
|
684
|
+
maximumFractionDigits: 0
|
|
685
|
+
}).format(value), []);
|
|
718
686
|
return /*#__PURE__*/_jsx(LineChart, {
|
|
719
687
|
enableScrubbing: true,
|
|
720
688
|
showArea: true,
|
|
721
689
|
showXAxis: true,
|
|
722
|
-
|
|
723
|
-
height:
|
|
724
|
-
inset: {
|
|
725
|
-
top: 4,
|
|
726
|
-
left: 0,
|
|
727
|
-
right: 0,
|
|
728
|
-
bottom: 0
|
|
729
|
-
},
|
|
690
|
+
showYAxis: true,
|
|
691
|
+
height: 200,
|
|
730
692
|
series: [{
|
|
731
|
-
id: '
|
|
732
|
-
data:
|
|
733
|
-
color:
|
|
693
|
+
id: 'pageViews',
|
|
694
|
+
data: pageViews,
|
|
695
|
+
color: theme.color.accentBoldGreen,
|
|
696
|
+
// Label will render next to scrubber beacon
|
|
697
|
+
label: 'Page Views'
|
|
734
698
|
}, {
|
|
735
|
-
id: '
|
|
736
|
-
data:
|
|
737
|
-
color:
|
|
738
|
-
|
|
699
|
+
id: 'uniqueVisitors',
|
|
700
|
+
data: uniqueVisitors,
|
|
701
|
+
color: theme.color.accentBoldPurple,
|
|
702
|
+
label: 'Unique Visitors',
|
|
703
|
+
// Default area is gradient
|
|
704
|
+
areaType: 'dotted'
|
|
739
705
|
}],
|
|
740
706
|
xAxis: {
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
tickInterval: 32
|
|
707
|
+
// Used on the x-axis to provide context for each index from the series data array
|
|
708
|
+
data: pages
|
|
744
709
|
},
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
id: '1D',
|
|
754
|
-
label: '1D'
|
|
755
|
-
}, {
|
|
756
|
-
id: '1W',
|
|
757
|
-
label: '1W'
|
|
758
|
-
}, {
|
|
759
|
-
id: '1M',
|
|
760
|
-
label: '1M'
|
|
761
|
-
}, {
|
|
762
|
-
id: '1Y',
|
|
763
|
-
label: '1Y'
|
|
764
|
-
}, {
|
|
765
|
-
id: 'All',
|
|
766
|
-
label: 'All'
|
|
767
|
-
}];
|
|
768
|
-
const [activeTab, setActiveTab] = useState(tabs[0]);
|
|
769
|
-
return /*#__PURE__*/_jsx(PeriodSelector, {
|
|
770
|
-
activeTab: activeTab,
|
|
771
|
-
onChange: tab => setActiveTab(tab),
|
|
772
|
-
tabs: tabs
|
|
773
|
-
});
|
|
774
|
-
};
|
|
775
|
-
const BTCTab = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref3, ref) => {
|
|
776
|
-
let {
|
|
777
|
-
label
|
|
778
|
-
} = _ref3,
|
|
779
|
-
props = _objectWithoutPropertiesLoose(_ref3, _excluded2);
|
|
780
|
-
const {
|
|
781
|
-
activeTab
|
|
782
|
-
} = useTabsContext();
|
|
783
|
-
const isActive = (activeTab == null ? void 0 : activeTab.id) === props.id;
|
|
784
|
-
return /*#__PURE__*/_jsx(SegmentedTab, _extends({
|
|
785
|
-
ref: ref,
|
|
786
|
-
label: /*#__PURE__*/_jsx(TextLabel1, {
|
|
787
|
-
style: {
|
|
788
|
-
color: isActive ? assets.btc.color : undefined
|
|
789
|
-
},
|
|
790
|
-
children: label
|
|
710
|
+
yAxis: {
|
|
711
|
+
showGrid: true,
|
|
712
|
+
tickLabelFormatter: numberFormatter
|
|
713
|
+
},
|
|
714
|
+
children: /*#__PURE__*/_jsx(Scrubber, {
|
|
715
|
+
idlePulse: true,
|
|
716
|
+
LineComponent: SolidLine,
|
|
717
|
+
seriesIds: ['pageViews']
|
|
791
718
|
})
|
|
792
|
-
}
|
|
793
|
-
}
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
});
|
|
805
|
-
const AssetPriceDotted = () => {
|
|
806
|
-
const currentPrice = sparklineInteractiveData.hour[sparklineInteractiveData.hour.length - 1].value;
|
|
807
|
-
const tabs = useMemo(() => [{
|
|
808
|
-
id: 'hour',
|
|
809
|
-
label: '1H'
|
|
810
|
-
}, {
|
|
811
|
-
id: 'day',
|
|
812
|
-
label: '1D'
|
|
813
|
-
}, {
|
|
814
|
-
id: 'week',
|
|
815
|
-
label: '1W'
|
|
816
|
-
}, {
|
|
817
|
-
id: 'month',
|
|
818
|
-
label: '1M'
|
|
819
|
-
}, {
|
|
820
|
-
id: 'year',
|
|
821
|
-
label: '1Y'
|
|
822
|
-
}, {
|
|
823
|
-
id: 'all',
|
|
824
|
-
label: 'All'
|
|
825
|
-
}], []);
|
|
826
|
-
const [timePeriod, setTimePeriod] = useState(tabs[0]);
|
|
827
|
-
const sparklineTimePeriodData = useMemo(() => {
|
|
828
|
-
return sparklineInteractiveData[timePeriod.id];
|
|
829
|
-
}, [timePeriod]);
|
|
830
|
-
const sparklineTimePeriodDataValues = useMemo(() => {
|
|
831
|
-
return sparklineTimePeriodData.map(d => d.value);
|
|
832
|
-
}, [sparklineTimePeriodData]);
|
|
833
|
-
const sparklineTimePeriodDataTimestamps = useMemo(() => {
|
|
834
|
-
return sparklineTimePeriodData.map(d => d.date);
|
|
835
|
-
}, [sparklineTimePeriodData]);
|
|
836
|
-
const onPeriodChange = useCallback(period => {
|
|
837
|
-
setTimePeriod(period || tabs[0]);
|
|
838
|
-
}, [tabs, setTimePeriod]);
|
|
719
|
+
});
|
|
720
|
+
}
|
|
721
|
+
function Compact() {
|
|
722
|
+
const theme = useTheme();
|
|
723
|
+
const dimensions = {
|
|
724
|
+
width: 62,
|
|
725
|
+
height: 18
|
|
726
|
+
};
|
|
727
|
+
const sparklineData = prices.map(price => parseFloat(price)).filter((price, index) => index % 10 === 0);
|
|
728
|
+
const positiveFloor = Math.min(...sparklineData) - 10;
|
|
729
|
+
const negativeData = sparklineData.map(price => -1 * price).reverse();
|
|
730
|
+
const negativeCeiling = Math.max(...negativeData) + 10;
|
|
839
731
|
const formatPrice = useCallback(price => {
|
|
840
|
-
return
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
}).format(price);
|
|
844
|
-
}, []);
|
|
845
|
-
const formatDate = useCallback(date => {
|
|
846
|
-
const dayOfWeek = date.toLocaleDateString('en-US', {
|
|
847
|
-
weekday: 'short'
|
|
732
|
+
return "$" + price.toLocaleString('en-US', {
|
|
733
|
+
minimumFractionDigits: 2,
|
|
734
|
+
maximumFractionDigits: 2
|
|
848
735
|
});
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
736
|
+
}, []);
|
|
737
|
+
const CompactChart = /*#__PURE__*/memo(_ref6 => {
|
|
738
|
+
let {
|
|
739
|
+
data,
|
|
740
|
+
showArea,
|
|
741
|
+
color,
|
|
742
|
+
referenceY
|
|
743
|
+
} = _ref6;
|
|
744
|
+
return /*#__PURE__*/_jsx(Box, {
|
|
745
|
+
style: {
|
|
746
|
+
padding: 1
|
|
747
|
+
},
|
|
748
|
+
children: /*#__PURE__*/_jsx(LineChart, _extends({}, dimensions, {
|
|
749
|
+
enableScrubbing: false,
|
|
750
|
+
inset: 0,
|
|
751
|
+
series: [{
|
|
752
|
+
id: 'btc',
|
|
753
|
+
data,
|
|
754
|
+
color
|
|
755
|
+
}],
|
|
756
|
+
showArea: showArea,
|
|
757
|
+
children: /*#__PURE__*/_jsx(ReferenceLine, {
|
|
758
|
+
dataY: referenceY
|
|
759
|
+
})
|
|
760
|
+
}))
|
|
852
761
|
});
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
762
|
+
});
|
|
763
|
+
const ChartCell = /*#__PURE__*/memo(_ref7 => {
|
|
764
|
+
let {
|
|
765
|
+
data,
|
|
766
|
+
showArea,
|
|
767
|
+
color,
|
|
768
|
+
referenceY,
|
|
769
|
+
subdetail
|
|
770
|
+
} = _ref7;
|
|
771
|
+
return /*#__PURE__*/_jsx(ListCell, {
|
|
772
|
+
detail: formatPrice(parseFloat(prices[0])),
|
|
773
|
+
intermediary: /*#__PURE__*/_jsx(CompactChart, {
|
|
774
|
+
color: color,
|
|
775
|
+
data: data,
|
|
776
|
+
referenceY: referenceY,
|
|
777
|
+
showArea: showArea
|
|
778
|
+
}),
|
|
779
|
+
media: /*#__PURE__*/_jsx(Avatar, {
|
|
780
|
+
src: assets.btc.imageUrl
|
|
781
|
+
}),
|
|
782
|
+
onPress: () => console.log('clicked'),
|
|
783
|
+
spacingVariant: "condensed",
|
|
784
|
+
style: {
|
|
785
|
+
padding: 0
|
|
786
|
+
},
|
|
787
|
+
subdetail: subdetail
|
|
857
788
|
});
|
|
858
|
-
|
|
789
|
+
});
|
|
790
|
+
return /*#__PURE__*/_jsxs(VStack, {
|
|
791
|
+
children: [/*#__PURE__*/_jsx(ChartCell, {
|
|
792
|
+
color: assets.btc.color,
|
|
793
|
+
data: sparklineData,
|
|
794
|
+
referenceY: parseFloat(prices[Math.floor(prices.length / 4)]),
|
|
795
|
+
subdetail: "-4.55%"
|
|
796
|
+
}), /*#__PURE__*/_jsx(ChartCell, {
|
|
797
|
+
showArea: true,
|
|
798
|
+
color: assets.btc.color,
|
|
799
|
+
data: sparklineData,
|
|
800
|
+
referenceY: parseFloat(prices[Math.floor(prices.length / 4)]),
|
|
801
|
+
subdetail: "-4.55%"
|
|
802
|
+
}), /*#__PURE__*/_jsx(ChartCell, {
|
|
803
|
+
showArea: true,
|
|
804
|
+
color: theme.color.fgPositive,
|
|
805
|
+
data: sparklineData,
|
|
806
|
+
referenceY: positiveFloor,
|
|
807
|
+
subdetail: "+0.25%"
|
|
808
|
+
}), /*#__PURE__*/_jsx(ChartCell, {
|
|
809
|
+
showArea: true,
|
|
810
|
+
color: theme.color.fgNegative,
|
|
811
|
+
data: negativeData,
|
|
812
|
+
referenceY: negativeCeiling,
|
|
813
|
+
subdetail: "-4.55%"
|
|
814
|
+
})]
|
|
815
|
+
});
|
|
816
|
+
}
|
|
817
|
+
function AssetPriceWithDottedArea() {
|
|
818
|
+
const fontMgr = useMemo(() => {
|
|
819
|
+
const fontProvider = Skia.TypefaceFontProvider.Make();
|
|
820
|
+
// Register system fonts if available, otherwise Skia will use defaults
|
|
821
|
+
return fontProvider;
|
|
859
822
|
}, []);
|
|
860
|
-
const
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
const
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
}
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
})) : lastDate.toLocaleDateString('en-US', _extends({}, dateRangeOptions, {
|
|
889
|
-
year: lastDate.getFullYear() !== currentYear ? 'numeric' : undefined
|
|
823
|
+
const BTCTab = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref8, ref) => {
|
|
824
|
+
let {
|
|
825
|
+
label
|
|
826
|
+
} = _ref8,
|
|
827
|
+
props = _objectWithoutPropertiesLoose(_ref8, _excluded2);
|
|
828
|
+
const {
|
|
829
|
+
activeTab
|
|
830
|
+
} = useTabsContext();
|
|
831
|
+
const isActive = (activeTab == null ? void 0 : activeTab.id) === props.id;
|
|
832
|
+
return /*#__PURE__*/_jsx(SegmentedTab, _extends({
|
|
833
|
+
ref: ref,
|
|
834
|
+
label: /*#__PURE__*/_jsx(TextLabel1, {
|
|
835
|
+
style: {
|
|
836
|
+
color: isActive ? assets.btc.color : undefined
|
|
837
|
+
},
|
|
838
|
+
children: label
|
|
839
|
+
})
|
|
840
|
+
}, props));
|
|
841
|
+
}));
|
|
842
|
+
const BTCActiveIndicator = /*#__PURE__*/memo(_ref9 => {
|
|
843
|
+
let {
|
|
844
|
+
style
|
|
845
|
+
} = _ref9,
|
|
846
|
+
props = _objectWithoutPropertiesLoose(_ref9, _excluded3);
|
|
847
|
+
return /*#__PURE__*/_jsx(PeriodSelectorActiveIndicator, _extends({}, props, {
|
|
848
|
+
style: [style, {
|
|
849
|
+
backgroundColor: assets.btc.color + "1A"
|
|
850
|
+
}]
|
|
890
851
|
}));
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
852
|
+
});
|
|
853
|
+
const AssetPriceDotted = /*#__PURE__*/memo(() => {
|
|
854
|
+
const theme = useTheme();
|
|
855
|
+
const currentPrice = sparklineInteractiveData.hour[sparklineInteractiveData.hour.length - 1].value;
|
|
856
|
+
const tabs = useMemo(() => [{
|
|
857
|
+
id: 'hour',
|
|
858
|
+
label: '1H'
|
|
859
|
+
}, {
|
|
860
|
+
id: 'day',
|
|
861
|
+
label: '1D'
|
|
862
|
+
}, {
|
|
863
|
+
id: 'week',
|
|
864
|
+
label: '1W'
|
|
865
|
+
}, {
|
|
866
|
+
id: 'month',
|
|
867
|
+
label: '1M'
|
|
868
|
+
}, {
|
|
869
|
+
id: 'year',
|
|
870
|
+
label: '1Y'
|
|
871
|
+
}, {
|
|
872
|
+
id: 'all',
|
|
873
|
+
label: 'All'
|
|
874
|
+
}], []);
|
|
875
|
+
const [timePeriod, setTimePeriod] = useState(tabs[0]);
|
|
876
|
+
const sparklineTimePeriodData = useMemo(() => {
|
|
877
|
+
return sparklineInteractiveData[timePeriod.id];
|
|
878
|
+
}, [timePeriod]);
|
|
879
|
+
const sparklineTimePeriodDataValues = useMemo(() => {
|
|
880
|
+
return sparklineTimePeriodData.map(d => d.value);
|
|
881
|
+
}, [sparklineTimePeriodData]);
|
|
882
|
+
const sparklineTimePeriodDataTimestamps = useMemo(() => {
|
|
883
|
+
return sparklineTimePeriodData.map(d => d.date);
|
|
884
|
+
}, [sparklineTimePeriodData]);
|
|
885
|
+
const onPeriodChange = useCallback(period => {
|
|
886
|
+
setTimePeriod(period || tabs[0]);
|
|
887
|
+
}, [tabs, setTimePeriod]);
|
|
888
|
+
const priceFormatter = useMemo(() => new Intl.NumberFormat('en-US', {
|
|
889
|
+
style: 'currency',
|
|
890
|
+
currency: 'USD'
|
|
891
|
+
}), []);
|
|
892
|
+
const formatPrice = useCallback(price => {
|
|
893
|
+
return priceFormatter.format(price);
|
|
894
|
+
}, [priceFormatter]);
|
|
895
|
+
const formatDate = useCallback(date => {
|
|
896
|
+
const dayOfWeek = date.toLocaleDateString('en-US', {
|
|
897
|
+
weekday: 'short'
|
|
898
|
+
});
|
|
899
|
+
const monthDay = date.toLocaleDateString('en-US', {
|
|
900
|
+
month: 'short',
|
|
901
|
+
day: 'numeric'
|
|
902
|
+
});
|
|
903
|
+
const time = date.toLocaleTimeString('en-US', {
|
|
904
|
+
hour: 'numeric',
|
|
905
|
+
minute: '2-digit',
|
|
906
|
+
hour12: true
|
|
907
|
+
});
|
|
908
|
+
return dayOfWeek + ", " + monthDay + ", " + time;
|
|
909
|
+
}, []);
|
|
910
|
+
return /*#__PURE__*/_jsxs(VStack, {
|
|
897
911
|
gap: 2,
|
|
898
912
|
children: [/*#__PURE__*/_jsx(SectionHeader, {
|
|
899
|
-
|
|
900
|
-
balance: /*#__PURE__*/_jsxs(Text, {
|
|
913
|
+
balance: /*#__PURE__*/_jsx(Text, {
|
|
901
914
|
font: "title2",
|
|
902
|
-
children:
|
|
915
|
+
children: formatPrice(currentPrice)
|
|
903
916
|
}),
|
|
904
917
|
end: /*#__PURE__*/_jsx(VStack, {
|
|
905
918
|
justifyContent: "center",
|
|
@@ -909,7 +922,6 @@ const AssetPriceDotted = () => {
|
|
|
909
922
|
source: assets.btc.imageUrl
|
|
910
923
|
})
|
|
911
924
|
}),
|
|
912
|
-
padding: 0,
|
|
913
925
|
title: /*#__PURE__*/_jsx(Text, {
|
|
914
926
|
font: "title1",
|
|
915
927
|
children: "Bitcoin"
|
|
@@ -917,9 +929,11 @@ const AssetPriceDotted = () => {
|
|
|
917
929
|
}), /*#__PURE__*/_jsx(LineChart, {
|
|
918
930
|
enableScrubbing: true,
|
|
919
931
|
showArea: true,
|
|
920
|
-
accessibilityLiveRegion: "polite",
|
|
921
932
|
areaType: "dotted",
|
|
922
|
-
height:
|
|
933
|
+
height: 200,
|
|
934
|
+
inset: {
|
|
935
|
+
top: 52
|
|
936
|
+
},
|
|
923
937
|
series: [{
|
|
924
938
|
id: 'btc',
|
|
925
939
|
data: sparklineTimePeriodDataValues,
|
|
@@ -927,42 +941,123 @@ const AssetPriceDotted = () => {
|
|
|
927
941
|
}],
|
|
928
942
|
children: /*#__PURE__*/_jsx(Scrubber, {
|
|
929
943
|
idlePulse: true,
|
|
930
|
-
|
|
944
|
+
labelElevated: true,
|
|
945
|
+
label: d => {
|
|
946
|
+
const date = formatDate(sparklineTimePeriodDataTimestamps[d]);
|
|
947
|
+
const price = formatPrice(sparklineTimePeriodDataValues[d]);
|
|
948
|
+
const regularStyle = {
|
|
949
|
+
fontFamilies: ['Inter'],
|
|
950
|
+
fontSize: 14,
|
|
951
|
+
fontStyle: {
|
|
952
|
+
weight: FontWeight.Normal
|
|
953
|
+
},
|
|
954
|
+
color: Skia.Color(theme.color.fgMuted)
|
|
955
|
+
};
|
|
956
|
+
const boldStyle = _extends({
|
|
957
|
+
fontFamilies: ['Inter']
|
|
958
|
+
}, regularStyle, {
|
|
959
|
+
fontStyle: {
|
|
960
|
+
weight: FontWeight.Bold
|
|
961
|
+
}
|
|
962
|
+
});
|
|
963
|
+
|
|
964
|
+
// 3. Use the ParagraphBuilder
|
|
965
|
+
const builder = Skia.ParagraphBuilder.Make({
|
|
966
|
+
textAlign: TextAlign.Left
|
|
967
|
+
}, fontMgr);
|
|
968
|
+
builder.pushStyle(boldStyle);
|
|
969
|
+
builder.addText(price);
|
|
970
|
+
builder.pushStyle(regularStyle);
|
|
971
|
+
builder.addText(" " + date);
|
|
972
|
+
const para = builder.build();
|
|
973
|
+
para.layout(512);
|
|
974
|
+
return para;
|
|
975
|
+
}
|
|
931
976
|
})
|
|
932
977
|
}), /*#__PURE__*/_jsx(PeriodSelector, {
|
|
933
978
|
TabComponent: BTCTab,
|
|
934
979
|
TabsActiveIndicatorComponent: BTCActiveIndicator,
|
|
935
|
-
accessibilityLabel: "Select time period for chart",
|
|
936
980
|
activeTab: timePeriod,
|
|
937
981
|
onChange: onPeriodChange,
|
|
938
982
|
tabs: tabs
|
|
939
983
|
})]
|
|
940
|
-
})
|
|
984
|
+
});
|
|
941
985
|
});
|
|
942
|
-
};
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
},
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
label
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
986
|
+
return /*#__PURE__*/_jsx(AssetPriceDotted, {});
|
|
987
|
+
}
|
|
988
|
+
const LegendDot = /*#__PURE__*/memo(props => {
|
|
989
|
+
return /*#__PURE__*/_jsx(Box, _extends({
|
|
990
|
+
borderRadius: 1000,
|
|
991
|
+
height: 10,
|
|
992
|
+
width: 10
|
|
993
|
+
}, props));
|
|
994
|
+
});
|
|
995
|
+
const LegendItem = /*#__PURE__*/memo(_ref0 => {
|
|
996
|
+
let {
|
|
997
|
+
color = assets.btc.color,
|
|
998
|
+
label,
|
|
999
|
+
value
|
|
1000
|
+
} = _ref0;
|
|
1001
|
+
return /*#__PURE__*/_jsxs(Box, {
|
|
1002
|
+
alignItems: "center",
|
|
1003
|
+
flexDirection: "row",
|
|
1004
|
+
gap: 0.5,
|
|
1005
|
+
children: [/*#__PURE__*/_jsx(LegendDot, {
|
|
1006
|
+
style: {
|
|
1007
|
+
backgroundColor: color
|
|
1008
|
+
}
|
|
1009
|
+
}), /*#__PURE__*/_jsx(Text, {
|
|
1010
|
+
font: "label2",
|
|
1011
|
+
children: label
|
|
1012
|
+
}), value && /*#__PURE__*/_jsx(Text, {
|
|
1013
|
+
color: "fgMuted",
|
|
1014
|
+
font: "label2",
|
|
1015
|
+
style: {
|
|
1016
|
+
fontWeight: 'bold'
|
|
1017
|
+
},
|
|
1018
|
+
children: value
|
|
1019
|
+
})]
|
|
1020
|
+
});
|
|
1021
|
+
});
|
|
1022
|
+
const PerformanceHeader = /*#__PURE__*/memo(_ref1 => {
|
|
1023
|
+
let {
|
|
1024
|
+
scrubberPosition,
|
|
1025
|
+
sparklineTimePeriodDataValues
|
|
1026
|
+
} = _ref1;
|
|
1027
|
+
const theme = useTheme();
|
|
1028
|
+
const formatPriceThousands = useCallback(price => {
|
|
1029
|
+
return new Intl.NumberFormat('en-US', {
|
|
1030
|
+
style: 'currency',
|
|
1031
|
+
currency: 'USD',
|
|
1032
|
+
minimumFractionDigits: 0,
|
|
1033
|
+
maximumFractionDigits: 0
|
|
1034
|
+
}).format(price / 1000) + "k";
|
|
1035
|
+
}, []);
|
|
1036
|
+
const shownPosition = scrubberPosition !== undefined ? scrubberPosition : sparklineTimePeriodDataValues.length - 1;
|
|
1037
|
+
return /*#__PURE__*/_jsxs(HStack, {
|
|
1038
|
+
gap: 1,
|
|
1039
|
+
paddingX: 1,
|
|
1040
|
+
children: [/*#__PURE__*/_jsx(LegendItem, {
|
|
1041
|
+
color: theme.color.fgPositive,
|
|
1042
|
+
label: "High Price",
|
|
1043
|
+
value: formatPriceThousands(sparklineTimePeriodDataValues[shownPosition] * 1.2)
|
|
1044
|
+
}), /*#__PURE__*/_jsx(LegendItem, {
|
|
1045
|
+
color: assets.btc.color,
|
|
1046
|
+
label: "Actual Price",
|
|
1047
|
+
value: formatPriceThousands(sparklineTimePeriodDataValues[shownPosition])
|
|
1048
|
+
}), /*#__PURE__*/_jsx(LegendItem, {
|
|
1049
|
+
color: theme.color.fgNegative,
|
|
1050
|
+
label: "Low Price",
|
|
1051
|
+
value: formatPriceThousands(sparklineTimePeriodDataValues[shownPosition] * 0.8)
|
|
1052
|
+
})]
|
|
1053
|
+
});
|
|
1054
|
+
});
|
|
1055
|
+
const PerformanceChart = /*#__PURE__*/memo(_ref10 => {
|
|
1056
|
+
let {
|
|
1057
|
+
timePeriod,
|
|
1058
|
+
onScrubberPositionChange
|
|
1059
|
+
} = _ref10;
|
|
1060
|
+
const theme = useTheme();
|
|
966
1061
|
const sparklineTimePeriodData = useMemo(() => {
|
|
967
1062
|
return sparklineInteractiveData[timePeriod.id];
|
|
968
1063
|
}, [timePeriod]);
|
|
@@ -972,14 +1067,13 @@ const AssetPriceDottedNonMemoized = () => {
|
|
|
972
1067
|
const sparklineTimePeriodDataTimestamps = useMemo(() => {
|
|
973
1068
|
return sparklineTimePeriodData.map(d => d.date);
|
|
974
1069
|
}, [sparklineTimePeriodData]);
|
|
975
|
-
const
|
|
976
|
-
setTimePeriod(period || tabs[0]);
|
|
977
|
-
}, [tabs, setTimePeriod]);
|
|
978
|
-
const formatPrice = useCallback(price => {
|
|
1070
|
+
const formatPriceThousands = useCallback(price => {
|
|
979
1071
|
return new Intl.NumberFormat('en-US', {
|
|
980
1072
|
style: 'currency',
|
|
981
|
-
currency: 'USD'
|
|
982
|
-
|
|
1073
|
+
currency: 'USD',
|
|
1074
|
+
minimumFractionDigits: 0,
|
|
1075
|
+
maximumFractionDigits: 0
|
|
1076
|
+
}).format(price / 1000) + "k";
|
|
983
1077
|
}, []);
|
|
984
1078
|
const formatDate = useCallback(date => {
|
|
985
1079
|
const dayOfWeek = date.toLocaleDateString('en-US', {
|
|
@@ -996,61 +1090,46 @@ const AssetPriceDottedNonMemoized = () => {
|
|
|
996
1090
|
});
|
|
997
1091
|
return dayOfWeek + ", " + monthDay + ", " + time;
|
|
998
1092
|
}, []);
|
|
999
|
-
const
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
data: sparklineTimePeriodDataValues,
|
|
1037
|
-
color: assets.btc.color
|
|
1038
|
-
}],
|
|
1039
|
-
children: /*#__PURE__*/_jsx(Scrubber, {
|
|
1040
|
-
label: scrubberLabel
|
|
1041
|
-
})
|
|
1042
|
-
}), /*#__PURE__*/_jsx(PeriodSelector, {
|
|
1043
|
-
TabComponent: BTCTab,
|
|
1044
|
-
TabsActiveIndicatorComponent: BTCActiveIndicator,
|
|
1045
|
-
activeTab: timePeriod,
|
|
1046
|
-
onChange: onPeriodChange,
|
|
1047
|
-
tabs: tabs
|
|
1048
|
-
})]
|
|
1093
|
+
const getScrubberLabel = useCallback(d => formatDate(sparklineTimePeriodDataTimestamps[d]), [formatDate, sparklineTimePeriodDataTimestamps]);
|
|
1094
|
+
return /*#__PURE__*/_jsx(LineChart, {
|
|
1095
|
+
enableScrubbing: true,
|
|
1096
|
+
showArea: true,
|
|
1097
|
+
showYAxis: true,
|
|
1098
|
+
areaType: "dotted",
|
|
1099
|
+
height: 300,
|
|
1100
|
+
inset: {
|
|
1101
|
+
top: 52,
|
|
1102
|
+
left: 0,
|
|
1103
|
+
right: 0
|
|
1104
|
+
},
|
|
1105
|
+
onScrubberPositionChange: onScrubberPositionChange,
|
|
1106
|
+
series: [{
|
|
1107
|
+
id: 'high',
|
|
1108
|
+
data: sparklineTimePeriodDataValues.map(d => d * 1.2),
|
|
1109
|
+
color: theme.color.fgPositive,
|
|
1110
|
+
label: 'High Price'
|
|
1111
|
+
}, {
|
|
1112
|
+
id: 'btc',
|
|
1113
|
+
data: sparklineTimePeriodDataValues,
|
|
1114
|
+
color: assets.btc.color,
|
|
1115
|
+
label: 'Actual Price'
|
|
1116
|
+
}, {
|
|
1117
|
+
id: 'low',
|
|
1118
|
+
data: sparklineTimePeriodDataValues.map(d => d * 0.8),
|
|
1119
|
+
color: theme.color.fgNegative,
|
|
1120
|
+
label: 'Low Price'
|
|
1121
|
+
}],
|
|
1122
|
+
yAxis: {
|
|
1123
|
+
showGrid: true,
|
|
1124
|
+
tickLabelFormatter: formatPriceThousands
|
|
1125
|
+
},
|
|
1126
|
+
children: /*#__PURE__*/_jsx(Scrubber, {
|
|
1127
|
+
idlePulse: true,
|
|
1128
|
+
label: getScrubberLabel
|
|
1129
|
+
})
|
|
1049
1130
|
});
|
|
1050
|
-
};
|
|
1051
|
-
|
|
1052
|
-
const [scrubIndex, setScrubIndex] = useState(undefined);
|
|
1053
|
-
const currentPrice = sparklineInteractiveData.hour[sparklineInteractiveData.hour.length - 1].value;
|
|
1131
|
+
});
|
|
1132
|
+
function Performance() {
|
|
1054
1133
|
const tabs = useMemo(() => [{
|
|
1055
1134
|
id: 'hour',
|
|
1056
1135
|
label: '1H'
|
|
@@ -1071,288 +1150,662 @@ const AssetPriceMultipleDotted = () => {
|
|
|
1071
1150
|
label: 'All'
|
|
1072
1151
|
}], []);
|
|
1073
1152
|
const [timePeriod, setTimePeriod] = useState(tabs[0]);
|
|
1153
|
+
const [scrubberPosition, setScrubberPosition] = useState();
|
|
1074
1154
|
const sparklineTimePeriodData = useMemo(() => {
|
|
1075
1155
|
return sparklineInteractiveData[timePeriod.id];
|
|
1076
1156
|
}, [timePeriod]);
|
|
1077
1157
|
const sparklineTimePeriodDataValues = useMemo(() => {
|
|
1078
1158
|
return sparklineTimePeriodData.map(d => d.value);
|
|
1079
1159
|
}, [sparklineTimePeriodData]);
|
|
1080
|
-
const sparklineTimePeriodDataTimestamps = useMemo(() => {
|
|
1081
|
-
return sparklineTimePeriodData.map(d => d.date);
|
|
1082
|
-
}, [sparklineTimePeriodData]);
|
|
1083
1160
|
const onPeriodChange = useCallback(period => {
|
|
1084
1161
|
setTimePeriod(period || tabs[0]);
|
|
1085
|
-
}, [tabs
|
|
1086
|
-
const formatPrice = useCallback(price => {
|
|
1087
|
-
return new Intl.NumberFormat('en-US', {
|
|
1088
|
-
style: 'currency',
|
|
1089
|
-
currency: 'USD'
|
|
1090
|
-
}).format(price);
|
|
1091
|
-
}, []);
|
|
1092
|
-
const formatDate = useCallback(date => {
|
|
1093
|
-
const dayOfWeek = date.toLocaleDateString('en-US', {
|
|
1094
|
-
weekday: 'short'
|
|
1095
|
-
});
|
|
1096
|
-
const monthDay = date.toLocaleDateString('en-US', {
|
|
1097
|
-
month: 'short',
|
|
1098
|
-
day: 'numeric'
|
|
1099
|
-
});
|
|
1100
|
-
const time = date.toLocaleTimeString('en-US', {
|
|
1101
|
-
hour: 'numeric',
|
|
1102
|
-
minute: '2-digit',
|
|
1103
|
-
hour12: true
|
|
1104
|
-
});
|
|
1105
|
-
return dayOfWeek + ", " + monthDay + ", " + time;
|
|
1106
|
-
}, []);
|
|
1107
|
-
const scrubberLabel = useMemo(() => {
|
|
1108
|
-
if (scrubIndex === undefined) return null;
|
|
1109
|
-
const price = new Intl.NumberFormat('en-US', {
|
|
1110
|
-
minimumFractionDigits: 2,
|
|
1111
|
-
maximumFractionDigits: 2
|
|
1112
|
-
}).format(sparklineTimePeriodDataValues[scrubIndex]);
|
|
1113
|
-
const date = formatDate(sparklineTimePeriodDataTimestamps[scrubIndex]);
|
|
1114
|
-
return price + " USD " + date;
|
|
1115
|
-
}, [scrubIndex, sparklineTimePeriodDataValues, formatDate, sparklineTimePeriodDataTimestamps]);
|
|
1162
|
+
}, [tabs]);
|
|
1116
1163
|
return /*#__PURE__*/_jsxs(VStack, {
|
|
1117
1164
|
gap: 2,
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
source: assets.btc.imageUrl
|
|
1129
|
-
})
|
|
1130
|
-
}),
|
|
1131
|
-
padding: 0,
|
|
1132
|
-
title: /*#__PURE__*/_jsx(Text, {
|
|
1133
|
-
font: "title1",
|
|
1134
|
-
children: "Bitcoin"
|
|
1135
|
-
})
|
|
1136
|
-
}), /*#__PURE__*/_jsx(LineChart, {
|
|
1137
|
-
enableScrubbing: true,
|
|
1138
|
-
height: defaultChartHeight,
|
|
1139
|
-
series: [{
|
|
1140
|
-
id: 'btc',
|
|
1141
|
-
data: sparklineTimePeriodDataValues,
|
|
1142
|
-
color: assets.btc.color
|
|
1143
|
-
}, {
|
|
1144
|
-
id: 'eth',
|
|
1145
|
-
data: sparklineTimePeriodDataValues.map(d => d * 0.75),
|
|
1146
|
-
color: assets.eth.color
|
|
1147
|
-
}, {
|
|
1148
|
-
id: 'xrp',
|
|
1149
|
-
data: sparklineTimePeriodDataValues.map(d => d * 0.5),
|
|
1150
|
-
color: assets.xrp.color
|
|
1151
|
-
}],
|
|
1152
|
-
children: /*#__PURE__*/_jsx(Scrubber, {})
|
|
1165
|
+
style: {
|
|
1166
|
+
marginLeft: -8,
|
|
1167
|
+
marginRight: -8
|
|
1168
|
+
},
|
|
1169
|
+
children: [/*#__PURE__*/_jsx(PerformanceHeader, {
|
|
1170
|
+
scrubberPosition: scrubberPosition,
|
|
1171
|
+
sparklineTimePeriodDataValues: sparklineTimePeriodDataValues
|
|
1172
|
+
}), /*#__PURE__*/_jsx(PerformanceChart, {
|
|
1173
|
+
onScrubberPositionChange: setScrubberPosition,
|
|
1174
|
+
timePeriod: timePeriod
|
|
1153
1175
|
}), /*#__PURE__*/_jsx(PeriodSelector, {
|
|
1154
|
-
TabComponent: BTCTab,
|
|
1155
|
-
TabsActiveIndicatorComponent: BTCActiveIndicator,
|
|
1156
1176
|
activeTab: timePeriod,
|
|
1157
1177
|
onChange: onPeriodChange,
|
|
1158
1178
|
tabs: tabs
|
|
1159
1179
|
})]
|
|
1160
1180
|
});
|
|
1161
|
-
}
|
|
1162
|
-
const
|
|
1181
|
+
}
|
|
1182
|
+
const candlestickStockData = btcCandles.slice(0, 90).reverse();
|
|
1183
|
+
const CandlesticksHeader = /*#__PURE__*/memo(_ref11 => {
|
|
1184
|
+
let {
|
|
1185
|
+
currentIndex
|
|
1186
|
+
} = _ref11;
|
|
1187
|
+
const formatPrice = useCallback(price => {
|
|
1188
|
+
return new Intl.NumberFormat('en-US', {
|
|
1189
|
+
style: 'currency',
|
|
1190
|
+
currency: 'USD'
|
|
1191
|
+
}).format(parseFloat(price));
|
|
1192
|
+
}, []);
|
|
1193
|
+
const formatThousandsPriceNumber = useCallback(price => {
|
|
1194
|
+
const formattedPrice = new Intl.NumberFormat('en-US', {
|
|
1195
|
+
style: 'currency',
|
|
1196
|
+
currency: 'USD',
|
|
1197
|
+
minimumFractionDigits: 0,
|
|
1198
|
+
maximumFractionDigits: 0
|
|
1199
|
+
}).format(price / 1000);
|
|
1200
|
+
return formattedPrice + "k";
|
|
1201
|
+
}, []);
|
|
1202
|
+
const currentText = useMemo(() => {
|
|
1203
|
+
if (currentIndex !== undefined) {
|
|
1204
|
+
return "Open: " + formatThousandsPriceNumber(parseFloat(candlestickStockData[currentIndex].open)) + ", Close: " + formatThousandsPriceNumber(parseFloat(candlestickStockData[currentIndex].close)) + ", Volume: " + (parseFloat(candlestickStockData[currentIndex].volume) / 1000).toFixed(2) + "k";
|
|
1205
|
+
}
|
|
1206
|
+
return formatPrice(candlestickStockData[candlestickStockData.length - 1].close);
|
|
1207
|
+
}, [currentIndex, formatThousandsPriceNumber, formatPrice]);
|
|
1208
|
+
return /*#__PURE__*/_jsx(Text, {
|
|
1209
|
+
"aria-live": "polite",
|
|
1210
|
+
font: "headline",
|
|
1211
|
+
children: currentText
|
|
1212
|
+
});
|
|
1213
|
+
});
|
|
1214
|
+
const CandlesticksChart = /*#__PURE__*/memo(_ref12 => {
|
|
1215
|
+
let {
|
|
1216
|
+
infoTextId,
|
|
1217
|
+
onScrubberPositionChange
|
|
1218
|
+
} = _ref12;
|
|
1163
1219
|
const theme = useTheme();
|
|
1164
|
-
const
|
|
1165
|
-
const
|
|
1166
|
-
|
|
1220
|
+
const min = useMemo(() => Math.min(...candlestickStockData.map(data => parseFloat(data.low))), []);
|
|
1221
|
+
const ThinSolidLine = /*#__PURE__*/memo(props => /*#__PURE__*/_jsx(SolidLine, _extends({}, props, {
|
|
1222
|
+
strokeWidth: 1
|
|
1223
|
+
})));
|
|
1224
|
+
|
|
1225
|
+
// Custom line component that renders a rect to highlight the entire bandwidth
|
|
1226
|
+
const BandwidthHighlight = /*#__PURE__*/memo(_ref13 => {
|
|
1227
|
+
let {
|
|
1228
|
+
stroke
|
|
1229
|
+
} = _ref13;
|
|
1230
|
+
const {
|
|
1231
|
+
getXSerializableScale,
|
|
1232
|
+
drawingArea
|
|
1233
|
+
} = useCartesianChartContext();
|
|
1234
|
+
const {
|
|
1235
|
+
scrubberPosition
|
|
1236
|
+
} = useScrubberContext();
|
|
1237
|
+
const xScale = useMemo(() => getXSerializableScale(), [getXSerializableScale]);
|
|
1238
|
+
const rectWidth = useMemo(() => {
|
|
1239
|
+
if (xScale !== undefined && xScale.type === 'band') {
|
|
1240
|
+
return xScale.bandwidth;
|
|
1241
|
+
}
|
|
1242
|
+
return 0;
|
|
1243
|
+
}, [xScale]);
|
|
1244
|
+
const xPos = useDerivedValue(() => {
|
|
1245
|
+
const position = unwrapAnimatedValue(scrubberPosition);
|
|
1246
|
+
const xPos = position !== undefined && xScale ? getPointOnSerializableScale(position, xScale) : undefined;
|
|
1247
|
+
return xPos !== undefined ? xPos - rectWidth / 2 : 0;
|
|
1248
|
+
}, [scrubberPosition, xScale]);
|
|
1249
|
+
const opacity = useDerivedValue(() => xPos.value !== undefined ? 1 : 0, [xPos]);
|
|
1250
|
+
return /*#__PURE__*/_jsx(Rect, {
|
|
1251
|
+
color: stroke,
|
|
1252
|
+
height: drawingArea.height,
|
|
1253
|
+
opacity: opacity,
|
|
1254
|
+
width: rectWidth,
|
|
1255
|
+
x: xPos,
|
|
1256
|
+
y: drawingArea.y
|
|
1257
|
+
});
|
|
1258
|
+
});
|
|
1259
|
+
const candlesData = useMemo(() => candlestickStockData.map(data => [parseFloat(data.low), parseFloat(data.high)]), []);
|
|
1260
|
+
const CandlestickBarComponent = /*#__PURE__*/memo(_ref14 => {
|
|
1261
|
+
var _yScale, _yScale2;
|
|
1167
1262
|
let {
|
|
1168
|
-
|
|
1169
|
-
|
|
1263
|
+
x,
|
|
1264
|
+
y,
|
|
1265
|
+
width,
|
|
1266
|
+
height,
|
|
1267
|
+
dataX
|
|
1268
|
+
} = _ref14,
|
|
1269
|
+
props = _objectWithoutPropertiesLoose(_ref14, _excluded4);
|
|
1170
1270
|
const {
|
|
1171
1271
|
getYScale
|
|
1172
1272
|
} = useCartesianChartContext();
|
|
1173
|
-
// get the default y-axis scale
|
|
1174
1273
|
const yScale = getYScale();
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
stopOpacity: 0.3
|
|
1225
|
-
})]
|
|
1226
|
-
})]
|
|
1227
|
-
});
|
|
1228
|
-
}
|
|
1229
|
-
return null;
|
|
1230
|
-
};
|
|
1231
|
-
const tickLabelFormatter = useCallback(value => new Intl.NumberFormat('en-US', {
|
|
1232
|
-
style: 'currency',
|
|
1233
|
-
currency: 'USD',
|
|
1234
|
-
maximumFractionDigits: 0
|
|
1235
|
-
}).format(value), []);
|
|
1236
|
-
const solidColor = "url(#" + gradientId + "-solid)";
|
|
1274
|
+
const wickX = x + width / 2;
|
|
1275
|
+
const timePeriodValue = candlestickStockData[dataX];
|
|
1276
|
+
const open = parseFloat(timePeriodValue.open);
|
|
1277
|
+
const close = parseFloat(timePeriodValue.close);
|
|
1278
|
+
const bullish = open < close;
|
|
1279
|
+
const theme = useTheme();
|
|
1280
|
+
const color = bullish ? theme.color.fgPositive : theme.color.fgNegative;
|
|
1281
|
+
const openY = (_yScale = yScale == null ? void 0 : yScale(open)) != null ? _yScale : 0;
|
|
1282
|
+
const closeY = (_yScale2 = yScale == null ? void 0 : yScale(close)) != null ? _yScale2 : 0;
|
|
1283
|
+
const bodyHeight = Math.abs(openY - closeY);
|
|
1284
|
+
const bodyY = openY < closeY ? openY : closeY;
|
|
1285
|
+
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
1286
|
+
children: [/*#__PURE__*/_jsx(SkiaLine, {
|
|
1287
|
+
color: color,
|
|
1288
|
+
p1: {
|
|
1289
|
+
x: wickX,
|
|
1290
|
+
y
|
|
1291
|
+
},
|
|
1292
|
+
p2: {
|
|
1293
|
+
x: wickX,
|
|
1294
|
+
y: y + height
|
|
1295
|
+
},
|
|
1296
|
+
strokeWidth: 1
|
|
1297
|
+
}), /*#__PURE__*/_jsx(Rect, {
|
|
1298
|
+
color: color,
|
|
1299
|
+
height: bodyHeight,
|
|
1300
|
+
width: width,
|
|
1301
|
+
x: x,
|
|
1302
|
+
y: bodyY
|
|
1303
|
+
})]
|
|
1304
|
+
});
|
|
1305
|
+
});
|
|
1306
|
+
const formatThousandsPriceNumber = useCallback(price => {
|
|
1307
|
+
const formattedPrice = new Intl.NumberFormat('en-US', {
|
|
1308
|
+
style: 'currency',
|
|
1309
|
+
currency: 'USD',
|
|
1310
|
+
minimumFractionDigits: 0,
|
|
1311
|
+
maximumFractionDigits: 0
|
|
1312
|
+
}).format(price / 1000);
|
|
1313
|
+
return formattedPrice + "k";
|
|
1314
|
+
}, []);
|
|
1315
|
+
const formatTime = useCallback(index => {
|
|
1316
|
+
if (index === null || index === undefined || index >= candlestickStockData.length) return '';
|
|
1317
|
+
const ts = parseInt(candlestickStockData[index].start);
|
|
1318
|
+
return new Date(ts * 1000).toLocaleDateString('en-US', {
|
|
1319
|
+
month: 'short',
|
|
1320
|
+
day: 'numeric'
|
|
1321
|
+
});
|
|
1322
|
+
}, []);
|
|
1237
1323
|
return /*#__PURE__*/_jsxs(CartesianChart, {
|
|
1238
1324
|
enableScrubbing: true,
|
|
1239
|
-
|
|
1325
|
+
animate: false,
|
|
1326
|
+
"aria-labelledby": infoTextId,
|
|
1327
|
+
borderRadius: 0,
|
|
1328
|
+
height: 150,
|
|
1240
1329
|
inset: {
|
|
1241
|
-
top:
|
|
1242
|
-
bottom:
|
|
1330
|
+
top: 8,
|
|
1331
|
+
bottom: 8,
|
|
1243
1332
|
left: 0,
|
|
1244
1333
|
right: 0
|
|
1245
1334
|
},
|
|
1335
|
+
onScrubberPositionChange: onScrubberPositionChange,
|
|
1246
1336
|
series: [{
|
|
1247
|
-
id: 'prices',
|
|
1248
|
-
data:
|
|
1249
|
-
color: solidColor
|
|
1337
|
+
id: 'stock-prices',
|
|
1338
|
+
data: candlesData
|
|
1250
1339
|
}],
|
|
1251
|
-
|
|
1340
|
+
xAxis: {
|
|
1341
|
+
scaleType: 'band'
|
|
1342
|
+
},
|
|
1343
|
+
yAxis: {
|
|
1344
|
+
domain: {
|
|
1345
|
+
min
|
|
1346
|
+
}
|
|
1347
|
+
},
|
|
1348
|
+
children: [/*#__PURE__*/_jsx(XAxis, {
|
|
1349
|
+
tickLabelFormatter: formatTime
|
|
1350
|
+
}), /*#__PURE__*/_jsx(YAxis, {
|
|
1252
1351
|
showGrid: true,
|
|
1253
|
-
|
|
1254
|
-
tickLabelFormatter:
|
|
1255
|
-
|
|
1256
|
-
curve: "monotone",
|
|
1257
|
-
fill: "url(#" + gradientId + "-gradient)",
|
|
1258
|
-
seriesId: "prices"
|
|
1259
|
-
}), /*#__PURE__*/_jsx(Line, {
|
|
1260
|
-
curve: "monotone",
|
|
1261
|
-
seriesId: "prices",
|
|
1262
|
-
stroke: solidColor,
|
|
1263
|
-
strokeWidth: 3
|
|
1352
|
+
GridLineComponent: ThinSolidLine,
|
|
1353
|
+
tickLabelFormatter: formatThousandsPriceNumber,
|
|
1354
|
+
width: 40
|
|
1264
1355
|
}), /*#__PURE__*/_jsx(Scrubber, {
|
|
1265
|
-
hideOverlay: true
|
|
1356
|
+
hideOverlay: true,
|
|
1357
|
+
LineComponent: BandwidthHighlight,
|
|
1358
|
+
lineStroke: theme.color.fgMuted,
|
|
1359
|
+
seriesIds: []
|
|
1360
|
+
}), /*#__PURE__*/_jsx(BarPlot, {
|
|
1361
|
+
BarComponent: CandlestickBarComponent,
|
|
1362
|
+
BarStackComponent: _ref15 => {
|
|
1363
|
+
let {
|
|
1364
|
+
children
|
|
1365
|
+
} = _ref15;
|
|
1366
|
+
return /*#__PURE__*/_jsx("g", {
|
|
1367
|
+
children: children
|
|
1368
|
+
});
|
|
1369
|
+
}
|
|
1370
|
+
})]
|
|
1371
|
+
});
|
|
1372
|
+
});
|
|
1373
|
+
function Candlesticks() {
|
|
1374
|
+
const infoTextId = useId();
|
|
1375
|
+
const [currentIndex, setCurrentIndex] = useState();
|
|
1376
|
+
return /*#__PURE__*/_jsxs(VStack, {
|
|
1377
|
+
gap: 2,
|
|
1378
|
+
children: [/*#__PURE__*/_jsx(CandlesticksHeader, {
|
|
1379
|
+
currentIndex: currentIndex
|
|
1380
|
+
}), /*#__PURE__*/_jsx(CandlesticksChart, {
|
|
1381
|
+
infoTextId: infoTextId,
|
|
1382
|
+
onScrubberPositionChange: setCurrentIndex
|
|
1266
1383
|
})]
|
|
1267
1384
|
});
|
|
1268
|
-
}
|
|
1269
|
-
|
|
1385
|
+
}
|
|
1386
|
+
function MonotoneAssetPrice() {
|
|
1270
1387
|
const theme = useTheme();
|
|
1271
|
-
const prices =
|
|
1272
|
-
const
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1388
|
+
const prices = sparklineInteractiveData.hour;
|
|
1389
|
+
const fontMgr = useMemo(() => {
|
|
1390
|
+
const fontProvider = Skia.TypefaceFontProvider.Make();
|
|
1391
|
+
// Register system fonts if available, otherwise Skia will use defaults
|
|
1392
|
+
return fontProvider;
|
|
1393
|
+
}, []);
|
|
1394
|
+
const priceFormatter = useMemo(() => new Intl.NumberFormat('en-US', {
|
|
1395
|
+
style: 'currency',
|
|
1396
|
+
currency: 'USD'
|
|
1397
|
+
}), []);
|
|
1398
|
+
const scrubberPriceFormatter = useMemo(() => new Intl.NumberFormat('en-US', {
|
|
1399
|
+
minimumFractionDigits: 2,
|
|
1400
|
+
maximumFractionDigits: 2
|
|
1401
|
+
}), []);
|
|
1402
|
+
const formatPrice = useCallback(price => {
|
|
1403
|
+
return priceFormatter.format(price);
|
|
1404
|
+
}, [priceFormatter]);
|
|
1405
|
+
const formatDate = useCallback(date => {
|
|
1406
|
+
const dayOfWeek = date.toLocaleDateString('en-US', {
|
|
1407
|
+
weekday: 'short'
|
|
1408
|
+
});
|
|
1409
|
+
const monthDay = date.toLocaleDateString('en-US', {
|
|
1410
|
+
month: 'short',
|
|
1411
|
+
day: 'numeric'
|
|
1412
|
+
});
|
|
1413
|
+
const time = date.toLocaleTimeString('en-US', {
|
|
1414
|
+
hour: 'numeric',
|
|
1415
|
+
minute: '2-digit',
|
|
1416
|
+
hour12: true
|
|
1417
|
+
});
|
|
1418
|
+
return dayOfWeek + ", " + monthDay + ", " + time;
|
|
1419
|
+
}, []);
|
|
1420
|
+
const scrubberLabel = useCallback(index => {
|
|
1421
|
+
const price = scrubberPriceFormatter.format(prices[index].value);
|
|
1422
|
+
const date = formatDate(prices[index].date);
|
|
1423
|
+
const regularStyle = {
|
|
1424
|
+
fontFamilies: ['Inter'],
|
|
1425
|
+
fontSize: 14,
|
|
1426
|
+
fontStyle: {
|
|
1427
|
+
weight: FontWeight.Normal
|
|
1296
1428
|
},
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1429
|
+
color: Skia.Color(theme.color.fgMuted)
|
|
1430
|
+
};
|
|
1431
|
+
const boldStyle = _extends({
|
|
1432
|
+
fontFamilies: ['Inter']
|
|
1433
|
+
}, regularStyle, {
|
|
1434
|
+
fontStyle: {
|
|
1435
|
+
weight: FontWeight.Bold
|
|
1436
|
+
}
|
|
1437
|
+
});
|
|
1438
|
+
const builder = Skia.ParagraphBuilder.Make({
|
|
1439
|
+
textAlign: TextAlign.Left
|
|
1440
|
+
}, fontMgr);
|
|
1441
|
+
builder.pushStyle(boldStyle);
|
|
1442
|
+
builder.addText(price + " USD");
|
|
1443
|
+
builder.pushStyle(regularStyle);
|
|
1444
|
+
builder.addText(" " + date);
|
|
1445
|
+
const para = builder.build();
|
|
1446
|
+
para.layout(512);
|
|
1447
|
+
return para;
|
|
1448
|
+
}, [scrubberPriceFormatter, prices, formatDate, theme.color.fgMuted, fontMgr]);
|
|
1449
|
+
const formatAxisLabelPrice = useCallback(price => {
|
|
1450
|
+
return formatPrice(price);
|
|
1451
|
+
}, [formatPrice]);
|
|
1452
|
+
|
|
1453
|
+
// Custom tick label component with offset positioning
|
|
1454
|
+
const CustomYAxisTickLabel = useCallback(props => /*#__PURE__*/_jsx(DefaultAxisTickLabel, _extends({}, props, {
|
|
1455
|
+
dx: 4,
|
|
1456
|
+
dy: -12,
|
|
1457
|
+
horizontalAlignment: "left"
|
|
1458
|
+
})), []);
|
|
1459
|
+
const CustomScrubberBeacon = /*#__PURE__*/memo(_ref16 => {
|
|
1460
|
+
let {
|
|
1461
|
+
dataX,
|
|
1462
|
+
dataY,
|
|
1463
|
+
seriesId,
|
|
1464
|
+
isIdle,
|
|
1465
|
+
animate = true
|
|
1466
|
+
} = _ref16;
|
|
1467
|
+
const {
|
|
1468
|
+
getSeries,
|
|
1469
|
+
getXSerializableScale,
|
|
1470
|
+
getYSerializableScale
|
|
1471
|
+
} = useCartesianChartContext();
|
|
1472
|
+
const targetSeries = useMemo(() => getSeries(seriesId), [getSeries, seriesId]);
|
|
1473
|
+
const xScale = useMemo(() => getXSerializableScale(), [getXSerializableScale]);
|
|
1474
|
+
const yScale = useMemo(() => getYSerializableScale(targetSeries == null ? void 0 : targetSeries.yAxisId), [getYSerializableScale, targetSeries == null ? void 0 : targetSeries.yAxisId]);
|
|
1475
|
+
const animatedX = useSharedValue(0);
|
|
1476
|
+
const animatedY = useSharedValue(0);
|
|
1477
|
+
|
|
1478
|
+
// Calculate the target point position - project data to pixels
|
|
1479
|
+
const targetPoint = useDerivedValue(() => {
|
|
1480
|
+
if (!xScale || !yScale) return {
|
|
1481
|
+
x: 0,
|
|
1482
|
+
y: 0
|
|
1483
|
+
};
|
|
1484
|
+
return projectPointWithSerializableScale({
|
|
1485
|
+
x: unwrapAnimatedValue(dataX),
|
|
1486
|
+
y: unwrapAnimatedValue(dataY),
|
|
1487
|
+
xScale,
|
|
1488
|
+
yScale
|
|
1489
|
+
});
|
|
1490
|
+
}, [dataX, dataY, xScale, yScale]);
|
|
1491
|
+
useAnimatedReaction(() => {
|
|
1492
|
+
return {
|
|
1493
|
+
point: targetPoint.value,
|
|
1494
|
+
isIdle: unwrapAnimatedValue(isIdle)
|
|
1495
|
+
};
|
|
1496
|
+
}, (current, previous) => {
|
|
1497
|
+
// When animation is disabled, on initial render, or when we are starting,
|
|
1498
|
+
// continuing, or finishing scrubbing we should immediately transition
|
|
1499
|
+
if (!animate || previous === null || !previous.isIdle || !current.isIdle) {
|
|
1500
|
+
animatedX.value = current.point.x;
|
|
1501
|
+
animatedY.value = current.point.y;
|
|
1502
|
+
return;
|
|
1503
|
+
}
|
|
1504
|
+
animatedX.value = buildTransition(current.point.x, defaultTransition);
|
|
1505
|
+
animatedY.value = buildTransition(current.point.y, defaultTransition);
|
|
1506
|
+
}, [animate]);
|
|
1507
|
+
|
|
1508
|
+
// Create animated point using the animated values
|
|
1509
|
+
const animatedPoint = useDerivedValue(() => {
|
|
1510
|
+
return {
|
|
1511
|
+
x: animatedX.value,
|
|
1512
|
+
y: animatedY.value
|
|
1513
|
+
};
|
|
1514
|
+
}, [animatedX, animatedY]);
|
|
1515
|
+
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
1516
|
+
children: [/*#__PURE__*/_jsx(Circle, {
|
|
1517
|
+
c: animatedPoint,
|
|
1518
|
+
color: theme.color.bg,
|
|
1519
|
+
r: 5
|
|
1520
|
+
}), /*#__PURE__*/_jsx(Circle, {
|
|
1521
|
+
c: animatedPoint,
|
|
1522
|
+
color: theme.color.fg,
|
|
1523
|
+
r: 5,
|
|
1524
|
+
strokeWidth: 3,
|
|
1525
|
+
style: "stroke"
|
|
1351
1526
|
})]
|
|
1527
|
+
});
|
|
1528
|
+
});
|
|
1529
|
+
return /*#__PURE__*/_jsx(LineChart, {
|
|
1530
|
+
enableScrubbing: true,
|
|
1531
|
+
showYAxis: true,
|
|
1532
|
+
height: 200,
|
|
1533
|
+
inset: {
|
|
1534
|
+
top: 64
|
|
1535
|
+
},
|
|
1536
|
+
series: [{
|
|
1537
|
+
id: 'btc',
|
|
1538
|
+
data: prices.map(price => price.value),
|
|
1539
|
+
color: theme.color.fg,
|
|
1540
|
+
gradient: {
|
|
1541
|
+
axis: 'x',
|
|
1542
|
+
stops: _ref17 => {
|
|
1543
|
+
let {
|
|
1544
|
+
min
|
|
1545
|
+
} = _ref17;
|
|
1546
|
+
return [{
|
|
1547
|
+
offset: min,
|
|
1548
|
+
color: theme.color.fg,
|
|
1549
|
+
opacity: 0
|
|
1550
|
+
}, {
|
|
1551
|
+
offset: 32,
|
|
1552
|
+
color: theme.color.fg,
|
|
1553
|
+
opacity: 1
|
|
1554
|
+
}];
|
|
1555
|
+
}
|
|
1556
|
+
}
|
|
1557
|
+
}],
|
|
1558
|
+
xAxis: {
|
|
1559
|
+
range: _ref18 => {
|
|
1560
|
+
let {
|
|
1561
|
+
max
|
|
1562
|
+
} = _ref18;
|
|
1563
|
+
return {
|
|
1564
|
+
min: 96,
|
|
1565
|
+
max
|
|
1566
|
+
};
|
|
1567
|
+
}
|
|
1568
|
+
},
|
|
1569
|
+
yAxis: {
|
|
1570
|
+
position: 'left',
|
|
1571
|
+
width: 0,
|
|
1572
|
+
showGrid: true,
|
|
1573
|
+
tickLabelFormatter: formatAxisLabelPrice,
|
|
1574
|
+
TickLabelComponent: CustomYAxisTickLabel
|
|
1575
|
+
},
|
|
1576
|
+
children: /*#__PURE__*/_jsx(Scrubber, {
|
|
1577
|
+
hideOverlay: true,
|
|
1578
|
+
labelElevated: true,
|
|
1579
|
+
BeaconComponent: CustomScrubberBeacon,
|
|
1580
|
+
LineComponent: SolidLine,
|
|
1581
|
+
label: scrubberLabel
|
|
1352
1582
|
})
|
|
1353
1583
|
});
|
|
1354
|
-
}
|
|
1355
|
-
|
|
1584
|
+
}
|
|
1585
|
+
function ServiceAvailability() {
|
|
1586
|
+
const theme = useTheme();
|
|
1587
|
+
const availabilityEvents = useMemo(() => [{
|
|
1588
|
+
date: new Date('2022-01-01'),
|
|
1589
|
+
availability: 79
|
|
1590
|
+
}, {
|
|
1591
|
+
date: new Date('2022-01-03'),
|
|
1592
|
+
availability: 81
|
|
1593
|
+
}, {
|
|
1594
|
+
date: new Date('2022-01-04'),
|
|
1595
|
+
availability: 82
|
|
1596
|
+
}, {
|
|
1597
|
+
date: new Date('2022-01-06'),
|
|
1598
|
+
availability: 91
|
|
1599
|
+
}, {
|
|
1600
|
+
date: new Date('2022-01-07'),
|
|
1601
|
+
availability: 92
|
|
1602
|
+
}, {
|
|
1603
|
+
date: new Date('2022-01-10'),
|
|
1604
|
+
availability: 86
|
|
1605
|
+
}], []);
|
|
1606
|
+
return /*#__PURE__*/_jsxs(CartesianChart, {
|
|
1607
|
+
enableScrubbing: true,
|
|
1608
|
+
height: 200,
|
|
1609
|
+
series: [{
|
|
1610
|
+
id: 'availability',
|
|
1611
|
+
data: availabilityEvents.map(event => event.availability),
|
|
1612
|
+
gradient: {
|
|
1613
|
+
stops: _ref19 => {
|
|
1614
|
+
let {
|
|
1615
|
+
min,
|
|
1616
|
+
max
|
|
1617
|
+
} = _ref19;
|
|
1618
|
+
return [{
|
|
1619
|
+
offset: min,
|
|
1620
|
+
color: theme.color.fgNegative
|
|
1621
|
+
}, {
|
|
1622
|
+
offset: 85,
|
|
1623
|
+
color: theme.color.fgNegative
|
|
1624
|
+
}, {
|
|
1625
|
+
offset: 85,
|
|
1626
|
+
color: theme.color.fgWarning
|
|
1627
|
+
}, {
|
|
1628
|
+
offset: 90,
|
|
1629
|
+
color: theme.color.fgWarning
|
|
1630
|
+
}, {
|
|
1631
|
+
offset: 90,
|
|
1632
|
+
color: theme.color.fgPositive
|
|
1633
|
+
}, {
|
|
1634
|
+
offset: max,
|
|
1635
|
+
color: theme.color.fgPositive
|
|
1636
|
+
}];
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
}],
|
|
1640
|
+
xAxis: {
|
|
1641
|
+
data: availabilityEvents.map(event => event.date.getTime())
|
|
1642
|
+
},
|
|
1643
|
+
yAxis: {
|
|
1644
|
+
domain: _ref20 => {
|
|
1645
|
+
let {
|
|
1646
|
+
min,
|
|
1647
|
+
max
|
|
1648
|
+
} = _ref20;
|
|
1649
|
+
return {
|
|
1650
|
+
min: Math.max(min - 2, 0),
|
|
1651
|
+
max: Math.min(max + 2, 100)
|
|
1652
|
+
};
|
|
1653
|
+
}
|
|
1654
|
+
},
|
|
1655
|
+
children: [/*#__PURE__*/_jsx(XAxis, {
|
|
1656
|
+
showGrid: true,
|
|
1657
|
+
showLine: true,
|
|
1658
|
+
showTickMarks: true,
|
|
1659
|
+
tickLabelFormatter: value => new Date(value).toLocaleDateString()
|
|
1660
|
+
}), /*#__PURE__*/_jsx(YAxis, {
|
|
1661
|
+
showGrid: true,
|
|
1662
|
+
showLine: true,
|
|
1663
|
+
showTickMarks: true,
|
|
1664
|
+
position: "left",
|
|
1665
|
+
tickLabelFormatter: value => value + "%"
|
|
1666
|
+
}), /*#__PURE__*/_jsx(Line, {
|
|
1667
|
+
curve: "stepAfter",
|
|
1668
|
+
points: props => _extends({}, props, {
|
|
1669
|
+
fill: theme.color.bg,
|
|
1670
|
+
stroke: props.fill
|
|
1671
|
+
}),
|
|
1672
|
+
seriesId: "availability"
|
|
1673
|
+
}), /*#__PURE__*/_jsx(Scrubber, {
|
|
1674
|
+
hideOverlay: true
|
|
1675
|
+
})]
|
|
1676
|
+
});
|
|
1677
|
+
}
|
|
1678
|
+
function ForecastAssetPrice() {
|
|
1679
|
+
const startYear = 2020;
|
|
1680
|
+
const data = [50, 45, 47, 46, 54, 54, 60, 61, 63, 66, 70];
|
|
1681
|
+
const currentIndex = 6;
|
|
1682
|
+
const strokeWidth = 3;
|
|
1683
|
+
// To prevent cutting off the edge of our lines
|
|
1684
|
+
const clipOffset = strokeWidth;
|
|
1685
|
+
const axisFormatter = useCallback(dataIndex => {
|
|
1686
|
+
return "" + (startYear + dataIndex);
|
|
1687
|
+
}, [startYear]);
|
|
1688
|
+
const HistoricalLineComponent = /*#__PURE__*/memo(props => {
|
|
1689
|
+
const {
|
|
1690
|
+
drawingArea,
|
|
1691
|
+
getXScale
|
|
1692
|
+
} = useCartesianChartContext();
|
|
1693
|
+
const xScale = getXScale();
|
|
1694
|
+
const historicalClipPath = useMemo(() => {
|
|
1695
|
+
if (!xScale || !drawingArea) return null;
|
|
1696
|
+
const currentX = xScale(currentIndex);
|
|
1697
|
+
if (currentX === undefined) return null;
|
|
1698
|
+
|
|
1699
|
+
// Create clip path for historical data (left side)
|
|
1700
|
+
const clip = Skia.Path.Make();
|
|
1701
|
+
clip.addRect({
|
|
1702
|
+
x: drawingArea.x - clipOffset,
|
|
1703
|
+
y: drawingArea.y - clipOffset,
|
|
1704
|
+
width: currentX + clipOffset - drawingArea.x,
|
|
1705
|
+
height: drawingArea.height + clipOffset * 2
|
|
1706
|
+
});
|
|
1707
|
+
return clip;
|
|
1708
|
+
}, [xScale, drawingArea]);
|
|
1709
|
+
if (!historicalClipPath) return null;
|
|
1710
|
+
return /*#__PURE__*/_jsx(Group, {
|
|
1711
|
+
clip: historicalClipPath,
|
|
1712
|
+
children: /*#__PURE__*/_jsx(SolidLine, _extends({
|
|
1713
|
+
strokeWidth: strokeWidth
|
|
1714
|
+
}, props))
|
|
1715
|
+
});
|
|
1716
|
+
});
|
|
1717
|
+
|
|
1718
|
+
// Since the solid and dotted line have different curves,
|
|
1719
|
+
// we need two separate line components. Otherwise we could
|
|
1720
|
+
// have one line component with SolidLine and DottedLine inside
|
|
1721
|
+
// of it and two clipPaths.
|
|
1722
|
+
const ForecastLineComponent = /*#__PURE__*/memo(props => {
|
|
1723
|
+
const {
|
|
1724
|
+
drawingArea,
|
|
1725
|
+
getXScale
|
|
1726
|
+
} = useCartesianChartContext();
|
|
1727
|
+
const xScale = getXScale();
|
|
1728
|
+
const forecastClipPath = useMemo(() => {
|
|
1729
|
+
if (!xScale || !drawingArea) return null;
|
|
1730
|
+
const currentX = xScale(currentIndex);
|
|
1731
|
+
if (currentX === undefined) return null;
|
|
1732
|
+
|
|
1733
|
+
// Create clip path for forecast data (right side)
|
|
1734
|
+
const clip = Skia.Path.Make();
|
|
1735
|
+
clip.addRect({
|
|
1736
|
+
x: currentX,
|
|
1737
|
+
y: drawingArea.y - clipOffset,
|
|
1738
|
+
width: drawingArea.x + drawingArea.width - currentX + clipOffset * 2,
|
|
1739
|
+
height: drawingArea.height + clipOffset * 2
|
|
1740
|
+
});
|
|
1741
|
+
return clip;
|
|
1742
|
+
}, [xScale, drawingArea]);
|
|
1743
|
+
if (!forecastClipPath) return null;
|
|
1744
|
+
return /*#__PURE__*/_jsx(Group, {
|
|
1745
|
+
clip: forecastClipPath,
|
|
1746
|
+
children: /*#__PURE__*/_jsx(DottedLine, _extends({
|
|
1747
|
+
dashIntervals: [0, strokeWidth * 2],
|
|
1748
|
+
strokeWidth: strokeWidth
|
|
1749
|
+
}, props))
|
|
1750
|
+
});
|
|
1751
|
+
});
|
|
1752
|
+
const CustomScrubber = /*#__PURE__*/memo(() => {
|
|
1753
|
+
const {
|
|
1754
|
+
scrubberPosition
|
|
1755
|
+
} = useScrubberContext();
|
|
1756
|
+
const idleScrubberOpacity = useDerivedValue(() => scrubberPosition.value === undefined ? 1 : 0, [scrubberPosition]);
|
|
1757
|
+
const scrubberOpacity = useDerivedValue(() => scrubberPosition.value !== undefined ? 1 : 0, [scrubberPosition]);
|
|
1758
|
+
|
|
1759
|
+
// Fade in animation for the Scrubber
|
|
1760
|
+
const fadeInOpacity = useSharedValue(0);
|
|
1761
|
+
useEffect(() => {
|
|
1762
|
+
fadeInOpacity.value = withDelay(350, withTiming(1, {
|
|
1763
|
+
duration: 150
|
|
1764
|
+
}));
|
|
1765
|
+
}, [fadeInOpacity]);
|
|
1766
|
+
return /*#__PURE__*/_jsxs(Group, {
|
|
1767
|
+
opacity: fadeInOpacity,
|
|
1768
|
+
children: [/*#__PURE__*/_jsx(Group, {
|
|
1769
|
+
opacity: scrubberOpacity,
|
|
1770
|
+
children: /*#__PURE__*/_jsx(Scrubber, {
|
|
1771
|
+
hideOverlay: true
|
|
1772
|
+
})
|
|
1773
|
+
}), /*#__PURE__*/_jsx(Group, {
|
|
1774
|
+
opacity: idleScrubberOpacity,
|
|
1775
|
+
children: /*#__PURE__*/_jsx(DefaultScrubberBeacon, {
|
|
1776
|
+
isIdle: true,
|
|
1777
|
+
dataX: currentIndex,
|
|
1778
|
+
dataY: data[currentIndex],
|
|
1779
|
+
seriesId: "price"
|
|
1780
|
+
})
|
|
1781
|
+
})]
|
|
1782
|
+
});
|
|
1783
|
+
});
|
|
1784
|
+
return /*#__PURE__*/_jsxs(CartesianChart, {
|
|
1785
|
+
enableScrubbing: true,
|
|
1786
|
+
height: 200,
|
|
1787
|
+
series: [{
|
|
1788
|
+
id: 'price',
|
|
1789
|
+
data,
|
|
1790
|
+
color: assets.btc.color
|
|
1791
|
+
}],
|
|
1792
|
+
children: [/*#__PURE__*/_jsx(Line, {
|
|
1793
|
+
LineComponent: HistoricalLineComponent,
|
|
1794
|
+
curve: "linear",
|
|
1795
|
+
seriesId: "price"
|
|
1796
|
+
}), /*#__PURE__*/_jsx(Line, {
|
|
1797
|
+
LineComponent: ForecastLineComponent,
|
|
1798
|
+
curve: "monotone",
|
|
1799
|
+
seriesId: "price",
|
|
1800
|
+
type: "dotted"
|
|
1801
|
+
}), /*#__PURE__*/_jsx(XAxis, {
|
|
1802
|
+
position: "bottom",
|
|
1803
|
+
requestedTickCount: 3,
|
|
1804
|
+
tickLabelFormatter: axisFormatter
|
|
1805
|
+
}), /*#__PURE__*/_jsx(CustomScrubber, {})]
|
|
1806
|
+
});
|
|
1807
|
+
}
|
|
1808
|
+
function ImperativeHandle() {
|
|
1356
1809
|
const theme = useTheme();
|
|
1357
1810
|
const scrubberRef = useRef(null);
|
|
1358
1811
|
return /*#__PURE__*/_jsxs(VStack, {
|
|
@@ -1360,26 +1813,41 @@ const ScrubberWithImperativeHandle = () => {
|
|
|
1360
1813
|
children: [/*#__PURE__*/_jsx(LineChart, {
|
|
1361
1814
|
enableScrubbing: true,
|
|
1362
1815
|
showYAxis: true,
|
|
1363
|
-
height:
|
|
1816
|
+
height: 250,
|
|
1364
1817
|
series: [{
|
|
1365
1818
|
id: 'priceA',
|
|
1366
1819
|
data: [2400, 1398, 9800, 3908, 4800, 3800, 4300],
|
|
1367
|
-
label: '
|
|
1368
|
-
color: theme.color.accentBoldBlue
|
|
1369
|
-
curve: 'natural'
|
|
1820
|
+
label: 'Price A',
|
|
1821
|
+
color: theme.color.accentBoldBlue
|
|
1370
1822
|
}, {
|
|
1371
1823
|
id: 'priceB',
|
|
1372
1824
|
data: [2000, 2491, 4501, 6049, 5019, 4930, 5910],
|
|
1373
|
-
label: '
|
|
1374
|
-
color: theme.color.accentBoldGreen
|
|
1375
|
-
curve: 'natural'
|
|
1825
|
+
label: 'Price B',
|
|
1826
|
+
color: theme.color.accentBoldGreen
|
|
1376
1827
|
}, {
|
|
1377
1828
|
id: 'priceC',
|
|
1378
1829
|
data: [1000, 4910, 2300, 5910, 3940, 2940, 1940],
|
|
1379
|
-
label: '
|
|
1380
|
-
color: theme.color.accentBoldPurple
|
|
1381
|
-
|
|
1830
|
+
label: 'Price C',
|
|
1831
|
+
color: theme.color.accentBoldPurple
|
|
1832
|
+
}, {
|
|
1833
|
+
id: 'priceD',
|
|
1834
|
+
data: [4810, 2030, 5810, 3940, 2940, 1940, 940],
|
|
1835
|
+
label: 'Price D',
|
|
1836
|
+
color: theme.color.accentBoldYellow
|
|
1382
1837
|
}],
|
|
1838
|
+
xAxis: {
|
|
1839
|
+
// Give space for pulse animation
|
|
1840
|
+
range: _ref21 => {
|
|
1841
|
+
let {
|
|
1842
|
+
min,
|
|
1843
|
+
max
|
|
1844
|
+
} = _ref21;
|
|
1845
|
+
return {
|
|
1846
|
+
min,
|
|
1847
|
+
max: max - 8
|
|
1848
|
+
};
|
|
1849
|
+
}
|
|
1850
|
+
},
|
|
1383
1851
|
yAxis: {
|
|
1384
1852
|
domain: {
|
|
1385
1853
|
min: 0
|
|
@@ -1392,857 +1860,512 @@ const ScrubberWithImperativeHandle = () => {
|
|
|
1392
1860
|
})
|
|
1393
1861
|
}), /*#__PURE__*/_jsx(Button, {
|
|
1394
1862
|
onPress: () => {
|
|
1395
|
-
var _scrubberRef$
|
|
1396
|
-
return (_scrubberRef$
|
|
1863
|
+
var _scrubberRef$current2;
|
|
1864
|
+
return (_scrubberRef$current2 = scrubberRef.current) == null ? void 0 : _scrubberRef$current2.pulse();
|
|
1397
1865
|
},
|
|
1398
|
-
children: "Pulse
|
|
1866
|
+
children: "Pulse"
|
|
1399
1867
|
})]
|
|
1400
1868
|
});
|
|
1401
|
-
}
|
|
1402
|
-
|
|
1403
|
-
const
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1869
|
+
}
|
|
1870
|
+
function CustomBeaconLabel() {
|
|
1871
|
+
const theme = useTheme();
|
|
1872
|
+
// This custom component label shows the percentage value of the data at the scrubber position.
|
|
1873
|
+
const MyScrubberBeaconLabel = /*#__PURE__*/memo(_ref22 => {
|
|
1874
|
+
let {
|
|
1875
|
+
seriesId,
|
|
1876
|
+
color,
|
|
1877
|
+
label
|
|
1878
|
+
} = _ref22,
|
|
1879
|
+
props = _objectWithoutPropertiesLoose(_ref22, _excluded5);
|
|
1880
|
+
const {
|
|
1881
|
+
getSeriesData,
|
|
1882
|
+
series
|
|
1883
|
+
} = useCartesianChartContext();
|
|
1884
|
+
const {
|
|
1885
|
+
scrubberPosition
|
|
1886
|
+
} = useScrubberContext();
|
|
1887
|
+
const seriesData = useMemo(() => getLineData(getSeriesData(seriesId)), [getSeriesData, seriesId]);
|
|
1888
|
+
const dataLength = useMemo(() => {
|
|
1889
|
+
var _series$reduce;
|
|
1890
|
+
return (_series$reduce = series == null ? void 0 : series.reduce((max, s) => {
|
|
1891
|
+
var _seriesData$length;
|
|
1892
|
+
const seriesData = getSeriesData(s.id);
|
|
1893
|
+
return Math.max(max, (_seriesData$length = seriesData == null ? void 0 : seriesData.length) != null ? _seriesData$length : 0);
|
|
1894
|
+
}, 0)) != null ? _series$reduce : 0;
|
|
1895
|
+
}, [series, getSeriesData]);
|
|
1896
|
+
const dataIndex = useDerivedValue(() => {
|
|
1897
|
+
var _scrubberPosition$val;
|
|
1898
|
+
return (_scrubberPosition$val = scrubberPosition.value) != null ? _scrubberPosition$val : Math.max(0, dataLength - 1);
|
|
1899
|
+
}, [scrubberPosition, dataLength]);
|
|
1900
|
+
const percentageLabel = useDerivedValue(() => {
|
|
1901
|
+
if (seriesData !== undefined) {
|
|
1902
|
+
const dataAtPosition = seriesData[dataIndex.value];
|
|
1903
|
+
return unwrapAnimatedValue(label) + " \xB7 " + dataAtPosition + "%";
|
|
1904
|
+
}
|
|
1905
|
+
return unwrapAnimatedValue(label);
|
|
1906
|
+
}, [label, seriesData, dataIndex]);
|
|
1907
|
+
return /*#__PURE__*/_jsx(DefaultScrubberBeaconLabel, _extends({}, props, {
|
|
1908
|
+
background: color,
|
|
1909
|
+
color: theme.color.bg,
|
|
1910
|
+
label: percentageLabel,
|
|
1911
|
+
seriesId: seriesId
|
|
1912
|
+
}));
|
|
1442
1913
|
});
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1914
|
+
return /*#__PURE__*/_jsx(LineChart, {
|
|
1915
|
+
enableScrubbing: true,
|
|
1916
|
+
showArea: true,
|
|
1917
|
+
showYAxis: true,
|
|
1918
|
+
areaType: "dotted",
|
|
1919
|
+
height: 200,
|
|
1920
|
+
series: [{
|
|
1921
|
+
id: 'Boston',
|
|
1922
|
+
data: [25, 30, 35, 45, 60, 100],
|
|
1923
|
+
color: "rgb(" + theme.spectrum.green40 + ")",
|
|
1924
|
+
label: 'Boston'
|
|
1925
|
+
}, {
|
|
1926
|
+
id: 'Miami',
|
|
1927
|
+
data: [20, 25, 30, 35, 20, 0],
|
|
1928
|
+
color: "rgb(" + theme.spectrum.blue40 + ")",
|
|
1929
|
+
label: 'Miami'
|
|
1930
|
+
}, {
|
|
1931
|
+
id: 'Denver',
|
|
1932
|
+
data: [10, 15, 20, 25, 40, 0],
|
|
1933
|
+
color: "rgb(" + theme.spectrum.orange40 + ")",
|
|
1934
|
+
label: 'Denver'
|
|
1935
|
+
}, {
|
|
1936
|
+
id: 'Phoenix',
|
|
1937
|
+
data: [15, 10, 5, 0, 0, 0],
|
|
1938
|
+
color: "rgb(" + theme.spectrum.red40 + ")",
|
|
1939
|
+
label: 'Phoenix'
|
|
1940
|
+
}],
|
|
1941
|
+
yAxis: {
|
|
1942
|
+
showGrid: true
|
|
1451
1943
|
},
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
gap: 3,
|
|
1455
|
-
width: "100%",
|
|
1456
|
-
children: [/*#__PURE__*/_jsxs(HStack, {
|
|
1457
|
-
alignItems: "flex-start",
|
|
1458
|
-
gap: 3,
|
|
1459
|
-
justifyContent: "space-between",
|
|
1460
|
-
padding: 4,
|
|
1461
|
-
children: [/*#__PURE__*/_jsxs(VStack, {
|
|
1462
|
-
flexGrow: 1,
|
|
1463
|
-
gap: 1,
|
|
1464
|
-
children: [/*#__PURE__*/_jsx(Text, {
|
|
1465
|
-
font: "title1",
|
|
1466
|
-
children: "Coinbase Wrapped BTC"
|
|
1467
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
1468
|
-
font: "title2",
|
|
1469
|
-
children: formattedPrice
|
|
1470
|
-
})]
|
|
1471
|
-
}), /*#__PURE__*/_jsx(VStack, {
|
|
1472
|
-
justifyContent: "center",
|
|
1473
|
-
children: /*#__PURE__*/_jsx(RemoteImage, {
|
|
1474
|
-
shape: "circle",
|
|
1475
|
-
size: "xxl",
|
|
1476
|
-
source: assets.btc.imageUrl
|
|
1477
|
-
})
|
|
1478
|
-
})]
|
|
1479
|
-
}), /*#__PURE__*/_jsxs(CartesianChart, {
|
|
1480
|
-
enableScrubbing: true,
|
|
1481
|
-
height: 200,
|
|
1482
|
-
inset: {
|
|
1483
|
-
bottom: 0,
|
|
1484
|
-
right: 3,
|
|
1485
|
-
left: 0,
|
|
1486
|
-
top: 6
|
|
1487
|
-
},
|
|
1488
|
-
onScrubberPositionChange: onScrubberPositionChange,
|
|
1489
|
-
series: [{
|
|
1490
|
-
id: 'price',
|
|
1491
|
-
data: currentData,
|
|
1492
|
-
color: 'black'
|
|
1493
|
-
}],
|
|
1494
|
-
width: "100%",
|
|
1495
|
-
children: [/*#__PURE__*/_jsx(Line, {
|
|
1496
|
-
showArea: true,
|
|
1497
|
-
AreaComponent: AreaComponent,
|
|
1498
|
-
seriesId: "price",
|
|
1499
|
-
strokeWidth: 3
|
|
1500
|
-
}), /*#__PURE__*/_jsx(Scrubber, {
|
|
1501
|
-
idlePulse: true,
|
|
1502
|
-
label: displayDate,
|
|
1503
|
-
labelProps: {
|
|
1504
|
-
color: 'black'
|
|
1505
|
-
},
|
|
1506
|
-
lineStroke: "black"
|
|
1507
|
-
})]
|
|
1508
|
-
}), /*#__PURE__*/_jsx(Box, {
|
|
1509
|
-
padding: 2,
|
|
1510
|
-
children: /*#__PURE__*/_jsx(PeriodSelector, {
|
|
1511
|
-
activeTab: activeTab,
|
|
1512
|
-
onChange: tab => setActiveTab(tab),
|
|
1513
|
-
tabs: tabs
|
|
1514
|
-
})
|
|
1515
|
-
})]
|
|
1944
|
+
children: /*#__PURE__*/_jsx(Scrubber, {
|
|
1945
|
+
BeaconLabelComponent: MyScrubberBeaconLabel
|
|
1516
1946
|
})
|
|
1517
1947
|
});
|
|
1518
|
-
}
|
|
1519
|
-
|
|
1520
|
-
const
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
const priceChange = (Math.random() - 0.5) * maxPercentChange;
|
|
1536
|
-
const newPrice = Math.round((lastPrice + priceChange) * 100) / 100;
|
|
1537
|
-
|
|
1538
|
-
// Check if we should roll over to a new data point
|
|
1539
|
-
const currentTime = Date.now();
|
|
1540
|
-
const timeSinceLastPoint = (currentTime - lastDataPointTimeRef.current) / 1000;
|
|
1541
|
-
if (timeSinceLastPoint >= intervalSeconds) {
|
|
1542
|
-
// Time for a new data point - remove first, add new at end
|
|
1543
|
-
lastDataPointTimeRef.current = currentTime;
|
|
1544
|
-
newData.shift(); // Remove oldest data point
|
|
1545
|
-
newData.push(newPrice); // Add new data point
|
|
1546
|
-
updateCountRef.current = 0;
|
|
1547
|
-
} else {
|
|
1548
|
-
// Just update the last data point
|
|
1549
|
-
newData[newData.length - 1] = newPrice;
|
|
1550
|
-
updateCountRef.current++;
|
|
1551
|
-
}
|
|
1552
|
-
return newData;
|
|
1553
|
-
});
|
|
1554
|
-
|
|
1555
|
-
// Pulse the scrubber on each update
|
|
1556
|
-
(_scrubberRef$current2 = scrubberRef.current) == null || _scrubberRef$current2.pulse();
|
|
1557
|
-
}, 2000 + Math.random() * 1000);
|
|
1558
|
-
return () => clearInterval(priceUpdateInterval);
|
|
1559
|
-
}, [intervalSeconds, maxPercentChange]);
|
|
1948
|
+
}
|
|
1949
|
+
function CustomLabelComponent() {
|
|
1950
|
+
const CustomLabelComponent = /*#__PURE__*/memo(props => {
|
|
1951
|
+
const theme = useTheme();
|
|
1952
|
+
const {
|
|
1953
|
+
drawingArea
|
|
1954
|
+
} = useCartesianChartContext();
|
|
1955
|
+
if (!drawingArea) return;
|
|
1956
|
+
return /*#__PURE__*/_jsx(DefaultScrubberLabel, _extends({}, props, {
|
|
1957
|
+
elevated: true,
|
|
1958
|
+
background: theme.color.bgPrimary,
|
|
1959
|
+
color: theme.color.bgPrimaryWash,
|
|
1960
|
+
dy: 32,
|
|
1961
|
+
fontWeight: FontWeight.Bold,
|
|
1962
|
+
y: drawingArea.y + drawingArea.height
|
|
1963
|
+
}));
|
|
1964
|
+
});
|
|
1560
1965
|
return /*#__PURE__*/_jsx(LineChart, {
|
|
1561
1966
|
enableScrubbing: true,
|
|
1562
1967
|
showArea: true,
|
|
1563
|
-
height:
|
|
1968
|
+
height: 200,
|
|
1969
|
+
inset: {
|
|
1970
|
+
top: 16,
|
|
1971
|
+
bottom: 64
|
|
1972
|
+
},
|
|
1564
1973
|
series: [{
|
|
1565
|
-
id: '
|
|
1566
|
-
data:
|
|
1567
|
-
color: assets.btc.color
|
|
1974
|
+
id: 'prices',
|
|
1975
|
+
data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58]
|
|
1568
1976
|
}],
|
|
1569
1977
|
children: /*#__PURE__*/_jsx(Scrubber, {
|
|
1570
|
-
|
|
1978
|
+
LabelComponent: CustomLabelComponent,
|
|
1979
|
+
label: dataIndex => "Day " + (dataIndex + 1)
|
|
1571
1980
|
})
|
|
1572
1981
|
});
|
|
1573
|
-
}
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
}, {
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
}
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
}, {
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
}
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1982
|
+
}
|
|
1983
|
+
function HiddenScrubberWhenIdle() {
|
|
1984
|
+
const MyScrubberBeacon = /*#__PURE__*/memo(props => {
|
|
1985
|
+
const {
|
|
1986
|
+
scrubberPosition
|
|
1987
|
+
} = useScrubberContext();
|
|
1988
|
+
const beaconOpacity = useDerivedValue(() => scrubberPosition.value !== undefined ? 1 : 0, [scrubberPosition]);
|
|
1989
|
+
return /*#__PURE__*/_jsx(DefaultScrubberBeacon, _extends({}, props, {
|
|
1990
|
+
opacity: beaconOpacity
|
|
1991
|
+
}));
|
|
1992
|
+
});
|
|
1993
|
+
const MyScrubberBeaconLabel = /*#__PURE__*/memo(props => {
|
|
1994
|
+
const {
|
|
1995
|
+
scrubberPosition
|
|
1996
|
+
} = useScrubberContext();
|
|
1997
|
+
const labelOpacity = useDerivedValue(() => scrubberPosition.value !== undefined ? 1 : 0, [scrubberPosition]);
|
|
1998
|
+
return /*#__PURE__*/_jsx(DefaultScrubberBeaconLabel, _extends({}, props, {
|
|
1999
|
+
opacity: labelOpacity
|
|
2000
|
+
}));
|
|
2001
|
+
});
|
|
2002
|
+
return /*#__PURE__*/_jsx(LineChart, {
|
|
2003
|
+
enableScrubbing: true,
|
|
2004
|
+
showArea: true,
|
|
2005
|
+
height: 150,
|
|
2006
|
+
series: [{
|
|
2007
|
+
id: 'prices',
|
|
2008
|
+
data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58],
|
|
2009
|
+
label: 'hello'
|
|
2010
|
+
}],
|
|
2011
|
+
children: /*#__PURE__*/_jsx(Scrubber, {
|
|
2012
|
+
BeaconComponent: MyScrubberBeacon,
|
|
2013
|
+
BeaconLabelComponent: MyScrubberBeaconLabel
|
|
2014
|
+
})
|
|
2015
|
+
});
|
|
2016
|
+
}
|
|
2017
|
+
function TwoLineScrubberLabel() {
|
|
2018
|
+
const theme = useTheme();
|
|
2019
|
+
const data = useMemo(() => [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58], []);
|
|
2020
|
+
const [alignment, setAlignment] = useState(TextAlign.Center);
|
|
2021
|
+
const fontMgr = useMemo(() => {
|
|
2022
|
+
const fontProvider = Skia.TypefaceFontProvider.Make();
|
|
2023
|
+
return fontProvider;
|
|
2024
|
+
}, []);
|
|
2025
|
+
const formatPrice = useCallback(price => {
|
|
2026
|
+
return new Intl.NumberFormat('en-US', {
|
|
2027
|
+
style: 'currency',
|
|
2028
|
+
currency: 'USD',
|
|
2029
|
+
minimumFractionDigits: 2,
|
|
2030
|
+
maximumFractionDigits: 2
|
|
2031
|
+
}).format(price);
|
|
2032
|
+
}, []);
|
|
2033
|
+
const scrubberLabel = useCallback(index => {
|
|
2034
|
+
const price = formatPrice(data[index] * 100);
|
|
2035
|
+
const day = "Day " + (index + 100);
|
|
2036
|
+
const priceStyle = {
|
|
2037
|
+
fontFamilies: ['Inter'],
|
|
2038
|
+
fontSize: 16,
|
|
2039
|
+
fontStyle: {
|
|
2040
|
+
weight: FontWeight.Bold
|
|
2041
|
+
},
|
|
2042
|
+
color: Skia.Color(theme.color.fg)
|
|
2043
|
+
};
|
|
2044
|
+
const dayStyle = {
|
|
2045
|
+
fontFamilies: ['Inter'],
|
|
2046
|
+
fontSize: 14,
|
|
2047
|
+
fontStyle: {
|
|
2048
|
+
weight: FontWeight.Normal
|
|
2049
|
+
},
|
|
2050
|
+
color: Skia.Color(theme.color.fgMuted)
|
|
2051
|
+
};
|
|
2052
|
+
const builder = Skia.ParagraphBuilder.Make({
|
|
2053
|
+
textAlign: alignment
|
|
2054
|
+
}, fontMgr);
|
|
2055
|
+
builder.pushStyle(priceStyle);
|
|
2056
|
+
builder.addText(price);
|
|
2057
|
+
builder.addText('\n');
|
|
2058
|
+
builder.pushStyle(dayStyle);
|
|
2059
|
+
builder.addText(day);
|
|
2060
|
+
const para = builder.build();
|
|
2061
|
+
// First layout with large width to get intrinsic size
|
|
2062
|
+
para.layout(384);
|
|
2063
|
+
return para;
|
|
2064
|
+
}, [data, formatPrice, theme.color.fg, theme.color.fgMuted, fontMgr, alignment]);
|
|
1610
2065
|
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
candidate3: Math.round(candidate3 * 10) / 10
|
|
1616
|
-
};
|
|
1617
|
-
});
|
|
1618
|
-
};
|
|
1619
|
-
return {
|
|
1620
|
-
hour: generateForPeriod(60, 60 * 1000),
|
|
1621
|
-
// 60 points, 1 min apart
|
|
1622
|
-
day: generateForPeriod(96, 15 * 60 * 1000),
|
|
1623
|
-
// 96 points, 15 min apart
|
|
1624
|
-
week: generateForPeriod(84, 2 * 60 * 60 * 1000),
|
|
1625
|
-
// 84 points, 2 hours apart
|
|
1626
|
-
month: generateForPeriod(120, 6 * 60 * 60 * 1000),
|
|
1627
|
-
// 120 points, 6 hours apart
|
|
1628
|
-
year: generateForPeriod(365, 24 * 60 * 60 * 1000),
|
|
1629
|
-
// 365 points, 1 day apart
|
|
1630
|
-
all: generateForPeriod(100, 7 * 24 * 60 * 60 * 1000) // 100 points, 1 week apart
|
|
1631
|
-
};
|
|
1632
|
-
};
|
|
1633
|
-
const predictionData = generatePredictionData();
|
|
1634
|
-
const PredictionLegend = /*#__PURE__*/memo(/*#__PURE__*/forwardRef((_ref6, ref) => {
|
|
1635
|
-
let {
|
|
1636
|
-
data,
|
|
1637
|
-
colors
|
|
1638
|
-
} = _ref6;
|
|
1639
|
-
const [selectedIndex, setSelectedIndex] = useState(data.candidate1.length - 1);
|
|
1640
|
-
useImperativeHandle(ref, () => ({
|
|
1641
|
-
updateSelectedIndex: index => {
|
|
1642
|
-
setSelectedIndex(index);
|
|
1643
|
-
}
|
|
1644
|
-
}));
|
|
1645
|
-
const candidate1Value = Math.round(data.candidate1[selectedIndex]);
|
|
1646
|
-
const candidate2Value = Math.round(data.candidate2[selectedIndex]);
|
|
1647
|
-
const candidate3Value = Math.round(data.candidate3[selectedIndex]);
|
|
2066
|
+
// Custom scrubber label component that uses the selected alignment
|
|
2067
|
+
const AlignedScrubberLabel = /*#__PURE__*/memo(props => /*#__PURE__*/_jsx(DefaultScrubberLabel, _extends({}, props, {
|
|
2068
|
+
paragraphAlignment: alignment
|
|
2069
|
+
})));
|
|
1648
2070
|
return /*#__PURE__*/_jsxs(VStack, {
|
|
1649
2071
|
gap: 2,
|
|
1650
2072
|
children: [/*#__PURE__*/_jsxs(HStack, {
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
}), /*#__PURE__*/_jsxs(HStack, {
|
|
1668
|
-
alignItems: "center",
|
|
1669
|
-
gap: 2,
|
|
1670
|
-
children: [/*#__PURE__*/_jsx(Box, {
|
|
1671
|
-
style: {
|
|
1672
|
-
width: 12,
|
|
1673
|
-
height: 12,
|
|
1674
|
-
borderRadius: 6,
|
|
1675
|
-
backgroundColor: colors.teal
|
|
1676
|
-
}
|
|
1677
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
1678
|
-
font: "label2",
|
|
1679
|
-
children: "Adam Scott"
|
|
1680
|
-
}), /*#__PURE__*/_jsxs(Text, {
|
|
1681
|
-
font: "label1",
|
|
1682
|
-
children: [candidate2Value, "%"]
|
|
1683
|
-
})]
|
|
1684
|
-
}), /*#__PURE__*/_jsxs(HStack, {
|
|
1685
|
-
alignItems: "center",
|
|
1686
|
-
gap: 2,
|
|
1687
|
-
children: [/*#__PURE__*/_jsx(Box, {
|
|
1688
|
-
style: {
|
|
1689
|
-
width: 12,
|
|
1690
|
-
height: 12,
|
|
1691
|
-
borderRadius: 6,
|
|
1692
|
-
backgroundColor: colors.green
|
|
1693
|
-
}
|
|
1694
|
-
}), /*#__PURE__*/_jsx(Text, {
|
|
1695
|
-
font: "label2",
|
|
1696
|
-
children: "Pedro Pascal"
|
|
1697
|
-
}), /*#__PURE__*/_jsxs(Text, {
|
|
1698
|
-
font: "label1",
|
|
1699
|
-
children: [candidate3Value, "%"]
|
|
2073
|
+
gap: 1,
|
|
2074
|
+
children: [/*#__PURE__*/_jsx(Button, {
|
|
2075
|
+
compact: true,
|
|
2076
|
+
onPress: () => setAlignment(TextAlign.Left),
|
|
2077
|
+
variant: alignment === TextAlign.Left ? 'primary' : 'secondary',
|
|
2078
|
+
children: "Left"
|
|
2079
|
+
}), /*#__PURE__*/_jsx(Button, {
|
|
2080
|
+
compact: true,
|
|
2081
|
+
onPress: () => setAlignment(TextAlign.Center),
|
|
2082
|
+
variant: alignment === TextAlign.Center ? 'primary' : 'secondary',
|
|
2083
|
+
children: "Center"
|
|
2084
|
+
}), /*#__PURE__*/_jsx(Button, {
|
|
2085
|
+
compact: true,
|
|
2086
|
+
onPress: () => setAlignment(TextAlign.Right),
|
|
2087
|
+
variant: alignment === TextAlign.Right ? 'primary' : 'secondary',
|
|
2088
|
+
children: "Right"
|
|
1700
2089
|
})]
|
|
2090
|
+
}), /*#__PURE__*/_jsx(LineChart, {
|
|
2091
|
+
enableScrubbing: true,
|
|
2092
|
+
showArea: true,
|
|
2093
|
+
height: 200,
|
|
2094
|
+
inset: {
|
|
2095
|
+
top: 64
|
|
2096
|
+
},
|
|
2097
|
+
series: [{
|
|
2098
|
+
id: 'prices',
|
|
2099
|
+
data: data,
|
|
2100
|
+
color: theme.color.accentBoldBlue
|
|
2101
|
+
}],
|
|
2102
|
+
children: /*#__PURE__*/_jsx(Scrubber, {
|
|
2103
|
+
idlePulse: true,
|
|
2104
|
+
labelElevated: true,
|
|
2105
|
+
LabelComponent: AlignedScrubberLabel,
|
|
2106
|
+
label: scrubberLabel
|
|
2107
|
+
})
|
|
1701
2108
|
})]
|
|
1702
2109
|
});
|
|
1703
|
-
}
|
|
1704
|
-
|
|
2110
|
+
}
|
|
2111
|
+
function ExampleNavigator() {
|
|
1705
2112
|
const theme = useTheme();
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
id: 'hour',
|
|
1718
|
-
label: '1H'
|
|
2113
|
+
const [currentIndex, setCurrentIndex] = useState(0);
|
|
2114
|
+
const examples = useMemo(() => [{
|
|
2115
|
+
title: 'Basic',
|
|
2116
|
+
component: /*#__PURE__*/_jsx(LineChart, {
|
|
2117
|
+
showArea: true,
|
|
2118
|
+
height: 200,
|
|
2119
|
+
series: [{
|
|
2120
|
+
id: 'prices',
|
|
2121
|
+
data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58]
|
|
2122
|
+
}]
|
|
2123
|
+
})
|
|
1719
2124
|
}, {
|
|
1720
|
-
|
|
1721
|
-
|
|
2125
|
+
title: 'Imperative Handle',
|
|
2126
|
+
component: /*#__PURE__*/_jsx(ImperativeHandle, {})
|
|
1722
2127
|
}, {
|
|
1723
|
-
|
|
1724
|
-
|
|
2128
|
+
title: 'Multiple Lines',
|
|
2129
|
+
component: /*#__PURE__*/_jsx(MultipleLine, {})
|
|
1725
2130
|
}, {
|
|
1726
|
-
|
|
1727
|
-
|
|
2131
|
+
title: 'Data Format',
|
|
2132
|
+
component: /*#__PURE__*/_jsx(DataFormat, {})
|
|
1728
2133
|
}, {
|
|
1729
|
-
|
|
1730
|
-
|
|
2134
|
+
title: 'Live Updates',
|
|
2135
|
+
component: /*#__PURE__*/_jsx(LiveUpdates, {})
|
|
1731
2136
|
}, {
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
}
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
})
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
},
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
2137
|
+
title: 'Missing Data',
|
|
2138
|
+
component: /*#__PURE__*/_jsx(MissingData, {})
|
|
2139
|
+
}, {
|
|
2140
|
+
title: 'Empty State',
|
|
2141
|
+
component: /*#__PURE__*/_jsx(LineChart, {
|
|
2142
|
+
height: 200,
|
|
2143
|
+
series: [{
|
|
2144
|
+
id: 'line',
|
|
2145
|
+
color: "rgb(" + theme.spectrum.gray50 + ")",
|
|
2146
|
+
data: [1, 1],
|
|
2147
|
+
showArea: true
|
|
2148
|
+
}],
|
|
2149
|
+
yAxis: {
|
|
2150
|
+
domain: {
|
|
2151
|
+
min: -1,
|
|
2152
|
+
max: 3
|
|
2153
|
+
}
|
|
2154
|
+
}
|
|
2155
|
+
})
|
|
2156
|
+
}, {
|
|
2157
|
+
title: 'Scales',
|
|
2158
|
+
component: /*#__PURE__*/_jsx(LineChart, {
|
|
2159
|
+
showArea: true,
|
|
2160
|
+
showYAxis: true,
|
|
2161
|
+
height: 200,
|
|
2162
|
+
series: [{
|
|
2163
|
+
id: 'prices',
|
|
2164
|
+
data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58]
|
|
2165
|
+
}],
|
|
2166
|
+
yAxis: {
|
|
2167
|
+
scaleType: 'log',
|
|
2168
|
+
showGrid: true,
|
|
2169
|
+
ticks: [1, 10, 100]
|
|
2170
|
+
}
|
|
2171
|
+
})
|
|
2172
|
+
}, {
|
|
2173
|
+
title: 'Interaction',
|
|
2174
|
+
component: /*#__PURE__*/_jsx(Interaction, {})
|
|
2175
|
+
}, {
|
|
2176
|
+
title: 'Points',
|
|
2177
|
+
component: /*#__PURE__*/_jsx(Points, {})
|
|
2178
|
+
}, {
|
|
2179
|
+
title: 'Transitions',
|
|
2180
|
+
component: /*#__PURE__*/_jsx(Transitions, {})
|
|
2181
|
+
}, {
|
|
2182
|
+
title: 'Basic Accessible',
|
|
2183
|
+
component: /*#__PURE__*/_jsx(BasicAccessible, {})
|
|
2184
|
+
}, {
|
|
2185
|
+
title: 'Styling Axes',
|
|
2186
|
+
component: /*#__PURE__*/_jsx(LineChart, {
|
|
2187
|
+
showArea: true,
|
|
2188
|
+
showXAxis: true,
|
|
2189
|
+
showYAxis: true,
|
|
2190
|
+
height: 200,
|
|
2191
|
+
series: [{
|
|
2192
|
+
id: 'prices',
|
|
2193
|
+
data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58]
|
|
2194
|
+
}],
|
|
2195
|
+
xAxis: {
|
|
2196
|
+
showGrid: true,
|
|
2197
|
+
showLine: true,
|
|
2198
|
+
showTickMarks: true,
|
|
2199
|
+
tickLabelFormatter: dataX => "Day " + dataX
|
|
2200
|
+
},
|
|
2201
|
+
yAxis: {
|
|
2202
|
+
showGrid: true,
|
|
2203
|
+
showLine: true,
|
|
2204
|
+
showTickMarks: true
|
|
2205
|
+
}
|
|
2206
|
+
})
|
|
2207
|
+
}, {
|
|
2208
|
+
title: 'Gradients',
|
|
2209
|
+
component: /*#__PURE__*/_jsx(Gradients, {})
|
|
2210
|
+
}, {
|
|
2211
|
+
title: 'Gain/Loss',
|
|
2212
|
+
component: /*#__PURE__*/_jsx(GainLossChart, {})
|
|
2213
|
+
}, {
|
|
2214
|
+
title: 'Styling Lines',
|
|
2215
|
+
component: /*#__PURE__*/_jsx(LineChart, {
|
|
2216
|
+
height: 200,
|
|
2217
|
+
series: [{
|
|
2218
|
+
id: 'top',
|
|
2219
|
+
data: [15, 28, 32, 44, 46, 36, 40, 45, 48, 38]
|
|
2220
|
+
}, {
|
|
2221
|
+
id: 'upperMiddle',
|
|
2222
|
+
data: [12, 23, 21, 29, 34, 28, 31, 38, 42, 35],
|
|
2223
|
+
color: '#ef4444',
|
|
2224
|
+
type: 'dotted'
|
|
2225
|
+
}, {
|
|
2226
|
+
id: 'lowerMiddle',
|
|
2227
|
+
data: [8, 15, 14, 25, 20, 18, 22, 28, 24, 30],
|
|
2228
|
+
color: '#f59e0b',
|
|
2229
|
+
curve: 'natural',
|
|
2230
|
+
gradient: {
|
|
2231
|
+
axis: 'x',
|
|
2232
|
+
stops: [{
|
|
2233
|
+
offset: 0,
|
|
2234
|
+
color: '#E3D74D'
|
|
2235
|
+
}, {
|
|
2236
|
+
offset: 9,
|
|
2237
|
+
color: '#F7931A'
|
|
2238
|
+
}]
|
|
2239
|
+
},
|
|
2240
|
+
strokeWidth: 6
|
|
2241
|
+
}, {
|
|
2242
|
+
id: 'bottom',
|
|
2243
|
+
data: [4, 8, 11, 15, 16, 14, 16, 10, 12, 14],
|
|
2244
|
+
color: '#800080',
|
|
2245
|
+
curve: 'step',
|
|
2246
|
+
AreaComponent: DottedArea,
|
|
2247
|
+
showArea: true
|
|
2248
|
+
}]
|
|
2249
|
+
})
|
|
2250
|
+
}, {
|
|
2251
|
+
title: 'Styling Reference Lines',
|
|
2252
|
+
component: /*#__PURE__*/_jsxs(LineChart, {
|
|
2253
|
+
enableScrubbing: true,
|
|
2254
|
+
showArea: true,
|
|
2255
|
+
height: 200,
|
|
2256
|
+
series: [{
|
|
2257
|
+
id: 'prices',
|
|
2258
|
+
data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58],
|
|
2259
|
+
color: theme.color.fgPositive
|
|
2260
|
+
}],
|
|
2261
|
+
xAxis: {
|
|
2262
|
+
// Give space before the end of the chart for the scrubber
|
|
2263
|
+
range: _ref23 => {
|
|
2264
|
+
let {
|
|
2265
|
+
min,
|
|
2266
|
+
max
|
|
2267
|
+
} = _ref23;
|
|
2268
|
+
return {
|
|
2269
|
+
min,
|
|
2270
|
+
max: max - 24
|
|
2271
|
+
};
|
|
2272
|
+
}
|
|
2273
|
+
},
|
|
2274
|
+
children: [/*#__PURE__*/_jsx(ReferenceLine, {
|
|
2275
|
+
LineComponent: props => /*#__PURE__*/_jsx(DottedLine, _extends({}, props, {
|
|
2276
|
+
dashIntervals: [0, 16],
|
|
2277
|
+
strokeWidth: 3
|
|
2278
|
+
})),
|
|
2279
|
+
dataY: 10,
|
|
2280
|
+
stroke: theme.color.fg
|
|
2281
|
+
}), /*#__PURE__*/_jsx(Scrubber, {})]
|
|
2282
|
+
})
|
|
2283
|
+
}, {
|
|
2284
|
+
title: 'High/Low Price',
|
|
2285
|
+
component: /*#__PURE__*/_jsx(HighLowPrice, {})
|
|
2286
|
+
}, {
|
|
2287
|
+
title: 'Styling Scrubber',
|
|
2288
|
+
component: /*#__PURE__*/_jsx(StylingScrubber, {})
|
|
2289
|
+
}, {
|
|
2290
|
+
title: 'Compact',
|
|
2291
|
+
component: /*#__PURE__*/_jsx(Compact, {})
|
|
2292
|
+
}, {
|
|
2293
|
+
title: 'Asset Price With Dotted Area',
|
|
2294
|
+
component: /*#__PURE__*/_jsx(AssetPriceWithDottedArea, {})
|
|
2295
|
+
}, {
|
|
2296
|
+
title: 'Performance',
|
|
2297
|
+
component: /*#__PURE__*/_jsx(Performance, {})
|
|
2298
|
+
}, {
|
|
2299
|
+
title: 'Candlesticks',
|
|
2300
|
+
component: /*#__PURE__*/_jsx(Candlesticks, {})
|
|
2301
|
+
}, {
|
|
2302
|
+
title: 'Monotone Asset Price',
|
|
2303
|
+
component: /*#__PURE__*/_jsx(MonotoneAssetPrice, {})
|
|
2304
|
+
}, {
|
|
2305
|
+
title: 'Service Availability',
|
|
2306
|
+
component: /*#__PURE__*/_jsx(ServiceAvailability, {})
|
|
2307
|
+
}, {
|
|
2308
|
+
title: 'Forecast Asset Price',
|
|
2309
|
+
component: /*#__PURE__*/_jsx(ForecastAssetPrice, {})
|
|
2310
|
+
}, {
|
|
2311
|
+
title: 'Custom Beacon Label',
|
|
2312
|
+
component: /*#__PURE__*/_jsx(CustomBeaconLabel, {})
|
|
2313
|
+
}, {
|
|
2314
|
+
title: 'Custom Label Component',
|
|
2315
|
+
component: /*#__PURE__*/_jsx(CustomLabelComponent, {})
|
|
2316
|
+
}, {
|
|
2317
|
+
title: 'Hidden Scrubber When Idle',
|
|
2318
|
+
component: /*#__PURE__*/_jsx(HiddenScrubberWhenIdle, {})
|
|
2319
|
+
}, {
|
|
2320
|
+
title: 'Two-Line Scrubber Label',
|
|
2321
|
+
component: /*#__PURE__*/_jsx(TwoLineScrubberLabel, {})
|
|
2322
|
+
}], [theme.color.fg, theme.color.fgPositive, theme.spectrum.gray50]);
|
|
2323
|
+
const currentExample = examples[currentIndex];
|
|
2324
|
+
const isFirstExample = currentIndex === 0;
|
|
2325
|
+
const isLastExample = currentIndex === examples.length - 1;
|
|
2326
|
+
const handlePrevious = useCallback(() => {
|
|
2327
|
+
setCurrentIndex(prev => Math.max(0, prev - 1));
|
|
2328
|
+
}, []);
|
|
2329
|
+
const handleNext = useCallback(() => {
|
|
2330
|
+
setCurrentIndex(prev => Math.min(examples.length - 1, prev + 1));
|
|
2331
|
+
}, [examples.length]);
|
|
2332
|
+
return /*#__PURE__*/_jsx(ExampleScreen, {
|
|
1809
2333
|
children: /*#__PURE__*/_jsxs(VStack, {
|
|
1810
2334
|
gap: 4,
|
|
1811
|
-
children: [/*#__PURE__*/
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
2335
|
+
children: [/*#__PURE__*/_jsxs(HStack, {
|
|
2336
|
+
alignItems: "center",
|
|
2337
|
+
justifyContent: "space-between",
|
|
2338
|
+
padding: 2,
|
|
2339
|
+
children: [/*#__PURE__*/_jsx(IconButton, {
|
|
2340
|
+
accessibilityHint: "Navigate to previous example",
|
|
2341
|
+
accessibilityLabel: "Previous",
|
|
2342
|
+
disabled: isFirstExample,
|
|
2343
|
+
name: "arrowLeft",
|
|
2344
|
+
onPress: handlePrevious,
|
|
2345
|
+
variant: "secondary"
|
|
2346
|
+
}), /*#__PURE__*/_jsxs(VStack, {
|
|
2347
|
+
alignItems: "center",
|
|
2348
|
+
gap: 1,
|
|
2349
|
+
children: [/*#__PURE__*/_jsx(Text, {
|
|
2350
|
+
font: "title3",
|
|
2351
|
+
children: currentExample.title
|
|
2352
|
+
}), /*#__PURE__*/_jsxs(TextLabel1, {
|
|
2353
|
+
color: "fgMuted",
|
|
2354
|
+
children: [currentIndex + 1, " / ", examples.length]
|
|
2355
|
+
})]
|
|
2356
|
+
}), /*#__PURE__*/_jsx(IconButton, {
|
|
2357
|
+
accessibilityHint: "Navigate to next example",
|
|
2358
|
+
accessibilityLabel: "Next",
|
|
2359
|
+
disabled: isLastExample,
|
|
2360
|
+
name: "arrowRight",
|
|
2361
|
+
onPress: handleNext,
|
|
2362
|
+
variant: "secondary"
|
|
2363
|
+
})]
|
|
1815
2364
|
}), /*#__PURE__*/_jsx(Box, {
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
marginRight: -16
|
|
1819
|
-
},
|
|
1820
|
-
children: /*#__PURE__*/_jsx(LineChart, {
|
|
1821
|
-
enableScrubbing: true,
|
|
1822
|
-
showYAxis: true,
|
|
1823
|
-
accessibilityLiveRegion: "polite",
|
|
1824
|
-
height: defaultChartHeight,
|
|
1825
|
-
inset: {
|
|
1826
|
-
left: 0
|
|
1827
|
-
},
|
|
1828
|
-
onScrubberPositionChange: onScrubberPositionChange,
|
|
1829
|
-
series: [{
|
|
1830
|
-
id: 'candidate1',
|
|
1831
|
-
data: candidate1Data,
|
|
1832
|
-
color: colors.pink
|
|
1833
|
-
}, {
|
|
1834
|
-
id: 'candidate2',
|
|
1835
|
-
data: candidate2Data,
|
|
1836
|
-
color: colors.teal
|
|
1837
|
-
}, {
|
|
1838
|
-
id: 'candidate3',
|
|
1839
|
-
data: candidate3Data,
|
|
1840
|
-
color: colors.green
|
|
1841
|
-
}],
|
|
1842
|
-
xAxis: {
|
|
1843
|
-
range: _ref7 => {
|
|
1844
|
-
let {
|
|
1845
|
-
min,
|
|
1846
|
-
max
|
|
1847
|
-
} = _ref7;
|
|
1848
|
-
return {
|
|
1849
|
-
min,
|
|
1850
|
-
max: max - 32
|
|
1851
|
-
};
|
|
1852
|
-
}
|
|
1853
|
-
},
|
|
1854
|
-
yAxis: {
|
|
1855
|
-
domain: {
|
|
1856
|
-
min: 0,
|
|
1857
|
-
max: 100
|
|
1858
|
-
},
|
|
1859
|
-
tickLabelFormatter: value => value + "%",
|
|
1860
|
-
requestedTickCount: 5,
|
|
1861
|
-
showGrid: true
|
|
1862
|
-
},
|
|
1863
|
-
children: /*#__PURE__*/_jsx(Scrubber, {
|
|
1864
|
-
idlePulse: true,
|
|
1865
|
-
label: scrubberLabel
|
|
1866
|
-
})
|
|
1867
|
-
})
|
|
1868
|
-
}), /*#__PURE__*/_jsx(PeriodSelector, {
|
|
1869
|
-
accessibilityLabel: "Select time period for prediction chart",
|
|
1870
|
-
activeTab: timePeriod,
|
|
1871
|
-
onChange: onPeriodChange,
|
|
1872
|
-
tabs: tabs
|
|
2365
|
+
padding: 1,
|
|
2366
|
+
children: currentExample.component
|
|
1873
2367
|
})]
|
|
1874
2368
|
})
|
|
1875
2369
|
});
|
|
1876
|
-
}
|
|
1877
|
-
|
|
1878
|
-
const theme = useTheme();
|
|
1879
|
-
const [scrubIndex, setScrubIndex] = useState();
|
|
1880
|
-
const ChartDefs = /*#__PURE__*/memo(_ref8 => {
|
|
1881
|
-
var _rangeBounds$min, _rangeBounds$max, _yScale, _yScale2, _yScale3, _yScale4;
|
|
1882
|
-
let {
|
|
1883
|
-
yellowThresholdPercentage = 85,
|
|
1884
|
-
greenThresholdPercentage = 90
|
|
1885
|
-
} = _ref8;
|
|
1886
|
-
const {
|
|
1887
|
-
getYScale,
|
|
1888
|
-
getYAxis
|
|
1889
|
-
} = useCartesianChartContext();
|
|
1890
|
-
const yScale = getYScale();
|
|
1891
|
-
const yAxis = getYAxis();
|
|
1892
|
-
if (!yScale) return null;
|
|
1893
|
-
const rangeBounds = yAxis == null ? void 0 : yAxis.domain;
|
|
1894
|
-
const rangeMin = (_rangeBounds$min = rangeBounds == null ? void 0 : rangeBounds.min) != null ? _rangeBounds$min : 0;
|
|
1895
|
-
const rangeMax = (_rangeBounds$max = rangeBounds == null ? void 0 : rangeBounds.max) != null ? _rangeBounds$max : 100;
|
|
1896
|
-
|
|
1897
|
-
// Calculate the Y positions in the chart coordinate system
|
|
1898
|
-
const yellowThresholdY = (_yScale = yScale(yellowThresholdPercentage)) != null ? _yScale : 0;
|
|
1899
|
-
const greenThresholdY = (_yScale2 = yScale(greenThresholdPercentage)) != null ? _yScale2 : 0;
|
|
1900
|
-
const minY = (_yScale3 = yScale(rangeMax)) != null ? _yScale3 : 0; // Top of chart (max value)
|
|
1901
|
-
const maxY = (_yScale4 = yScale(rangeMin)) != null ? _yScale4 : 0; // Bottom of chart (min value)
|
|
1902
|
-
|
|
1903
|
-
// Calculate percentages based on actual chart positions
|
|
1904
|
-
const yellowThreshold = (yellowThresholdY - minY) / (maxY - minY) * 100;
|
|
1905
|
-
const greenThreshold = (greenThresholdY - minY) / (maxY - minY) * 100;
|
|
1906
|
-
return /*#__PURE__*/_jsx(Defs, {
|
|
1907
|
-
children: /*#__PURE__*/_jsxs(LinearGradient, {
|
|
1908
|
-
gradientUnits: "userSpaceOnUse",
|
|
1909
|
-
id: "availabilityGradient",
|
|
1910
|
-
x1: "0%",
|
|
1911
|
-
x2: "0%",
|
|
1912
|
-
y1: minY,
|
|
1913
|
-
y2: maxY,
|
|
1914
|
-
children: [/*#__PURE__*/_jsx(Stop, {
|
|
1915
|
-
offset: "0%",
|
|
1916
|
-
stopColor: theme.color.fgPositive
|
|
1917
|
-
}), /*#__PURE__*/_jsx(Stop, {
|
|
1918
|
-
offset: greenThreshold + "%",
|
|
1919
|
-
stopColor: theme.color.fgPositive
|
|
1920
|
-
}), /*#__PURE__*/_jsx(Stop, {
|
|
1921
|
-
offset: greenThreshold + "%",
|
|
1922
|
-
stopColor: theme.color.fgWarning
|
|
1923
|
-
}), /*#__PURE__*/_jsx(Stop, {
|
|
1924
|
-
offset: yellowThreshold + "%",
|
|
1925
|
-
stopColor: theme.color.fgWarning
|
|
1926
|
-
}), /*#__PURE__*/_jsx(Stop, {
|
|
1927
|
-
offset: yellowThreshold + "%",
|
|
1928
|
-
stopColor: theme.color.fgNegative
|
|
1929
|
-
}), /*#__PURE__*/_jsx(Stop, {
|
|
1930
|
-
offset: "100%",
|
|
1931
|
-
stopColor: theme.color.fgNegative
|
|
1932
|
-
})]
|
|
1933
|
-
})
|
|
1934
|
-
});
|
|
1935
|
-
});
|
|
1936
|
-
return /*#__PURE__*/_jsxs(CartesianChart, {
|
|
1937
|
-
enableScrubbing: true,
|
|
1938
|
-
height: defaultChartHeight,
|
|
1939
|
-
onScrubberPositionChange: setScrubIndex,
|
|
1940
|
-
series: [{
|
|
1941
|
-
id: 'availability',
|
|
1942
|
-
data: availabilityEvents.map(event => event.availability),
|
|
1943
|
-
color: 'url(#availabilityGradient)'
|
|
1944
|
-
}],
|
|
1945
|
-
xAxis: {
|
|
1946
|
-
data: availabilityEvents.map(event => event.date.getTime())
|
|
1947
|
-
},
|
|
1948
|
-
yAxis: {
|
|
1949
|
-
domain: _ref9 => {
|
|
1950
|
-
let {
|
|
1951
|
-
min,
|
|
1952
|
-
max
|
|
1953
|
-
} = _ref9;
|
|
1954
|
-
return {
|
|
1955
|
-
min: Math.max(min - 2, 0),
|
|
1956
|
-
max: Math.min(max + 2, 100)
|
|
1957
|
-
};
|
|
1958
|
-
}
|
|
1959
|
-
},
|
|
1960
|
-
children: [/*#__PURE__*/_jsx(ChartDefs, {}), /*#__PURE__*/_jsx(XAxis, {
|
|
1961
|
-
showGrid: true,
|
|
1962
|
-
showLine: true,
|
|
1963
|
-
showTickMarks: true,
|
|
1964
|
-
tickLabelFormatter: value => new Date(value).toLocaleDateString()
|
|
1965
|
-
}), /*#__PURE__*/_jsx(YAxis, {
|
|
1966
|
-
showGrid: true,
|
|
1967
|
-
showLine: true,
|
|
1968
|
-
showTickMarks: true,
|
|
1969
|
-
position: "left",
|
|
1970
|
-
tickLabelFormatter: value => value + "%"
|
|
1971
|
-
}), /*#__PURE__*/_jsx(Line, {
|
|
1972
|
-
curve: "stepAfter",
|
|
1973
|
-
renderPoints: () => ({
|
|
1974
|
-
fill: theme.color.bg,
|
|
1975
|
-
stroke: 'url(#availabilityGradient)',
|
|
1976
|
-
strokeWidth: 2
|
|
1977
|
-
}),
|
|
1978
|
-
seriesId: "availability"
|
|
1979
|
-
}), /*#__PURE__*/_jsx(Scrubber, {
|
|
1980
|
-
overlayOffset: 10
|
|
1981
|
-
})]
|
|
1982
|
-
});
|
|
1983
|
-
};
|
|
1984
|
-
const sampleData = [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58];
|
|
1985
|
-
const LineChartStories = () => {
|
|
1986
|
-
const theme = useTheme();
|
|
1987
|
-
return /*#__PURE__*/_jsxs(ExampleScreen, {
|
|
1988
|
-
children: [/*#__PURE__*/_jsx(Example, {
|
|
1989
|
-
title: "Basic",
|
|
1990
|
-
children: /*#__PURE__*/_jsx(LineChart, {
|
|
1991
|
-
enableScrubbing: true,
|
|
1992
|
-
showArea: true,
|
|
1993
|
-
showYAxis: true,
|
|
1994
|
-
curve: "monotone",
|
|
1995
|
-
height: defaultChartHeight,
|
|
1996
|
-
series: [{
|
|
1997
|
-
id: 'prices',
|
|
1998
|
-
data: sampleData
|
|
1999
|
-
}],
|
|
2000
|
-
yAxis: {
|
|
2001
|
-
showGrid: true
|
|
2002
|
-
},
|
|
2003
|
-
children: /*#__PURE__*/_jsx(Scrubber, {})
|
|
2004
|
-
})
|
|
2005
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2006
|
-
title: "Simple",
|
|
2007
|
-
children: /*#__PURE__*/_jsx(LineChart, {
|
|
2008
|
-
curve: "monotone",
|
|
2009
|
-
height: defaultChartHeight,
|
|
2010
|
-
series: [{
|
|
2011
|
-
id: 'prices',
|
|
2012
|
-
data: sampleData
|
|
2013
|
-
}]
|
|
2014
|
-
})
|
|
2015
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2016
|
-
title: "Gain/Loss",
|
|
2017
|
-
children: /*#__PURE__*/_jsx(GainLossChart, {})
|
|
2018
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2019
|
-
title: "BTC Price Chart",
|
|
2020
|
-
children: /*#__PURE__*/_jsx(BTCPriceChart, {})
|
|
2021
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2022
|
-
title: "Price Chart",
|
|
2023
|
-
children: /*#__PURE__*/_jsx(PriceChart, {})
|
|
2024
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2025
|
-
title: "Asset Price Dotted",
|
|
2026
|
-
children: /*#__PURE__*/_jsx(AssetPriceDotted, {})
|
|
2027
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2028
|
-
title: "Multiple Series",
|
|
2029
|
-
children: /*#__PURE__*/_jsx(LineChart, {
|
|
2030
|
-
enableScrubbing: true,
|
|
2031
|
-
showXAxis: true,
|
|
2032
|
-
showYAxis: true,
|
|
2033
|
-
height: defaultChartHeight,
|
|
2034
|
-
series: [{
|
|
2035
|
-
id: 'pageViews',
|
|
2036
|
-
data: [2400, 1398, 9800, 3908, 4800, 3800, 4300],
|
|
2037
|
-
label: 'Page Views',
|
|
2038
|
-
color: theme.color.accentBoldBlue,
|
|
2039
|
-
curve: 'natural'
|
|
2040
|
-
}, {
|
|
2041
|
-
id: 'uniqueVisitors',
|
|
2042
|
-
data: [4000, 3000, 2000, 2780, 1890, 2390, 3490],
|
|
2043
|
-
label: 'Unique Visitors',
|
|
2044
|
-
color: theme.color.accentBoldGreen,
|
|
2045
|
-
curve: 'natural'
|
|
2046
|
-
}],
|
|
2047
|
-
xAxis: {
|
|
2048
|
-
data: ['Page A', 'Page B', 'Page C', 'Page D', 'Page E', 'Page F', 'Page G'],
|
|
2049
|
-
scaleType: 'band'
|
|
2050
|
-
},
|
|
2051
|
-
yAxis: {
|
|
2052
|
-
domain: {
|
|
2053
|
-
min: 0
|
|
2054
|
-
},
|
|
2055
|
-
showGrid: true,
|
|
2056
|
-
tickLabelFormatter: value => value.toLocaleString()
|
|
2057
|
-
},
|
|
2058
|
-
children: /*#__PURE__*/_jsx(Scrubber, {})
|
|
2059
|
-
})
|
|
2060
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2061
|
-
title: "Points",
|
|
2062
|
-
children: /*#__PURE__*/_jsxs(CartesianChart, {
|
|
2063
|
-
height: defaultChartHeight,
|
|
2064
|
-
series: [{
|
|
2065
|
-
id: 'prices',
|
|
2066
|
-
data: [10, 22, 29, 45, 98, 45, 22, 52, 21, 4, 68, 20, 21, 58]
|
|
2067
|
-
}],
|
|
2068
|
-
children: [/*#__PURE__*/_jsx(Area, {
|
|
2069
|
-
curve: "monotone",
|
|
2070
|
-
fill: "rgb(" + theme.spectrum.blue5 + ")",
|
|
2071
|
-
seriesId: "prices"
|
|
2072
|
-
}), /*#__PURE__*/_jsx(Line, {
|
|
2073
|
-
curve: "monotone",
|
|
2074
|
-
renderPoints: _ref0 => {
|
|
2075
|
-
let {
|
|
2076
|
-
dataX
|
|
2077
|
-
} = _ref0,
|
|
2078
|
-
props = _objectWithoutPropertiesLoose(_ref0, _excluded4);
|
|
2079
|
-
return [4, 6, 7, 9, 10].includes(dataX) ? _extends({}, props, {
|
|
2080
|
-
strokeWidth: 2,
|
|
2081
|
-
stroke: theme.color.bg,
|
|
2082
|
-
radius: 5,
|
|
2083
|
-
onClick: () => alert('You have clicked a key market shift!')
|
|
2084
|
-
}) : false;
|
|
2085
|
-
},
|
|
2086
|
-
seriesId: "prices"
|
|
2087
|
-
})]
|
|
2088
|
-
})
|
|
2089
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2090
|
-
title: "Data Formats",
|
|
2091
|
-
children: /*#__PURE__*/_jsx(LineChart, {
|
|
2092
|
-
enableScrubbing: true,
|
|
2093
|
-
showArea: true,
|
|
2094
|
-
showXAxis: true,
|
|
2095
|
-
showYAxis: true,
|
|
2096
|
-
curve: "natural",
|
|
2097
|
-
height: defaultChartHeight,
|
|
2098
|
-
renderPoints: () => true,
|
|
2099
|
-
series: [{
|
|
2100
|
-
id: 'line',
|
|
2101
|
-
data: [2, 5.5, 2, 8.5, 1.5, 5]
|
|
2102
|
-
}],
|
|
2103
|
-
xAxis: {
|
|
2104
|
-
data: [1, 2, 3, 5, 8, 10],
|
|
2105
|
-
showLine: true,
|
|
2106
|
-
showTickMarks: true,
|
|
2107
|
-
showGrid: true
|
|
2108
|
-
},
|
|
2109
|
-
yAxis: {
|
|
2110
|
-
domain: {
|
|
2111
|
-
min: 0
|
|
2112
|
-
},
|
|
2113
|
-
position: 'left',
|
|
2114
|
-
showLine: true,
|
|
2115
|
-
showTickMarks: true,
|
|
2116
|
-
showGrid: true
|
|
2117
|
-
},
|
|
2118
|
-
children: /*#__PURE__*/_jsx(Scrubber, {})
|
|
2119
|
-
})
|
|
2120
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2121
|
-
title: "Bitcoin Chart with Scrubber Beacon",
|
|
2122
|
-
children: /*#__PURE__*/_jsx(BitcoinChartWithScrubberBeacon, {})
|
|
2123
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2124
|
-
title: "Scrubber with Imperative Handle",
|
|
2125
|
-
children: /*#__PURE__*/_jsx(ScrubberWithImperativeHandle, {})
|
|
2126
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2127
|
-
title: "Asset Price",
|
|
2128
|
-
children: /*#__PURE__*/_jsx(AssetPrice, {})
|
|
2129
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2130
|
-
title: "Line Styles",
|
|
2131
|
-
children: /*#__PURE__*/_jsx(LineStyles, {})
|
|
2132
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2133
|
-
title: "Chart Scale",
|
|
2134
|
-
children: /*#__PURE__*/_jsx(ChartScale, {})
|
|
2135
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2136
|
-
title: "Color Shift Chart",
|
|
2137
|
-
children: /*#__PURE__*/_jsx(ColorShiftChart, {})
|
|
2138
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2139
|
-
title: "Price Chart",
|
|
2140
|
-
children: /*#__PURE__*/_jsx(PriceChart, {})
|
|
2141
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2142
|
-
title: "Forecast Chart",
|
|
2143
|
-
children: /*#__PURE__*/_jsx(ForecastChart, {})
|
|
2144
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2145
|
-
title: "Period Selector",
|
|
2146
|
-
children: /*#__PURE__*/_jsx(PeriodSelectorExample, {})
|
|
2147
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2148
|
-
title: "Live Asset Price",
|
|
2149
|
-
children: /*#__PURE__*/_jsx(LiveAssetPrice, {})
|
|
2150
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2151
|
-
title: "Availability Chart",
|
|
2152
|
-
children: /*#__PURE__*/_jsx(AvailabilityChart, {})
|
|
2153
|
-
})]
|
|
2154
|
-
});
|
|
2155
|
-
};
|
|
2156
|
-
const AssetPriceScreen = () => {
|
|
2157
|
-
return /*#__PURE__*/_jsxs(ExampleScreen, {
|
|
2158
|
-
children: [/*#__PURE__*/_jsx(Example, {
|
|
2159
|
-
title: "Scrubber with Imperative Handle",
|
|
2160
|
-
children: /*#__PURE__*/_jsx(ScrubberWithImperativeHandle, {})
|
|
2161
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2162
|
-
title: "Basic",
|
|
2163
|
-
children: /*#__PURE__*/_jsx(LineChart, {
|
|
2164
|
-
enableScrubbing: true,
|
|
2165
|
-
showArea: true,
|
|
2166
|
-
showYAxis: true,
|
|
2167
|
-
curve: "monotone",
|
|
2168
|
-
height: defaultChartHeight,
|
|
2169
|
-
series: [{
|
|
2170
|
-
id: 'prices',
|
|
2171
|
-
data: sampleData
|
|
2172
|
-
}],
|
|
2173
|
-
yAxis: {
|
|
2174
|
-
showGrid: true
|
|
2175
|
-
},
|
|
2176
|
-
children: /*#__PURE__*/_jsx(Scrubber, {})
|
|
2177
|
-
})
|
|
2178
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2179
|
-
title: "Simple",
|
|
2180
|
-
children: /*#__PURE__*/_jsx(LineChart, {
|
|
2181
|
-
curve: "monotone",
|
|
2182
|
-
height: defaultChartHeight,
|
|
2183
|
-
series: [{
|
|
2184
|
-
id: 'prices',
|
|
2185
|
-
data: sampleData
|
|
2186
|
-
}]
|
|
2187
|
-
})
|
|
2188
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2189
|
-
title: "Data Formats",
|
|
2190
|
-
children: /*#__PURE__*/_jsx(LineChart, {
|
|
2191
|
-
enableScrubbing: true,
|
|
2192
|
-
showArea: true,
|
|
2193
|
-
showXAxis: true,
|
|
2194
|
-
showYAxis: true,
|
|
2195
|
-
curve: "natural",
|
|
2196
|
-
height: defaultChartHeight,
|
|
2197
|
-
series: [{
|
|
2198
|
-
id: 'line',
|
|
2199
|
-
data: [2, 5.5, 2, 8.5, 1.5, 5]
|
|
2200
|
-
}],
|
|
2201
|
-
xAxis: {
|
|
2202
|
-
data: [1, 2, 3, 5, 8, 10],
|
|
2203
|
-
showLine: true,
|
|
2204
|
-
showTickMarks: true,
|
|
2205
|
-
showGrid: true
|
|
2206
|
-
},
|
|
2207
|
-
yAxis: {
|
|
2208
|
-
domain: {
|
|
2209
|
-
min: 0
|
|
2210
|
-
},
|
|
2211
|
-
position: 'left',
|
|
2212
|
-
showLine: true,
|
|
2213
|
-
showTickMarks: true,
|
|
2214
|
-
showGrid: true
|
|
2215
|
-
},
|
|
2216
|
-
children: /*#__PURE__*/_jsx(Scrubber, {})
|
|
2217
|
-
})
|
|
2218
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2219
|
-
title: "Color Shift Chart",
|
|
2220
|
-
children: /*#__PURE__*/_jsx(ColorShiftChart, {})
|
|
2221
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2222
|
-
title: "Asset Price Dotted",
|
|
2223
|
-
children: /*#__PURE__*/_jsx(AssetPriceDotted, {})
|
|
2224
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2225
|
-
title: "Asset Price Multiple Dotted",
|
|
2226
|
-
children: /*#__PURE__*/_jsx(AssetPriceMultipleDotted, {})
|
|
2227
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2228
|
-
title: "Asset Price Dotted (Old)",
|
|
2229
|
-
children: /*#__PURE__*/_jsx(AssetPriceDottedNonMemoized, {})
|
|
2230
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2231
|
-
title: "BTC Price Chart",
|
|
2232
|
-
children: /*#__PURE__*/_jsx(BTCPriceChart, {})
|
|
2233
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2234
|
-
title: "Gain/Loss",
|
|
2235
|
-
children: /*#__PURE__*/_jsx(GainLossChart, {})
|
|
2236
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2237
|
-
title: "Live Asset Price",
|
|
2238
|
-
children: /*#__PURE__*/_jsx(LiveAssetPrice, {})
|
|
2239
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2240
|
-
title: "Prediction Chart",
|
|
2241
|
-
children: /*#__PURE__*/_jsx(PredictionChart, {})
|
|
2242
|
-
}), /*#__PURE__*/_jsx(Example, {
|
|
2243
|
-
title: "Availability Chart",
|
|
2244
|
-
children: /*#__PURE__*/_jsx(AvailabilityChart, {})
|
|
2245
|
-
})]
|
|
2246
|
-
});
|
|
2247
|
-
};
|
|
2248
|
-
export default AssetPriceScreen;
|
|
2370
|
+
}
|
|
2371
|
+
export default ExampleNavigator;
|